Merge "Fix "pm list permissions GROUP""
diff --git a/api/current.txt b/api/current.txt
index 77c64d7..c3a4a0c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24962,6 +24962,7 @@
public static class CallLog.Calls implements android.provider.BaseColumns {
ctor public CallLog.Calls();
method public static java.lang.String getLastOutgoingCall(android.content.Context);
+ field public static final int BLOCKED_TYPE = 6; // 0x6
field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
field public static final java.lang.String CACHED_MATCHED_NUMBER = "matched_number";
@@ -25000,6 +25001,7 @@
field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
field public static final int PRESENTATION_RESTRICTED = 2; // 0x2
field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
+ field public static final int REJECTED_TYPE = 5; // 0x5
field public static final java.lang.String TRANSCRIPTION = "transcription";
field public static final java.lang.String TYPE = "type";
field public static final int VOICEMAIL_TYPE = 4; // 0x4
diff --git a/api/system-current.txt b/api/system-current.txt
index cff0055..325aa28b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -26918,6 +26918,7 @@
public static class CallLog.Calls implements android.provider.BaseColumns {
ctor public CallLog.Calls();
method public static java.lang.String getLastOutgoingCall(android.content.Context);
+ field public static final int BLOCKED_TYPE = 6; // 0x6
field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
field public static final java.lang.String CACHED_MATCHED_NUMBER = "matched_number";
@@ -26956,6 +26957,7 @@
field public static final int PRESENTATION_PAYPHONE = 4; // 0x4
field public static final int PRESENTATION_RESTRICTED = 2; // 0x2
field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
+ field public static final int REJECTED_TYPE = 5; // 0x5
field public static final java.lang.String TRANSCRIPTION = "transcription";
field public static final java.lang.String TYPE = "type";
field public static final int VOICEMAIL_TYPE = 4; // 0x4
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 5c9fd51..4a13136 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -44,6 +44,7 @@
import android.content.pm.IPackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.net.Uri;
@@ -63,6 +64,7 @@
import android.view.IWindowManager;
import com.android.internal.os.BaseCommand;
+import com.android.internal.util.Preconditions;
import java.io.BufferedReader;
import java.io.File;
@@ -168,6 +170,7 @@
" am get-inactive [--user <USER_ID>] <PACKAGE>\n" +
" am send-trim-memory [--user <USER_ID>] <PROCESS>\n" +
" [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]\n" +
+ " am get-current-user\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
@@ -334,7 +337,9 @@
"\n" +
"am get-inactive: returns the inactive state of an app.\n" +
"\n" +
- "am send-trim-memory: Send a memory trim event to a <PROCESS>.\n" +
+ "am send-trim-memory: send a memory trim event to a <PROCESS>.\n" +
+ "\n" +
+ "am get-current-user: returns id of the current foreground user.\n" +
"\n" +
"<INTENT> specifications include these flags and arguments:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
@@ -464,6 +469,8 @@
runGetInactive();
} else if (op.equals("send-trim-memory")) {
runSendTrimMemory();
+ } else if (op.equals("get-current-user")) {
+ runGetCurrentUser();
} else {
showError("Error: unknown command '" + op + "'");
}
@@ -2712,6 +2719,12 @@
}
}
+ private void runGetCurrentUser() throws Exception {
+ UserInfo currentUser = Preconditions.checkNotNull(mAm.getCurrentUser(),
+ "Current user not set");
+ System.out.println(currentUser.id);
+ }
+
/**
* Open the given file for sending into the system process. This verifies
* with SELinux that the system will have access to the file.
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 16f825d..d444638 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -603,7 +603,17 @@
createDependencyGraph();
// Now that all dependencies are set up, start the animations that should be started.
- start(mRootNode);
+ boolean setIsEmpty = false;
+ if (mStartDelay > 0) {
+ start(mRootNode);
+ } else if (mNodes.size() > 1) {
+ // No delay, but there are other animators in the set
+ onChildAnimatorEnded(mDelayAnim);
+ } else {
+ // Set is empty, no delay, no other animation. Skip to end in this case
+ setIsEmpty = true;
+ }
+
if (mListeners != null) {
ArrayList<AnimatorListener> tmpListeners =
(ArrayList<AnimatorListener>) mListeners.clone();
@@ -612,18 +622,9 @@
tmpListeners.get(i).onAnimationStart(this);
}
}
- if (mNodes.size() == 0 && mStartDelay == 0) {
- // Handle unusual case where empty AnimatorSet is started - should send out
- // end event immediately since the event will not be sent out at all otherwise
- mStarted = false;
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(this);
- }
- }
+ if (setIsEmpty) {
+ // In the case of empty AnimatorSet, we will trigger the onAnimationEnd() right away.
+ onChildAnimatorEnded(mDelayAnim);
}
}
@@ -751,44 +752,7 @@
public void onAnimationEnd(Animator animation) {
animation.removeListener(this);
mAnimatorSet.mPlayingSet.remove(animation);
- Node animNode = mAnimatorSet.mNodeMap.get(animation);
- animNode.mEnded = true;
-
- if (!mAnimatorSet.mTerminated) {
- List<Node> children = animNode.mChildNodes;
- // Start children animations, if any.
- int childrenSize = children == null ? 0 : children.size();
- for (int i = 0; i < childrenSize; i++) {
- if (children.get(i).mLatestParent == animNode) {
- mAnimatorSet.start(children.get(i));
- }
- }
- // Listeners are already notified of the AnimatorSet ending in cancel() or
- // end(); the logic below only kicks in when animations end normally
- boolean allDone = true;
- // Traverse the tree and find if there's any unfinished node
- int size = mAnimatorSet.mNodes.size();
- for (int i = 0; i < size; i++) {
- if (!mAnimatorSet.mNodes.get(i).mEnded) {
- allDone = false;
- break;
- }
- }
- if (allDone) {
- // If this was the last child animation to end, then notify listeners that this
- // AnimatorSet has ended
- if (mAnimatorSet.mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mAnimatorSet.mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
- }
- }
- mAnimatorSet.mStarted = false;
- mAnimatorSet.mPaused = false;
- }
- }
+ mAnimatorSet.onChildAnimatorEnded(animation);
}
// Nothing to do
@@ -801,6 +765,47 @@
}
+ private void onChildAnimatorEnded(Animator animation) {
+ Node animNode = mNodeMap.get(animation);
+ animNode.mEnded = true;
+
+ if (!mTerminated) {
+ List<Node> children = animNode.mChildNodes;
+ // Start children animations, if any.
+ int childrenSize = children == null ? 0 : children.size();
+ for (int i = 0; i < childrenSize; i++) {
+ if (children.get(i).mLatestParent == animNode) {
+ start(children.get(i));
+ }
+ }
+ // Listeners are already notified of the AnimatorSet ending in cancel() or
+ // end(); the logic below only kicks in when animations end normally
+ boolean allDone = true;
+ // Traverse the tree and find if there's any unfinished node
+ int size = mNodes.size();
+ for (int i = 0; i < size; i++) {
+ if (!mNodes.get(i).mEnded) {
+ allDone = false;
+ break;
+ }
+ }
+ if (allDone) {
+ // If this was the last child animation to end, then notify listeners that this
+ // AnimatorSet has ended
+ if (mListeners != null) {
+ ArrayList<AnimatorListener> tmpListeners =
+ (ArrayList<AnimatorListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onAnimationEnd(this);
+ }
+ }
+ mStarted = false;
+ mPaused = false;
+ }
+ }
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 5af6504..1995ef5 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -932,6 +932,13 @@
updateScaledDuration(); // in case the scale factor has changed since creation time
AnimationHandler animationHandler = AnimationHandler.getInstance();
animationHandler.addAnimationFrameCallback(this, mStartDelay);
+
+ if (mStartDelay == 0) {
+ // If there's no start delay, init the animation and notify start listeners right away
+ // Otherwise, postpone this until the first frame after the start delay.
+ startAnimation();
+ setCurrentFraction(mSeekFraction == -1 ? 0 : mSeekFraction);
+ }
}
@Override
@@ -1075,6 +1082,7 @@
mStartListenersCalled = false;
mPlayingBackwards = false;
mReversing = false;
+ mLastFrameTime = 0;
mCurrentIteration = 0;
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
@@ -1184,12 +1192,13 @@
* @hide
*/
public final void doAnimationFrame(long frameTime) {
- mLastFrameTime = frameTime;
AnimationHandler handler = AnimationHandler.getInstance();
- if (!mRunning) {
+ if (mLastFrameTime == 0) {
// First frame
handler.addOneShotCommitCallback(this);
- startAnimation();
+ if (mStartDelay > 0) {
+ startAnimation();
+ }
if (mSeekFraction < 0) {
mStartTime = frameTime;
} else {
@@ -1199,6 +1208,7 @@
}
mStartTimeCommitted = false; // allow start time to be compensated for jank
}
+ mLastFrameTime = frameTime;
if (mPaused) {
if (mPauseTime < 0) {
mPauseTime = frameTime;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index e965d65..3f566eb 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1545,7 +1545,7 @@
/**
* <p>Whether video stabilization is
* active.</p>
- * <p>Video stabilization automatically translates and scales images from
+ * <p>Video stabilization automatically warps images from
* the camera in order to stabilize motion between consecutive frames.</p>
* <p>If enabled, video stabilization can modify the
* {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream stabilized.</p>
@@ -1555,6 +1555,15 @@
* the video stabilization modes in the first several capture results may
* still be "OFF", and it will become "ON" when the initialization is
* done.</p>
+ * <p>In addition, not all recording sizes or frame rates may be supported for
+ * stabilization by a device that reports stabilization support. It is guaranteed
+ * that an output targeting a MediaRecorder or MediaCodec will be stabilized if
+ * the recording resolution is less than or equal to 1920 x 1080 (width less than
+ * or equal to 1920, height less than or equal to 1080), and the recording
+ * frame rate is less than or equal to 30fps. At other sizes, the CaptureResult
+ * {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE android.control.videoStabilizationMode} field will return
+ * OFF if the recording output is not stabilized, or if there are no output
+ * Surface types that can be stabilized.</p>
* <p>If a camera device supports both this mode and OIS
* ({@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}), turning both modes on may
* produce undesirable interaction, so it is recommended not to enable
@@ -1566,6 +1575,7 @@
* </ul></p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
* @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 46eddb3..b3acf2b 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2056,7 +2056,7 @@
/**
* <p>Whether video stabilization is
* active.</p>
- * <p>Video stabilization automatically translates and scales images from
+ * <p>Video stabilization automatically warps images from
* the camera in order to stabilize motion between consecutive frames.</p>
* <p>If enabled, video stabilization can modify the
* {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream stabilized.</p>
@@ -2066,6 +2066,15 @@
* the video stabilization modes in the first several capture results may
* still be "OFF", and it will become "ON" when the initialization is
* done.</p>
+ * <p>In addition, not all recording sizes or frame rates may be supported for
+ * stabilization by a device that reports stabilization support. It is guaranteed
+ * that an output targeting a MediaRecorder or MediaCodec will be stabilized if
+ * the recording resolution is less than or equal to 1920 x 1080 (width less than
+ * or equal to 1920, height less than or equal to 1080), and the recording
+ * frame rate is less than or equal to 30fps. At other sizes, the CaptureResult
+ * {@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE android.control.videoStabilizationMode} field will return
+ * OFF if the recording output is not stabilized, or if there are no output
+ * Surface types that can be stabilized.</p>
* <p>If a camera device supports both this mode and OIS
* ({@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}), turning both modes on may
* produce undesirable interaction, so it is recommended not to enable
@@ -2077,6 +2086,7 @@
* </ul></p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
* @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index c373308..cd483b1 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.MathUtils;
import java.io.Serializable;
import java.util.ArrayList;
@@ -1345,18 +1346,19 @@
*/
void readFromParcelInner(Parcel parcel) {
int length = parcel.readInt();
- if (length < 0) {
- throw new RuntimeException("Bad length in parcel: " + length);
- }
readFromParcelInner(parcel, length);
}
private void readFromParcelInner(Parcel parcel, int length) {
- if (length == 0) {
+ if (length < 0) {
+ throw new RuntimeException("Bad length in parcel: " + length);
+
+ } else if (length == 0) {
// Empty Bundle or end of data.
mParcelledData = EMPTY_PARCEL;
return;
}
+
int magic = parcel.readInt();
if (magic != BUNDLE_MAGIC) {
//noinspection ThrowableInstanceNeverThrown
@@ -1366,7 +1368,7 @@
// Advance within this Parcel
int offset = parcel.dataPosition();
- parcel.setDataPosition(offset + length);
+ parcel.setDataPosition(MathUtils.addOrThrow(offset, length));
Parcel p = Parcel.obtain();
p.setDataPosition(0);
diff --git a/core/java/android/os/ParcelableParcel.java b/core/java/android/os/ParcelableParcel.java
index 11785f1..5bbe6488 100644
--- a/core/java/android/os/ParcelableParcel.java
+++ b/core/java/android/os/ParcelableParcel.java
@@ -16,6 +16,8 @@
package android.os;
+import android.util.MathUtils;
+
/**
* Parcelable containing a raw Parcel of data.
* @hide
@@ -33,9 +35,13 @@
mParcel = Parcel.obtain();
mClassLoader = loader;
int size = src.readInt();
+ if (size < 0) {
+ throw new IllegalArgumentException("Negative size read from parcel");
+ }
+
int pos = src.dataPosition();
- mParcel.appendFrom(src, src.dataPosition(), size);
- src.setDataPosition(pos + size);
+ src.setDataPosition(MathUtils.addOrThrow(pos, size));
+ mParcel.appendFrom(src, pos, size);
}
public Parcel getParcel() {
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 4f880b1..342f8c7 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -153,6 +153,18 @@
/**
* The type of the call (incoming, outgoing or missed).
* <P>Type: INTEGER (int)</P>
+ *
+ * <p>
+ * Allowed values:
+ * <ul>
+ * <li>{@link #INCOMING_TYPE}</li>
+ * <li>{@link #OUTGOING_TYPE}</li>
+ * <li>{@link #MISSED_TYPE}</li>
+ * <li>{@link #VOICEMAIL_TYPE}</li>
+ * <li>{@link #REJECTED_TYPE}</li>
+ * <li>{@link #BLOCKED_TYPE}</li>
+ * </ul>
+ * </p>
*/
public static final String TYPE = "type";
@@ -164,6 +176,10 @@
public static final int MISSED_TYPE = 3;
/** Call log type for voicemails. */
public static final int VOICEMAIL_TYPE = 4;
+ /** Call log type for calls rejected by direct user action. */
+ public static final int REJECTED_TYPE = 5;
+ /** Call log type for calls blocked automatically. */
+ public static final int BLOCKED_TYPE = 6;
/**
* Bit-mask describing features of the call (e.g. video).
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 8b57d3d..32aac13 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -156,6 +156,27 @@
return start + (stop - start) * amount;
}
+ /**
+ * Returns an interpolated angle in degrees between a set of start and end
+ * angles.
+ * <p>
+ * Unlike {@link #lerp(float, float, float)}, the direction and distance of
+ * travel is determined by the shortest angle between the start and end
+ * angles. For example, if the starting angle is 0 and the ending angle is
+ * 350, then the interpolated angle will be in the range [0,-10] rather
+ * than [0,350].
+ *
+ * @param start the starting angle in degrees
+ * @param end the ending angle in degrees
+ * @param amount the position between start and end in the range [0,1]
+ * where 0 is the starting angle and 1 is the ending angle
+ * @return the interpolated angle in degrees
+ */
+ public static float lerpDeg(float start, float end, float amount) {
+ final float minAngle = (((end - start) + 180) % 360) - 180;
+ return minAngle * amount + start;
+ }
+
public static float norm(float start, float stop, float value) {
return (value - start) / (stop - start);
}
@@ -185,4 +206,24 @@
public static void randomSeed(long seed) {
sRandom.setSeed(seed);
}
+
+ /**
+ * Returns the sum of the two parameters, or throws an exception if the resulting sum would
+ * cause an overflow or underflow.
+ * @throws IllegalArgumentException when overflow or underflow would occur.
+ */
+ public static int addOrThrow(int a, int b) throws IllegalArgumentException {
+ if (b == 0) {
+ return a;
+ }
+
+ if (b > 0 && a <= (Integer.MAX_VALUE - b)) {
+ return a + b;
+ }
+
+ if (b < 0 && a >= (Integer.MIN_VALUE - b)) {
+ return a + b;
+ }
+ throw new IllegalArgumentException("Addition overflow: " + a + " + " + b);
+ }
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index dcef142..304e9c0 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -349,7 +349,7 @@
* @param right The right side of the protected bounds.
* @param bottom The bottom side of the protected bounds.
*/
- public void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
+ public void setContentDrawBounds(int left, int top, int right, int bottom) {
mStagedContentBounds.set(left, top, right, bottom);
}
@@ -370,9 +370,9 @@
// renderer.
if (!mCurrentContentBounds.equals(mStagedContentBounds)) {
mCurrentContentBounds.set(mStagedContentBounds);
- nSetContentOverdrawProtectionBounds(mNativeProxy, mCurrentContentBounds.left,
- mCurrentContentBounds.top, mCurrentContentBounds.right,
- mCurrentContentBounds.bottom);
+ nSetContentDrawBounds(mNativeProxy, mCurrentContentBounds.left,
+ mCurrentContentBounds.top, mCurrentContentBounds.right,
+ mCurrentContentBounds.bottom);
}
attachInfo.mIgnoreDirtyState = false;
@@ -600,6 +600,6 @@
boolean placeFront);
private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
- private static native void nSetContentOverdrawProtectionBounds(long nativeProxy, int left,
+ private static native void nSetContentDrawBounds(long nativeProxy, int left,
int top, int right, int bottom);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f6c60ed..7cf23e7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -73,6 +73,7 @@
import android.view.animation.Interpolator;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.view.WindowCallbacks;
import android.widget.Scroller;
import com.android.internal.R;
@@ -115,6 +116,12 @@
private static final boolean DEBUG_INPUT_STAGES = false || LOCAL_LOGV;
/**
+ * Set to false if we do not want to use the multi threaded renderer. Note that by disabling
+ * this, WindowCallbacks will not fire.
+ */
+ private static final boolean USE_MT_RENDERER = true;
+
+ /**
* Set this system property to true to force the view hierarchy to render
* at 60 Hz. This can be used to measure the potential framerate.
*/
@@ -132,11 +139,11 @@
static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
- static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<Runnable>();
+ static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
static boolean sFirstDrawComplete = false;
+ static final ArrayList<WindowCallbacks> sWindowCallbacks = new ArrayList();
- static final ArrayList<ComponentCallbacks> sConfigCallbacks
- = new ArrayList<ComponentCallbacks>();
+ static final ArrayList<ComponentCallbacks> sConfigCallbacks = new ArrayList();
final Context mContext;
final IWindowSession mWindowSession;
@@ -417,6 +424,22 @@
}
}
+ public static void addWindowCallbacks(WindowCallbacks callback) {
+ if (USE_MT_RENDERER) {
+ synchronized (sWindowCallbacks) {
+ sWindowCallbacks.add(callback);
+ }
+ }
+ }
+
+ public static void removeWindowCallbacks(WindowCallbacks callback) {
+ if (USE_MT_RENDERER) {
+ synchronized (sWindowCallbacks) {
+ sWindowCallbacks.remove(callback);
+ }
+ }
+ }
+
// FIXME for perf testing only
private boolean mProfile = false;
@@ -1378,6 +1401,7 @@
mAttachInfo.mWindowVisibility = viewVisibility;
host.dispatchWindowVisibilityChanged(viewVisibility);
if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
+ endDragResizing();
destroyHardwareResources();
}
if (viewVisibility == View.GONE) {
@@ -1701,14 +1725,20 @@
final boolean dragResizing = (relayoutResult
& WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING) != 0;
if (mDragResizing != dragResizing) {
- mDragResizing = dragResizing;
- mFullRedrawNeeded = true;
+ if (dragResizing) {
+ startDragResizing(frame);
+ } else {
+ // We shouldn't come here, but if we come we should end the resize.
+ endDragResizing();
+ }
}
- if (dragResizing) {
- mCanvasOffsetX = mWinFrame.left;
- mCanvasOffsetY = mWinFrame.top;
- } else {
- mCanvasOffsetX = mCanvasOffsetY = 0;
+ if (!USE_MT_RENDERER) {
+ if (dragResizing) {
+ mCanvasOffsetX = mWinFrame.left;
+ mCanvasOffsetY = mWinFrame.top;
+ } else {
+ mCanvasOffsetX = mCanvasOffsetY = 0;
+ }
}
} catch (RemoteException e) {
}
@@ -6635,6 +6665,15 @@
Configuration newConfig) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
+ // Tell all listeners that we are resizing the window so that the chrome can get
+ // updated as fast as possible on a separate thread,
+ if (mViewAncestor.get().mDragResizing) {
+ synchronized (sWindowCallbacks) {
+ for (int i = sWindowCallbacks.size() - 1; i >= 0; i--) {
+ sWindowCallbacks.get(i).onWindowSizeIsChanging(frame);
+ }
+ }
+ }
viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
visibleInsets, stableInsets, outsets, reportDraw, newConfig);
}
@@ -6804,6 +6843,36 @@
}
/**
+ * Start a drag resizing which will inform all listeners that a window resize is taking place.
+ */
+ private void startDragResizing(Rect initialBounds) {
+ if (!mDragResizing) {
+ mDragResizing = true;
+ synchronized (sWindowCallbacks) {
+ for (int i = sWindowCallbacks.size() - 1; i >= 0; i--) {
+ sWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds);
+ }
+ }
+ mFullRedrawNeeded = true;
+ }
+ }
+
+ /**
+ * End a drag resize which will inform all listeners that a window resize has ended.
+ */
+ private void endDragResizing() {
+ if (mDragResizing) {
+ mDragResizing = false;
+ synchronized (sWindowCallbacks) {
+ for (int i = sWindowCallbacks.size() - 1; i >= 0; i--) {
+ sWindowCallbacks.get(i).onWindowDragResizeEnd();
+ }
+ }
+ mFullRedrawNeeded = true;
+ }
+ }
+
+ /**
* Class for managing the accessibility interaction connection
* based on the global accessibility state.
*/
diff --git a/core/java/android/view/WindowCallbacks.java b/core/java/android/view/WindowCallbacks.java
new file mode 100644
index 0000000..cb6e983
--- /dev/null
+++ b/core/java/android/view/WindowCallbacks.java
@@ -0,0 +1,48 @@
+/*
+ * 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 android.view;
+
+import android.graphics.Rect;
+
+/**
+ * These callbacks are used to communicate window configuration changes while the user is performing
+ * window changes.
+ * @hide
+ */
+public interface WindowCallbacks {
+ /**
+ * Called by the system when the window got changed by the user, before the layouter got called.
+ * It can be used to perform a "quick and dirty" resize which should never take more then 4ms to
+ * complete.
+ *
+ * <p>At the time the layouting has not happened yet.
+ *
+ * @param newBounds The new window frame bounds.
+ */
+ void onWindowSizeIsChanging(Rect newBounds);
+
+ /**
+ * Called when a drag resize starts.
+ * @param initialBounds The initial bounds where the window will be.
+ */
+ void onWindowDragResizeStart(Rect initialBounds);
+
+ /**
+ * Called when a drag resize ends.
+ */
+ void onWindowDragResizeEnd();
+}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 72971e8..81ec330 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -88,6 +88,9 @@
/** @hide */
public static final int DALTONIZER_CORRECT_DEUTERANOMALY = 12;
+ /** @hide */
+ public static final int AUTOCLICK_DELAY_DEFAULT = 600;
+
static final Object sInstanceSync = new Object();
private static AccessibilityManager sInstance;
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 9571109..7220256 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -16,12 +16,7 @@
package android.widget;
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.Keyframe;
import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -35,6 +30,7 @@
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.util.IntArray;
import android.util.Log;
import android.util.MathUtils;
@@ -50,7 +46,6 @@
import com.android.internal.R;
import com.android.internal.widget.ExploreByTouchHelper;
-import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
@@ -60,6 +55,7 @@
* @hide
*/
public class RadialTimePickerView extends View {
+
private static final String TAG = "RadialTimePickerView";
private static final int HOURS = 0;
@@ -73,12 +69,6 @@
private static final int AM = 0;
private static final int PM = 1;
- // Opaque alpha level
- private static final int ALPHA_OPAQUE = 255;
-
- // Transparent alpha level
- private static final int ALPHA_TRANSPARENT = 0;
-
private static final int HOURS_IN_CIRCLE = 12;
private static final int MINUTES_IN_CIRCLE = 60;
private static final int DEGREES_FOR_ONE_HOUR = 360 / HOURS_IN_CIRCLE;
@@ -88,8 +78,8 @@
private static final int[] HOURS_NUMBERS_24 = {0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
private static final int[] MINUTES_NUMBERS = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
- private static final int FADE_OUT_DURATION = 500;
- private static final int FADE_IN_DURATION = 500;
+ private static final int ANIM_DURATION_NORMAL = 500;
+ private static final int ANIM_DURATION_TOUCH = 60;
private static final int[] SNAP_PREFER_30S_MAP = new int[361];
@@ -97,6 +87,9 @@
private static final float[] COS_30 = new float[NUM_POSITIONS];
private static final float[] SIN_30 = new float[NUM_POSITIONS];
+ /** "Something is wrong" color used when a color attribute is missing. */
+ private static final int MISSING_COLOR = Color.MAGENTA;
+
static {
// Prepare mapping to snap touchable degrees to selectable degrees.
preparePrefer30sMap();
@@ -110,8 +103,19 @@
}
}
- private final InvalidateUpdateListener mInvalidateUpdateListener =
- new InvalidateUpdateListener();
+ private final FloatProperty<RadialTimePickerView> HOURS_TO_MINUTES =
+ new FloatProperty<RadialTimePickerView>("hoursToMinutes") {
+ @Override
+ public Float get(RadialTimePickerView radialTimePickerView) {
+ return radialTimePickerView.mHoursToMinutes;
+ }
+
+ @Override
+ public void setValue(RadialTimePickerView object, float value) {
+ object.mHoursToMinutes = value;
+ object.invalidate();
+ }
+ };
private final String[] mHours12Texts = new String[12];
private final String[] mOuterHours24Texts = new String[12];
@@ -119,15 +123,8 @@
private final String[] mMinutesTexts = new String[12];
private final Paint[] mPaint = new Paint[2];
- private final IntHolder[] mAlpha = new IntHolder[2];
-
private final Paint mPaintCenter = new Paint();
-
- private final Paint[][] mPaintSelector = new Paint[2][3];
-
- private final int mSelectorColor;
- private final int mSelectorDotColor;
-
+ private final Paint[] mPaintSelector = new Paint[3];
private final Paint mPaintBackground = new Paint();
private final Typeface mTypeface;
@@ -144,9 +141,6 @@
private final int[] mSelectionDegrees = new int[2];
- private final ArrayList<Animator> mHoursToMinutesAnims = new ArrayList<>();
- private final ArrayList<Animator> mMinuteToHoursAnims = new ArrayList<>();
-
private final RadialPickerTouchHelper mTouchHelper;
private final Path mSelectorPath = new Path();
@@ -154,6 +148,9 @@
private boolean mIs24HourMode;
private boolean mShowHours;
+ private ObjectAnimator mHoursToMinutesAnimator;
+ private float mHoursToMinutes;
+
/**
* When in 24-hour mode, indicates that the current hour is between
* 1 and 12 (inclusive).
@@ -165,6 +162,9 @@
private int mSelectorDotRadius;
private int mCenterDotRadius;
+ private int mSelectorColor;
+ private int mSelectorDotColor;
+
private int mXCenter;
private int mYCenter;
private int mCircleRadius;
@@ -176,7 +176,6 @@
private String[] mOuterTextHours;
private String[] mInnerTextHours;
private String[] mMinutesText;
- private AnimatorSet mTransition;
private int mAmOrPm;
@@ -304,27 +303,15 @@
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs);
+ applyAttributes(attrs, defStyleAttr, defStyleRes);
+
// Pull disabled alpha from theme.
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
mDisabledAlpha = outValue.getFloat();
- // process style attributes
- final Resources res = getResources();
- final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker,
- defStyleAttr, defStyleRes);
-
mTypeface = Typeface.create("sans-serif", Typeface.NORMAL);
- // Initialize all alpha values to opaque.
- for (int i = 0; i < mAlpha.length; i++) {
- mAlpha[i] = new IntHolder(ALPHA_OPAQUE);
- }
-
- mTextColor[HOURS] = a.getColorStateList(R.styleable.TimePicker_numbersTextColor);
- mTextColor[HOURS_INNER] = a.getColorStateList(R.styleable.TimePicker_numbersInnerTextColor);
- mTextColor[MINUTES] = mTextColor[HOURS];
-
mPaint[HOURS] = new Paint();
mPaint[HOURS].setAntiAlias(true);
mPaint[HOURS].setTextAlign(Paint.Align.CENTER);
@@ -333,44 +320,21 @@
mPaint[MINUTES].setAntiAlias(true);
mPaint[MINUTES].setTextAlign(Paint.Align.CENTER);
- final ColorStateList selectorColors = a.getColorStateList(
- R.styleable.TimePicker_numbersSelectorColor);
- final int selectorActivatedColor = selectorColors.getColorForState(
- StateSet.get(StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED), 0);
-
- mPaintCenter.setColor(selectorActivatedColor);
mPaintCenter.setAntiAlias(true);
- final int[] activatedStateSet = StateSet.get(
- StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED);
+ mPaintSelector[SELECTOR_CIRCLE] = new Paint();
+ mPaintSelector[SELECTOR_CIRCLE].setAntiAlias(true);
- mSelectorColor = selectorActivatedColor;
- mSelectorDotColor = mTextColor[HOURS].getColorForState(activatedStateSet, 0);
+ mPaintSelector[SELECTOR_DOT] = new Paint();
+ mPaintSelector[SELECTOR_DOT].setAntiAlias(true);
- mPaintSelector[HOURS][SELECTOR_CIRCLE] = new Paint();
- mPaintSelector[HOURS][SELECTOR_CIRCLE].setAntiAlias(true);
+ mPaintSelector[SELECTOR_LINE] = new Paint();
+ mPaintSelector[SELECTOR_LINE].setAntiAlias(true);
+ mPaintSelector[SELECTOR_LINE].setStrokeWidth(2);
- mPaintSelector[HOURS][SELECTOR_DOT] = new Paint();
- mPaintSelector[HOURS][SELECTOR_DOT].setAntiAlias(true);
-
- mPaintSelector[HOURS][SELECTOR_LINE] = new Paint();
- mPaintSelector[HOURS][SELECTOR_LINE].setAntiAlias(true);
- mPaintSelector[HOURS][SELECTOR_LINE].setStrokeWidth(2);
-
- mPaintSelector[MINUTES][SELECTOR_CIRCLE] = new Paint();
- mPaintSelector[MINUTES][SELECTOR_CIRCLE].setAntiAlias(true);
-
- mPaintSelector[MINUTES][SELECTOR_DOT] = new Paint();
- mPaintSelector[MINUTES][SELECTOR_DOT].setAntiAlias(true);
-
- mPaintSelector[MINUTES][SELECTOR_LINE] = new Paint();
- mPaintSelector[MINUTES][SELECTOR_LINE].setAntiAlias(true);
- mPaintSelector[MINUTES][SELECTOR_LINE].setStrokeWidth(2);
-
- mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
- context.getColor(R.color.timepicker_default_numbers_background_color_material)));
mPaintBackground.setAntiAlias(true);
+ final Resources res = getResources();
mSelectorRadius = res.getDimensionPixelSize(R.dimen.timepicker_selector_radius);
mSelectorStroke = res.getDimensionPixelSize(R.dimen.timepicker_selector_stroke);
mSelectorDotRadius = res.getDimensionPixelSize(R.dimen.timepicker_selector_dot_radius);
@@ -385,6 +349,7 @@
mTextInset[HOURS_INNER] = res.getDimensionPixelSize(R.dimen.timepicker_text_inset_inner);
mShowHours = true;
+ mHoursToMinutes = HOURS;
mIs24HourMode = false;
mAmOrPm = AM;
@@ -399,8 +364,6 @@
initHoursAndMinutesText();
initData();
- a.recycle();
-
// Initial values
final Calendar calendar = Calendar.getInstance(Locale.getDefault());
final int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
@@ -412,6 +375,48 @@
setHapticFeedbackEnabled(true);
}
+ void applyAttributes(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ final Context context = getContext();
+ final TypedArray a = getContext().obtainStyledAttributes(attrs,
+ R.styleable.TimePicker, defStyleAttr, defStyleRes);
+
+ final ColorStateList numbersTextColor = a.getColorStateList(
+ R.styleable.TimePicker_numbersTextColor);
+ final ColorStateList numbersInnerTextColor = a.getColorStateList(
+ R.styleable.TimePicker_numbersInnerTextColor);
+ mTextColor[HOURS] = numbersTextColor == null ?
+ ColorStateList.valueOf(MISSING_COLOR) : numbersTextColor;
+ mTextColor[HOURS_INNER] = numbersInnerTextColor == null ?
+ ColorStateList.valueOf(MISSING_COLOR) : numbersInnerTextColor;
+ mTextColor[MINUTES] = mTextColor[HOURS];
+
+ // Set up various colors derived from the selector "activated" state.
+ final ColorStateList selectorColors = a.getColorStateList(
+ R.styleable.TimePicker_numbersSelectorColor);
+ final int selectorActivatedColor;
+ if (selectorColors != null) {
+ final int[] stateSetEnabledActivated = StateSet.get(
+ StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED);
+ selectorActivatedColor = selectorColors.getColorForState(
+ stateSetEnabledActivated, 0);
+ } else {
+ selectorActivatedColor = MISSING_COLOR;
+ }
+
+ mPaintCenter.setColor(selectorActivatedColor);
+
+ final int[] stateSetActivated = StateSet.get(
+ StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_ACTIVATED);
+
+ mSelectorColor = selectorActivatedColor;
+ mSelectorDotColor = mTextColor[HOURS].getColorForState(stateSetActivated, 0);
+
+ mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
+ context.getColor(R.color.timepicker_default_numbers_background_color_material)));
+
+ a.recycle();
+ }
+
public void initialize(int hour, int minute, boolean is24HourMode) {
if (mIs24HourMode != is24HourMode) {
mIs24HourMode = is24HourMode;
@@ -569,35 +574,11 @@
}
public void showHours(boolean animate) {
- if (mShowHours) {
- return;
- }
-
- mShowHours = true;
-
- if (animate) {
- startMinutesToHoursAnimation();
- }
-
- initData();
- invalidate();
- mTouchHelper.invalidateRoot();
+ showPicker(true, animate);
}
public void showMinutes(boolean animate) {
- if (!mShowHours) {
- return;
- }
-
- mShowHours = false;
-
- if (animate) {
- startHoursToMinutesAnimation();
- }
-
- initData();
- invalidate();
- mTouchHelper.invalidateRoot();
+ showPicker(false, animate);
}
private void initHoursAndMinutesText() {
@@ -620,12 +601,6 @@
}
mMinutesText = mMinutesTexts;
-
- final int hoursAlpha = mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT;
- mAlpha[HOURS].setValue(hoursAlpha);
-
- final int minutesAlpha = mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE;
- mAlpha[MINUTES].setValue(minutesAlpha);
}
@Override
@@ -653,90 +628,144 @@
final float alphaMod = mInputEnabled ? 1 : mDisabledAlpha;
drawCircleBackground(canvas);
- drawHours(canvas, alphaMod);
- drawMinutes(canvas, alphaMod);
+
+ final Path selectorPath = mSelectorPath;
+ drawSelector(canvas, selectorPath);
+ drawHours(canvas, selectorPath, alphaMod);
+ drawMinutes(canvas, selectorPath, alphaMod);
drawCenter(canvas, alphaMod);
}
+ private void showPicker(boolean hours, boolean animate) {
+ if (mShowHours == hours) {
+ return;
+ }
+
+ mShowHours = hours;
+
+ if (animate) {
+ animatePicker(hours, ANIM_DURATION_NORMAL);
+ }
+
+ initData();
+ invalidate();
+ mTouchHelper.invalidateRoot();
+ }
+
+ private void animatePicker(boolean hoursToMinutes, long duration) {
+ final float target = hoursToMinutes ? HOURS : MINUTES;
+ if (mHoursToMinutes == target) {
+ // If we have a pending or running animator, cancel it.
+ if (mHoursToMinutesAnimator != null && mHoursToMinutesAnimator.isStarted()) {
+ mHoursToMinutesAnimator.cancel();
+ mHoursToMinutesAnimator = null;
+ }
+
+ // We're already showing the correct picker.
+ return;
+ }
+
+ mHoursToMinutesAnimator = ObjectAnimator.ofFloat(this, HOURS_TO_MINUTES, target);
+ mHoursToMinutesAnimator.setAutoCancel(true);
+ mHoursToMinutesAnimator.setDuration(duration);
+ mHoursToMinutesAnimator.start();
+ }
+
private void drawCircleBackground(Canvas canvas) {
canvas.drawCircle(mXCenter, mYCenter, mCircleRadius, mPaintBackground);
}
- private void drawHours(Canvas canvas, float alphaMod) {
- final int hoursAlpha = (int) (mAlpha[HOURS].getValue() * alphaMod + 0.5f);
+ private void drawHours(Canvas canvas, Path selectorPath, float alphaMod) {
+ final int hoursAlpha = (int) (255f * (1f - mHoursToMinutes) * alphaMod + 0.5f);
if (hoursAlpha > 0) {
- // Draw the hour selector under the elements.
- drawSelector(canvas, mIsOnInnerCircle ? HOURS_INNER : HOURS, null, alphaMod);
-
- // Draw outer hours.
- drawTextElements(canvas, mTextSize[HOURS], mTypeface, mTextColor[HOURS],
- mOuterTextHours, mOuterTextX[HOURS], mOuterTextY[HOURS], mPaint[HOURS],
- hoursAlpha, !mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
-
- // Draw inner hours (13-00) for 24-hour time.
- if (mIs24HourMode && mInnerTextHours != null) {
- drawTextElements(canvas, mTextSize[HOURS_INNER], mTypeface, mTextColor[HOURS_INNER],
- mInnerTextHours, mInnerTextX, mInnerTextY, mPaint[HOURS], hoursAlpha,
- mIsOnInnerCircle, mSelectionDegrees[HOURS], false);
- }
- }
- }
-
- private void drawMinutes(Canvas canvas, float alphaMod) {
- final int minutesAlpha = (int) (mAlpha[MINUTES].getValue() * alphaMod + 0.5f);
- if (minutesAlpha > 0) {
- // Draw the minute selector under the elements.
- drawSelector(canvas, MINUTES, mSelectorPath, alphaMod);
-
- // Exclude the selector region, then draw minutes with no
+ // Exclude the selector region, then draw inner/outer hours with no
// activated states.
canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipPath(mSelectorPath, Region.Op.DIFFERENCE);
- drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES],
- mMinutesText, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
- minutesAlpha, false, 0, false);
+ canvas.clipPath(selectorPath, Region.Op.DIFFERENCE);
+ drawHoursClipped(canvas, hoursAlpha, false);
canvas.restore();
// Intersect the selector region, then draw minutes with only
// activated states.
canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipPath(mSelectorPath, Region.Op.INTERSECT);
- drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES],
- mMinutesText, mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES],
- minutesAlpha, true, mSelectionDegrees[MINUTES], true);
+ canvas.clipPath(selectorPath, Region.Op.INTERSECT);
+ drawHoursClipped(canvas, hoursAlpha, true);
canvas.restore();
}
}
+ private void drawHoursClipped(Canvas canvas, int hoursAlpha, boolean showActivated) {
+ // Draw outer hours.
+ drawTextElements(canvas, mTextSize[HOURS], mTypeface, mTextColor[HOURS], mOuterTextHours,
+ mOuterTextX[HOURS], mOuterTextY[HOURS], mPaint[HOURS], hoursAlpha,
+ showActivated && !mIsOnInnerCircle, mSelectionDegrees[HOURS], showActivated);
+
+ // Draw inner hours (13-00) for 24-hour time.
+ if (mIs24HourMode && mInnerTextHours != null) {
+ drawTextElements(canvas, mTextSize[HOURS_INNER], mTypeface, mTextColor[HOURS_INNER],
+ mInnerTextHours, mInnerTextX, mInnerTextY, mPaint[HOURS], hoursAlpha,
+ showActivated && mIsOnInnerCircle, mSelectionDegrees[HOURS], showActivated);
+ }
+ }
+
+ private void drawMinutes(Canvas canvas, Path selectorPath, float alphaMod) {
+ final int minutesAlpha = (int) (255f * mHoursToMinutes * alphaMod + 0.5f);
+ if (minutesAlpha > 0) {
+ // Exclude the selector region, then draw minutes with no
+ // activated states.
+ canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipPath(selectorPath, Region.Op.DIFFERENCE);
+ drawMinutesClipped(canvas, minutesAlpha, false);
+ canvas.restore();
+
+ // Intersect the selector region, then draw minutes with only
+ // activated states.
+ canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipPath(selectorPath, Region.Op.INTERSECT);
+ drawMinutesClipped(canvas, minutesAlpha, true);
+ canvas.restore();
+ }
+ }
+
+ private void drawMinutesClipped(Canvas canvas, int minutesAlpha, boolean showActivated) {
+ drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mTextColor[MINUTES], mMinutesText,
+ mOuterTextX[MINUTES], mOuterTextY[MINUTES], mPaint[MINUTES], minutesAlpha,
+ showActivated, mSelectionDegrees[MINUTES], showActivated);
+ }
+
private void drawCenter(Canvas canvas, float alphaMod) {
mPaintCenter.setAlpha((int) (255 * alphaMod + 0.5f));
canvas.drawCircle(mXCenter, mYCenter, mCenterDotRadius, mPaintCenter);
}
- private int applyAlpha(int argb, int alpha) {
- final int srcAlpha = (argb >> 24) & 0xFF;
- final int dstAlpha = (int) (srcAlpha * (alpha / 255.0) + 0.5f);
- return (0xFFFFFF & argb) | (dstAlpha << 24);
- }
-
private int getMultipliedAlpha(int argb, int alpha) {
return (int) (Color.alpha(argb) * (alpha / 255.0) + 0.5);
}
- private void drawSelector(Canvas canvas, int index, Path selectorPath, float alphaMod) {
- final int alpha = (int) (mAlpha[index % 2].getValue() * alphaMod + 0.5f);
- final int color = applyAlpha(mSelectorColor, alpha);
+ private void drawSelector(Canvas canvas, Path selectorPath) {
+ // Determine the current length, angle, and dot scaling factor.
+ final int hoursIndex = mIsOnInnerCircle ? HOURS_INNER : HOURS;
+ final int hoursInset = mTextInset[hoursIndex];
+ final int hoursAngleDeg = mSelectionDegrees[hoursIndex % 2];
+ final float hoursDotScale = mSelectionDegrees[hoursIndex % 2] % 30 != 0 ? 1 : 0;
+
+ final int minutesIndex = MINUTES;
+ final int minutesInset = mTextInset[minutesIndex];
+ final int minutesAngleDeg = mSelectionDegrees[minutesIndex];
+ final float minutesDotScale = mSelectionDegrees[minutesIndex] % 30 != 0 ? 1 : 0;
// Calculate the current radius at which to place the selection circle.
final int selRadius = mSelectorRadius;
- final int selLength = mCircleRadius - mTextInset[index];
- final double selAngleRad = Math.toRadians(mSelectionDegrees[index % 2]);
+ final float selLength =
+ mCircleRadius - MathUtils.lerp(hoursInset, minutesInset, mHoursToMinutes);
+ final double selAngleRad =
+ Math.toRadians(MathUtils.lerpDeg(hoursAngleDeg, minutesAngleDeg, mHoursToMinutes));
final float selCenterX = mXCenter + selLength * (float) Math.sin(selAngleRad);
final float selCenterY = mYCenter - selLength * (float) Math.cos(selAngleRad);
// Draw the selection circle.
- final Paint paint = mPaintSelector[index % 2][SELECTOR_CIRCLE];
- paint.setColor(color);
+ final Paint paint = mPaintSelector[SELECTOR_CIRCLE];
+ paint.setColor(mSelectorColor);
canvas.drawCircle(selCenterX, selCenterY, selRadius, paint);
// If needed, set up the clip path for later.
@@ -746,26 +775,26 @@
}
// Draw the dot if we're between two items.
- final boolean shouldDrawDot = mSelectionDegrees[index % 2] % 30 != 0;
- if (shouldDrawDot) {
- final Paint dotPaint = mPaintSelector[index % 2][SELECTOR_DOT];
+ final float dotScale = MathUtils.lerp(hoursDotScale, minutesDotScale, mHoursToMinutes);
+ if (dotScale > 0) {
+ final Paint dotPaint = mPaintSelector[SELECTOR_DOT];
dotPaint.setColor(mSelectorDotColor);
- canvas.drawCircle(selCenterX, selCenterY, mSelectorDotRadius, dotPaint);
+ canvas.drawCircle(selCenterX, selCenterY, mSelectorDotRadius * dotScale, dotPaint);
}
// Shorten the line to only go from the edge of the center dot to the
// edge of the selection circle.
final double sin = Math.sin(selAngleRad);
final double cos = Math.cos(selAngleRad);
- final int lineLength = selLength - selRadius;
+ final float lineLength = selLength - selRadius;
final int centerX = mXCenter + (int) (mCenterDotRadius * sin);
final int centerY = mYCenter - (int) (mCenterDotRadius * cos);
final float linePointX = centerX + (int) (lineLength * sin);
final float linePointY = centerY - (int) (lineLength * cos);
// Draw the line.
- final Paint linePaint = mPaintSelector[index % 2][SELECTOR_LINE];
- linePaint.setColor(color);
+ final Paint linePaint = mPaintSelector[SELECTOR_LINE];
+ linePaint.setColor(mSelectorColor);
linePaint.setStrokeWidth(mSelectorStroke);
canvas.drawLine(mXCenter, mYCenter, linePointX, linePointY, linePaint);
}
@@ -842,73 +871,6 @@
}
}
- private static ObjectAnimator getFadeOutAnimator(IntHolder target, int startAlpha, int endAlpha,
- InvalidateUpdateListener updateListener) {
- final ObjectAnimator animator = ObjectAnimator.ofInt(target, "value", startAlpha, endAlpha);
- animator.setDuration(FADE_OUT_DURATION);
- animator.addUpdateListener(updateListener);
- return animator;
- }
-
- private static ObjectAnimator getFadeInAnimator(IntHolder target, int startAlpha, int endAlpha,
- InvalidateUpdateListener updateListener) {
- final float delayMultiplier = 0.25f;
- final float transitionDurationMultiplier = 1f;
- final float totalDurationMultiplier = transitionDurationMultiplier + delayMultiplier;
- final int totalDuration = (int) (FADE_IN_DURATION * totalDurationMultiplier);
- final float delayPoint = (delayMultiplier * FADE_IN_DURATION) / totalDuration;
-
- final Keyframe kf0, kf1, kf2;
- kf0 = Keyframe.ofInt(0f, startAlpha);
- kf1 = Keyframe.ofInt(delayPoint, startAlpha);
- kf2 = Keyframe.ofInt(1f, endAlpha);
- final PropertyValuesHolder fadeIn = PropertyValuesHolder.ofKeyframe("value", kf0, kf1, kf2);
-
- final ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(target, fadeIn);
- animator.setDuration(totalDuration);
- animator.addUpdateListener(updateListener);
- return animator;
- }
-
- private class InvalidateUpdateListener implements ValueAnimator.AnimatorUpdateListener {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- RadialTimePickerView.this.invalidate();
- }
- }
-
- private void startHoursToMinutesAnimation() {
- if (mHoursToMinutesAnims.size() == 0) {
- mHoursToMinutesAnims.add(getFadeOutAnimator(mAlpha[HOURS],
- ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeInAnimator(mAlpha[MINUTES],
- ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
- }
-
- if (mTransition != null && mTransition.isRunning()) {
- mTransition.end();
- }
- mTransition = new AnimatorSet();
- mTransition.playTogether(mHoursToMinutesAnims);
- mTransition.start();
- }
-
- private void startMinutesToHoursAnimation() {
- if (mMinuteToHoursAnims.size() == 0) {
- mMinuteToHoursAnims.add(getFadeOutAnimator(mAlpha[MINUTES],
- ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeInAnimator(mAlpha[HOURS],
- ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
- }
-
- if (mTransition != null && mTransition.isRunning()) {
- mTransition.end();
- }
- mTransition = new AnimatorSet();
- mTransition.playTogether(mMinuteToHoursAnims);
- mTransition.start();
- }
-
private int getDegreesFromXY(float x, float y, boolean constrainOutside) {
// Ensure the point is inside the touchable area.
final int innerBound;
@@ -992,6 +954,9 @@
return false;
}
+ // Ensure we're showing the correct picker.
+ animatePicker(mShowHours, ANIM_DURATION_TOUCH);
+
final int type;
final int newValue;
final boolean valueChanged;
@@ -1356,20 +1321,4 @@
return id >>> SHIFT_VALUE & MASK_VALUE;
}
}
-
- private static class IntHolder {
- private int mValue;
-
- public IntHolder(int value) {
- mValue = value;
- }
-
- public void setValue(int value) {
- mValue = value;
- }
-
- public int getValue() {
- return mValue;
- }
- }
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 61ef6dc..6d41c1d 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -200,8 +200,8 @@
a.recycle();
- mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(
- R.id.radial_picker);
+ mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(R.id.radial_picker);
+ mRadialTimePickerView.applyAttributes(attrs, defStyleAttr, defStyleRes);
setupListeners();
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index b6d7364..c9b8119 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2615,7 +2615,7 @@
if (action == MotionEvent.ACTION_DOWN) {
int y = (int)event.getY();
if (y >= (getHeight()-5) && !mWindow.hasChildren()) {
- Log.i(TAG, "Watchiing!");
+ Log.i(TAG, "Watching!");
mWatchingForMenu = true;
}
return false;
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 56cf921..7b80ac2 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -17,15 +17,23 @@
package com.android.internal.widget;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.AttributeSet;
+import android.view.Choreographer;
+import android.view.DisplayListCanvas;
import android.view.MotionEvent;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
import android.view.View;
+import android.view.ViewRootImpl;
import android.widget.LinearLayout;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.Window;
+import android.view.WindowCallbacks;
import android.util.Log;
import android.util.TypedValue;
@@ -58,7 +66,7 @@
* This will be mitigated once b/22527834 will be addressed.
*/
public class NonClientDecorView extends LinearLayout
- implements View.OnClickListener, View.OnTouchListener {
+ implements View.OnClickListener, View.OnTouchListener, WindowCallbacks {
private final static String TAG = "NonClientDecorView";
// The height of a window which has focus in DIP.
private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
@@ -67,6 +75,8 @@
private PhoneWindow mOwner = null;
private boolean mWindowHasShadow = false;
private boolean mShowDecor = false;
+ // True when this object is listening for window size changes.
+ private boolean mAttachedCallbacksToRootViewImpl = false;
// True if the window is being dragged.
private boolean mDragging = false;
@@ -85,6 +95,9 @@
// to max until the first layout command has been executed.
private boolean mAllowUpdateElevation = false;
+ // The resize frame renderer.
+ private ResizeFrameThread mFrameRendererThread = null;
+
public NonClientDecorView(Context context) {
super(context);
}
@@ -108,6 +121,18 @@
// By changing the outline provider to BOUNDS, the window can remove its
// background without removing the shadow.
mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
+
+ if (!mAttachedCallbacksToRootViewImpl) {
+ // If there is no window callback installed there was no window set before. Set it now.
+ // Note that our ViewRootImpl object will not change.
+ getViewRootImpl().addWindowCallbacks(this);
+ mAttachedCallbacksToRootViewImpl = true;
+ } else if (mFrameRendererThread != null) {
+ // We are resizing and this call happened due to a configuration change. Tell the
+ // renderer about it.
+ mFrameRendererThread.onConfigurationChange();
+ }
+
findViewById(R.id.maximize_window).setOnClickListener(this);
findViewById(R.id.close_window).setOnClickListener(this);
}
@@ -251,7 +276,9 @@
**/
private void updateElevation() {
float elevation = 0;
- if (mWindowHasShadow) {
+ // Do not use a shadow when we are in resizing mode (mRenderer not null) since the shadow
+ // is bound to the content size and not the target size.
+ if (mWindowHasShadow && mFrameRendererThread == null) {
boolean fill = isFillingScreen();
elevation = fill ? 0 :
(mWindowHasFocus ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP :
@@ -293,4 +320,274 @@
}
}
}
+
+ @Override
+ public void onWindowDragResizeStart(Rect initialBounds) {
+ if (mOwner.isDestroyed()) {
+ // If the owner's window is gone, we should not be able to come here anymore.
+ releaseResources();
+ return;
+ }
+ if (mFrameRendererThread != null) {
+ return;
+ }
+ final ThreadedRenderer renderer =
+ (ThreadedRenderer) mOwner.getDecorView().getHardwareRenderer();
+ if (renderer != null) {
+ mFrameRendererThread = new ResizeFrameThread(renderer, initialBounds);
+ // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
+ // If we want to get the shadow shown while resizing, we would need to elevate a new
+ // element which owns the caption and has the elevation.
+ updateElevation();
+ }
+ }
+
+ @Override
+ public void onWindowDragResizeEnd() {
+ releaseThreadedRenderer();
+ }
+
+ @Override
+ public void onWindowSizeIsChanging(Rect newBounds) {
+ if (mFrameRendererThread != null) {
+ mFrameRendererThread.setTargetRect(newBounds);
+ }
+ }
+
+ /**
+ * Release the renderer thread which is usually done when the user stops resizing.
+ */
+ private void releaseThreadedRenderer() {
+ if (mFrameRendererThread != null) {
+ mFrameRendererThread.releaseRenderer();
+ mFrameRendererThread = null;
+ // Bring the shadow back.
+ updateElevation();
+ }
+ }
+
+ /**
+ * Called when the parent window is destroyed to release all resources. Note that this will also
+ * destroy the renderer thread.
+ */
+ private void releaseResources() {
+ releaseThreadedRenderer();
+ if (mAttachedCallbacksToRootViewImpl) {
+ ViewRootImpl.removeWindowCallbacks(this);
+ mAttachedCallbacksToRootViewImpl = false;
+ }
+ }
+
+ /**
+ * The thread which draws the chrome while we are resizing.
+ * It starts with the creation and it ends once someone calls destroy().
+ * Any size changes can be passed by a call to setTargetRect will passed to the thread and
+ * executed via the Choreographer.
+ */
+ private class ResizeFrameThread extends Thread implements Choreographer.FrameCallback {
+ // This is containing the last requested size by a resize command. Note that this size might
+ // or might not have been applied to the output already.
+ private final Rect mTargetRect = new Rect();
+
+ // The render nodes for the multi threaded renderer.
+ private ThreadedRenderer mRenderer;
+ private RenderNode mFrameNode;
+ private RenderNode mBackdropNode;
+
+ private final Rect mOldTargetRect = new Rect();
+ private final Rect mNewTargetRect = new Rect();
+ private Choreographer mChoreographer;
+
+ // Cached size values from the last render for the case that the view hierarchy is gone
+ // during a configuration change.
+ private int mLastContentWidth;
+ private int mLastContentHeight;
+ private int mLastCaptionHeight;
+ private int mLastXOffset;
+ private int mLastYOffset;
+
+ ResizeFrameThread(ThreadedRenderer renderer, Rect initialBounds) {
+ mRenderer = renderer;
+
+ // Create the render nodes for our frame and backdrop which can be resized independently
+ // from the content.
+ mFrameNode = RenderNode.create("FrameNode", null);
+ mBackdropNode = RenderNode.create("BackdropNode", null);
+
+ mRenderer.addRenderNode(mFrameNode, false);
+ mRenderer.addRenderNode(mBackdropNode, true);
+
+ // Set the initial bounds and draw once so that we do not get a broken frame.
+ mTargetRect.set(initialBounds);
+ changeWindowSize(initialBounds);
+
+ // Kick off our draw thread.
+ start();
+ }
+
+ /**
+ * Call this function asynchronously when the window size has been changed. The change will
+ * be picked up once per frame and the frame will be re-rendered accordingly.
+ * @param newTargetBounds The new target bounds.
+ */
+ public void setTargetRect(Rect newTargetBounds) {
+ synchronized (this) {
+ mTargetRect.set(newTargetBounds);
+ // Notify of a bounds change.
+ pingRenderLocked();
+ }
+ }
+
+ /**
+ * The window got replaced due to a configuration change.
+ */
+ public void onConfigurationChange() {
+ if (mRenderer != null) {
+ // Enforce a window redraw.
+ mOldTargetRect.set(0, 0, 0, 0);
+ pingRenderLocked();
+ }
+ }
+
+ /**
+ * All resources of the renderer will be released. This function can be called from the
+ * the UI thread as well as the renderer thread.
+ */
+ public void releaseRenderer() {
+ synchronized (this) {
+ if (mRenderer != null) {
+ // Invalidate the current content bounds.
+ mRenderer.setContentDrawBounds(0, 0, 0, 0);
+
+ // Remove the render nodes again (see comment above - better to do that only once).
+ mRenderer.removeRenderNode(mFrameNode);
+ mRenderer.removeRenderNode(mBackdropNode);
+
+ mRenderer = null;
+
+ // Exit the renderer loop.
+ pingRenderLocked();
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ Looper.prepare();
+ mChoreographer = Choreographer.getInstance();
+ Looper.loop();
+ } finally {
+ releaseRenderer();
+ }
+ synchronized (this) {
+ // Make sure no more messages are being sent.
+ mChoreographer = null;
+ }
+ }
+
+ /**
+ * The implementation of the FrameCallback.
+ * @param frameTimeNanos The time in nanoseconds when the frame started being rendered,
+ * in the {@link System#nanoTime()} timebase. Divide this value by {@code 1000000}
+ */
+ @Override
+ public void doFrame(long frameTimeNanos) {
+ if (mRenderer == null) {
+ // Tell the looper to stop. We are done.
+ Looper.myLooper().quit();
+ return;
+ }
+ // Prevent someone from changing this while we are copying.
+ synchronized (this) {
+ mNewTargetRect.set(mTargetRect);
+ }
+ if (!mNewTargetRect.equals(mOldTargetRect)) {
+ mOldTargetRect.set(mNewTargetRect);
+ changeWindowSize(mNewTargetRect);
+ }
+ }
+
+ /**
+ * Resizing the frame to fit the new window size.
+ * @param newBounds The window bounds which needs to be drawn.
+ */
+ private void changeWindowSize(Rect newBounds) {
+ long startTime = System.currentTimeMillis();
+
+ // While a configuration change is taking place the view hierarchy might become
+ // inaccessible. For that case we remember the previous metrics to avoid flashes.
+ View caption = getChildAt(0);
+ View content = getChildAt(1);
+ if (caption != null && content != null) {
+ int captionHeight = caption.getHeight();
+ int contentWidth = content.getWidth();
+ int contentHeight = content.getHeight();
+ // Get the draw position within our surface (shadow offsets).
+ int[] surfaceOrigin = new int[2];
+ surfaceOrigin[0] = 0;
+ surfaceOrigin[1] = 0;
+ getLocationInSurface(surfaceOrigin);
+ // Only update if a layout has already be performed (which might not be after a
+ // relayout. Otherwise use the previous values for the content.
+ if (captionHeight != 0 && contentWidth != 0 && contentHeight != 0) {
+ mLastCaptionHeight = captionHeight;
+ mLastXOffset = surfaceOrigin[0];
+ mLastYOffset = surfaceOrigin[1];
+ mLastContentWidth = contentWidth;
+ mLastContentHeight = contentHeight;
+ }
+ }
+
+ // Since the surface is spanning the entire screen, we have to add the start offset of
+ // the bounds to get to the surface location.
+ final int left = mLastXOffset + newBounds.left;
+ final int top = mLastYOffset + newBounds.top;
+ final int width = newBounds.width();
+ final int height = newBounds.height();
+
+ // Produce the draw calls.
+ // TODO(skuhne): Create a separate caption view which draws this. If the shadow should
+ // be resized while the window resizes, this hierarchy needs to have the elevation.
+ // That said - it is probably no good idea to draw the shadow every time since it costs
+ // a considerable time which we should rather spend for resizing the content and it does
+ // barely show while the entire screen is moving.
+ mFrameNode.setLeftTopRightBottom(left, top, left + width, top + mLastCaptionHeight);
+ DisplayListCanvas canvas = mFrameNode.start(width, height);
+ canvas.drawColor(Color.BLACK);
+ mFrameNode.end(canvas);
+
+ mBackdropNode.setLeftTopRightBottom(left, top + mLastCaptionHeight, left + width,
+ top + height);
+
+ // The backdrop: clear everything with the background. Clipping is done elsewhere.
+ canvas = mBackdropNode.start(width, height - mLastCaptionHeight);
+ // TODO(skuhne): mOwner.getDecorView().mBackgroundFallback.draw(..) - or similar.
+ // Note: This might not work (calculator for example uses a transparent background).
+ canvas.drawColor(0xff808080);
+ mBackdropNode.end(canvas);
+
+ // The current content buffer is drawn here.
+ mRenderer.setContentDrawBounds(
+ mLastXOffset,
+ mLastYOffset + mLastCaptionHeight,
+ mLastXOffset + mLastContentWidth,
+ mLastYOffset + mLastCaptionHeight + mLastContentHeight);
+
+ // We need to render both rendered nodes explicitly.
+ mRenderer.drawRenderNode(mFrameNode);
+ mRenderer.drawRenderNode(mBackdropNode);
+ }
+
+ /**
+ * Sends a message to the renderer to wake up and perform the next action which can be
+ * either the next rendering or the self destruction if mRenderer is null.
+ * Note: This call must be synchronized.
+ */
+ private void pingRenderLocked() {
+ if (mChoreographer != null) {
+ mChoreographer.postFrameCallback(this);
+ }
+ }
+ }
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 223dae0..314e4b6 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -66,10 +66,6 @@
static jclass gFontMetricsInt_class;
static JMetricsID gFontMetricsInt_fieldID;
-static jclass gPaint_class;
-static jfieldID gPaint_nativeInstanceID;
-static jfieldID gPaint_nativeTypefaceID;
-
static void defaultSettingsForAndroid(Paint* paint) {
// GlyphID encoding is required because we are using Harfbuzz shaping
paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
@@ -82,37 +78,17 @@
static thread_local LocaleCacheEntry sSingleEntryLocaleCache;
-class PaintGlue {
-public:
+namespace PaintGlue {
enum MoveOpt {
AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
};
- static Paint* getNativePaint(JNIEnv* env, jobject paint) {
- SkASSERT(env);
- SkASSERT(paint);
- SkASSERT(env->IsInstanceOf(paint, gPaint_class));
- jlong paintHandle = env->GetLongField(paint, gPaint_nativeInstanceID);
- android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle);
- SkASSERT(p);
- return p;
- }
-
- static TypefaceImpl* getNativeTypeface(JNIEnv* env, jobject paint) {
- SkASSERT(env);
- SkASSERT(paint);
- SkASSERT(env->IsInstanceOf(paint, gPaint_class));
- jlong typefaceHandle = env->GetLongField(paint, gPaint_nativeTypefaceID);
- android::TypefaceImpl* p = reinterpret_cast<android::TypefaceImpl*>(typefaceHandle);
- return p;
- }
-
static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
Paint* obj = reinterpret_cast<Paint*>(objHandle);
delete obj;
}
- static jlong init(JNIEnv* env, jobject clazz) {
+ static jlong init(JNIEnv* env, jobject) {
static_assert(1 << 0 == SkPaint::kAntiAlias_Flag, "paint_flags_mismatch");
static_assert(1 << 2 == SkPaint::kDither_Flag, "paint_flags_mismatch");
static_assert(1 << 3 == SkPaint::kUnderlineText_Flag, "paint_flags_mismatch");
@@ -149,9 +125,8 @@
// Equivalent to the Java Paint's FILTER_BITMAP_FLAG.
static const uint32_t sFilterBitmapFlag = 0x02;
- static jint getFlags(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- Paint* nativePaint = getNativePaint(env, paint);
+ static jint getFlags(JNIEnv* env, jobject, jlong paintHandle) {
+ Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle);
uint32_t result = nativePaint->getFlags();
result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away.
if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) {
@@ -160,9 +135,8 @@
return static_cast<jint>(result);
}
- static void setFlags(JNIEnv* env, jobject paint, jint flags) {
- NPE_CHECK_RETURN_VOID(env, paint);
- Paint* nativePaint = getNativePaint(env, paint);
+ static void setFlags(JNIEnv* env, jobject, jlong paintHandle, jint flags) {
+ Paint* nativePaint = reinterpret_cast<Paint*>(paintHandle);
// Instead of modifying 0x02, change the filter level.
nativePaint->setFilterQuality(flags & sFilterBitmapFlag
? kLow_SkFilterQuality
@@ -175,57 +149,47 @@
nativePaint->setFlags(flags);
}
- static jint getHinting(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- return getNativePaint(env, paint)->getHinting()
+ static jint getHinting(JNIEnv* env, jobject, jlong paintHandle) {
+ return reinterpret_cast<Paint*>(paintHandle)->getHinting()
== Paint::kNo_Hinting ? 0 : 1;
}
- static void setHinting(JNIEnv* env, jobject paint, jint mode) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setHinting(
+ static void setHinting(JNIEnv* env, jobject, jlong paintHandle, jint mode) {
+ reinterpret_cast<Paint*>(paintHandle)->setHinting(
mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting);
}
- static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setAntiAlias(aa);
+ static void setAntiAlias(JNIEnv* env, jobject, jlong paintHandle, jboolean aa) {
+ reinterpret_cast<Paint*>(paintHandle)->setAntiAlias(aa);
}
- static void setLinearText(JNIEnv* env, jobject paint, jboolean linearText) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setLinearText(linearText);
+ static void setLinearText(JNIEnv* env, jobject, jlong paintHandle, jboolean linearText) {
+ reinterpret_cast<Paint*>(paintHandle)->setLinearText(linearText);
}
- static void setSubpixelText(JNIEnv* env, jobject paint, jboolean subpixelText) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setSubpixelText(subpixelText);
+ static void setSubpixelText(JNIEnv* env, jobject, jlong paintHandle, jboolean subpixelText) {
+ reinterpret_cast<Paint*>(paintHandle)->setSubpixelText(subpixelText);
}
- static void setUnderlineText(JNIEnv* env, jobject paint, jboolean underlineText) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setUnderlineText(underlineText);
+ static void setUnderlineText(JNIEnv* env, jobject, jlong paintHandle, jboolean underlineText) {
+ reinterpret_cast<Paint*>(paintHandle)->setUnderlineText(underlineText);
}
- static void setStrikeThruText(JNIEnv* env, jobject paint, jboolean strikeThruText) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setStrikeThruText(strikeThruText);
+ static void setStrikeThruText(JNIEnv* env, jobject, jlong paintHandle, jboolean strikeThruText) {
+ reinterpret_cast<Paint*>(paintHandle)->setStrikeThruText(strikeThruText);
}
- static void setFakeBoldText(JNIEnv* env, jobject paint, jboolean fakeBoldText) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setFakeBoldText(fakeBoldText);
+ static void setFakeBoldText(JNIEnv* env, jobject, jlong paintHandle, jboolean fakeBoldText) {
+ reinterpret_cast<Paint*>(paintHandle)->setFakeBoldText(fakeBoldText);
}
- static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setFilterQuality(
+ static void setFilterBitmap(JNIEnv* env, jobject, jlong paintHandle, jboolean filterBitmap) {
+ reinterpret_cast<Paint*>(paintHandle)->setFilterQuality(
filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality);
}
- static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setDither(dither);
+ static void setDither(JNIEnv* env, jobject, jlong paintHandle, jboolean dither) {
+ reinterpret_cast<Paint*>(paintHandle)->setDither(dither);
}
static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) {
@@ -239,48 +203,40 @@
obj->setStyle(style);
}
- static jint getColor(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
+ static jint getColor(JNIEnv* env, jobject, jlong paintHandle) {
int color;
- color = getNativePaint(env, paint)->getColor();
+ color = reinterpret_cast<Paint*>(paintHandle)->getColor();
return static_cast<jint>(color);
}
- static jint getAlpha(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
+ static jint getAlpha(JNIEnv* env, jobject, jlong paintHandle) {
int alpha;
- alpha = getNativePaint(env, paint)->getAlpha();
+ alpha = reinterpret_cast<Paint*>(paintHandle)->getAlpha();
return static_cast<jint>(alpha);
}
- static void setColor(JNIEnv* env, jobject paint, jint color) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setColor(color);
+ static void setColor(JNIEnv* env, jobject, jlong paintHandle, jint color) {
+ reinterpret_cast<Paint*>(paintHandle)->setColor(color);
}
- static void setAlpha(JNIEnv* env, jobject paint, jint a) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setAlpha(a);
+ static void setAlpha(JNIEnv* env, jobject, jlong paintHandle, jint a) {
+ reinterpret_cast<Paint*>(paintHandle)->setAlpha(a);
}
- static jfloat getStrokeWidth(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- return SkScalarToFloat(getNativePaint(env, paint)->getStrokeWidth());
+ static jfloat getStrokeWidth(JNIEnv* env, jobject, jlong paintHandle) {
+ return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeWidth());
}
- static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setStrokeWidth(width);
+ static void setStrokeWidth(JNIEnv* env, jobject, jlong paintHandle, jfloat width) {
+ reinterpret_cast<Paint*>(paintHandle)->setStrokeWidth(width);
}
- static jfloat getStrokeMiter(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- return SkScalarToFloat(getNativePaint(env, paint)->getStrokeMiter());
+ static jfloat getStrokeMiter(JNIEnv* env, jobject, jlong paintHandle) {
+ return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getStrokeMiter());
}
- static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setStrokeMiter(miter);
+ static void setStrokeMiter(JNIEnv* env, jobject, jlong paintHandle, jfloat miter) {
+ reinterpret_cast<Paint*>(paintHandle)->setStrokeMiter(miter);
}
static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) {
@@ -417,46 +373,38 @@
obj->setTextLocale(sSingleEntryLocaleCache.languageTag);
}
- static jboolean isElegantTextHeight(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- Paint* obj = getNativePaint(env, paint);
+ static jboolean isElegantTextHeight(JNIEnv* env, jobject, jlong paintHandle) {
+ Paint* obj = reinterpret_cast<Paint*>(paintHandle);
return obj->getFontVariant() == VARIANT_ELEGANT;
}
- static void setElegantTextHeight(JNIEnv* env, jobject paint, jboolean aa) {
- NPE_CHECK_RETURN_VOID(env, paint);
- Paint* obj = getNativePaint(env, paint);
+ static void setElegantTextHeight(JNIEnv* env, jobject, jlong paintHandle, jboolean aa) {
+ Paint* obj = reinterpret_cast<Paint*>(paintHandle);
obj->setFontVariant(aa ? VARIANT_ELEGANT : VARIANT_DEFAULT);
}
- static jfloat getTextSize(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- return SkScalarToFloat(getNativePaint(env, paint)->getTextSize());
+ static jfloat getTextSize(JNIEnv* env, jobject, jlong paintHandle) {
+ return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSize());
}
- static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setTextSize(textSize);
+ static void setTextSize(JNIEnv* env, jobject, jlong paintHandle, jfloat textSize) {
+ reinterpret_cast<Paint*>(paintHandle)->setTextSize(textSize);
}
- static jfloat getTextScaleX(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- return SkScalarToFloat(getNativePaint(env, paint)->getTextScaleX());
+ static jfloat getTextScaleX(JNIEnv* env, jobject, jlong paintHandle) {
+ return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextScaleX());
}
- static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setTextScaleX(scaleX);
+ static void setTextScaleX(JNIEnv* env, jobject, jlong paintHandle, jfloat scaleX) {
+ reinterpret_cast<Paint*>(paintHandle)->setTextScaleX(scaleX);
}
- static jfloat getTextSkewX(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- return SkScalarToFloat(getNativePaint(env, paint)->getTextSkewX());
+ static jfloat getTextSkewX(JNIEnv* env, jobject, jlong paintHandle) {
+ return SkScalarToFloat(reinterpret_cast<Paint*>(paintHandle)->getTextSkewX());
}
- static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) {
- NPE_CHECK_RETURN_VOID(env, paint);
- getNativePaint(env, paint)->setTextSkewX(skewX);
+ static void setTextSkewX(JNIEnv* env, jobject, jlong paintHandle, jfloat skewX) {
+ reinterpret_cast<Paint*>(paintHandle)->setTextSkewX(skewX);
}
static jfloat getLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle) {
@@ -489,14 +437,15 @@
paint->setHyphenEdit((uint32_t)hyphen);
}
- static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, Paint::FontMetrics *metrics) {
+ static SkScalar getMetricsInternal(jlong paintHandle, jlong typefaceHandle,
+ Paint::FontMetrics *metrics) {
const int kElegantTop = 2500;
const int kElegantBottom = -1000;
const int kElegantAscent = 1900;
const int kElegantDescent = -500;
const int kElegantLeading = 0;
- Paint* paint = getNativePaint(env, jpaint);
- TypefaceImpl* typeface = getNativeTypeface(env, jpaint);
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
typeface = TypefaceImpl_resolveDefault(typeface);
FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
float saveSkewX = paint->getTextSkewX();
@@ -520,24 +469,22 @@
return spacing;
}
- static jfloat ascent(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
+ static jfloat ascent(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle) {
Paint::FontMetrics metrics;
- getMetricsInternal(env, paint, &metrics);
+ getMetricsInternal(paintHandle, typefaceHandle, &metrics);
return SkScalarToFloat(metrics.fAscent);
}
- static jfloat descent(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
+ static jfloat descent(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle) {
Paint::FontMetrics metrics;
- getMetricsInternal(env, paint, &metrics);
+ getMetricsInternal(paintHandle, typefaceHandle, &metrics);
return SkScalarToFloat(metrics.fDescent);
}
- static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
- NPE_CHECK_RETURN_ZERO(env, paint);
+ static jfloat getFontMetrics(JNIEnv* env, jobject, jlong paintHandle,
+ jlong typefaceHandle, jobject metricsObj) {
Paint::FontMetrics metrics;
- SkScalar spacing = getMetricsInternal(env, paint, &metrics);
+ SkScalar spacing = getMetricsInternal(paintHandle, typefaceHandle, &metrics);
if (metricsObj) {
SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
@@ -550,11 +497,11 @@
return SkScalarToFloat(spacing);
}
- static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) {
- NPE_CHECK_RETURN_ZERO(env, paint);
+ static jint getFontMetricsInt(JNIEnv* env, jobject, jlong paintHandle,
+ jlong typefaceHandle, jobject metricsObj) {
Paint::FontMetrics metrics;
- getMetricsInternal(env, paint, &metrics);
+ getMetricsInternal(paintHandle, typefaceHandle, &metrics);
int ascent = SkScalarRoundToInt(metrics.fAscent);
int descent = SkScalarRoundToInt(metrics.fDescent);
int leading = SkScalarRoundToInt(metrics.fLeading);
@@ -573,7 +520,6 @@
static jfloat doTextAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface,
const jchar *text, jint start, jint count, jint contextCount, jint bidiFlags,
jfloatArray advances, jint advancesIndex) {
- NPE_CHECK_RETURN_ZERO(env, paint);
NPE_CHECK_RETURN_ZERO(env, text);
if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) {
@@ -841,7 +787,7 @@
static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
- const Paint* paint = reinterpret_cast<Paint*>(paintHandle);;
+ const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags);
@@ -961,97 +907,97 @@
return result;
}
-};
+}; // namespace PaintGlue
static const JNINativeMethod methods[] = {
- {"finalizer", "(J)V", (void*) PaintGlue::finalizer},
- {"native_init","()J", (void*) PaintGlue::init},
- {"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
+ {"nFinalizer", "(J)V", (void*) PaintGlue::finalizer},
+ {"nInit","()J", (void*) PaintGlue::init},
+ {"nInitWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
- {"native_reset","!(J)V", (void*) PaintGlue::reset},
- {"native_set","!(JJ)V", (void*) PaintGlue::assign},
- {"getFlags","!()I", (void*) PaintGlue::getFlags},
- {"setFlags","!(I)V", (void*) PaintGlue::setFlags},
- {"getHinting","!()I", (void*) PaintGlue::getHinting},
- {"setHinting","!(I)V", (void*) PaintGlue::setHinting},
- {"setAntiAlias","!(Z)V", (void*) PaintGlue::setAntiAlias},
- {"setSubpixelText","!(Z)V", (void*) PaintGlue::setSubpixelText},
- {"setLinearText","!(Z)V", (void*) PaintGlue::setLinearText},
- {"setUnderlineText","!(Z)V", (void*) PaintGlue::setUnderlineText},
- {"setStrikeThruText","!(Z)V", (void*) PaintGlue::setStrikeThruText},
- {"setFakeBoldText","!(Z)V", (void*) PaintGlue::setFakeBoldText},
- {"setFilterBitmap","!(Z)V", (void*) PaintGlue::setFilterBitmap},
- {"setDither","!(Z)V", (void*) PaintGlue::setDither},
- {"native_getStyle","!(J)I", (void*) PaintGlue::getStyle},
- {"native_setStyle","!(JI)V", (void*) PaintGlue::setStyle},
- {"getColor","!()I", (void*) PaintGlue::getColor},
- {"setColor","!(I)V", (void*) PaintGlue::setColor},
- {"getAlpha","!()I", (void*) PaintGlue::getAlpha},
- {"setAlpha","!(I)V", (void*) PaintGlue::setAlpha},
- {"getStrokeWidth","!()F", (void*) PaintGlue::getStrokeWidth},
- {"setStrokeWidth","!(F)V", (void*) PaintGlue::setStrokeWidth},
- {"getStrokeMiter","!()F", (void*) PaintGlue::getStrokeMiter},
- {"setStrokeMiter","!(F)V", (void*) PaintGlue::setStrokeMiter},
- {"native_getStrokeCap","!(J)I", (void*) PaintGlue::getStrokeCap},
- {"native_setStrokeCap","!(JI)V", (void*) PaintGlue::setStrokeCap},
- {"native_getStrokeJoin","!(J)I", (void*) PaintGlue::getStrokeJoin},
- {"native_setStrokeJoin","!(JI)V", (void*) PaintGlue::setStrokeJoin},
- {"native_getFillPath","!(JJJ)Z", (void*) PaintGlue::getFillPath},
- {"native_setShader","!(JJ)J", (void*) PaintGlue::setShader},
- {"native_setColorFilter","!(JJ)J", (void*) PaintGlue::setColorFilter},
- {"native_setXfermode","!(JJ)J", (void*) PaintGlue::setXfermode},
- {"native_setPathEffect","!(JJ)J", (void*) PaintGlue::setPathEffect},
- {"native_setMaskFilter","!(JJ)J", (void*) PaintGlue::setMaskFilter},
- {"native_setTypeface","!(JJ)J", (void*) PaintGlue::setTypeface},
- {"native_setRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer},
- {"native_getTextAlign","!(J)I", (void*) PaintGlue::getTextAlign},
- {"native_setTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign},
- {"native_setTextLocale","!(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale},
- {"isElegantTextHeight","!()Z", (void*) PaintGlue::isElegantTextHeight},
- {"setElegantTextHeight","!(Z)V", (void*) PaintGlue::setElegantTextHeight},
- {"getTextSize","!()F", (void*) PaintGlue::getTextSize},
- {"setTextSize","!(F)V", (void*) PaintGlue::setTextSize},
- {"getTextScaleX","!()F", (void*) PaintGlue::getTextScaleX},
- {"setTextScaleX","!(F)V", (void*) PaintGlue::setTextScaleX},
- {"getTextSkewX","!()F", (void*) PaintGlue::getTextSkewX},
- {"setTextSkewX","!(F)V", (void*) PaintGlue::setTextSkewX},
- {"native_getLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing},
- {"native_setLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing},
- {"native_setFontFeatureSettings","(JLjava/lang/String;)V",
+ {"nReset","!(J)V", (void*) PaintGlue::reset},
+ {"nSet","!(JJ)V", (void*) PaintGlue::assign},
+ {"nGetFlags","!(J)I", (void*) PaintGlue::getFlags},
+ {"nSetFlags","!(JI)V", (void*) PaintGlue::setFlags},
+ {"nGetHinting","!(J)I", (void*) PaintGlue::getHinting},
+ {"nSetHinting","!(JI)V", (void*) PaintGlue::setHinting},
+ {"nSetAntiAlias","!(JZ)V", (void*) PaintGlue::setAntiAlias},
+ {"nSetSubpixelText","!(JZ)V", (void*) PaintGlue::setSubpixelText},
+ {"nSetLinearText","!(JZ)V", (void*) PaintGlue::setLinearText},
+ {"nSetUnderlineText","!(JZ)V", (void*) PaintGlue::setUnderlineText},
+ {"nSetStrikeThruText","!(JZ)V", (void*) PaintGlue::setStrikeThruText},
+ {"nSetFakeBoldText","!(JZ)V", (void*) PaintGlue::setFakeBoldText},
+ {"nSetFilterBitmap","!(JZ)V", (void*) PaintGlue::setFilterBitmap},
+ {"nSetDither","!(JZ)V", (void*) PaintGlue::setDither},
+ {"nGetStyle","!(J)I", (void*) PaintGlue::getStyle},
+ {"nSetStyle","!(JI)V", (void*) PaintGlue::setStyle},
+ {"nGetColor","!(J)I", (void*) PaintGlue::getColor},
+ {"nSetColor","!(JI)V", (void*) PaintGlue::setColor},
+ {"nGetAlpha","!(J)I", (void*) PaintGlue::getAlpha},
+ {"nSetAlpha","!(JI)V", (void*) PaintGlue::setAlpha},
+ {"nGetStrokeWidth","!(J)F", (void*) PaintGlue::getStrokeWidth},
+ {"nSetStrokeWidth","!(JF)V", (void*) PaintGlue::setStrokeWidth},
+ {"nGetStrokeMiter","!(J)F", (void*) PaintGlue::getStrokeMiter},
+ {"nSetStrokeMiter","!(JF)V", (void*) PaintGlue::setStrokeMiter},
+ {"nGetStrokeCap","!(J)I", (void*) PaintGlue::getStrokeCap},
+ {"nSetStrokeCap","!(JI)V", (void*) PaintGlue::setStrokeCap},
+ {"nGetStrokeJoin","!(J)I", (void*) PaintGlue::getStrokeJoin},
+ {"nSetStrokeJoin","!(JI)V", (void*) PaintGlue::setStrokeJoin},
+ {"nGetFillPath","!(JJJ)Z", (void*) PaintGlue::getFillPath},
+ {"nSetShader","!(JJ)J", (void*) PaintGlue::setShader},
+ {"nSetColorFilter","!(JJ)J", (void*) PaintGlue::setColorFilter},
+ {"nSetXfermode","!(JJ)J", (void*) PaintGlue::setXfermode},
+ {"nSetPathEffect","!(JJ)J", (void*) PaintGlue::setPathEffect},
+ {"nSetMaskFilter","!(JJ)J", (void*) PaintGlue::setMaskFilter},
+ {"nSetTypeface","!(JJ)J", (void*) PaintGlue::setTypeface},
+ {"nSetRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer},
+ {"nGetTextAlign","!(J)I", (void*) PaintGlue::getTextAlign},
+ {"nSetTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign},
+ {"nSetTextLocale","!(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale},
+ {"nIsElegantTextHeight","!(J)Z", (void*) PaintGlue::isElegantTextHeight},
+ {"nSetElegantTextHeight","!(JZ)V", (void*) PaintGlue::setElegantTextHeight},
+ {"nGetTextSize","!(J)F", (void*) PaintGlue::getTextSize},
+ {"nSetTextSize","!(JF)V", (void*) PaintGlue::setTextSize},
+ {"nGetTextScaleX","!(J)F", (void*) PaintGlue::getTextScaleX},
+ {"nSetTextScaleX","!(JF)V", (void*) PaintGlue::setTextScaleX},
+ {"nGetTextSkewX","!(J)F", (void*) PaintGlue::getTextSkewX},
+ {"nSetTextSkewX","!(JF)V", (void*) PaintGlue::setTextSkewX},
+ {"nGetLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing},
+ {"nSetLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing},
+ {"nSetFontFeatureSettings","(JLjava/lang/String;)V",
(void*) PaintGlue::setFontFeatureSettings},
- {"native_getHyphenEdit", "!(J)I", (void*) PaintGlue::getHyphenEdit},
- {"native_setHyphenEdit", "!(JI)V", (void*) PaintGlue::setHyphenEdit},
- {"ascent","!()F", (void*) PaintGlue::ascent},
- {"descent","!()F", (void*) PaintGlue::descent},
+ {"nGetHyphenEdit", "!(J)I", (void*) PaintGlue::getHyphenEdit},
+ {"nSetHyphenEdit", "!(JI)V", (void*) PaintGlue::setHyphenEdit},
+ {"nAscent","!(JJ)F", (void*) PaintGlue::ascent},
+ {"nDescent","!(JJ)F", (void*) PaintGlue::descent},
- {"getFontMetrics", "!(Landroid/graphics/Paint$FontMetrics;)F",
+ {"nGetFontMetrics", "!(JJLandroid/graphics/Paint$FontMetrics;)F",
(void*)PaintGlue::getFontMetrics},
- {"getFontMetricsInt", "!(Landroid/graphics/Paint$FontMetricsInt;)I",
+ {"nGetFontMetricsInt", "!(JJLandroid/graphics/Paint$FontMetricsInt;)I",
(void*)PaintGlue::getFontMetricsInt},
- {"native_breakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC},
- {"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
- {"native_getTextAdvances","(JJ[CIIIII[FI)F",
+ {"nBreakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC},
+ {"nBreakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
+ {"nGetTextAdvances","(JJ[CIIIII[FI)F",
(void*) PaintGlue::getTextAdvances___CIIIII_FI},
- {"native_getTextAdvances","(JJLjava/lang/String;IIIII[FI)F",
+ {"nGetTextAdvances","(JJLjava/lang/String;IIIII[FI)F",
(void*) PaintGlue::getTextAdvances__StringIIIII_FI},
- {"native_getTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
- {"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
+ {"nGetTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
+ {"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I",
(void*) PaintGlue::getTextRunCursor__String},
- {"native_getTextPath", "(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
- {"native_getTextPath", "(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
- {"nativeGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V",
+ {"nGetTextPath", "(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
+ {"nGetTextPath", "(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
+ {"nGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V",
(void*) PaintGlue::getStringBounds },
- {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
+ {"nGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
(void*) PaintGlue::getCharArrayBounds },
- {"native_hasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
- {"native_getRunAdvance", "(JJ[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
- {"native_getOffsetForAdvance", "(JJ[CIIIIZF)I",
+ {"nHasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
+ {"nGetRunAdvance", "(JJ[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
+ {"nGetOffsetForAdvance", "(JJ[CIIIIZF)I",
(void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I},
- {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
- {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
+ {"nSetShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
+ {"nHasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
};
int register_android_graphics_Paint(JNIEnv* env) {
@@ -1073,10 +1019,6 @@
gFontMetricsInt_fieldID.bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I");
gFontMetricsInt_fieldID.leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I");
- gPaint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Paint"));
- gPaint_nativeInstanceID = GetFieldIDOrDie(env, gPaint_class, "mNativePaint", "J");
- gPaint_nativeTypefaceID = GetFieldIDOrDie(env, gPaint_class, "mNativeTypeface", "J");
-
return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods));
}
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index c79f833..17eb876 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -461,10 +461,10 @@
proxy->drawRenderNode(renderNode);
}
-static void android_view_ThreadedRenderer_setContentOverdrawProtectionBounds(JNIEnv* env,
+static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->setContentOverdrawProtectionBounds(left, top, right, bottom);
+ proxy->setContentDrawBounds(left, top, right, bottom);
}
// ----------------------------------------------------------------------------
@@ -522,8 +522,7 @@
{ "nAddRenderNode", "(JJZ)V", (void*) android_view_ThreadedRenderer_addRenderNode},
{ "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
- { "nSetContentOverdrawProtectionBounds", "(JIIII)V",
- (void*)android_view_ThreadedRenderer_setContentOverdrawProtectionBounds},
+ { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 38a1693..58640eb 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -307,9 +307,10 @@
<style name="TextAppearance.Material.Widget.PopupMenu"/>
<style name="TextAppearance.Material.Widget.PopupMenu.Large" parent="TextAppearance.Material.Menu" />
<style name="TextAppearance.Material.Widget.PopupMenu.Small" parent="TextAppearance.Material.Menu" />
- <style name="TextAppearance.Material.Widget.PopupMenu.Header" parent="TextAppearance.Material.Subhead">
+ <style name="TextAppearance.Material.Widget.PopupMenu.Header">
<item name="fontFamily">@string/font_family_title_material</item>
<item name="textSize">@dimen/text_size_menu_header_material</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Material.Widget.DropDownHint" parent="TextAppearance.Material.Menu" />
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 58de87a..11b4a9e 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -430,7 +430,7 @@
* @param flags initial flag bits, as if they were passed via setFlags().
*/
public Paint(int flags) {
- mNativePaint = native_init();
+ mNativePaint = nInit();
setFlags(flags | HIDDEN_DEFAULT_PAINT_FLAGS);
// TODO: Turning off hinting has undesirable side effects, we need to
// revisit hinting once we add support for subpixel positioning
@@ -448,13 +448,14 @@
* new paint.
*/
public Paint(Paint paint) {
- mNativePaint = native_initWithPaint(paint.getNativeInstance());
+ mNativePaint = nInitWithPaint(paint.getNativeInstance());
setClassVariablesFrom(paint);
}
/** Restores the paint to its default settings. */
public void reset() {
- native_reset(mNativePaint);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nReset(mNativePaint);
setFlags(HIDDEN_DEFAULT_PAINT_FLAGS);
// TODO: Turning off hinting has undesirable side effects, we need to
@@ -488,9 +489,11 @@
* methods on this.
*/
public void set(Paint src) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ if (src.mNativePaint == 0) throw new NullPointerException("Source is already finalized!");
if (this != src) {
// copy over the native settings
- native_set(mNativePaint, src.mNativePaint);
+ nSet(mNativePaint, src.mNativePaint);
setClassVariablesFrom(src);
}
}
@@ -538,10 +541,11 @@
* @hide
*/
public long getNativeInstance() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
if (newNativeShader != mNativeShader) {
mNativeShader = newNativeShader;
- native_setShader(mNativePaint, mNativeShader);
+ nSetShader(mNativePaint, mNativeShader);
}
return mNativePaint;
}
@@ -574,26 +578,46 @@
*
* @return the paint's flags (see enums ending in _Flag for bit masks)
*/
- public native int getFlags();
+ public int getFlags() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetFlags(mNativePaint);
+ }
+
+ private native int nGetFlags(long paintPtr);
/**
* Set the paint's flags. Use the Flag enum to specific flag values.
*
* @param flags The new flag bits for the paint
*/
- public native void setFlags(int flags);
+ public void setFlags(int flags) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetFlags(mNativePaint, flags);
+ }
+
+ private native void nSetFlags(long paintPtr, int flags);
/**
* Return the paint's hinting mode. Returns either
* {@link #HINTING_OFF} or {@link #HINTING_ON}.
*/
- public native int getHinting();
+ public int getHinting() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetHinting(mNativePaint);
+ }
+
+ private native int nGetHinting(long paintPtr);
/**
* Set the paint's hinting mode. May be either
* {@link #HINTING_OFF} or {@link #HINTING_ON}.
*/
- public native void setHinting(int mode);
+ public void setHinting(int mode) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetHinting(mNativePaint, mode);
+ }
+
+ private native void nSetHinting(long paintPtr, int mode);
/**
* Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set
@@ -615,7 +639,12 @@
*
* @param aa true to set the antialias bit in the flags, false to clear it
*/
- public native void setAntiAlias(boolean aa);
+ public void setAntiAlias(boolean aa) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetAntiAlias(mNativePaint, aa);
+ }
+
+ private native void nSetAntiAlias(long paintPtr, boolean aa);
/**
* Helper for getFlags(), returning true if DITHER_FLAG bit is set
@@ -641,7 +670,12 @@
*
* @param dither true to set the dithering bit in flags, false to clear it
*/
- public native void setDither(boolean dither);
+ public void setDither(boolean dither) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetDither(mNativePaint, dither);
+ }
+
+ private native void nSetDither(long paintPtr, boolean dither);
/**
* Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set
@@ -658,7 +692,12 @@
* @param linearText true to set the linearText bit in the paint's flags,
* false to clear it.
*/
- public native void setLinearText(boolean linearText);
+ public void setLinearText(boolean linearText) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetLinearText(mNativePaint, linearText);
+ }
+
+ private native void nSetLinearText(long paintPtr, boolean linearText);
/**
* Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set
@@ -675,7 +714,12 @@
* @param subpixelText true to set the subpixelText bit in the paint's
* flags, false to clear it.
*/
- public native void setSubpixelText(boolean subpixelText);
+ public void setSubpixelText(boolean subpixelText) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetSubpixelText(mNativePaint, subpixelText);
+ }
+
+ private native void nSetSubpixelText(long paintPtr, boolean subpixelText);
/**
* Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
@@ -692,7 +736,12 @@
* @param underlineText true to set the underlineText bit in the paint's
* flags, false to clear it.
*/
- public native void setUnderlineText(boolean underlineText);
+ public void setUnderlineText(boolean underlineText) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetUnderlineText(mNativePaint, underlineText);
+ }
+
+ private native void nSetUnderlineText(long paintPtr, boolean underlineText);
/**
* Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
@@ -709,7 +758,12 @@
* @param strikeThruText true to set the strikeThruText bit in the paint's
* flags, false to clear it.
*/
- public native void setStrikeThruText(boolean strikeThruText);
+ public void setStrikeThruText(boolean strikeThruText) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetStrikeThruText(mNativePaint, strikeThruText);
+ }
+
+ private native void nSetStrikeThruText(long paintPtr, boolean strikeThruText);
/**
* Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set
@@ -726,7 +780,12 @@
* @param fakeBoldText true to set the fakeBoldText bit in the paint's
* flags, false to clear it.
*/
- public native void setFakeBoldText(boolean fakeBoldText);
+ public void setFakeBoldText(boolean fakeBoldText) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetFakeBoldText(mNativePaint, fakeBoldText);
+ }
+
+ private native void nSetFakeBoldText(long paintPtr, boolean fakeBoldText);
/**
* Whether or not the bitmap filter is activated.
@@ -749,7 +808,12 @@
* @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
* flags, false to clear it.
*/
- public native void setFilterBitmap(boolean filter);
+ public void setFilterBitmap(boolean filter) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetFilterBitmap(mNativePaint, filter);
+ }
+
+ private native void nSetFilterBitmap(long paintPtr, boolean filter);
/**
* Return the paint's style, used for controlling how primitives'
@@ -759,7 +823,8 @@
* @return the paint's style setting (Fill, Stroke, StrokeAndFill)
*/
public Style getStyle() {
- return sStyleArray[native_getStyle(mNativePaint)];
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return sStyleArray[nGetStyle(mNativePaint)];
}
/**
@@ -770,7 +835,8 @@
* @param style The new style to set in the paint
*/
public void setStyle(Style style) {
- native_setStyle(mNativePaint, style.nativeInt);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetStyle(mNativePaint, style.nativeInt);
}
/**
@@ -782,7 +848,12 @@
* @return the paint's color (and alpha).
*/
@ColorInt
- public native int getColor();
+ public int getColor() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetColor(mNativePaint);
+ }
+
+ private native int nGetColor(long paintPtr);
/**
* Set the paint's color. Note that the color is an int containing alpha
@@ -792,7 +863,12 @@
*
* @param color The new color (including alpha) to set in the paint.
*/
- public native void setColor(@ColorInt int color);
+ public void setColor(@ColorInt int color) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetColor(mNativePaint, color);
+ }
+
+ private native void nSetColor(long paintPtr, @ColorInt int color);
/**
* Helper to getColor() that just returns the color's alpha value. This is
@@ -801,7 +877,12 @@
*
* @return the alpha component of the paint's color.
*/
- public native int getAlpha();
+ public int getAlpha() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetAlpha(mNativePaint);
+ }
+
+ private native int nGetAlpha(long paintPtr);
/**
* Helper to setColor(), that only assigns the color's alpha value,
@@ -810,7 +891,12 @@
*
* @param a set the alpha component [0..255] of the paint's color.
*/
- public native void setAlpha(int a);
+ public void setAlpha(int a) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetAlpha(mNativePaint, a);
+ }
+
+ private native void nSetAlpha(long paintPtr, int a);
/**
* Helper to setColor(), that takes a,r,g,b and constructs the color int
@@ -833,7 +919,12 @@
* @return the paint's stroke width, used whenever the paint's style is
* Stroke or StrokeAndFill.
*/
- public native float getStrokeWidth();
+ public float getStrokeWidth() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetStrokeWidth(mNativePaint);
+ }
+
+ private native float nGetStrokeWidth(long paintPtr);
/**
* Set the width for stroking.
@@ -843,7 +934,12 @@
* @param width set the paint's stroke width, used whenever the paint's
* style is Stroke or StrokeAndFill.
*/
- public native void setStrokeWidth(float width);
+ public void setStrokeWidth(float width) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetStrokeWidth(mNativePaint, width);
+ }
+
+ private native void nSetStrokeWidth(long paintPtr, float width);
/**
* Return the paint's stroke miter value. Used to control the behavior
@@ -852,7 +948,12 @@
* @return the paint's miter limit, used whenever the paint's style is
* Stroke or StrokeAndFill.
*/
- public native float getStrokeMiter();
+ public float getStrokeMiter() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetStrokeMiter(mNativePaint);
+ }
+
+ private native float nGetStrokeMiter(long paintPtr);
/**
* Set the paint's stroke miter value. This is used to control the behavior
@@ -861,7 +962,12 @@
* @param miter set the miter limit on the paint, used whenever the paint's
* style is Stroke or StrokeAndFill.
*/
- public native void setStrokeMiter(float miter);
+ public void setStrokeMiter(float miter) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetStrokeMiter(mNativePaint, miter);
+ }
+
+ private native void nSetStrokeMiter(long paintPtr, float miter);
/**
* Return the paint's Cap, controlling how the start and end of stroked
@@ -871,7 +977,8 @@
* style is Stroke or StrokeAndFill.
*/
public Cap getStrokeCap() {
- return sCapArray[native_getStrokeCap(mNativePaint)];
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return sCapArray[nGetStrokeCap(mNativePaint)];
}
/**
@@ -881,7 +988,8 @@
* style is Stroke or StrokeAndFill.
*/
public void setStrokeCap(Cap cap) {
- native_setStrokeCap(mNativePaint, cap.nativeInt);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetStrokeCap(mNativePaint, cap.nativeInt);
}
/**
@@ -890,7 +998,8 @@
* @return the paint's Join.
*/
public Join getStrokeJoin() {
- return sJoinArray[native_getStrokeJoin(mNativePaint)];
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return sJoinArray[nGetStrokeJoin(mNativePaint)];
}
/**
@@ -900,7 +1009,8 @@
* Stroke or StrokeAndFill.
*/
public void setStrokeJoin(Join join) {
- native_setStrokeJoin(mNativePaint, join.nativeInt);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetStrokeJoin(mNativePaint, join.nativeInt);
}
/**
@@ -915,7 +1025,8 @@
* drawn with a hairline (width == 0)
*/
public boolean getFillPath(Path src, Path dst) {
- return native_getFillPath(mNativePaint, src.ni(), dst.ni());
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetFillPath(mNativePaint, src.ni(), dst.ni());
}
/**
@@ -958,10 +1069,11 @@
* @return filter
*/
public ColorFilter setColorFilter(ColorFilter filter) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long filterNative = 0;
if (filter != null)
filterNative = filter.native_instance;
- native_setColorFilter(mNativePaint, filterNative);
+ nSetColorFilter(mNativePaint, filterNative);
mColorFilter = filter;
return filter;
}
@@ -985,10 +1097,11 @@
* @return xfermode
*/
public Xfermode setXfermode(Xfermode xfermode) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long xfermodeNative = 0;
if (xfermode != null)
xfermodeNative = xfermode.native_instance;
- native_setXfermode(mNativePaint, xfermodeNative);
+ nSetXfermode(mNativePaint, xfermodeNative);
mXfermode = xfermode;
return xfermode;
}
@@ -1012,11 +1125,12 @@
* @return effect
*/
public PathEffect setPathEffect(PathEffect effect) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long effectNative = 0;
if (effect != null) {
effectNative = effect.native_instance;
}
- native_setPathEffect(mNativePaint, effectNative);
+ nSetPathEffect(mNativePaint, effectNative);
mPathEffect = effect;
return effect;
}
@@ -1041,11 +1155,12 @@
* @return maskfilter
*/
public MaskFilter setMaskFilter(MaskFilter maskfilter) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long maskfilterNative = 0;
if (maskfilter != null) {
maskfilterNative = maskfilter.native_instance;
}
- native_setMaskFilter(mNativePaint, maskfilterNative);
+ nSetMaskFilter(mNativePaint, maskfilterNative);
mMaskFilter = maskfilter;
return maskfilter;
}
@@ -1072,11 +1187,12 @@
* @return typeface
*/
public Typeface setTypeface(Typeface typeface) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long typefaceNative = 0;
if (typeface != null) {
typefaceNative = typeface.native_instance;
}
- native_setTypeface(mNativePaint, typefaceNative);
+ nSetTypeface(mNativePaint, typefaceNative);
mTypeface = typeface;
mNativeTypeface = typefaceNative;
return typeface;
@@ -1110,11 +1226,12 @@
*/
@Deprecated
public Rasterizer setRasterizer(Rasterizer rasterizer) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
long rasterizerNative = 0;
if (rasterizer != null) {
rasterizerNative = rasterizer.native_instance;
}
- native_setRasterizer(mNativePaint, rasterizerNative);
+ nSetRasterizer(mNativePaint, rasterizerNative);
mRasterizer = rasterizer;
return rasterizer;
}
@@ -1132,7 +1249,8 @@
* opaque, or the alpha from the shadow color if not.
*/
public void setShadowLayer(float radius, float dx, float dy, int shadowColor) {
- native_setShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetShadowLayer(mNativePaint, radius, dx, dy, shadowColor);
}
/**
@@ -1149,7 +1267,8 @@
* @hide
*/
public boolean hasShadowLayer() {
- return native_hasShadowLayer(mNativePaint);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nHasShadowLayer(mNativePaint);
}
/**
@@ -1161,7 +1280,8 @@
* @return the paint's Align value for drawing text.
*/
public Align getTextAlign() {
- return sAlignArray[native_getTextAlign(mNativePaint)];
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return sAlignArray[nGetTextAlign(mNativePaint)];
}
/**
@@ -1173,7 +1293,8 @@
* @param align set the paint's Align value for drawing text.
*/
public void setTextAlign(Align align) {
- native_setTextAlign(mNativePaint, align.nativeInt);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetTextAlign(mNativePaint, align.nativeInt);
}
/**
@@ -1206,6 +1327,7 @@
* @param locale the paint's locale value for drawing text, must not be null.
*/
public void setTextLocale(@NonNull Locale locale) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (locale == null) {
throw new IllegalArgumentException("locale cannot be null");
}
@@ -1213,7 +1335,7 @@
return;
}
mLocales = new LocaleList(locale);
- native_setTextLocale(mNativePaint, locale.toString());
+ nSetTextLocale(mNativePaint, locale.toString());
}
/**
@@ -1244,13 +1366,14 @@
* @param locales the paint's locale list for drawing text, must not be null or empty.
*/
public void setTextLocales(@NonNull @Size(min=1) LocaleList locales) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (locales == null || locales.isEmpty()) {
throw new IllegalArgumentException("locales cannot be null or empty");
}
if (locales.equals(mLocales)) return;
mLocales = locales;
// TODO: Pass the whole LocaleList to native code
- native_setTextLocale(mNativePaint, locales.getPrimary().toString());
+ nSetTextLocale(mNativePaint, locales.getPrimary().toString());
}
/**
@@ -1258,7 +1381,12 @@
*
* @return true if elegant metrics are enabled for text drawing.
*/
- public native boolean isElegantTextHeight();
+ public boolean isElegantTextHeight() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nIsElegantTextHeight(mNativePaint);
+ }
+
+ private native boolean nIsElegantTextHeight(long paintPtr);
/**
* Set the paint's elegant height metrics flag. This setting selects font
@@ -1267,21 +1395,36 @@
*
* @param elegant set the paint's elegant metrics flag for drawing text.
*/
- public native void setElegantTextHeight(boolean elegant);
+ public void setElegantTextHeight(boolean elegant) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetElegantTextHeight(mNativePaint, elegant);
+ }
+
+ private native void nSetElegantTextHeight(long paintPtr, boolean elegant);
/**
* Return the paint's text size.
*
* @return the paint's text size.
*/
- public native float getTextSize();
+ public float getTextSize() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetTextSize(mNativePaint);
+ }
+
+ private native float nGetTextSize(long paintPtr);
/**
* Set the paint's text size. This value must be > 0
*
* @param textSize set the paint's text size.
*/
- public native void setTextSize(float textSize);
+ public void setTextSize(float textSize) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetTextSize(mNativePaint, textSize);
+ }
+
+ private native void nSetTextSize(long paintPtr, float textSize);
/**
* Return the paint's horizontal scale factor for text. The default value
@@ -1289,7 +1432,12 @@
*
* @return the paint's scale factor in X for drawing/measuring text
*/
- public native float getTextScaleX();
+ public float getTextScaleX() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetTextScaleX(mNativePaint);
+ }
+
+ private native float nGetTextScaleX(long paintPtr);
/**
* Set the paint's horizontal scale factor for text. The default value
@@ -1298,7 +1446,12 @@
*
* @param scaleX set the paint's scale in X for drawing/measuring text.
*/
- public native void setTextScaleX(float scaleX);
+ public void setTextScaleX(float scaleX) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetTextScaleX(mNativePaint, scaleX);
+ }
+
+ private native void nSetTextScaleX(long paintPtr, float scaleX);
/**
* Return the paint's horizontal skew factor for text. The default value
@@ -1306,7 +1459,12 @@
*
* @return the paint's skew factor in X for drawing text.
*/
- public native float getTextSkewX();
+ public float getTextSkewX() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetTextSkewX(mNativePaint);
+ }
+
+ private native float nGetTextSkewX(long paintPtr);
/**
* Set the paint's horizontal skew factor for text. The default value
@@ -1314,7 +1472,12 @@
*
* @param skewX set the paint's skew factor in X for drawing text.
*/
- public native void setTextSkewX(float skewX);
+ public void setTextSkewX(float skewX) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetTextSkewX(mNativePaint, skewX);
+ }
+
+ private native void nSetTextSkewX(long paintPtr, float skewX);
/**
* Return the paint's letter-spacing for text. The default value
@@ -1323,7 +1486,8 @@
* @return the paint's letter-spacing for drawing text.
*/
public float getLetterSpacing() {
- return native_getLetterSpacing(mNativePaint);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetLetterSpacing(mNativePaint);
}
/**
@@ -1334,7 +1498,8 @@
* @param letterSpacing set the paint's letter-spacing for drawing text.
*/
public void setLetterSpacing(float letterSpacing) {
- native_setLetterSpacing(mNativePaint, letterSpacing);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetLetterSpacing(mNativePaint, letterSpacing);
}
/**
@@ -1355,6 +1520,7 @@
* @param settings the font feature settings string to use, may be null.
*/
public void setFontFeatureSettings(String settings) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (settings != null && settings.equals("")) {
settings = null;
}
@@ -1363,7 +1529,7 @@
return;
}
mFontFeatureSettings = settings;
- native_setFontFeatureSettings(mNativePaint, settings);
+ nSetFontFeatureSettings(mNativePaint, settings);
}
/**
@@ -1374,7 +1540,8 @@
* @hide
*/
public int getHyphenEdit() {
- return native_getHyphenEdit(mNativePaint);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetHyphenEdit(mNativePaint);
}
/**
@@ -1386,7 +1553,8 @@
* @hide
*/
public void setHyphenEdit(int hyphen) {
- native_setHyphenEdit(mNativePaint, hyphen);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ nSetHyphenEdit(mNativePaint, hyphen);
}
/**
@@ -1396,7 +1564,12 @@
* @return the distance above (negative) the baseline (ascent) based on the
* current typeface and text size.
*/
- public native float ascent();
+ public float ascent() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nAscent(mNativePaint, mNativeTypeface);
+ }
+
+ private native float nAscent(long paintPtr, long typefacePtr);
/**
* Return the distance below (positive) the baseline (descent) based on the
@@ -1405,7 +1578,12 @@
* @return the distance below (positive) the baseline (descent) based on
* the current typeface and text size.
*/
- public native float descent();
+ public float descent() {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nDescent(mNativePaint, mNativeTypeface);
+ }
+
+ private native float nDescent(long paintPtr, long typefacePtr);
/**
* Class that describes the various metrics for a font at a given text size.
@@ -1447,7 +1625,13 @@
* the appropriate values given the paint's text attributes.
* @return the font's recommended interline spacing.
*/
- public native float getFontMetrics(FontMetrics metrics);
+ public float getFontMetrics(FontMetrics metrics) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetFontMetrics(mNativePaint, mNativeTypeface, metrics);
+ }
+
+ private native float nGetFontMetrics(long paintPtr,
+ long typefacePtr, FontMetrics metrics);
/**
* Allocates a new FontMetrics object, and then calls getFontMetrics(fm)
@@ -1487,7 +1671,13 @@
*
* @return the font's interline spacing.
*/
- public native int getFontMetricsInt(FontMetricsInt fmi);
+ public int getFontMetricsInt(FontMetricsInt fmi) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nGetFontMetricsInt(mNativePaint, mNativeTypeface, fmi);
+ }
+
+ private native int nGetFontMetricsInt(long paintPtr,
+ long typefacePtr, FontMetricsInt fmi);
public FontMetricsInt getFontMetricsInt() {
FontMetricsInt fm = new FontMetricsInt();
@@ -1515,6 +1705,7 @@
* @return The width of the text
*/
public float measureText(char[] text, int index, int count) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1526,13 +1717,13 @@
return 0f;
}
if (!mHasCompatScaling) {
- return (float) Math.ceil(native_getTextAdvances(mNativePaint, mNativeTypeface, text,
+ return (float) Math.ceil(nGetTextAdvances(mNativePaint, mNativeTypeface, text,
index, count, index, count, mBidiFlags, null, 0));
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- float w = native_getTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index,
+ float w = nGetTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index,
count, mBidiFlags, null, 0);
setTextSize(oldSize);
return (float) Math.ceil(w*mInvCompatScaling);
@@ -1547,6 +1738,7 @@
* @return The width of the text
*/
public float measureText(String text, int start, int end) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1558,12 +1750,12 @@
return 0f;
}
if (!mHasCompatScaling) {
- return (float) Math.ceil(native_getTextAdvances(mNativePaint, mNativeTypeface, text,
+ return (float) Math.ceil(nGetTextAdvances(mNativePaint, mNativeTypeface, text,
start, end, start, end, mBidiFlags, null, 0));
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- float w = native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start,
+ float w = nGetTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start,
end, mBidiFlags, null, 0);
setTextSize(oldSize);
return (float) Math.ceil(w * mInvCompatScaling);
@@ -1576,6 +1768,7 @@
* @return The width of the text
*/
public float measureText(String text) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1636,6 +1829,7 @@
*/
public int breakText(char[] text, int index, int count,
float maxWidth, float[] measuredWidth) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1647,20 +1841,20 @@
return 0;
}
if (!mHasCompatScaling) {
- return native_breakText(mNativePaint, mNativeTypeface, text, index, count, maxWidth,
+ return nBreakText(mNativePaint, mNativeTypeface, text, index, count, maxWidth,
mBidiFlags, measuredWidth);
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- int res = native_breakText(mNativePaint, mNativeTypeface, text, index, count,
+ int res = nBreakText(mNativePaint, mNativeTypeface, text, index, count,
maxWidth * mCompatScaling, mBidiFlags, measuredWidth);
setTextSize(oldSize);
if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
return res;
}
- private static native int native_breakText(long native_object, long native_typeface,
+ private static native int nBreakText(long nObject, long nTypeface,
char[] text, int index, int count,
float maxWidth, int bidiFlags, float[] measuredWidth);
@@ -1683,6 +1877,7 @@
public int breakText(CharSequence text, int start, int end,
boolean measureForwards,
float maxWidth, float[] measuredWidth) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1731,6 +1926,7 @@
*/
public int breakText(String text, boolean measureForwards,
float maxWidth, float[] measuredWidth) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1739,20 +1935,20 @@
return 0;
}
if (!mHasCompatScaling) {
- return native_breakText(mNativePaint, mNativeTypeface, text, measureForwards,
+ return nBreakText(mNativePaint, mNativeTypeface, text, measureForwards,
maxWidth, mBidiFlags, measuredWidth);
}
final float oldSize = getTextSize();
setTextSize(oldSize*mCompatScaling);
- int res = native_breakText(mNativePaint, mNativeTypeface, text, measureForwards,
+ int res = nBreakText(mNativePaint, mNativeTypeface, text, measureForwards,
maxWidth*mCompatScaling, mBidiFlags, measuredWidth);
setTextSize(oldSize);
if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
return res;
}
- private static native int native_breakText(long native_object, long native_typeface,
+ private static native int nBreakText(long nObject, long nTypeface,
String text, boolean measureForwards,
float maxWidth, int bidiFlags, float[] measuredWidth);
@@ -1768,6 +1964,7 @@
*/
public int getTextWidths(char[] text, int index, int count,
float[] widths) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1780,14 +1977,14 @@
return 0;
}
if (!mHasCompatScaling) {
- native_getTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index, count,
+ nGetTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index, count,
mBidiFlags, widths, 0);
return count;
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- native_getTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index, count,
+ nGetTextAdvances(mNativePaint, mNativeTypeface, text, index, count, index, count,
mBidiFlags, widths, 0);
setTextSize(oldSize);
for (int i = 0; i < count; i++) {
@@ -1851,6 +2048,7 @@
* @return the number of code units in the specified text.
*/
public int getTextWidths(String text, int start, int end, float[] widths) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1865,14 +2063,14 @@
return 0;
}
if (!mHasCompatScaling) {
- native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start, end,
+ nGetTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start, end,
mBidiFlags, widths, 0);
return end - start;
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start, end,
+ nGetTextAdvances(mNativePaint, mNativeTypeface, text, start, end, start, end,
mBidiFlags, widths, 0);
setTextSize(oldSize);
for (int i = 0; i < end - start; i++) {
@@ -1904,6 +2102,7 @@
int contextIndex, int contextCount, boolean isRtl, float[] advances,
int advancesIndex) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (chars == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -1920,14 +2119,14 @@
return 0f;
}
if (!mHasCompatScaling) {
- return native_getTextAdvances(mNativePaint, mNativeTypeface, chars, index, count,
+ return nGetTextAdvances(mNativePaint, mNativeTypeface, chars, index, count,
contextIndex, contextCount, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- float res = native_getTextAdvances(mNativePaint, mNativeTypeface, chars, index, count,
+ float res = nGetTextAdvances(mNativePaint, mNativeTypeface, chars, index, count,
contextIndex, contextCount, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
setTextSize(oldSize);
@@ -1950,7 +2149,7 @@
public float getTextRunAdvances(CharSequence text, int start, int end,
int contextStart, int contextEnd, boolean isRtl, float[] advances,
int advancesIndex) {
-
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2032,6 +2231,7 @@
*/
public float getTextRunAdvances(String text, int start, int end, int contextStart,
int contextEnd, boolean isRtl, float[] advances, int advancesIndex) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2048,14 +2248,14 @@
}
if (!mHasCompatScaling) {
- return native_getTextAdvances(mNativePaint, mNativeTypeface, text, start, end,
+ return nGetTextAdvances(mNativePaint, mNativeTypeface, text, start, end,
contextStart, contextEnd, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
}
final float oldSize = getTextSize();
setTextSize(oldSize * mCompatScaling);
- float totalAdvance = native_getTextAdvances(mNativePaint, mNativeTypeface, text, start,
+ float totalAdvance = nGetTextAdvances(mNativePaint, mNativeTypeface, text, start,
end, contextStart, contextEnd, isRtl ? BIDI_FORCE_RTL : BIDI_FORCE_LTR, advances,
advancesIndex);
setTextSize(oldSize);
@@ -2096,6 +2296,7 @@
*/
public int getTextRunCursor(char[] text, int contextStart, int contextLength,
int dir, int offset, int cursorOpt) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
int contextEnd = contextStart + contextLength;
if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
| (offset - contextStart) | (contextEnd - offset)
@@ -2104,7 +2305,7 @@
throw new IndexOutOfBoundsException();
}
- return native_getTextRunCursor(mNativePaint, text,
+ return nGetTextRunCursor(mNativePaint, text,
contextStart, contextLength, dir, offset, cursorOpt);
}
@@ -2183,6 +2384,7 @@
*/
public int getTextRunCursor(String text, int contextStart, int contextEnd,
int dir, int offset, int cursorOpt) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
| (offset - contextStart) | (contextEnd - offset)
| (text.length() - contextEnd) | cursorOpt) < 0)
@@ -2190,7 +2392,7 @@
throw new IndexOutOfBoundsException();
}
- return native_getTextRunCursor(mNativePaint, text,
+ return nGetTextRunCursor(mNativePaint, text,
contextStart, contextEnd, dir, offset, cursorOpt);
}
@@ -2209,10 +2411,11 @@
*/
public void getTextPath(char[] text, int index, int count,
float x, float y, Path path) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if ((index | count) < 0 || index + count > text.length) {
throw new ArrayIndexOutOfBoundsException();
}
- native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, index, count, x, y,
+ nGetTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, index, count, x, y,
path.ni());
}
@@ -2231,10 +2434,11 @@
*/
public void getTextPath(String text, int start, int end,
float x, float y, Path path) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
- native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y,
+ nGetTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y,
path.ni());
}
@@ -2249,13 +2453,14 @@
* allocated by the caller.
*/
public void getTextBounds(String text, int start, int end, Rect bounds) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
if (bounds == null) {
throw new NullPointerException("need bounds Rect");
}
- nativeGetStringBounds(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, bounds);
+ nGetStringBounds(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, bounds);
}
/**
@@ -2269,13 +2474,14 @@
* allocated by the caller.
*/
public void getTextBounds(char[] text, int index, int count, Rect bounds) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if ((index | count) < 0 || index + count > text.length) {
throw new ArrayIndexOutOfBoundsException();
}
if (bounds == null) {
throw new NullPointerException("need bounds Rect");
}
- nativeGetCharArrayBounds(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags,
+ nGetCharArrayBounds(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags,
bounds);
}
@@ -2296,7 +2502,8 @@
* @return true if the typeface has a glyph for the string
*/
public boolean hasGlyph(String string) {
- return native_hasGlyph(mNativePaint, mNativeTypeface, mBidiFlags, string);
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
+ return nHasGlyph(mNativePaint, mNativeTypeface, mBidiFlags, string);
}
/**
@@ -2337,6 +2544,7 @@
*/
public float getRunAdvance(char[] text, int start, int end, int contextStart, int contextEnd,
boolean isRtl, int offset) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2349,7 +2557,7 @@
return 0.0f;
}
// TODO: take mCompatScaling into account (or eliminate compat scaling)?
- return native_getRunAdvance(mNativePaint, mNativeTypeface, text, start, end,
+ return nGetRunAdvance(mNativePaint, mNativeTypeface, text, start, end,
contextStart, contextEnd, isRtl, offset);
}
@@ -2367,6 +2575,7 @@
*/
public float getRunAdvance(CharSequence text, int start, int end, int contextStart,
int contextEnd, boolean isRtl, int offset) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2417,6 +2626,7 @@
*/
public int getOffsetForAdvance(char[] text, int start, int end, int contextStart,
int contextEnd, boolean isRtl, float advance) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2426,7 +2636,7 @@
throw new IndexOutOfBoundsException();
}
// TODO: take mCompatScaling into account (or eliminate compat scaling)?
- return native_getOffsetForAdvance(mNativePaint, mNativeTypeface, text, start, end,
+ return nGetOffsetForAdvance(mNativePaint, mNativeTypeface, text, start, end,
contextStart, contextEnd, isRtl, advance);
}
@@ -2444,6 +2654,7 @@
*/
public int getOffsetForAdvance(CharSequence text, int start, int end, int contextStart,
int contextEnd, boolean isRtl, float advance) {
+ if (mNativePaint == 0) throw new NullPointerException("Already finalized!");
if (text == null) {
throw new IllegalArgumentException("text cannot be null");
}
@@ -2464,90 +2675,88 @@
@Override
protected void finalize() throws Throwable {
try {
- finalizer(mNativePaint);
- mNativePaint = 0;
+ if (mNativePaint != 0) {
+ nFinalizer(mNativePaint);
+ mNativePaint = 0;
+ }
} finally {
super.finalize();
}
}
- private static native long native_init();
- private static native long native_initWithPaint(long paint);
- private static native void native_reset(long native_object);
- private static native void native_set(long native_dst, long native_src);
- private static native int native_getStyle(long native_object);
- private static native void native_setStyle(long native_object, int style);
- private static native int native_getStrokeCap(long native_object);
- private static native void native_setStrokeCap(long native_object, int cap);
- private static native int native_getStrokeJoin(long native_object);
- private static native void native_setStrokeJoin(long native_object,
+ private static native long nInit();
+ private static native long nInitWithPaint(long paint);
+ private static native void nReset(long paintPtr);
+ private static native void nSet(long paintPtrDest, long paintPtrSrc);
+ private static native int nGetStyle(long paintPtr);
+ private static native void nSetStyle(long paintPtr, int style);
+ private static native int nGetStrokeCap(long paintPtr);
+ private static native void nSetStrokeCap(long paintPtr, int cap);
+ private static native int nGetStrokeJoin(long paintPtr);
+ private static native void nSetStrokeJoin(long paintPtr,
int join);
- private static native boolean native_getFillPath(long native_object,
+ private static native boolean nGetFillPath(long paintPtr,
long src, long dst);
- private static native long native_setShader(long native_object, long shader);
- private static native long native_setColorFilter(long native_object,
+ private static native long nSetShader(long paintPtr, long shader);
+ private static native long nSetColorFilter(long paintPtr,
long filter);
- private static native long native_setXfermode(long native_object,
+ private static native long nSetXfermode(long paintPtr,
long xfermode);
- private static native long native_setPathEffect(long native_object,
+ private static native long nSetPathEffect(long paintPtr,
long effect);
- private static native long native_setMaskFilter(long native_object,
+ private static native long nSetMaskFilter(long paintPtr,
long maskfilter);
- private static native long native_setTypeface(long native_object,
+ private static native long nSetTypeface(long paintPtr,
long typeface);
- private static native long native_setRasterizer(long native_object,
+ private static native long nSetRasterizer(long paintPtr,
long rasterizer);
- private static native int native_getTextAlign(long native_object);
- private static native void native_setTextAlign(long native_object,
+ private static native int nGetTextAlign(long paintPtr);
+ private static native void nSetTextAlign(long paintPtr,
int align);
- private static native void native_setTextLocale(long native_object,
+ private static native void nSetTextLocale(long paintPtr,
String locale);
- private static native int native_getTextGlyphs(long native_object,
- String text, int start, int end, int contextStart, int contextEnd,
- int flags, char[] glyphs);
-
- private static native float native_getTextAdvances(long native_object, long native_typeface,
+ private static native float nGetTextAdvances(long paintPtr, long typefacePtr,
char[] text, int index, int count, int contextIndex, int contextCount,
int bidiFlags, float[] advances, int advancesIndex);
- private static native float native_getTextAdvances(long native_object, long native_typeface,
+ private static native float nGetTextAdvances(long paintPtr, long typefacePtr,
String text, int start, int end, int contextStart, int contextEnd,
int bidiFlags, float[] advances, int advancesIndex);
- private native int native_getTextRunCursor(long native_object, char[] text,
+ private native int nGetTextRunCursor(long paintPtr, char[] text,
int contextStart, int contextLength, int dir, int offset, int cursorOpt);
- private native int native_getTextRunCursor(long native_object, String text,
+ private native int nGetTextRunCursor(long paintPtr, String text,
int contextStart, int contextEnd, int dir, int offset, int cursorOpt);
- private static native void native_getTextPath(long native_object, long native_typeface,
+ private static native void nGetTextPath(long paintPtr, long typefacePtr,
int bidiFlags, char[] text, int index, int count, float x, float y, long path);
- private static native void native_getTextPath(long native_object, long native_typeface,
+ private static native void nGetTextPath(long paintPtr, long typefacePtr,
int bidiFlags, String text, int start, int end, float x, float y, long path);
- private static native void nativeGetStringBounds(long nativePaint, long native_typeface,
+ private static native void nGetStringBounds(long nativePaint, long typefacePtr,
String text, int start, int end, int bidiFlags, Rect bounds);
- private static native void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
+ private static native void nGetCharArrayBounds(long nativePaint, long typefacePtr,
char[] text, int index, int count, int bidiFlags, Rect bounds);
- private static native void finalizer(long nativePaint);
+ private static native void nFinalizer(long nativePaint);
- private static native void native_setShadowLayer(long native_object,
+ private static native void nSetShadowLayer(long paintPtr,
float radius, float dx, float dy, int color);
- private static native boolean native_hasShadowLayer(long native_object);
+ private static native boolean nHasShadowLayer(long paintPtr);
- private static native float native_getLetterSpacing(long native_object);
- private static native void native_setLetterSpacing(long native_object,
+ private static native float nGetLetterSpacing(long paintPtr);
+ private static native void nSetLetterSpacing(long paintPtr,
float letterSpacing);
- private static native void native_setFontFeatureSettings(long native_object,
+ private static native void nSetFontFeatureSettings(long paintPtr,
String settings);
- private static native int native_getHyphenEdit(long native_object);
- private static native void native_setHyphenEdit(long native_object, int hyphen);
- private static native boolean native_hasGlyph(long native_object, long native_typeface,
+ private static native int nGetHyphenEdit(long paintPtr);
+ private static native void nSetHyphenEdit(long paintPtr, int hyphen);
+ private static native boolean nHasGlyph(long paintPtr, long typefacePtr,
int bidiFlags, String string);
- private static native float native_getRunAdvance(long native_object, long native_typeface,
+ private static native float nGetRunAdvance(long paintPtr, long typefacePtr,
char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
int offset);
- private static native int native_getOffsetForAdvance(long native_object,
- long native_typeface, char[] text, int start, int end, int contextStart, int contextEnd,
+ private static native int nGetOffsetForAdvance(long paintPtr,
+ long typefacePtr, char[] text, int start, int end, int contextStart, int contextEnd,
boolean isRtl, float advance);
}
diff --git a/graphics/tests/graphicstests/src/android/graphics/PaintTest.java b/graphics/tests/graphicstests/src/android/graphics/PaintTest.java
index b67aa7d..6763dd1 100644
--- a/graphics/tests/graphicstests/src/android/graphics/PaintTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/PaintTest.java
@@ -162,4 +162,60 @@
} catch (IndexOutOfBoundsException e) {
}
}
+
+ public void testMeasureTextBidi() {
+ Paint p = new Paint();
+ {
+ String bidiText = "abc \u0644\u063A\u0629 def";
+ p.setBidiFlags(Paint.BIDI_LTR);
+ float width = p.measureText(bidiText, 0, 4);
+ p.setBidiFlags(Paint.BIDI_RTL);
+ width += p.measureText(bidiText, 4, 7);
+ p.setBidiFlags(Paint.BIDI_LTR);
+ width += p.measureText(bidiText, 7, bidiText.length());
+ assertEquals(width, p.measureText(bidiText), 1.0f);
+ }
+ {
+ String bidiText = "abc \u0644\u063A\u0629 def";
+ p.setBidiFlags(Paint.BIDI_DEFAULT_LTR);
+ float width = p.measureText(bidiText, 0, 4);
+ width += p.measureText(bidiText, 4, 7);
+ width += p.measureText(bidiText, 7, bidiText.length());
+ assertEquals(width, p.measureText(bidiText), 1.0f);
+ }
+ {
+ String bidiText = "abc \u0644\u063A\u0629 def";
+ p.setBidiFlags(Paint.BIDI_FORCE_LTR);
+ float width = p.measureText(bidiText, 0, 4);
+ width += p.measureText(bidiText, 4, 7);
+ width += p.measureText(bidiText, 7, bidiText.length());
+ assertEquals(width, p.measureText(bidiText), 1.0f);
+ }
+ {
+ String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
+ p.setBidiFlags(Paint.BIDI_RTL);
+ float width = p.measureText(bidiText, 0, 4);
+ p.setBidiFlags(Paint.BIDI_LTR);
+ width += p.measureText(bidiText, 4, 7);
+ p.setBidiFlags(Paint.BIDI_RTL);
+ width += p.measureText(bidiText, 7, bidiText.length());
+ assertEquals(width, p.measureText(bidiText), 1.0f);
+ }
+ {
+ String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
+ p.setBidiFlags(Paint.BIDI_DEFAULT_RTL);
+ float width = p.measureText(bidiText, 0, 4);
+ width += p.measureText(bidiText, 4, 7);
+ width += p.measureText(bidiText, 7, bidiText.length());
+ assertEquals(width, p.measureText(bidiText), 1.0f);
+ }
+ {
+ String bidiText = "\u0644\u063A\u0629 abc \u0644\u063A\u0629";
+ p.setBidiFlags(Paint.BIDI_FORCE_RTL);
+ float width = p.measureText(bidiText, 0, 4);
+ width += p.measureText(bidiText, 4, 7);
+ width += p.measureText(bidiText, 7, bidiText.length());
+ assertEquals(width, p.measureText(bidiText), 1.0f);
+ }
+ }
}
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index e0bf26d..0c29a9e 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -44,6 +44,12 @@
#define DEBUG_COLOR_MERGEDBATCH 0x5f7f7fff
#define DEBUG_COLOR_MERGEDBATCH_SOLO 0x5f7fff7f
+static bool avoidOverdraw() {
+ // Don't avoid overdraw when visualizing it, since that makes it harder to
+ // debug where it's coming from, and when the problem occurs.
+ return !Properties::debugOverdraw;
+};
+
/////////////////////////////////////////////////////////////////////////////////
// Operation Batches
/////////////////////////////////////////////////////////////////////////////////
@@ -218,7 +224,10 @@
// if paints are equal, then modifiers + paint attribs don't need to be compared
if (op->mPaint == mOps[0].op->mPaint) return true;
- if (op->getPaintAlpha() != mOps[0].op->getPaintAlpha()) return false;
+ if (PaintUtils::getAlphaDirect(op->mPaint)
+ != PaintUtils::getAlphaDirect(mOps[0].op->mPaint)) {
+ return false;
+ }
if (op->mPaint && mOps[0].op->mPaint &&
op->mPaint->getColorFilter() != mOps[0].op->mPaint->getColorFilter()) {
@@ -495,7 +504,7 @@
&& mSaveStack.empty()
&& !state->mRoundRectClipState;
- if (CC_LIKELY(mAvoidOverdraw) && mBatches.size() &&
+ if (CC_LIKELY(avoidOverdraw()) && mBatches.size() &&
state->mClipSideFlags != kClipSide_ConservativeFull &&
deferInfo.opaqueOverBounds && state->mBounds.contains(mBounds)) {
// avoid overdraw by resetting drawing state + discarding drawing ops
@@ -647,7 +656,7 @@
// save and restore so that reordering doesn't affect final state
renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- if (CC_LIKELY(mAvoidOverdraw)) {
+ if (CC_LIKELY(avoidOverdraw())) {
for (unsigned int i = 1; i < mBatches.size(); i++) {
if (mBatches[i] && mBatches[i]->coversBounds(mBounds)) {
discardDrawingBatches(i - 1);
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 748bff6..7873fbd 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -83,8 +83,8 @@
class DeferredDisplayList {
friend struct DeferStateStruct; // used to give access to allocator
public:
- DeferredDisplayList(const Rect& bounds, bool avoidOverdraw = true) :
- mBounds(bounds), mAvoidOverdraw(avoidOverdraw) {
+ DeferredDisplayList(const Rect& bounds)
+ : mBounds(bounds) {
clear();
}
~DeferredDisplayList() { clear(); }
@@ -152,7 +152,6 @@
// layer space bounds of rendering
Rect mBounds;
- const bool mAvoidOverdraw;
/**
* At defer time, stores the *defer time* savecount of save/saveLayer ops that were deferred, so
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 38f2363f..7038334 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -47,7 +47,8 @@
}
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
- OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode);
+ mAlpha = PaintUtils::getAlphaDirect(paint);
+ mMode = PaintUtils::getXfermodeDirect(paint);
SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : nullptr;
SkRefCnt_SafeAssign(mColorFilter, colorFilter);
}
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index dc5cb8b..ddfc533 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -172,10 +172,6 @@
void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
bool getQuickRejected() { return mQuickRejected; }
- inline int getPaintAlpha() const {
- return OpenGLRenderer::getAlphaDirect(mPaint);
- }
-
virtual bool hasTextShadow() const {
return false;
}
@@ -213,7 +209,7 @@
if (state.mAlpha != 1.0f) return false;
- SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
+ SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
return (mode == SkXfermode::kSrcOver_Mode ||
mode == SkXfermode::kSrc_Mode);
@@ -249,8 +245,8 @@
virtual bool getLocalBounds(Rect& localBounds) override {
localBounds.set(mLocalBounds);
- OpenGLRenderer::TextShadow textShadow;
- if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
+ PaintUtils::TextShadow textShadow;
+ if (PaintUtils::getTextShadow(mPaint, &textShadow)) {
Rect shadow(mLocalBounds);
shadow.translate(textShadow.dx, textShadow.dx);
shadow.outset(textShadow.radius);
@@ -372,8 +368,8 @@
private:
bool isSaveLayerAlpha() const {
- SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
- int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
+ SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
+ int alpha = PaintUtils::getAlphaDirect(mPaint);
return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
}
@@ -691,7 +687,7 @@
// TODO: support clipped bitmaps by handling them in SET_TEXTURE
deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
!state.mClipSideFlags &&
- OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
+ PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
(mBitmap->colorType() != kAlpha_8_SkColorType);
}
@@ -895,7 +891,7 @@
deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
- OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
+ PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
}
@@ -1241,7 +1237,7 @@
}
virtual bool hasTextShadow() const override {
- return OpenGLRenderer::hasTextShadow(mPaint);
+ return PaintUtils::hasTextShadow(mPaint);
}
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
@@ -1330,7 +1326,7 @@
deferInfo.mergeable = state.mMatrix.isPureTranslate()
&& !hasDecorations
- && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
+ && PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
}
virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 4b9d4f9..ccf0b48 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -667,14 +667,6 @@
return mDrawn;
}
-void FontRenderer::removeFont(const Font* font) {
- mActiveFonts.remove(font->getDescription());
-
- if (mCurrentFont == font) {
- mCurrentFont = nullptr;
- }
-}
-
void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) {
uint32_t intRadius = Blur::convertRadiusToInt(radius);
#ifdef ANDROID_ENABLE_RENDERSCRIPT
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 936c838..8172312 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -147,8 +147,6 @@
float x3, float y3, float u3, float v3,
float x4, float y4, float u4, float v4, CacheTexture* texture);
- void removeFont(const Font* font);
-
void checkTextureUpdate();
void setTextureDirty() {
diff --git a/libs/hwui/Glop.h b/libs/hwui/Glop.h
index fa20b08..4785ea4 100644
--- a/libs/hwui/Glop.h
+++ b/libs/hwui/Glop.h
@@ -135,10 +135,6 @@
} fill;
struct Transform {
- // Orthographic projection matrix for current FBO
- // TODO: move out of Glop, since this is static per FBO
- Matrix4 ortho;
-
// modelView transform, accounting for delta between mesh transform and content of the mesh
// often represents x/y offsets within command, or scaling for mesh unit size
Matrix4 modelView;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index 69559a7..fa166ae 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -461,11 +461,10 @@
// Transform
////////////////////////////////////////////////////////////////////////////////
-void GlopBuilder::setTransform(const Matrix4& ortho, const Matrix4& canvas,
+void GlopBuilder::setTransform(const Matrix4& canvas,
const int transformFlags) {
TRIGGER_STAGE(kTransformStage);
- mOutGlop->transform.ortho = ortho;
mOutGlop->transform.canvas = canvas;
mOutGlop->transform.transformFlags = transformFlags;
}
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index 549bb21..8d05570 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -71,7 +71,7 @@
GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
- setTransform(snapshot.getOrthoMatrix(), *snapshot.transform, transformFlags);
+ setTransform(*snapshot.transform, transformFlags);
return *this;
}
@@ -102,8 +102,7 @@
void setFill(int color, float alphaScale,
SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
const SkShader* shader, const SkColorFilter* colorFilter);
- void setTransform(const Matrix4& ortho, const Matrix4& canvas,
- const int transformFlags);
+ void setTransform(const Matrix4& canvas, const int transformFlags);
enum StageFlags {
kInitialStage = 0,
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 8d85289..f99d92b 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -170,7 +170,8 @@
}
void Layer::setPaint(const SkPaint* paint) {
- OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+ alpha = PaintUtils::getAlphaDirect(paint);
+ mode = PaintUtils::getXfermodeDirect(paint);
setColorFilter((paint) ? paint->getColorFilter() : nullptr);
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a401ce1..9f24e37 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -540,7 +540,7 @@
Rect bounds(left, top, right, bottom);
Rect clip;
calculateLayerBoundsAndClip(bounds, clip, true);
- updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint));
+ updateSnapshotIgnoreForLayer(bounds, clip, true, PaintUtils::getAlphaDirect(paint));
if (!mState.currentlyIgnored()) {
writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f);
@@ -615,7 +615,7 @@
Rect clip;
Rect bounds(left, top, right, bottom);
calculateLayerBoundsAndClip(bounds, clip, fboLayer);
- updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, getAlphaDirect(paint));
+ updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, PaintUtils::getAlphaDirect(paint));
// Bail out if we won't draw in this snapshot
if (mState.currentlyIgnored()) {
@@ -1405,7 +1405,7 @@
setStencilFromClip();
}
- mRenderState.render(glop);
+ mRenderState.render(glop, currentSnapshot()->getOrthoMatrix());
if (type == GlopRenderType::Standard && !mRenderState.stencil().isWriteEnabled()) {
// TODO: specify more clearly when a draw should dirty the layer.
// is writing to the stencil the only time we should ignore this?
@@ -1431,10 +1431,7 @@
return;
}
- // Don't avoid overdraw when visualizing, since that makes it harder to
- // debug where it's coming from, and when the problem occurs.
- bool avoidOverdraw = !Properties::debugOverdraw;
- DeferredDisplayList deferredList(mState.currentClipRect(), avoidOverdraw);
+ DeferredDisplayList deferredList(mState.currentClipRect());
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
renderNode->defer(deferStruct, 0);
@@ -1958,8 +1955,8 @@
FontRenderer& fontRenderer, int alpha, float x, float y) {
mCaches.textureState().activateTexture(0);
- TextShadow textShadow;
- if (!getTextShadow(paint, &textShadow)) {
+ PaintUtils::TextShadow textShadow;
+ if (!PaintUtils::getTextShadow(paint, &textShadow)) {
LOG_ALWAYS_FATAL("failed to query shadow attributes");
}
@@ -1987,8 +1984,10 @@
renderGlop(glop);
}
+// TODO: remove this, once mState.currentlyIgnored captures snapshot alpha
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
- float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
+ float alpha = (PaintUtils::hasTextShadow(paint)
+ ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
return MathUtils::isZero(alpha)
&& PaintUtils::getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
}
@@ -2017,11 +2016,10 @@
FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
fontRenderer.setFont(paint, SkMatrix::I());
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
+ int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
+ SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);
- if (CC_UNLIKELY(hasTextShadow(paint))) {
+ if (CC_UNLIKELY(PaintUtils::hasTextShadow(paint))) {
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, 0.0f, 0.0f);
}
@@ -2162,13 +2160,12 @@
y = floorf(y + transform.getTranslateY() + 0.5f);
}
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
+ int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
+ SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);
FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
- if (CC_UNLIKELY(hasTextShadow(paint))) {
+ if (CC_UNLIKELY(PaintUtils::hasTextShadow(paint))) {
fontRenderer.setFont(paint, SkMatrix::I());
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
alpha, oldX, oldY);
@@ -2238,9 +2235,8 @@
fontRenderer.setFont(paint, SkMatrix::I());
fontRenderer.setTextureFiltering(true);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
+ int alpha = PaintUtils::getAlphaDirect(paint) * currentSnapshot()->alpha;
+ SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(paint);
TextDrawFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint);
const Rect* clip = &writableSnapshot()->getLocalClip();
@@ -2530,12 +2526,6 @@
renderGlop(glop);
}
-void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha,
- SkXfermode::Mode* mode) const {
- getAlphaAndModeDirect(paint, alpha, mode);
- *alpha *= currentSnapshot()->alpha;
-}
-
float OpenGLRenderer::getLayerAlpha(const Layer* layer) const {
return (layer->getAlpha() / 255.0f) * currentSnapshot()->alpha;
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 910af57..400c225 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -260,57 +260,6 @@
void endMark() const;
/**
- * Gets the alpha and xfermode out of a paint object. If the paint is null
- * alpha will be 255 and the xfermode will be SRC_OVER. This method does
- * not multiply the paint's alpha by the current snapshot's alpha, and does
- * not replace the alpha with the overrideLayerAlpha
- *
- * @param paint The paint to extract values from
- * @param alpha Where to store the resulting alpha
- * @param mode Where to store the resulting xfermode
- */
- static inline void getAlphaAndModeDirect(const SkPaint* paint, int* alpha,
- SkXfermode::Mode* mode) {
- *mode = getXfermodeDirect(paint);
- *alpha = getAlphaDirect(paint);
- }
-
- static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) {
- if (!paint) return SkXfermode::kSrcOver_Mode;
- return PaintUtils::getXfermode(paint->getXfermode());
- }
-
- static inline int getAlphaDirect(const SkPaint* paint) {
- if (!paint) return 255;
- return paint->getAlpha();
- }
-
- struct TextShadow {
- SkScalar radius;
- float dx;
- float dy;
- SkColor color;
- };
-
- static inline bool getTextShadow(const SkPaint* paint, TextShadow* textShadow) {
- SkDrawLooper::BlurShadowRec blur;
- if (paint && paint->getLooper() && paint->getLooper()->asABlurShadow(&blur)) {
- if (textShadow) {
- textShadow->radius = Blur::convertSigmaToRadius(blur.fSigma);
- textShadow->dx = blur.fOffset.fX;
- textShadow->dy = blur.fOffset.fY;
- textShadow->color = blur.fColor;
- }
- return true;
- }
- return false;
- }
-
- static inline bool hasTextShadow(const SkPaint* paint) {
- return getTextShadow(paint, nullptr);
- }
-
- /**
* Build the best transform to use to rasterize text given a full
* transform matrix, and whether filteration is needed.
*
@@ -493,16 +442,6 @@
void drawTextureLayer(Layer* layer, const Rect& rect);
/**
- * Gets the alpha and xfermode out of a paint object. If the paint is null
- * alpha will be 255 and the xfermode will be SRC_OVER. Accounts for snapshot alpha.
- *
- * @param paint The paint to extract values from
- * @param alpha Where to store the resulting alpha
- * @param mode Where to store the resulting xfermode
- */
- inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const;
-
- /**
* Gets the alpha from a layer, accounting for snapshot alpha
*
* @param layer The layer from which the alpha is extracted
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index ddc7ecd..bf1b4d0 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -725,7 +725,9 @@
void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) {
if (properties().getAlpha() <= 0.0f
|| properties().getOutline().getAlpha() <= 0.0f
- || !properties().getOutline().getPath()) {
+ || !properties().getOutline().getPath()
+ || properties().getScaleX() == 0
+ || properties().getScaleY() == 0) {
// no shadow to draw
return;
}
@@ -915,7 +917,10 @@
const bool useViewProperties = (!mLayer || drawLayer);
if (useViewProperties) {
const Outline& outline = properties().getOutline();
- if (properties().getAlpha() <= 0 || (outline.getShouldClip() && outline.isEmpty())) {
+ if (properties().getAlpha() <= 0
+ || (outline.getShouldClip() && outline.isEmpty())
+ || properties().getScaleX() == 0
+ || properties().getScaleY() == 0) {
DISPLAY_LIST_LOGD("%*sRejected display list (%p, %s)", handler.level() * 2, "",
this, getName());
return;
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index ad74bff..ce1bd6a 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -52,11 +52,8 @@
bool LayerProperties::setFromPaint(const SkPaint* paint) {
bool changed = false;
- SkXfermode::Mode mode;
- int alpha;
- OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
- changed |= setAlpha(static_cast<uint8_t>(alpha));
- changed |= setXferMode(mode);
+ changed |= setAlpha(static_cast<uint8_t>(PaintUtils::getAlphaDirect(paint)));
+ changed |= setXferMode(PaintUtils::getXfermodeDirect(paint));
changed |= setColorFilter(paint ? paint->getColorFilter() : nullptr);
return changed;
}
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 2209365..eb0fa74 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -73,8 +73,8 @@
}
#if DEBUG_SHADOW
- ALOGD("light center %f %f %f",
- adjustedLightCenter.x, adjustedLightCenter.y, adjustedLightCenter.z);
+ ALOGD("light center %f %f %f %d",
+ adjustedLightCenter.x, adjustedLightCenter.y, adjustedLightCenter.z, lightRadius);
#endif
// light position (because it's in local space) needs to compensate for receiver transform
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 9b0a1aa..bdce73c 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -1051,7 +1051,7 @@
*/
void SpotShadow::dumpPolygon(const Vector3* poly, int polyLength, const char* polyName) {
for (int i = 0; i < polyLength; i++) {
- ALOGD("polygon %s i %d x %f y %f", polyName, i, poly[i].x, poly[i].y);
+ ALOGD("polygon %s i %d x %f y %f z %f", polyName, i, poly[i].x, poly[i].y, poly[i].z);
}
}
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index fb0753b..d680f99 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -61,8 +61,6 @@
}
Font::~Font() {
- mState->removeFont(this);
-
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
delete mCachedGlyphs.valueAt(i);
}
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index c5126de..dfa70ac 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -208,7 +208,7 @@
// Render
///////////////////////////////////////////////////////////////////////////////
-void RenderState::render(const Glop& glop) {
+void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) {
const Glop::Mesh& mesh = glop.mesh;
const Glop::Mesh::Vertices& vertices = mesh.vertices;
const Glop::Mesh::Indices& indices = mesh.indices;
@@ -223,7 +223,7 @@
fill.program->setColor(fill.color);
}
- fill.program->set(glop.transform.ortho,
+ fill.program->set(orthoMatrix,
glop.transform.modelView,
glop.transform.meshTransform(),
glop.transform.transformFlags & TransformFlags::OffsetByFudgeFactor);
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index 4fd792c..9ae0845 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -84,7 +84,7 @@
// more thinking...
void postDecStrong(VirtualLightRefBase* object);
- void render(const Glop& glop);
+ void render(const Glop& glop, const Matrix4& orthoMatrix);
AssetAtlas& assetAtlas() { return mAssetAtlas; }
Blend& blend() { return *mBlend; }
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9dc5b45..ddfd621 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -62,7 +62,7 @@
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
, mJankTracker(thread.timeLord().frameIntervalNanos())
, mProfiler(mFrames)
- , mContentOverdrawProtectionBounds(0, 0, 0, 0) {
+ , mContentDrawBounds(0, 0, 0, 0) {
mRenderNodes.emplace_back(rootRenderNode);
mRenderThread.renderState().registerCanvasContext(this);
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
@@ -309,7 +309,7 @@
Rect outBounds;
// It there are multiple render nodes, they are as follows:
// #0 - backdrop
- // #1 - content (with - and clipped to - bounds mContentOverdrawProtectionBounds)
+ // #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
// #2 - frame
// Usually the backdrop cannot be seen since it will be entirely covered by the content. While
// resizing however it might become partially visible. The following render loop will crop the
@@ -317,66 +317,72 @@
// against the backdrop (since that indicates a shrinking of the window) and then the frame
// around everything.
// The bounds of the backdrop against which the content should be clipped.
- Rect backdropBounds = mContentOverdrawProtectionBounds;
+ Rect backdropBounds = mContentDrawBounds;
+ // Usually the contents bounds should be mContentDrawBounds - however - we will
+ // move it towards the fixed edge to give it a more stable appearance (for the moment).
+ Rect contentBounds;
// If there is no content bounds we ignore the layering as stated above and start with 2.
- int layer = mContentOverdrawProtectionBounds.isEmpty() ? 2 : 0;
+ int layer = (mContentDrawBounds.isEmpty() || mRenderNodes.size() <= 2) ? 2 : 0;
// Draw all render nodes. Note that
for (const sp<RenderNode>& node : mRenderNodes) {
if (layer == 0) { // Backdrop.
- // Draw the backdrop clipped to the inverse content bounds.
+ // Draw the backdrop clipped to the inverse content bounds, but assume that the content
+ // was moved to the upper left corner.
const RenderProperties& properties = node->properties();
Rect targetBounds(properties.getLeft(), properties.getTop(),
properties.getRight(), properties.getBottom());
+ // Move the content bounds towards the fixed corner of the backdrop.
+ const int x = targetBounds.left;
+ const int y = targetBounds.top;
+ contentBounds.set(x, y, x + mContentDrawBounds.getWidth(),
+ y + mContentDrawBounds.getHeight());
// Remember the intersection of the target bounds and the intersection bounds against
// which we have to crop the content.
+ backdropBounds.set(x, y, x + backdropBounds.getWidth(), y + backdropBounds.getHeight());
backdropBounds.intersect(targetBounds);
// Check if we have to draw something on the left side ...
- if (targetBounds.left < mContentOverdrawProtectionBounds.left) {
+ if (targetBounds.left < contentBounds.left) {
mCanvas->save(SkCanvas::kClip_SaveFlag);
if (mCanvas->clipRect(targetBounds.left, targetBounds.top,
- mContentOverdrawProtectionBounds.left, targetBounds.bottom,
+ contentBounds.left, targetBounds.bottom,
SkRegion::kIntersect_Op)) {
mCanvas->drawRenderNode(node.get(), outBounds);
}
// Reduce the target area by the area we have just painted.
- targetBounds.left = std::min(mContentOverdrawProtectionBounds.left,
- targetBounds.right);
+ targetBounds.left = std::min(contentBounds.left, targetBounds.right);
mCanvas->restore();
}
// ... or on the right side ...
- if (targetBounds.right > mContentOverdrawProtectionBounds.right &&
+ if (targetBounds.right > contentBounds.right &&
!targetBounds.isEmpty()) {
mCanvas->save(SkCanvas::kClip_SaveFlag);
- if (mCanvas->clipRect(mContentOverdrawProtectionBounds.right, targetBounds.top,
+ if (mCanvas->clipRect(contentBounds.right, targetBounds.top,
targetBounds.right, targetBounds.bottom,
SkRegion::kIntersect_Op)) {
mCanvas->drawRenderNode(node.get(), outBounds);
}
// Reduce the target area by the area we have just painted.
- targetBounds.right = std::max(targetBounds.left,
- mContentOverdrawProtectionBounds.right);
+ targetBounds.right = std::max(targetBounds.left, contentBounds.right);
mCanvas->restore();
}
// ... or at the top ...
- if (targetBounds.top < mContentOverdrawProtectionBounds.top &&
+ if (targetBounds.top < contentBounds.top &&
!targetBounds.isEmpty()) {
mCanvas->save(SkCanvas::kClip_SaveFlag);
if (mCanvas->clipRect(targetBounds.left, targetBounds.top, targetBounds.right,
- mContentOverdrawProtectionBounds.top,
+ contentBounds.top,
SkRegion::kIntersect_Op)) {
mCanvas->drawRenderNode(node.get(), outBounds);
}
// Reduce the target area by the area we have just painted.
- targetBounds.top = std::min(mContentOverdrawProtectionBounds.top,
- targetBounds.bottom);
+ targetBounds.top = std::min(contentBounds.top, targetBounds.bottom);
mCanvas->restore();
}
// ... or at the bottom.
- if (targetBounds.bottom > mContentOverdrawProtectionBounds.bottom &&
+ if (targetBounds.bottom > contentBounds.bottom &&
!targetBounds.isEmpty()) {
mCanvas->save(SkCanvas::kClip_SaveFlag);
- if (mCanvas->clipRect(targetBounds.left,
- mContentOverdrawProtectionBounds.bottom, targetBounds.right,
+ if (mCanvas->clipRect(targetBounds.left, contentBounds.bottom, targetBounds.right,
targetBounds.bottom, SkRegion::kIntersect_Op)) {
mCanvas->drawRenderNode(node.get(), outBounds);
}
@@ -384,10 +390,17 @@
}
} else if (layer == 1) { // Content
// It gets cropped against the bounds of the backdrop to stay inside.
- mCanvas->save(SkCanvas::kClip_SaveFlag);
- if (mCanvas->clipRect(backdropBounds.left, backdropBounds.top,
- backdropBounds.right, backdropBounds.bottom,
- SkRegion::kIntersect_Op)) {
+ mCanvas->save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+
+ // We shift and clip the content to match its final location in the window.
+ const float left = mContentDrawBounds.left;
+ const float top = mContentDrawBounds.top;
+ const float dx = backdropBounds.left - left;
+ const float dy = backdropBounds.top - top;
+ const float width = backdropBounds.getWidth();
+ const float height = backdropBounds.getHeight();
+ mCanvas->translate(dx, dy);
+ if (mCanvas->clipRect(left, top, left + width, top + height, SkRegion::kIntersect_Op)) {
mCanvas->drawRenderNode(node.get(), outBounds);
}
mCanvas->restore();
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 1c3845c..e0cbabd 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -126,8 +126,8 @@
mRenderNodes.end());
}
- void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
- mContentOverdrawProtectionBounds.set(left, top, right, bottom);
+ void setContentDrawBounds(int left, int top, int right, int bottom) {
+ mContentDrawBounds.set(left, top, right, bottom);
}
private:
@@ -167,7 +167,7 @@
std::set<RenderNode*> mPrefetechedLayers;
// Stores the bounds of the main content.
- Rect mContentOverdrawProtectionBounds;
+ Rect mContentDrawBounds;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index f43a769..26aae90 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -529,15 +529,14 @@
staticPostAndWait(task);
}
-CREATE_BRIDGE5(setContentOverdrawProtectionBounds, CanvasContext* context, int left, int top,
+CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
int right, int bottom) {
- args->context->setContentOverdrawProtectionBounds(args->left, args->top, args->right,
- args->bottom);
+ args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
return nullptr;
}
-void RenderProxy::setContentOverdrawProtectionBounds(int left, int top, int right, int bottom) {
- SETUP_TASK(setContentOverdrawProtectionBounds);
+void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
+ SETUP_TASK(setContentDrawBounds);
args->context = mContext;
args->left = left;
args->top = top;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 046f24a..d1b62f1 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -109,7 +109,7 @@
ANDROID_API void addRenderNode(RenderNode* node, bool placeFront);
ANDROID_API void removeRenderNode(RenderNode* node);
ANDROID_API void drawRenderNode(RenderNode* node);
- ANDROID_API void setContentOverdrawProtectionBounds(int left, int top, int right, int bottom);
+ ANDROID_API void setContentDrawBounds(int left, int top, int right, int bottom);
private:
RenderThread& mRenderThread;
diff --git a/libs/hwui/utils/PaintUtils.h b/libs/hwui/utils/PaintUtils.h
index ba02f5f..d00236e 100644
--- a/libs/hwui/utils/PaintUtils.h
+++ b/libs/hwui/utils/PaintUtils.h
@@ -16,12 +16,19 @@
#ifndef PAINT_UTILS_H
#define PAINT_UTILS_H
+#include <utils/Blur.h>
+
#include <SkColorFilter.h>
+#include <SkDrawLooper.h>
#include <SkXfermode.h>
namespace android {
namespace uirenderer {
+/**
+ * Utility methods for accessing data within SkPaint, and providing defaults
+ * with optional SkPaint pointers.
+ */
class PaintUtils {
public:
@@ -73,6 +80,39 @@
return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
}
+ struct TextShadow {
+ SkScalar radius;
+ float dx;
+ float dy;
+ SkColor color;
+ };
+
+ static inline bool getTextShadow(const SkPaint* paint, TextShadow* textShadow) {
+ SkDrawLooper::BlurShadowRec blur;
+ if (paint && paint->getLooper() && paint->getLooper()->asABlurShadow(&blur)) {
+ if (textShadow) {
+ textShadow->radius = Blur::convertSigmaToRadius(blur.fSigma);
+ textShadow->dx = blur.fOffset.fX;
+ textShadow->dy = blur.fOffset.fY;
+ textShadow->color = blur.fColor;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ static inline bool hasTextShadow(const SkPaint* paint) {
+ return getTextShadow(paint, nullptr);
+ }
+
+ static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) {
+ return paint ? getXfermode(paint->getXfermode()) : SkXfermode::kSrcOver_Mode;
+ }
+
+ static inline int getAlphaDirect(const SkPaint* paint) {
+ return paint ? paint->getAlpha() : 255;
+ }
+
}; // class PaintUtils
} /* namespace uirenderer */
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 54ad60e..4b8f81e 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.util.Log;
+import android.util.MathUtils;
import java.util.Calendar;
import java.util.Collections;
@@ -332,7 +333,14 @@
}
// Skip to the next one.
- parcel.setDataPosition(start + size);
+ try {
+ parcel.setDataPosition(MathUtils.addOrThrow(start, size));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Invalid size: " + e.getMessage());
+ error = true;
+ break;
+ }
+
bytesLeft -= size;
++recCount;
}
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 673a254..7e0649b 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -23,13 +23,6 @@
android:actionViewClass="android.widget.SearchView"
android:imeOptions="actionSearch" />
<item
- android:id="@+id/menu_create_dir"
- android:title="@string/menu_create_dir"
- android:icon="@drawable/ic_menu_new_folder"
- android:alphabeticShortcut="e"
- android:showAsAction="always"
- android:visible="false" />
- <item
android:id="@+id/menu_sort"
android:title="@string/menu_sort"
android:icon="@drawable/ic_menu_sortby"
@@ -63,6 +56,13 @@
android:showAsAction="never"
android:visible="false" />
<item
+ android:id="@+id/menu_create_dir"
+ android:title="@string/menu_create_dir"
+ android:icon="@drawable/ic_menu_new_folder"
+ android:alphabeticShortcut="e"
+ android:showAsAction="always"
+ android:visible="false" />
+ <item
android:id="@+id/menu_paste_from_clipboard"
android:title="@string/menu_paste_from_clipboard"
android:alphabeticShortcut="v"
@@ -70,11 +70,11 @@
android:visible="false" />
<!-- Copy action is defined in mode_directory.xml -->
<item
- android:id="@+id/menu_advanced"
+ android:id="@+id/menu_file_size"
android:showAsAction="never"
android:visible="false" />
<item
- android:id="@+id/menu_file_size"
+ android:id="@+id/menu_advanced"
android:showAsAction="never"
android:visible="false" />
<item
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index c2b6dbc..ba92c00 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Lêers"</string>
<string name="title_open" msgid="4353228937663917801">"Maak oop vanuit"</string>
<string name="title_save" msgid="2433679664882857999">"Stoor na"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Skep vouer"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Roosteraansig"</string>
<string name="menu_list" msgid="7279285939892417279">"Lysaansig"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sorteer volgens"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Kies alles"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopieer na …"</string>
<string name="menu_move" msgid="1828090633118079817">"Skuif na …"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nuwe venster"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopieer"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Plak"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Wys interne berging"</string>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index b82fa93..7fb3b74 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ፋይሎች"</string>
<string name="title_open" msgid="4353228937663917801">"ክፈት ከ"</string>
<string name="title_save" msgid="2433679664882857999">"አስቀምጥ ወደ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"አቃፊ ፍጠር"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"የፍርግርግ እይታ"</string>
<string name="menu_list" msgid="7279285939892417279">"የዝርዝር እይታ"</string>
<string name="menu_sort" msgid="7677740407158414452">"ደርድር በ"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"ሁሉንም ምረጥ"</string>
<string name="menu_copy" msgid="3612326052677229148">"ቅዳ ወደ…"</string>
<string name="menu_move" msgid="1828090633118079817">"ይውሰዱ ወደ..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"አዲሰ መስኮት"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"ቅዳ"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ለጥፍ"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ውስጣዊ ማከማቻ አሳይ"</string>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index c7c9ef2..b61d190 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"الملفات"</string>
<string name="title_open" msgid="4353228937663917801">"فتح من"</string>
<string name="title_save" msgid="2433679664882857999">"حفظ في"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"إنشاء مجلد"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"عرض الشبكة"</string>
<string name="menu_list" msgid="7279285939892417279">"عرض القائمة"</string>
<string name="menu_sort" msgid="7677740407158414452">"ترتيب بحسب"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"تحديد الكل"</string>
<string name="menu_copy" msgid="3612326052677229148">"نسخ إلى…"</string>
<string name="menu_move" msgid="1828090633118079817">"نقل إلى..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"نافذة جديدة"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"نسخ"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"لصق"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"إظهار وحدة التخزين الداخلية"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"نسخ"</string>
<string name="button_move" msgid="2202666023104202232">"نقل"</string>
<string name="button_dismiss" msgid="3714065566893946085">"إزالة"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"إعادة المحاولة"</string>
<string name="sort_name" msgid="9183560467917256779">"بحسب الاسم"</string>
<string name="sort_date" msgid="586080032956151448">"بحسب تاريخ التعديل"</string>
<string name="sort_size" msgid="3350681319735474741">"بحسب الحجم"</string>
diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
index 8c79ceb..dc3827e 100644
--- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml
+++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fayllar"</string>
<string name="title_open" msgid="4353228937663917801">"Vasitəsilə açın"</string>
<string name="title_save" msgid="2433679664882857999">"buraya saxlayın"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Qovluq yaradın"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Torlu görünüş"</string>
<string name="menu_list" msgid="7279285939892417279">"Siyahı görünüşü"</string>
<string name="menu_sort" msgid="7677740407158414452">"Bunlardan biri üzrə sırala"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Hamısını seçin"</string>
<string name="menu_copy" msgid="3612326052677229148">"Buraya kopyalayın:"</string>
<string name="menu_move" msgid="1828090633118079817">"Köçürün…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Yeni pəncərə"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopyalayın"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Yerləşdirin"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Daxili yaddaşı göstərin"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopyala"</string>
<string name="button_move" msgid="2202666023104202232">"Köçürün"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Rədd edin"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Yenidən cəhd edin"</string>
<string name="sort_name" msgid="9183560467917256779">"Ad üzrə"</string>
<string name="sort_date" msgid="586080032956151448">"Tarix üzrə dəyişmiş"</string>
<string name="sort_size" msgid="3350681319735474741">"Ölçü üzrə"</string>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index fdf57d0..e8c5822 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Файлове"</string>
<string name="title_open" msgid="4353228937663917801">"Отваряне от"</string>
<string name="title_save" msgid="2433679664882857999">"Запазване във:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Създаване на папка"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Изглед в мрежа"</string>
<string name="menu_list" msgid="7279285939892417279">"Списъчен изглед"</string>
<string name="menu_sort" msgid="7677740407158414452">"Сортиране по"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Избиране на всичко"</string>
<string name="menu_copy" msgid="3612326052677229148">"Копиране във…"</string>
<string name="menu_move" msgid="1828090633118079817">"Преместване във…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Нов прозорец"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Копиране"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Поставяне"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Вътр. хранилище: Показв."</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Копиране"</string>
<string name="button_move" msgid="2202666023104202232">"Преместване"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Отхвърляне"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Нов опит"</string>
<string name="sort_name" msgid="9183560467917256779">"По име"</string>
<string name="sort_date" msgid="586080032956151448">"По дата на промяната"</string>
<string name="sort_size" msgid="3350681319735474741">"По размер"</string>
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 7caf57f..dc20b16 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ফাইলগুলি"</string>
<string name="title_open" msgid="4353228937663917801">"এখান থেকে খুলুন"</string>
<string name="title_save" msgid="2433679664882857999">"এতে সংরক্ষণ করুন"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ফোল্ডার তৈরি করুন"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"গ্রিড দৃশ্য"</string>
<string name="menu_list" msgid="7279285939892417279">"তালিকা দৃশ্য"</string>
<string name="menu_sort" msgid="7677740407158414452">"এই অনুসারে বাছুন"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"সবগুলি নির্বাচন করুন"</string>
<string name="menu_copy" msgid="3612326052677229148">"এতে অনুলিপি করুন…"</string>
<string name="menu_move" msgid="1828090633118079817">"এতে সরান..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"নতুন উইন্ডো"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"প্রতিলিপি করুন"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"আটকান"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"অভ্যন্তরীণ সঞ্চয়স্থান দেখান"</string>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index ab365ce..ab90f1f 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fitxers"</string>
<string name="title_open" msgid="4353228937663917801">"Obre des de"</string>
<string name="title_save" msgid="2433679664882857999">"Desa a"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Crea una carpeta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Visualització de quadrícula"</string>
<string name="menu_list" msgid="7279285939892417279">"Visualització de llista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordena per"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Selecciona-ho tot"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copia a…"</string>
<string name="menu_move" msgid="1828090633118079817">"Mou a..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Finestra nova"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copia"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Enganxa"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostra emmagatz. intern"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Copia"</string>
<string name="button_move" msgid="2202666023104202232">"Desplaça"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Ignora"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Torna-ho a provar"</string>
<string name="sort_name" msgid="9183560467917256779">"Per nom"</string>
<string name="sort_date" msgid="586080032956151448">"Per data de modificació"</string>
<string name="sort_size" msgid="3350681319735474741">"Per mida"</string>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index 62b313c..9b1b0c8 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Soubory"</string>
<string name="title_open" msgid="4353228937663917801">"Otevřít"</string>
<string name="title_save" msgid="2433679664882857999">"Uložit do"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Vytvořit složku"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Mřížkové zobrazení"</string>
<string name="menu_list" msgid="7279285939892417279">"Zobrazení seznamu"</string>
<string name="menu_sort" msgid="7677740407158414452">"Řadit podle"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Vybrat vše"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopírovat do…"</string>
<string name="menu_move" msgid="1828090633118079817">"Přesunout do…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nové okno"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopírovat"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Vložit"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Zobrazit inter. úložiště"</string>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index c3d7cdd..284d87e 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Filer"</string>
<string name="title_open" msgid="4353228937663917801">"Åbn fra"</string>
<string name="title_save" msgid="2433679664882857999">"Gem i"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Opret mappe"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Gittervisning"</string>
<string name="menu_list" msgid="7279285939892417279">"Listevisning"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortér efter"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Markér alle"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiér til…"</string>
<string name="menu_move" msgid="1828090633118079817">"Flyt til…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nyt vindue"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiér"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Indsæt"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Vis intern lagerplads"</string>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index f88b5c4..1fe53ff 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Dateien"</string>
<string name="title_open" msgid="4353228937663917801">"Öffnen von"</string>
<string name="title_save" msgid="2433679664882857999">"Speichern unter"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Ordner erstellen"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Rasteransicht"</string>
<string name="menu_list" msgid="7279285939892417279">"Listenansicht"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortieren nach"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Alle auswählen"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopieren nach..."</string>
<string name="menu_move" msgid="1828090633118079817">"Verschieben nach…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Neues Fenster"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopieren"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Einfügen"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Int. Speicher anzeigen"</string>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index dcca46c..e9743ee 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Αρχεία"</string>
<string name="title_open" msgid="4353228937663917801">"Άνοιγμα από"</string>
<string name="title_save" msgid="2433679664882857999">"Αποθήκευση σε"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Δημιουργία φακέλου"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Προβολή πλέγματος"</string>
<string name="menu_list" msgid="7279285939892417279">"Προβολή λίστας"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ταξινόμηση κατά"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Επιλογή όλων"</string>
<string name="menu_copy" msgid="3612326052677229148">"Αντιγραφή σε…"</string>
<string name="menu_move" msgid="1828090633118079817">"Μετακίνηση σε..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Νέο παράθυρο"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Αντιγραφή"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Επικόλληση"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Εμφ.εσωτ.χώρου αποθήκ."</string>
diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml
index 26fd30f..03399e2 100644
--- a/packages/DocumentsUI/res/values-en-rAU/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Files"</string>
<string name="title_open" msgid="4353228937663917801">"Open from"</string>
<string name="title_save" msgid="2433679664882857999">"Save to"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Create folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Grid view"</string>
<string name="menu_list" msgid="7279285939892417279">"List view"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sort by"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Select all"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copy to…"</string>
<string name="menu_move" msgid="1828090633118079817">"Move to…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"New window"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copy"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Paste"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Show internal storage"</string>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index 26fd30f..03399e2 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Files"</string>
<string name="title_open" msgid="4353228937663917801">"Open from"</string>
<string name="title_save" msgid="2433679664882857999">"Save to"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Create folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Grid view"</string>
<string name="menu_list" msgid="7279285939892417279">"List view"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sort by"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Select all"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copy to…"</string>
<string name="menu_move" msgid="1828090633118079817">"Move to…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"New window"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copy"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Paste"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Show internal storage"</string>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index 26fd30f..03399e2 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Files"</string>
<string name="title_open" msgid="4353228937663917801">"Open from"</string>
<string name="title_save" msgid="2433679664882857999">"Save to"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Create folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Grid view"</string>
<string name="menu_list" msgid="7279285939892417279">"List view"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sort by"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Select all"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copy to…"</string>
<string name="menu_move" msgid="1828090633118079817">"Move to…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"New window"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copy"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Paste"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Show internal storage"</string>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 6e805b9..cc99d7f 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Archivos"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir desde"</string>
<string name="title_save" msgid="2433679664882857999">"Guardar en"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Crear carpeta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Vista de cuadrícula"</string>
<string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Seleccionar todo"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiar a…"</string>
<string name="menu_move" msgid="1828090633118079817">"Mover a…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Ventana nueva"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiar"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Pegar"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar almacen. interno"</string>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 8fa1d2e..83403e0 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Archivos"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir desde"</string>
<string name="title_save" msgid="2433679664882857999">"Guardar en"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Crear carpeta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Vista de cuadrícula"</string>
<string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Seleccionar todo"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiar en…"</string>
<string name="menu_move" msgid="1828090633118079817">"Mover a…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nueva ventana"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiar"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Pegar"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar almac. interno"</string>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 7008885..b38fcd99 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Failid"</string>
<string name="title_open" msgid="4353228937663917801">"Ava:"</string>
<string name="title_save" msgid="2433679664882857999">"Salvesta:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Loo kaust"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Ruudustikkuva"</string>
<string name="menu_list" msgid="7279285939892417279">"Loendikuva"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortimisalus:"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Vali kõik"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopeeri asukohta ..."</string>
<string name="menu_move" msgid="1828090633118079817">"Teisaldamine kohta ..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Uus aken"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopeeri"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Kleebi"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Kuva sis. salvestusruum"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopeeri"</string>
<string name="button_move" msgid="2202666023104202232">"Teisalda"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Loobu"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Proovi uuesti"</string>
<string name="sort_name" msgid="9183560467917256779">"Nime järgi"</string>
<string name="sort_date" msgid="586080032956151448">"Muutmiskuupäeva järgi"</string>
<string name="sort_size" msgid="3350681319735474741">"Suuruse järgi"</string>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index 17d7c66..9939b1d 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fitxategiak"</string>
<string name="title_open" msgid="4353228937663917801">"Ireki hemendik"</string>
<string name="title_save" msgid="2433679664882857999">"Gorde hemen"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Sortu karpeta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Sareta-ikuspegia"</string>
<string name="menu_list" msgid="7279285939892417279">"Zerrenda-ikuspegia"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordenatzeko irizpidea"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Hautatu guztiak"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiatu hemen…"</string>
<string name="menu_move" msgid="1828090633118079817">"Eraman hona…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Leiho berria"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiatu"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Itsatsi"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Erakutsi barneko memoria"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopiatu"</string>
<string name="button_move" msgid="2202666023104202232">"Mugitu"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Baztertu"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Saiatu berriro"</string>
<string name="sort_name" msgid="9183560467917256779">"Izenaren arabera"</string>
<string name="sort_date" msgid="586080032956151448">"Aldatze-dataren arabera"</string>
<string name="sort_size" msgid="3350681319735474741">"Tamainaren arabera"</string>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index c4f6d58..297e4a1 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"فایلها"</string>
<string name="title_open" msgid="4353228937663917801">"باز کردن از"</string>
<string name="title_save" msgid="2433679664882857999">"ذخیره در"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ایجاد پوشه"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"نمای جدولی"</string>
<string name="menu_list" msgid="7279285939892417279">"نمای فهرستی"</string>
<string name="menu_sort" msgid="7677740407158414452">"مرتبسازی براساس"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"انتخاب همه"</string>
<string name="menu_copy" msgid="3612326052677229148">"کپی در..."</string>
<string name="menu_move" msgid="1828090633118079817">"انتقال به…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"پنجره جدید"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"کپی"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"جایگذاری"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"نمایش فضای ذخیرهسازی داخلی"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"کپی"</string>
<string name="button_move" msgid="2202666023104202232">"انتقال"</string>
<string name="button_dismiss" msgid="3714065566893946085">"نپذیرفتن"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"دوباره امتحان کنید"</string>
<string name="sort_name" msgid="9183560467917256779">"براساس نام"</string>
<string name="sort_date" msgid="586080032956151448">"براساس تاریخ اصلاح"</string>
<string name="sort_size" msgid="3350681319735474741">"براساس اندازه"</string>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 3e87300..a4c742a 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Tiedostot"</string>
<string name="title_open" msgid="4353228937663917801">"Avaa sijainnista"</string>
<string name="title_save" msgid="2433679664882857999">"Tallenna kohteeseen"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Luo kansio"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Ruudukkonäkymä"</string>
<string name="menu_list" msgid="7279285939892417279">"Luettelonäkymä"</string>
<string name="menu_sort" msgid="7677740407158414452">"Lajitteluperuste"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Valitse kaikki"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopioi kohteeseen…"</string>
<string name="menu_move" msgid="1828090633118079817">"Siirrä kohteeseen…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Uusi ikkuna"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopioi"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Liitä"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Näytä sis. tallennustila"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopioi"</string>
<string name="button_move" msgid="2202666023104202232">"Siirrä"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Hylkää"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Yritä uudelleen"</string>
<string name="sort_name" msgid="9183560467917256779">"Nimen mukaan"</string>
<string name="sort_date" msgid="586080032956151448">"Muokkauspäivän mukaan"</string>
<string name="sort_size" msgid="3350681319735474741">"Koon mukaan"</string>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 3e82f34..80cd0b2 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fichiers"</string>
<string name="title_open" msgid="4353228937663917801">"Ouvrir à partir de"</string>
<string name="title_save" msgid="2433679664882857999">"Enregistrer dans"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Créer un dossier"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Grille"</string>
<string name="menu_list" msgid="7279285939892417279">"Liste"</string>
<string name="menu_sort" msgid="7677740407158414452">"Trier par"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Tout sélectionner"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copier vers..."</string>
<string name="menu_move" msgid="1828090633118079817">"Déplacer dans…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nouvelle fenêtre"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copier"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Coller"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Aff. mém. stock. interne"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Copier"</string>
<string name="button_move" msgid="2202666023104202232">"Déplacer"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Faire disparaître"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Réessayer"</string>
<string name="sort_name" msgid="9183560467917256779">"Par nom"</string>
<string name="sort_date" msgid="586080032956151448">"Par date de modification"</string>
<string name="sort_size" msgid="3350681319735474741">"Par taille"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 0512ab1..9616f63 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fichiers"</string>
<string name="title_open" msgid="4353228937663917801">"Ouvrir à partir de"</string>
<string name="title_save" msgid="2433679664882857999">"Enregistrer sous"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Créer un dossier"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Grille"</string>
<string name="menu_list" msgid="7279285939892417279">"Liste"</string>
<string name="menu_sort" msgid="7677740407158414452">"Trier par"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Tout sélectionner"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copier vers…"</string>
<string name="menu_move" msgid="1828090633118079817">"Placer dans…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nouvelle fenêtre"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copier"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Coller"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Aff. mém. stock. interne"</string>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index a1cd614..aebf3a7 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Ficheiros"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir desde"</string>
<string name="title_save" msgid="2433679664882857999">"Gardar en"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Crear cartafol"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Vista de grade"</string>
<string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Seleccionar todo"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiar en…"</string>
<string name="menu_move" msgid="1828090633118079817">"Mover a…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nova ventá"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiar"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Pegar"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar almacen. interno"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Copiar"</string>
<string name="button_move" msgid="2202666023104202232">"Mover"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Ignorar"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Tentar de novo"</string>
<string name="sort_name" msgid="9183560467917256779">"Por nome"</string>
<string name="sort_date" msgid="586080032956151448">"Por data de modificación"</string>
<string name="sort_size" msgid="3350681319735474741">"Por tamaño"</string>
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 059fb2c..9694afa 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ફાઇલો"</string>
<string name="title_open" msgid="4353228937663917801">"અહીંથી ખોલો"</string>
<string name="title_save" msgid="2433679664882857999">"આમાં સાચવો"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ફોલ્ડર બનાવો"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ગ્રિડ દૃશ્ય"</string>
<string name="menu_list" msgid="7279285939892417279">"સૂચિ દૃશ્ય"</string>
<string name="menu_sort" msgid="7677740407158414452">"આ પ્રમાણે સૉર્ટ કરો"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"બધા પસંદ કરો"</string>
<string name="menu_copy" msgid="3612326052677229148">"આના પર કૉપિ કરો…"</string>
<string name="menu_move" msgid="1828090633118079817">"આમાં ખસેડો…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"નવી વિંડો"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"કૉપિ કરો"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"પેસ્ટ કરો"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"આંતરિક સ્ટોરેજ બતાવો"</string>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index 8e33a00..3ee3d8b8 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"फ़ाइलें"</string>
<string name="title_open" msgid="4353228937663917801">"यहां से खोलें"</string>
<string name="title_save" msgid="2433679664882857999">"यहां सहेजें"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"फ़ोल्डर बनाएं"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ग्रिड दृश्य"</string>
<string name="menu_list" msgid="7279285939892417279">"सूची दृश्य"</string>
<string name="menu_sort" msgid="7677740407158414452">"इससे क्रमित करें"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"सभी चुनें"</string>
<string name="menu_copy" msgid="3612326052677229148">"इनकी कॉपी बनाएं..."</string>
<string name="menu_move" msgid="1828090633118079817">"इसमें ले जाएं…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"नई विंडो"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"कॉपी करें"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"चिपकाएं"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"आंतरिक मेमोरी दिखाएं"</string>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index 4774753..9d4393e 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Datoteke"</string>
<string name="title_open" msgid="4353228937663917801">"Otvori iz"</string>
<string name="title_save" msgid="2433679664882857999">"Spremi u"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Izradi mapu"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Prikaz rešetke"</string>
<string name="menu_list" msgid="7279285939892417279">"Prikaz popisa"</string>
<string name="menu_sort" msgid="7677740407158414452">"Poredano po"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Odaberi sve"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiraj u…"</string>
<string name="menu_move" msgid="1828090633118079817">"Premjesti u…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Novi prozor"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiraj"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Zalijepi"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Pokaži internu pohranu"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopiraj"</string>
<string name="button_move" msgid="2202666023104202232">"Premjesti"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Odbaci"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Pokušaj ponovo"</string>
<string name="sort_name" msgid="9183560467917256779">"Po nazivu"</string>
<string name="sort_date" msgid="586080032956151448">"Po datumu izmjene"</string>
<string name="sort_size" msgid="3350681319735474741">"Po veličini"</string>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index 7a521ec..18dcd70 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fájlok"</string>
<string name="title_open" msgid="4353228937663917801">"Megnyitás innen"</string>
<string name="title_save" msgid="2433679664882857999">"Mentés ide"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Mappa létrehozása"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Rács"</string>
<string name="menu_list" msgid="7279285939892417279">"Lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Rendezés"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Összes kijelölése"</string>
<string name="menu_copy" msgid="3612326052677229148">"Másolás ide…"</string>
<string name="menu_move" msgid="1828090633118079817">"Áthelyezés…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Új ablak"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Másolás"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Beillesztés"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Belső tárhely"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Másolás"</string>
<string name="button_move" msgid="2202666023104202232">"Áthelyezés"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Elvetés"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Újrapróbálkozás"</string>
<string name="sort_name" msgid="9183560467917256779">"Név szerint"</string>
<string name="sort_date" msgid="586080032956151448">"Módosítás dátuma szerint"</string>
<string name="sort_size" msgid="3350681319735474741">"Méret szerint"</string>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index 95d73f0..67d7f6a 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Ֆայլեր"</string>
<string name="title_open" msgid="4353228937663917801">"Բացել այստեղից"</string>
<string name="title_save" msgid="2433679664882857999">"Պահել այստեղ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Ստեղծել պանակ"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Ցանցի տեսքով"</string>
<string name="menu_list" msgid="7279285939892417279">"Ցուցակի տեսք"</string>
<string name="menu_sort" msgid="7677740407158414452">"Դասավորել ըստ"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Ընտրել բոլորը"</string>
<string name="menu_copy" msgid="3612326052677229148">"Պատճենել…"</string>
<string name="menu_move" msgid="1828090633118079817">"Տեղափոխում դեպի…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Նոր պատուհան"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Պատճենել"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Տեղադրել"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ցույց տալ ներքին պահոցը"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Պատճենել"</string>
<string name="button_move" msgid="2202666023104202232">"Տեղափոխել"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Փակել"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Փորձել նորից"</string>
<string name="sort_name" msgid="9183560467917256779">"Ըստ անվան"</string>
<string name="sort_date" msgid="586080032956151448">"Ըստ փոփոխման ամսաթվի"</string>
<string name="sort_size" msgid="3350681319735474741">"Ըստ չափի"</string>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 63d415c..a6f69bd 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"File"</string>
<string name="title_open" msgid="4353228937663917801">"Buka dari"</string>
<string name="title_save" msgid="2433679664882857999">"Simpan ke"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Buat folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Tampilan kisi"</string>
<string name="menu_list" msgid="7279285939892417279">"Tampilan daftar"</string>
<string name="menu_sort" msgid="7677740407158414452">"Urutkan menurut"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Pilih semua"</string>
<string name="menu_copy" msgid="3612326052677229148">"Salin ke…"</string>
<string name="menu_move" msgid="1828090633118079817">"Pindahkan ke..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Jendela baru"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Salin"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Tempel"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Tampilkan simpanan internal"</string>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index 0c0e47f..89d2e03 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Skrár"</string>
<string name="title_open" msgid="4353228937663917801">"Opna frá"</string>
<string name="title_save" msgid="2433679664882857999">"Vista í"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Búa til möppu"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Töfluyfirlit"</string>
<string name="menu_list" msgid="7279285939892417279">"Listayfirlit"</string>
<string name="menu_sort" msgid="7677740407158414452">"Raða eftir"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Velja allt"</string>
<string name="menu_copy" msgid="3612326052677229148">"Afrita í ..."</string>
<string name="menu_move" msgid="1828090633118079817">"Færa í…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nýr gluggi"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Afrita"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Líma"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Sýna innbyggða geymslu"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index de129a7..02a111e 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"File"</string>
<string name="title_open" msgid="4353228937663917801">"Apri da"</string>
<string name="title_save" msgid="2433679664882857999">"Salva in"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Crea cartella"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Visualizzazione griglia"</string>
<string name="menu_list" msgid="7279285939892417279">"Visualizzazione elenco"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordina per"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Seleziona tutto"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copia in…"</string>
<string name="menu_move" msgid="1828090633118079817">"Sposta in..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nuova finestra"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copia"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Incolla"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostra memoria interna"</string>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index dbe4630..3d3c489 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"קבצים"</string>
<string name="title_open" msgid="4353228937663917801">"פתח מ-"</string>
<string name="title_save" msgid="2433679664882857999">"שמור ב-"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"צור תיקיה"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"תצוגת רשת"</string>
<string name="menu_list" msgid="7279285939892417279">"תצוגת רשימה"</string>
<string name="menu_sort" msgid="7677740407158414452">"מיין לפי"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"בחר הכל"</string>
<string name="menu_copy" msgid="3612326052677229148">"העתק אל…"</string>
<string name="menu_move" msgid="1828090633118079817">"העברה אל…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"חלון חדש"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"העתק"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"הדבק"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"הצג אחסון פנימי"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"העתק"</string>
<string name="button_move" msgid="2202666023104202232">"העבר"</string>
<string name="button_dismiss" msgid="3714065566893946085">"הסר"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"נסה שוב"</string>
<string name="sort_name" msgid="9183560467917256779">"לפי שם"</string>
<string name="sort_date" msgid="586080032956151448">"לפי תאריך שינוי"</string>
<string name="sort_size" msgid="3350681319735474741">"לפי גודל"</string>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index 45f0ea1..a58c0a5 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ファイル"</string>
<string name="title_open" msgid="4353228937663917801">"次から開く:"</string>
<string name="title_save" msgid="2433679664882857999">"次に保存:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"フォルダを作成"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"グリッド表示"</string>
<string name="menu_list" msgid="7279285939892417279">"リスト表示"</string>
<string name="menu_sort" msgid="7677740407158414452">"並べ替え"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"すべて選択"</string>
<string name="menu_copy" msgid="3612326052677229148">"コピー…"</string>
<string name="menu_move" msgid="1828090633118079817">"移動..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"新しいウィンドウ"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"コピー"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"貼り付け"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"内部ストレージを表示"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"コピー"</string>
<string name="button_move" msgid="2202666023104202232">"移動"</string>
<string name="button_dismiss" msgid="3714065566893946085">"表示しない"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"再試行"</string>
<string name="sort_name" msgid="9183560467917256779">"名前順"</string>
<string name="sort_date" msgid="586080032956151448">"更新日順"</string>
<string name="sort_size" msgid="3350681319735474741">"サイズ順"</string>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 114e73c..cf4b5d6 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ფაილები"</string>
<string name="title_open" msgid="4353228937663917801">"გახსნა აქედან:"</string>
<string name="title_save" msgid="2433679664882857999">"შენახვა აქ:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"საქაღალდის შექმნა"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ბადის ხედი"</string>
<string name="menu_list" msgid="7279285939892417279">"სიის ხედი"</string>
<string name="menu_sort" msgid="7677740407158414452">"სორტირება:"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"ყველას არჩევა"</string>
<string name="menu_copy" msgid="3612326052677229148">"კოპირება…"</string>
<string name="menu_move" msgid="1828090633118079817">"გადაადგილება..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"ახალი ფანჯარა"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"კოპირება"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ჩასმა"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"შიდა საცავის ჩვენება"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"კოპირება"</string>
<string name="button_move" msgid="2202666023104202232">"გადაადგილება"</string>
<string name="button_dismiss" msgid="3714065566893946085">"დახურვა"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"ისევ ცდა"</string>
<string name="sort_name" msgid="9183560467917256779">"სახელით"</string>
<string name="sort_date" msgid="586080032956151448">"ცვლილების თარიღით"</string>
<string name="sort_size" msgid="3350681319735474741">"ზომით"</string>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index af123c6..5ec16a9 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Файлдар"</string>
<string name="title_open" msgid="4353228937663917801">"Мынадан ашу:"</string>
<string name="title_save" msgid="2433679664882857999">"Сақталатын орны"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Қалта жасақтау"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Торлы көрініс"</string>
<string name="menu_list" msgid="7279285939892417279">"Тізім көрінісі"</string>
<string name="menu_sort" msgid="7677740407158414452">"Белгіге қарай сұрыптау"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Барлығын таңдау"</string>
<string name="menu_copy" msgid="3612326052677229148">"Көшіру орны…"</string>
<string name="menu_move" msgid="1828090633118079817">"Орнын ауыстыру…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Жаңа терезе"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Көшіру"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Қою"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ішкі жадты көрсету"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Көшіру"</string>
<string name="button_move" msgid="2202666023104202232">"Жылжыту"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Өшіру"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Әрекетті қайталау"</string>
<string name="sort_name" msgid="9183560467917256779">"Атауы бойынша"</string>
<string name="sort_date" msgid="586080032956151448">"Өзгертілген мерзімі бойынша"</string>
<string name="sort_size" msgid="3350681319735474741">"Өлшемі бойынша"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 8f3feae..7377882 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ឯកសារ"</string>
<string name="title_open" msgid="4353228937663917801">"បើកពី"</string>
<string name="title_save" msgid="2433679664882857999">"រក្សាទុកទៅ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"បង្កើតថត"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាពក្រឡា"</string>
<string name="menu_list" msgid="7279285939892417279">"ទិដ្ឋភាពបញ្ជី"</string>
<string name="menu_sort" msgid="7677740407158414452">"តម្រៀបតាម"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"ជ្រើសរើសទាំងអស់"</string>
<string name="menu_copy" msgid="3612326052677229148">"ថតចម្លងទៅ…"</string>
<string name="menu_move" msgid="1828090633118079817">"ផ្លាស់ទីទៅ៖"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"បង្អួចថ្មី"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"ចម្លង"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"បិទភ្ជាប់"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"បង្ហាញឧបករណ៍ផ្ទុកខាងក្នុង"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"ចម្លង"</string>
<string name="button_move" msgid="2202666023104202232">"ផ្លាស់ទី"</string>
<string name="button_dismiss" msgid="3714065566893946085">"បដិសេធ"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"ព្យាយាមម្ដងទៀត"</string>
<string name="sort_name" msgid="9183560467917256779">"តាមឈ្មោះ"</string>
<string name="sort_date" msgid="586080032956151448">"តាមកាលបរិច្ឆេទបានកែប្រែ"</string>
<string name="sort_size" msgid="3350681319735474741">"តាមទំហំ"</string>
diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
index 826cf1e..a5cad7b 100644
--- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ಫೈಲ್ಗಳು"</string>
<string name="title_open" msgid="4353228937663917801">"ಇದರ ಮೂಲಕ ತೆರೆಯಿರಿ"</string>
<string name="title_save" msgid="2433679664882857999">"ಇವುಗಳಲ್ಲಿ ಉಳಿಸಿ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ಫೋಲ್ಡರ್ ರಚಿಸು"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ಗ್ರಿಡ್ ವೀಕ್ಷಣೆ"</string>
<string name="menu_list" msgid="7279285939892417279">"ಪಟ್ಟಿ ವೀಕ್ಷಣೆ"</string>
<string name="menu_sort" msgid="7677740407158414452">"ಈ ಪ್ರಕಾರ ವಿಂಗಡಿಸು"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"ಎಲ್ಲವನ್ನೂ ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="menu_copy" msgid="3612326052677229148">"ಇದಕ್ಕೆ ನಕಲಿಸಿ…"</string>
<string name="menu_move" msgid="1828090633118079817">"ಇದಕ್ಕೆ ಸರಿಸು…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"ಹೊಸ ವಿಂಡೋ"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"ನಕಲಿಸು"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ಅಂಟಿಸು"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆಯನ್ನು ತೋರಿಸು"</string>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 322b43b..1426bf8 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"파일"</string>
<string name="title_open" msgid="4353228937663917801">"열기:"</string>
<string name="title_save" msgid="2433679664882857999">"저장 위치:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"폴더 만들기"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"바둑판식 보기"</string>
<string name="menu_list" msgid="7279285939892417279">"목록 보기"</string>
<string name="menu_sort" msgid="7677740407158414452">"정렬 기준"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"모두 선택"</string>
<string name="menu_copy" msgid="3612326052677229148">"복사…"</string>
<string name="menu_move" msgid="1828090633118079817">"이동…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"새 창"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"복사"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"붙여넣기"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"내부 저장소 표시"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"복사"</string>
<string name="button_move" msgid="2202666023104202232">"이동"</string>
<string name="button_dismiss" msgid="3714065566893946085">"닫기"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"다시 시도"</string>
<string name="sort_name" msgid="9183560467917256779">"이름순"</string>
<string name="sort_date" msgid="586080032956151448">"수정된 날짜순"</string>
<string name="sort_size" msgid="3350681319735474741">"크기순"</string>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index c8aa69e..c1eadb7 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Файлдар"</string>
<string name="title_open" msgid="4353228937663917801">"Кийинкиден ачуу:"</string>
<string name="title_save" msgid="2433679664882857999">"Кийинкиге сактоо:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Папка түзүү"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Тор көрүнүшү"</string>
<string name="menu_list" msgid="7279285939892417279">"Тизмек көрүнүшү"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ылгоо"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Бардыгын тандоо"</string>
<string name="menu_copy" msgid="3612326052677229148">"Төмөнкүгө көчүрүү…"</string>
<string name="menu_move" msgid="1828090633118079817">"Төмөнкүгө жылдыруу..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Жаңы терезе"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Көчүрүү"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Чаптоо"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ички сактагычты көрсөтүү"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Көчүрүү"</string>
<string name="button_move" msgid="2202666023104202232">"Жылдыруу"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Этибарга албоо"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Дагы аракет кылыңыз"</string>
<string name="sort_name" msgid="9183560467917256779">"Аты боюнча"</string>
<string name="sort_date" msgid="586080032956151448">"Өзгөртүлгөн күнү боюнча"</string>
<string name="sort_size" msgid="3350681319735474741">"Өлчөмү боюнча"</string>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index dedfa05..5c0ffdb 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ໄຟລ໌"</string>
<string name="title_open" msgid="4353228937663917801">"ເປີດຈາກ"</string>
<string name="title_save" msgid="2433679664882857999">"ບັນທຶກໄປທີ່"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ສ້າງໂຟນເດີ"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ມຸມມອງແບບຊ່ອງ"</string>
<string name="menu_list" msgid="7279285939892417279">"ມຸມມອງແບບລາຍຊື່"</string>
<string name="menu_sort" msgid="7677740407158414452">"ຮຽງລຳດັບຕາມ"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"ເລືອກທັງຫມົດ"</string>
<string name="menu_copy" msgid="3612326052677229148">"ອັດສຳເນົາໃສ່…"</string>
<string name="menu_move" msgid="1828090633118079817">"ຍ້າຍໄປໃສ່..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"ໜ້າຈໍໃໝ່"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"ສຳເນົາ"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ວາງໃສ່"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ສະແດງໂຕເກັບຂໍ້ມູນພາຍໃນ"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"ສຳເນົາ"</string>
<string name="button_move" msgid="2202666023104202232">"ຍ້າຍ"</string>
<string name="button_dismiss" msgid="3714065566893946085">"ປິດໄວ້"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"ລອງໃໝ່ອີກ"</string>
<string name="sort_name" msgid="9183560467917256779">"ຕາມຊື່"</string>
<string name="sort_date" msgid="586080032956151448">"ຕາມວັນທີທີ່ແກ້ໄຂ"</string>
<string name="sort_size" msgid="3350681319735474741">"ຕາມຂະໜາດ"</string>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 0c8b443..49774e8c 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Failai"</string>
<string name="title_open" msgid="4353228937663917801">"Atidaryti iš"</string>
<string name="title_save" msgid="2433679664882857999">"Išsaugoti į"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Kurti aplanką"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Tinklelio rodinys"</string>
<string name="menu_list" msgid="7279285939892417279">"Sąrašo rodinys"</string>
<string name="menu_sort" msgid="7677740407158414452">"Rūšiuoti pagal"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Pasirinkti viską"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopijuoti į..."</string>
<string name="menu_move" msgid="1828090633118079817">"Perkelti į…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Naujas langas"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopijuoti"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Įklijuoti"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Rodyti vidinę atmintį"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopijuoti"</string>
<string name="button_move" msgid="2202666023104202232">"Perkelti"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Atsisakyti"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Bandyti dar kartą"</string>
<string name="sort_name" msgid="9183560467917256779">"Pagal pavadinimą"</string>
<string name="sort_date" msgid="586080032956151448">"Pagal keitimo datą"</string>
<string name="sort_size" msgid="3350681319735474741">"Pagal dydį"</string>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 5c79554..9cb3425 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Faili"</string>
<string name="title_open" msgid="4353228937663917801">"Atvēršana no:"</string>
<string name="title_save" msgid="2433679664882857999">"Saglabāšana:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Izveidot mapi"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Režģis"</string>
<string name="menu_list" msgid="7279285939892417279">"Saraksts"</string>
<string name="menu_sort" msgid="7677740407158414452">"Kārtot pēc"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Atlasīt visus"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopēt…"</string>
<string name="menu_move" msgid="1828090633118079817">"Pārvietot uz…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Jauns logs"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopēt"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Ielīmēt"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Rādīt iekšējo atmiņu"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopēt"</string>
<string name="button_move" msgid="2202666023104202232">"Pārvietot"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Noraidīt"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Mēģināt vēlreiz"</string>
<string name="sort_name" msgid="9183560467917256779">"Pēc nosaukuma"</string>
<string name="sort_date" msgid="586080032956151448">"Pēc pārveidošanas datuma"</string>
<string name="sort_size" msgid="3350681319735474741">"Pēc lieluma"</string>
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index b2cb9f1..149d0d4 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Датотеки"</string>
<string name="title_open" msgid="4353228937663917801">"Отвори од"</string>
<string name="title_save" msgid="2433679664882857999">"Зачувај во"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Создади папка"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Приказ на мрежа"</string>
<string name="menu_list" msgid="7279285939892417279">"Приказ на список"</string>
<string name="menu_sort" msgid="7677740407158414452">"Подреди по"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Избери ги сите"</string>
<string name="menu_copy" msgid="3612326052677229148">"Копирај во…"</string>
<string name="menu_move" msgid="1828090633118079817">"Премести во..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Нов прозорец"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Копирај"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Залепи"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Прикажи внатрешна мемор."</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Копирај"</string>
<string name="button_move" msgid="2202666023104202232">"Премести"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Отфрли"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Обиди се пак"</string>
<string name="sort_name" msgid="9183560467917256779">"По име"</string>
<string name="sort_date" msgid="586080032956151448">"Изменети по датум"</string>
<string name="sort_size" msgid="3350681319735474741">"По големина"</string>
diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
index 07efa66..c621359 100644
--- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ഫയലുകൾ"</string>
<string name="title_open" msgid="4353228937663917801">"ഇതിൽ നിന്നും തുറക്കുക"</string>
<string name="title_save" msgid="2433679664882857999">"ഇതില് സംരക്ഷിക്കുക"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ഫോൾഡർ സൃഷ്ടിക്കുക"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ഗ്രിഡ് കാഴ്ച"</string>
<string name="menu_list" msgid="7279285939892417279">"ലിസ്റ്റ് കാഴ്ച"</string>
<string name="menu_sort" msgid="7677740407158414452">"ഇപ്രകാരം അടുക്കുക"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"എല്ലാം തിരഞ്ഞെടുക്കുക"</string>
<string name="menu_copy" msgid="3612326052677229148">"ഇതിൽ പകർത്തുക…"</string>
<string name="menu_move" msgid="1828090633118079817">"ഇതിലേക്ക് നീക്കുക..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"പുതിയ വിന്ഡോ"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"പകര്ത്തുക"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ഒട്ടിക്കുക"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ആന്തരിക സ്റ്റോറേജ് കാണിക്കുക"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"പകര്ത്തുക"</string>
<string name="button_move" msgid="2202666023104202232">"നീക്കുക"</string>
<string name="button_dismiss" msgid="3714065566893946085">"ഡിസ്മിസ് ചെയ്യുക"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"വീണ്ടും ശ്രമിക്കുക"</string>
<string name="sort_name" msgid="9183560467917256779">"പേര് പ്രകാരം"</string>
<string name="sort_date" msgid="586080032956151448">"പരിഷ്ക്കരിച്ച തീയതി പ്രകാരം"</string>
<string name="sort_size" msgid="3350681319735474741">"വലുപ്പം പ്രകാരം"</string>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index d45778c..fb7503e 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Файл"</string>
<string name="title_open" msgid="4353228937663917801">"Нээх"</string>
<string name="title_save" msgid="2433679664882857999">"Хадгалах"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Фолдер үүсгэх"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Эгнүүлж харах"</string>
<string name="menu_list" msgid="7279285939892417279">"Жагсааж харах"</string>
<string name="menu_sort" msgid="7677740407158414452">"Эрэмбэлэх"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Бүгдийг сонгох"</string>
<string name="menu_copy" msgid="3612326052677229148">"...руу хуулах"</string>
<string name="menu_move" msgid="1828090633118079817">"Байршуулах газар"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Шинэ цонх"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Хуулах"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Буулгах"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Дотоод санг харуулах"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Хуулах"</string>
<string name="button_move" msgid="2202666023104202232">"Зөөх"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Алгасах"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Дахин оролдоно уу"</string>
<string name="sort_name" msgid="9183560467917256779">"Нэрээр"</string>
<string name="sort_date" msgid="586080032956151448">"Өөрчлөгдсөн огноогоор"</string>
<string name="sort_size" msgid="3350681319735474741">"Хэмжээгээр"</string>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index 8d70143..8d5885a 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"फायली"</string>
<string name="title_open" msgid="4353228937663917801">"वरून उघडा"</string>
<string name="title_save" msgid="2433679664882857999">"येथे जतन करा"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"फोल्डर तयार करा"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ग्रिड दृश्य"</string>
<string name="menu_list" msgid="7279285939892417279">"सूची"</string>
<string name="menu_sort" msgid="7677740407158414452">"नुसार क्रमवारी लावा"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"सर्व निवडा"</string>
<string name="menu_copy" msgid="3612326052677229148">"यावर कॉपी करा…"</string>
<string name="menu_move" msgid="1828090633118079817">"यावर हलवा…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"नवीन विंडो"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"कॉपी करा"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"पेस्ट करा"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"अंतर्गत संचयन दर्शवा"</string>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 2250109..6904e10 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fail"</string>
<string name="title_open" msgid="4353228937663917801">"Buka dari"</string>
<string name="title_save" msgid="2433679664882857999">"Simpan ke"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Buat folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Paparan grid"</string>
<string name="menu_list" msgid="7279285939892417279">"Paparan senarai"</string>
<string name="menu_sort" msgid="7677740407158414452">"Isih mengikut"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Pilih semua"</string>
<string name="menu_copy" msgid="3612326052677229148">"Salin ke..."</string>
<string name="menu_move" msgid="1828090633118079817">"Alihkan ke…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Tetingkap baharu"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Salin"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Tampal"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Papar storan dalaman"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Salin"</string>
<string name="button_move" msgid="2202666023104202232">"Alihkan"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Tolak"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Cuba Lagi"</string>
<string name="sort_name" msgid="9183560467917256779">"Mengikut nama"</string>
<string name="sort_date" msgid="586080032956151448">"Mengikut tarikh diubah"</string>
<string name="sort_size" msgid="3350681319735474741">"Mengikut saiz"</string>
diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml
index 480c27b..f3ed0f7 100644
--- a/packages/DocumentsUI/res/values-my-rMM/strings.xml
+++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ဖိုင်များ"</string>
<string name="title_open" msgid="4353228937663917801">"မှ ဖွင့်ပါ"</string>
<string name="title_save" msgid="2433679664882857999">"သို့ သိမ်းပါ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"အကန့် တည်ဆောက်ရန်"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ဖယားကွက်မြင်ကွင်း"</string>
<string name="menu_list" msgid="7279285939892417279">"အစဉ်လိုက်မြင်ကွင်း"</string>
<string name="menu_sort" msgid="7677740407158414452">"အစဉ်အလိုက် စီခြင်း"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"အားလုံးကို ရွေးရန်"</string>
<string name="menu_copy" msgid="3612326052677229148">"သို့ကူးယူရန်…"</string>
<string name="menu_move" msgid="1828090633118079817">"...သို့ ရွှေ့ရန်"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"ဝင်းဒိုးသစ်"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"ကူးယူရန်"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ကပ်ရန်"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"စက်ရှိစတိုရုံ ပြပါ"</string>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 48355aa..5f71805 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Filer"</string>
<string name="title_open" msgid="4353228937663917801">"Åpne fra"</string>
<string name="title_save" msgid="2433679664882857999">"Lagre i"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Opprett en mappe"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Rutenettvisning"</string>
<string name="menu_list" msgid="7279285939892417279">"Listevisning"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortér etter"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Markér alt"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiér til …"</string>
<string name="menu_move" msgid="1828090633118079817">"Flytt til"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nytt vindu"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiér"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Lim inn"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Vis den interne lagringen"</string>
diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
index 53942c1..1bc6a29 100644
--- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml
+++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"फाइलहरू"</string>
<string name="title_open" msgid="4353228937663917801">"यसबाट खोल्नुहोस्"</string>
<string name="title_save" msgid="2433679664882857999">"यसमा सुरक्षित गर्नुहोस्"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"फोल्डर सिर्जना गर्नुहोस्"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ग्रिड दृश्य"</string>
<string name="menu_list" msgid="7279285939892417279">"सूची दृश्य"</string>
<string name="menu_sort" msgid="7677740407158414452">"यसद्वारा क्रमवद्घ गर्नुहोस्"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"सबै चयन गर्नुहोस्"</string>
<string name="menu_copy" msgid="3612326052677229148">"यसमा प्रतिलिपि गर्नुहोस् ..."</string>
<string name="menu_move" msgid="1828090633118079817">"…मा सार्नुहोस्"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"नयाँ विन्डो"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"प्रतिलिपि बनाउनुहोस्"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"टाँस्नुहोस्"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"आन्तरिक भण्डारण देखाउनुहोस्"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"प्रतिलिपि बनाउनुहोस्"</string>
<string name="button_move" msgid="2202666023104202232">"सार्नुहोस्"</string>
<string name="button_dismiss" msgid="3714065566893946085">"खारेज गर्नुहोस्"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"पुन: प्रयास गर्नुहोस्"</string>
<string name="sort_name" msgid="9183560467917256779">"नाम अनुसार"</string>
<string name="sort_date" msgid="586080032956151448">"परिमार्जित मिति अनुसार"</string>
<string name="sort_size" msgid="3350681319735474741">"आकार अनुसार"</string>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index d3e6bbe..79a6de9 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Bestanden"</string>
<string name="title_open" msgid="4353228937663917801">"Openen vanuit"</string>
<string name="title_save" msgid="2433679664882857999">"Opslaan in"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Map maken"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Rasterweergave"</string>
<string name="menu_list" msgid="7279285939892417279">"Lijstweergave"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sorteren op"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Alles selecteren"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiëren naar…"</string>
<string name="menu_move" msgid="1828090633118079817">"Verplaatsen naar…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nieuw venster"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiëren"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Plakken"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Interne opslag weergeven"</string>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 3b14396..c4fe4e4 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ਫਾਈਲਾਂ"</string>
<string name="title_open" msgid="4353228937663917801">"ਤੋਂ ਖੋਲ੍ਹੋ"</string>
<string name="title_save" msgid="2433679664882857999">"ਇਸ ਵਿੱਚ ਸੁਰੱਖਿਅਤ ਕਰੋ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ਫੋਲਡਰ ਬਣਾਓ"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ਗ੍ਰਿਡ ਵਿਊ"</string>
<string name="menu_list" msgid="7279285939892417279">"ਸੂਚੀ ਦ੍ਰਿਸ਼"</string>
<string name="menu_sort" msgid="7677740407158414452">"ਇਸ ਅਨੁਸਾਰ ਛਾਂਟੋ"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"ਸਾਰੇ ਚੁਣੋ"</string>
<string name="menu_copy" msgid="3612326052677229148">"ਇਸ ਵਿੱਚ ਕਾਪੀ ਕਰੋ…"</string>
<string name="menu_move" msgid="1828090633118079817">"ਇਸ ਵਿੱਚ ਮੂਵ ਕਰੋ..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"ਨਵੀਂ ਵਿੰਡੋ"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"ਕਾਪੀ ਕਰੋ"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ਪੇਸਟ ਕਰੋ"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਦਿਖਾਓ"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"ਕਾਪੀ ਕਰੋ"</string>
<string name="button_move" msgid="2202666023104202232">"ਮੂਵ ਕਰੋ"</string>
<string name="button_dismiss" msgid="3714065566893946085">"ਬਰਖਾਸਤ ਕਰੋ"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="sort_name" msgid="9183560467917256779">"ਨਾਮ ਮੁਤਾਬਕ"</string>
<string name="sort_date" msgid="586080032956151448">"ਤਾਰੀਖ ਮੁਤਾਬਕ ਸੰਸ਼ੋਧਿਤ"</string>
<string name="sort_size" msgid="3350681319735474741">"ਆਕਾਰ ਮੁਤਾਬਕ"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 3e4ef68..30b0806 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Pliki"</string>
<string name="title_open" msgid="4353228937663917801">"Otwórz z"</string>
<string name="title_save" msgid="2433679664882857999">"Zapisz w"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Utwórz folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Widok siatki"</string>
<string name="menu_list" msgid="7279285939892417279">"Widok listy"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortuj według"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Zaznacz wszystko"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiuj do…"</string>
<string name="menu_move" msgid="1828090633118079817">"Przenieś do…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nowe okno"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiuj"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Wklej"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Pokaż pamięć wewnętrzną"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopiuj"</string>
<string name="button_move" msgid="2202666023104202232">"Przenieś"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Zamknij"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Spróbuj ponownie"</string>
<string name="sort_name" msgid="9183560467917256779">"Według nazwy"</string>
<string name="sort_date" msgid="586080032956151448">"Według daty edycji"</string>
<string name="sort_size" msgid="3350681319735474741">"Według rozmiaru"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index ca984cf..0233e3d 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Arquivos"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir de"</string>
<string name="title_save" msgid="2433679664882857999">"Salvar em"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Criar pasta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Visualização em grade"</string>
<string name="menu_list" msgid="7279285939892417279">"Visualização em lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Classificar por"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Selecionar tudo"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiar para..."</string>
<string name="menu_move" msgid="1828090633118079817">"Mover para..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nova janela"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiar"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Colar"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar armaz. interno"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index ab67358..0c41a91 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Ficheiros"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir de"</string>
<string name="title_save" msgid="2433679664882857999">"Guardar em"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Criar pasta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Vista de grelha"</string>
<string name="menu_list" msgid="7279285939892417279">"Vista de lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Ordenar por"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Selecionar tudo"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiar para…"</string>
<string name="menu_move" msgid="1828090633118079817">"Mover para..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nova janela"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiar"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Colar"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar mem. armaz. int."</string>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index ca984cf..0233e3d 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Arquivos"</string>
<string name="title_open" msgid="4353228937663917801">"Abrir de"</string>
<string name="title_save" msgid="2433679664882857999">"Salvar em"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Criar pasta"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Visualização em grade"</string>
<string name="menu_list" msgid="7279285939892417279">"Visualização em lista"</string>
<string name="menu_sort" msgid="7677740407158414452">"Classificar por"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Selecionar tudo"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiar para..."</string>
<string name="menu_move" msgid="1828090633118079817">"Mover para..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nova janela"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiar"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Colar"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Mostrar armaz. interno"</string>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index e927b78..27734d5 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fișiere"</string>
<string name="title_open" msgid="4353228937663917801">"Deschideți din"</string>
<string name="title_save" msgid="2433679664882857999">"Salvați în"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Creați un dosar"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Afișare tip grilă"</string>
<string name="menu_list" msgid="7279285939892417279">"Afișare tip listă"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortați după"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Selectați tot"</string>
<string name="menu_copy" msgid="3612326052677229148">"Copiați în…"</string>
<string name="menu_move" msgid="1828090633118079817">"Mutați în…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Fereastră nouă"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Copiați"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Inserați"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Afișați stocarea internă"</string>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index cdf20ca..152992e 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Файлы"</string>
<string name="title_open" msgid="4353228937663917801">"Открыть"</string>
<string name="title_save" msgid="2433679664882857999">"Сохранить"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Новая папка"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Сетка"</string>
<string name="menu_list" msgid="7279285939892417279">"Список"</string>
<string name="menu_sort" msgid="7677740407158414452">"Сортировать"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Выбрать все"</string>
<string name="menu_copy" msgid="3612326052677229148">"Копировать в…"</string>
<string name="menu_move" msgid="1828090633118079817">"Переместить"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Новое окно"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Копировать"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Вставить"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Внутренняя память"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Копировать"</string>
<string name="button_move" msgid="2202666023104202232">"Переместить"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Скрыть"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Повторить"</string>
<string name="sort_name" msgid="9183560467917256779">"По названию"</string>
<string name="sort_date" msgid="586080032956151448">"По дате изменения"</string>
<string name="sort_size" msgid="3350681319735474741">"По размеру"</string>
diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml
index 138f8a6..a8165a1 100644
--- a/packages/DocumentsUI/res/values-si-rLK/strings.xml
+++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ගොනු"</string>
<string name="title_open" msgid="4353228937663917801">"විවෘත වන්නේ"</string>
<string name="title_save" msgid="2433679664882857999">"සුරකින්නේ"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ෆෝල්ඩරයක් සාදන්න"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"ජාල පෙනුම"</string>
<string name="menu_list" msgid="7279285939892417279">"ලැයිස්තු පෙනුම"</string>
<string name="menu_sort" msgid="7677740407158414452">"අනුපිළිවෙලට සකසා ඇත්තේ"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"සියල්ල තෝරන්න"</string>
<string name="menu_copy" msgid="3612326052677229148">"වෙත පිටපත් කරන්න..."</string>
<string name="menu_move" msgid="1828090633118079817">"වෙත ගෙනයන්න..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"නව කවුළුව"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"පිටපත් කරන්න"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"අලවන්න"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"අභ්යන්තර ආචයනය පෙන්වන්න"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"පිටපත් කිරීම"</string>
<string name="button_move" msgid="2202666023104202232">"ගෙන යන්න"</string>
<string name="button_dismiss" msgid="3714065566893946085">"ඉවතලන්න"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"නැවත උත්සාහ කරන්න"</string>
<string name="sort_name" msgid="9183560467917256779">"නමින්"</string>
<string name="sort_date" msgid="586080032956151448">"වෙනස් කරන ලද දිනයෙන්"</string>
<string name="sort_size" msgid="3350681319735474741">"ප්රමාණය මගින්"</string>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 4310819..3441f26 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Súbory"</string>
<string name="title_open" msgid="4353228937663917801">"Otvoriť z"</string>
<string name="title_save" msgid="2433679664882857999">"Uložiť do"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Vytvoriť priečinok"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Zobrazenie mriežky"</string>
<string name="menu_list" msgid="7279285939892417279">"Zobrazenie zoznamu"</string>
<string name="menu_sort" msgid="7677740407158414452">"Zoradiť podľa"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Vybrať všetko"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopírovať do…"</string>
<string name="menu_move" msgid="1828090633118079817">"Presunúť do…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nové okno"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopírovať"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Prilepiť"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Zobraziť interné úložisko"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopírovať"</string>
<string name="button_move" msgid="2202666023104202232">"Presunúť"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Odmietnuť"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Skúsiť znova"</string>
<string name="sort_name" msgid="9183560467917256779">"Podľa názvu"</string>
<string name="sort_date" msgid="586080032956151448">"Podľa dátumu zmeny"</string>
<string name="sort_size" msgid="3350681319735474741">"Podľa veľkosti"</string>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index c9982a7..fe36664 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Datoteke"</string>
<string name="title_open" msgid="4353228937663917801">"Odpri iz mape"</string>
<string name="title_save" msgid="2433679664882857999">"Shrani v"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Ustvarjanje mape"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Mrežni pogled"</string>
<string name="menu_list" msgid="7279285939892417279">"Pogled seznama"</string>
<string name="menu_sort" msgid="7677740407158414452">"Razvrsti glede na"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Izberi vse"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiraj v …"</string>
<string name="menu_move" msgid="1828090633118079817">"Premakni v ..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Novo okno"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiraj"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Prilepi"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Pokaži notranjo shrambo"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopiraj"</string>
<string name="button_move" msgid="2202666023104202232">"Premik"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Opusti"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Poskusite znova"</string>
<string name="sort_name" msgid="9183560467917256779">"Po imenu"</string>
<string name="sort_date" msgid="586080032956151448">"Po datumu spremembe"</string>
<string name="sort_size" msgid="3350681319735474741">"Po velikosti"</string>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index f1ee1bc..18794f5 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Skedarët"</string>
<string name="title_open" msgid="4353228937663917801">"Hap nga"</string>
<string name="title_save" msgid="2433679664882857999">"Ruaje te"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Krijo dosje"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Pamje rrjete"</string>
<string name="menu_list" msgid="7279285939892417279">"Pamje liste"</string>
<string name="menu_sort" msgid="7677740407158414452">"Rendit sipas"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Zgjidhi të gjitha"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopjo te..."</string>
<string name="menu_move" msgid="1828090633118079817">"Zhvendos te..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Dritare e re"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopjo"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Ngjit"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Trego hapësirën e brendshme ruajtëse"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopjo"</string>
<string name="button_move" msgid="2202666023104202232">"Zhvendos"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Largoje"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Provo sërish"</string>
<string name="sort_name" msgid="9183560467917256779">"Sipas emrit"</string>
<string name="sort_date" msgid="586080032956151448">"Sipas datës së modifikimit"</string>
<string name="sort_size" msgid="3350681319735474741">"Sipas madhësisë"</string>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index c5116c2..fa047f2 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Датотеке"</string>
<string name="title_open" msgid="4353228937663917801">"Отвори са"</string>
<string name="title_save" msgid="2433679664882857999">"Сачувај у"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Направи директоријум"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Приказ мреже"</string>
<string name="menu_list" msgid="7279285939892417279">"Приказ листе"</string>
<string name="menu_sort" msgid="7677740407158414452">"Сортирај према"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Изабери све"</string>
<string name="menu_copy" msgid="3612326052677229148">"Копирај на..."</string>
<string name="menu_move" msgid="1828090633118079817">"Премести у..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Нови прозор"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Копирај"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Налепи"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Прикажи интерну меморију"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Копирај"</string>
<string name="button_move" msgid="2202666023104202232">"Премести"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Одбаци"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Покушај поново"</string>
<string name="sort_name" msgid="9183560467917256779">"Према имену"</string>
<string name="sort_date" msgid="586080032956151448">"Према датуму измене"</string>
<string name="sort_size" msgid="3350681319735474741">"Према величини"</string>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 06e6514..5ac8691 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Filer"</string>
<string name="title_open" msgid="4353228937663917801">"Öppna från"</string>
<string name="title_save" msgid="2433679664882857999">"Spara till"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Skapa mapp"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Rutnätsvy"</string>
<string name="menu_list" msgid="7279285939892417279">"Listvy"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sortera efter"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Markera allt"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopiera till …"</string>
<string name="menu_move" msgid="1828090633118079817">"Flytta till ..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Nytt fönster"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopiera"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Klistra in"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Visa internminne"</string>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index 79bae1f..3daa18e 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Faili"</string>
<string name="title_open" msgid="4353228937663917801">"Fungua kutoka"</string>
<string name="title_save" msgid="2433679664882857999">"Hifadhi kwenye"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Unda folda"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Mwonekano gridi"</string>
<string name="menu_list" msgid="7279285939892417279">"Mwonekano orodha"</string>
<string name="menu_sort" msgid="7677740407158414452">"Panga kwa"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Chagua zote"</string>
<string name="menu_copy" msgid="3612326052677229148">"Nakili kwenda..."</string>
<string name="menu_move" msgid="1828090633118079817">"Hamisha hadi..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Dirisha jipya"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Nakili"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Bandika"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Onyesha hifadhi ya ndani"</string>
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 117aabc..14fa702 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"கோப்புகள்"</string>
<string name="title_open" msgid="4353228937663917801">"இதில் திற"</string>
<string name="title_save" msgid="2433679664882857999">"இதில் சேமி"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"கோப்புறையை உருவாக்கு"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"கட்டக் காட்சி"</string>
<string name="menu_list" msgid="7279285939892417279">"பட்டியல்"</string>
<string name="menu_sort" msgid="7677740407158414452">"இதன்படி வரிசைப்படுத்து"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"எல்லாவற்றையும் தேர்ந்தெடு"</string>
<string name="menu_copy" msgid="3612326052677229148">"இங்கு நகலெடு…"</string>
<string name="menu_move" msgid="1828090633118079817">"இதற்கு நகர்த்து…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"புதிய சாளரம்"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"நகலெடு"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"ஒட்டு"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"அகச் சேமிப்பகத்தைக் காட்டு"</string>
diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml
index 21b7f58..17c0066 100644
--- a/packages/DocumentsUI/res/values-te-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ఫైల్లు"</string>
<string name="title_open" msgid="4353228937663917801">"ఇక్కడి నుండి తెరువు"</string>
<string name="title_save" msgid="2433679664882857999">"ఇందులో సేవ్ చేయి"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"ఫోల్డర్ను సృష్టించు"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"గ్రిడ్ వీక్షణ"</string>
<string name="menu_list" msgid="7279285939892417279">"జాబితా వీక్షణ"</string>
<string name="menu_sort" msgid="7677740407158414452">"ఇలా క్రమబద్ధీకరించు"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"అన్నీ ఎంచుకోండి"</string>
<string name="menu_copy" msgid="3612326052677229148">"ఇక్కడికి కాపీ చేయి…"</string>
<string name="menu_move" msgid="1828090633118079817">"దీనికి తరలించు..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"కొత్త విండో"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"కాపీ చేయి"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"అతికించు"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"అంతర్గత నిల్వను చూపు"</string>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 8a49708..47e12b6 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"ไฟล์"</string>
<string name="title_open" msgid="4353228937663917801">"เปิดจาก"</string>
<string name="title_save" msgid="2433679664882857999">"บันทึกไปยัง"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"สร้างโฟลเดอร์"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"มุมมองตาราง"</string>
<string name="menu_list" msgid="7279285939892417279">"มุมมองรายการ"</string>
<string name="menu_sort" msgid="7677740407158414452">"จัดเรียงตาม"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"เลือกทั้งหมด"</string>
<string name="menu_copy" msgid="3612326052677229148">"คัดลอกไปยัง…"</string>
<string name="menu_move" msgid="1828090633118079817">"ย้ายไปที่…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"หน้าต่างใหม่"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"คัดลอก"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"วาง"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"แสดงที่จัดเก็บภายใน"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"คัดลอก"</string>
<string name="button_move" msgid="2202666023104202232">"ย้าย"</string>
<string name="button_dismiss" msgid="3714065566893946085">"ปิด"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"ลองอีกครั้ง"</string>
<string name="sort_name" msgid="9183560467917256779">"ตามชื่อ"</string>
<string name="sort_date" msgid="586080032956151448">"ตามวันที่ที่ปรับเปลี่ยน"</string>
<string name="sort_size" msgid="3350681319735474741">"ตามขนาด"</string>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 5c0dc12..b09820c 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Mga File"</string>
<string name="title_open" msgid="4353228937663917801">"Buksan mula sa"</string>
<string name="title_save" msgid="2433679664882857999">"I-save sa"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Gumawa ng folder"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"View na grid"</string>
<string name="menu_list" msgid="7279285939892417279">"View na listahan"</string>
<string name="menu_sort" msgid="7677740407158414452">"Uriin ayon sa"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Piliin lahat"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopyahin sa..."</string>
<string name="menu_move" msgid="1828090633118079817">"Ilipat sa…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Bagong window"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopyahin"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"I-paste"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ipakita internal storage"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopyahin"</string>
<string name="button_move" msgid="2202666023104202232">"Ilipat"</string>
<string name="button_dismiss" msgid="3714065566893946085">"I-dismiss"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Subukang Muli"</string>
<string name="sort_name" msgid="9183560467917256779">"Ayon sa pangalan"</string>
<string name="sort_date" msgid="586080032956151448">"Ayon sa petsa ng pagbago"</string>
<string name="sort_size" msgid="3350681319735474741">"Ayon sa laki"</string>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 092b38e..50fa357 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Dosyalar"</string>
<string name="title_open" msgid="4353228937663917801">"Şuradan aç:"</string>
<string name="title_save" msgid="2433679664882857999">"Şuraya kaydet:"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Klasör oluştur"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Tablo görünümü"</string>
<string name="menu_list" msgid="7279285939892417279">"Liste görünümü"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sıralama ölçütü"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Tümünü seç"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopyala…"</string>
<string name="menu_move" msgid="1828090633118079817">"Taşı..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Yeni pencere"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopyala"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Yapıştır"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Dahili depolamayı göster"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Kopyala"</string>
<string name="button_move" msgid="2202666023104202232">"Taşı"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Kapat"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Tekrar Dene"</string>
<string name="sort_name" msgid="9183560467917256779">"Ada göre"</string>
<string name="sort_date" msgid="586080032956151448">"Değişiklik tarihine göre"</string>
<string name="sort_size" msgid="3350681319735474741">"Boyuta göre"</string>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index dff37c3..7382bf8 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Файли"</string>
<string name="title_open" msgid="4353228937663917801">"Відкрити"</string>
<string name="title_save" msgid="2433679664882857999">"Зберегти в"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Створити папку"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Режим таблиці"</string>
<string name="menu_list" msgid="7279285939892417279">"Режим списку"</string>
<string name="menu_sort" msgid="7677740407158414452">"Параметри сортування"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Вибрати все"</string>
<string name="menu_copy" msgid="3612326052677229148">"Копіювати в…"</string>
<string name="menu_move" msgid="1828090633118079817">"Перемістити в…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Нове вікно"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Копіювати"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Вставити"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Показати внутр. пам’ять"</string>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 82822ec..0e5544f 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"فائلیں"</string>
<string name="title_open" msgid="4353228937663917801">"کھولیں از"</string>
<string name="title_save" msgid="2433679664882857999">"اس میں محفوظ کریں"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"فولڈر بنائیں"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"گرڈ منظر"</string>
<string name="menu_list" msgid="7279285939892417279">"فہرست منظر"</string>
<string name="menu_sort" msgid="7677740407158414452">"ترتیب دیں بلحاظ"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"سبھی کو منتخب کریں"</string>
<string name="menu_copy" msgid="3612326052677229148">"اس میں کاپی کریں…"</string>
<string name="menu_move" msgid="1828090633118079817">"اس میں منتقل کریں…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"نئی ونڈو"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"کاپی کریں"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"پیسٹ کریں"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"داخلی اسٹوریج دکھائیں"</string>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index d0cfacc..9cc6bca 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Fayllar"</string>
<string name="title_open" msgid="4353228937663917801">"Ochish"</string>
<string name="title_save" msgid="2433679664882857999">"Saqlash"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Jild yaratish"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Katak ko‘rinishida"</string>
<string name="menu_list" msgid="7279285939892417279">"Ro‘yxat ko‘rinishida"</string>
<string name="menu_sort" msgid="7677740407158414452">"Saralash"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Barchasini belgilash"</string>
<string name="menu_copy" msgid="3612326052677229148">"Nusxalash…"</string>
<string name="menu_move" msgid="1828090633118079817">"Ko‘chirib o‘tkazish…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Yangi oyna"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Nusxalash"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Joylash"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Ichki xotirani ko‘rsatish"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Nusxalash"</string>
<string name="button_move" msgid="2202666023104202232">"Ko‘chirib o‘tkazish"</string>
<string name="button_dismiss" msgid="3714065566893946085">"O‘chirish"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Qayta urinish"</string>
<string name="sort_name" msgid="9183560467917256779">"Nomi bo‘yicha"</string>
<string name="sort_date" msgid="586080032956151448">"Tahrir sanasi bo‘yicha"</string>
<string name="sort_size" msgid="3350681319735474741">"Hajmi bo‘yicha"</string>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 4583362..1d55338 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Tệp"</string>
<string name="title_open" msgid="4353228937663917801">"Mở từ"</string>
<string name="title_save" msgid="2433679664882857999">"Lưu vào"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Tạo thư mục"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Chế độ xem lưới"</string>
<string name="menu_list" msgid="7279285939892417279">"Chế độ xem danh sách"</string>
<string name="menu_sort" msgid="7677740407158414452">"Sắp xếp theo"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Chọn tất cả"</string>
<string name="menu_copy" msgid="3612326052677229148">"Sao chép vào…"</string>
<string name="menu_move" msgid="1828090633118079817">"Chuyển tới..."</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Cửa sổ mới"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Sao chép"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Dán"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Hiển thị bộ nhớ trong"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"Sao chép"</string>
<string name="button_move" msgid="2202666023104202232">"Di chuyển"</string>
<string name="button_dismiss" msgid="3714065566893946085">"Loại bỏ"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"Thử lại"</string>
<string name="sort_name" msgid="9183560467917256779">"Theo tên"</string>
<string name="sort_date" msgid="586080032956151448">"Theo ngày sửa đổi"</string>
<string name="sort_size" msgid="3350681319735474741">"Theo kích thước"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index d577e14..7e2e3d5 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"文件"</string>
<string name="title_open" msgid="4353228937663917801">"打开文件"</string>
<string name="title_save" msgid="2433679664882857999">"保存文件"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"新建文件夹"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"网格视图"</string>
<string name="menu_list" msgid="7279285939892417279">"列表视图"</string>
<string name="menu_sort" msgid="7677740407158414452">"排序依据"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"全选"</string>
<string name="menu_copy" msgid="3612326052677229148">"复制到…"</string>
<string name="menu_move" msgid="1828090633118079817">"移动到…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"新建窗口"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"复制"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"粘贴"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"显示内部存储设备"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"复制"</string>
<string name="button_move" msgid="2202666023104202232">"移动"</string>
<string name="button_dismiss" msgid="3714065566893946085">"关闭"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"重试"</string>
<string name="sort_name" msgid="9183560467917256779">"按名称"</string>
<string name="sort_date" msgid="586080032956151448">"按修改日期"</string>
<string name="sort_size" msgid="3350681319735474741">"按大小"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index 3d44047..6cbdf01 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"檔案"</string>
<string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
<string name="title_save" msgid="2433679664882857999">"儲存至"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"建立資料夾"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"格狀檢視"</string>
<string name="menu_list" msgid="7279285939892417279">"清單檢視"</string>
<string name="menu_sort" msgid="7677740407158414452">"排序方式"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"全部選取"</string>
<string name="menu_copy" msgid="3612326052677229148">"複製到…"</string>
<string name="menu_move" msgid="1828090633118079817">"移至…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"新視窗"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"複製"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"貼上"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"顯示內部儲存空間"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"複製"</string>
<string name="button_move" msgid="2202666023104202232">"移動"</string>
<string name="button_dismiss" msgid="3714065566893946085">"關閉"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"再試一次"</string>
<string name="sort_name" msgid="9183560467917256779">"按名稱"</string>
<string name="sort_date" msgid="586080032956151448">"按修改日期"</string>
<string name="sort_size" msgid="3350681319735474741">"按大小"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index aaad98c..850f9b0 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"檔案"</string>
<string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
<string name="title_save" msgid="2433679664882857999">"儲存至"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"建立資料夾"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"格狀檢視"</string>
<string name="menu_list" msgid="7279285939892417279">"清單檢視"</string>
<string name="menu_sort" msgid="7677740407158414452">"排序依據"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"全選"</string>
<string name="menu_copy" msgid="3612326052677229148">"複製到…"</string>
<string name="menu_move" msgid="1828090633118079817">"移至…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"新視窗"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"複製"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"貼上"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"顯示內部儲存空間"</string>
@@ -45,8 +47,7 @@
<string name="button_copy" msgid="8706475544635021302">"複製"</string>
<string name="button_move" msgid="2202666023104202232">"移動"</string>
<string name="button_dismiss" msgid="3714065566893946085">"關閉"</string>
- <!-- no translation found for button_retry (4392027584153752797) -->
- <skip />
+ <string name="button_retry" msgid="4392027584153752797">"再試一次"</string>
<string name="sort_name" msgid="9183560467917256779">"依名稱"</string>
<string name="sort_date" msgid="586080032956151448">"依修改日期"</string>
<string name="sort_size" msgid="3350681319735474741">"依大小"</string>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index 8f20cc4..fdf278d 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -20,7 +20,8 @@
<string name="files_label" msgid="6051402950202690279">"Amafayela"</string>
<string name="title_open" msgid="4353228937663917801">"Vula kusuka ku-"</string>
<string name="title_save" msgid="2433679664882857999">"Londoloza ku-"</string>
- <string name="menu_create_dir" msgid="5947289605844398389">"Dala ifolda"</string>
+ <!-- no translation found for menu_create_dir (2547620241173881754) -->
+ <skip />
<string name="menu_grid" msgid="6878021334497835259">"Ukubuka kwegridi"</string>
<string name="menu_list" msgid="7279285939892417279">"Ukubuka uhlu"</string>
<string name="menu_sort" msgid="7677740407158414452">"Hlunga nge-"</string>
@@ -33,6 +34,7 @@
<string name="menu_select_all" msgid="8323579667348729928">"Khetha konke"</string>
<string name="menu_copy" msgid="3612326052677229148">"Kopishela ku…"</string>
<string name="menu_move" msgid="1828090633118079817">"Hambisa ku…"</string>
+ <string name="menu_new_window" msgid="1226032889278727538">"Iwindi elisha"</string>
<string name="menu_copy_to_clipboard" msgid="489311381979634291">"Kopisha"</string>
<string name="menu_paste_from_clipboard" msgid="2071583031180257091">"Namathisela"</string>
<string name="menu_advanced_show" product="nosdcard" msgid="4693652895715631401">"Bonisa isitoreji sangaphakathi"</string>
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ce5b174..ed7820b 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -15,5 +15,5 @@
-->
<resources>
- <bool name="productivity_device">false</bool>
+ <bool name="productivity_device">true</bool>
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index a4acb60..d21b5ee 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -27,7 +27,7 @@
<string name="title_save">Save to</string>
<!-- Menu item that creates a new directory/folder at the current location [CHAR LIMIT=24] -->
- <string name="menu_create_dir">Create folder</string>
+ <string name="menu_create_dir">New folder</string>
<!-- Menu item that switches view to show documents as a large-format grid of thumbnails [CHAR LIMIT=24] -->
<string name="menu_grid">Grid view</string>
<!-- Menu item that switches view to show documents as a list [CHAR LIMIT=24] -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index ab0f666..caaa2b9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -128,10 +128,10 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- boolean shown = super.onPrepareOptionsMenu(menu);
+ super.onPrepareOptionsMenu(menu);
final RootInfo root = getCurrentRoot();
- final DocumentInfo cwd = getCurrentDirectory();
+ final boolean inRecents = getCurrentDirectory() == null;
final MenuItem sort = menu.findItem(R.id.menu_sort);
final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
@@ -141,24 +141,28 @@
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- mSearchManager.update(root);
+ // I'm thinkin' this isn't necesary here. If it is...'cuz of a bug....
+ // then uncomment the linke and let's get a proper bug reference here.
+ // mSearchManager.update(root);
// Search uses backend ranking; no sorting
- sort.setVisible(cwd != null && !mSearchManager.isSearching());
+ sort.setVisible(!inRecents && !mSearchManager.isSearching());
+
+ // grid/list is effectively a toggle.
+ grid.setVisible(mState.derivedMode != State.MODE_GRID);
+ list.setVisible(mState.derivedMode != State.MODE_LIST);
+
+ sortSize.setVisible(mState.showSize); // Only sort by size when visible
+ fileSize.setVisible(!mState.forceSize);
+ advanced.setVisible(!mState.forceAdvanced);
+ settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
? R.string.menu_advanced_hide : R.string.menu_advanced_show);
fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
? R.string.menu_file_size_hide : R.string.menu_file_size_show);
- sortSize.setVisible(mState.showSize); // Only sort by size when visible
- fileSize.setVisible(!mState.showSize);
- grid.setVisible(mState.derivedMode != State.MODE_GRID);
- list.setVisible(mState.derivedMode != State.MODE_LIST);
- advanced.setVisible(!mState.showAdvanced);
- settings.setVisible((root.flags & Root.FLAG_HAS_SETTINGS) != 0);
-
- return shown;
+ return true;
}
State buildDefaultState() {
@@ -277,6 +281,7 @@
return cwd != null
&& cwd.isCreateSupported()
&& !mSearchManager.isSearching()
+ && !root.isRecents()
&& !root.isDownloads();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index 362052c..66f8acd 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -119,7 +119,7 @@
int toastMessage = (mode == TRANSFER_MODE_COPY) ? R.plurals.copy_begin
: R.plurals.move_begin;
- Shared.makeSnackbar(activity,
+ Snackbars.makeSnackbar(activity,
res.getQuantityString(toastMessage, srcDocs.size(), srcDocs.size()),
Snackbar.LENGTH_SHORT).show();
activity.startService(copyIntent);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 9f44516..c6425a6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -147,7 +147,7 @@
// Navigate into newly created child
mActivity.onDirectoryCreated(result);
} else {
- Shared.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT).show();
+ Snackbars.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT).show();
}
mActivity.setPending(false);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index b3ce103..0abbf4e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -44,7 +44,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
-import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -54,7 +53,6 @@
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CancellationSignal;
-import android.os.Handler;
import android.os.Looper;
import android.os.OperationCanceledException;
import android.os.Parcelable;
@@ -134,8 +132,6 @@
private Model mModel;
private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
- private final Handler mHandler = new Handler(Looper.getMainLooper());
-
private View mEmptyView;
private RecyclerView mRecView;
@@ -217,8 +213,6 @@
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- final Context context = inflater.getContext();
- final Resources res = context.getResources();
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mMessageBar = MessageBar.create(getChildFragmentManager());
@@ -678,6 +672,7 @@
checkNotNull(mMenu);
// Delegate update logic to our owning action, since specialized logic is desired.
mFragmentTuner.updateActionMenu(mMenu, mType, mNoDeleteCount == 0);
+ Menus.disableHiddenItems(mMenu);
}
@Override
@@ -799,13 +794,12 @@
private void deleteDocuments(final Selection selected) {
Context context = getActivity();
- ContentResolver resolver = context.getContentResolver();
String message = Shared.getQuantityString(context, R.plurals.deleting, selected.size());
mModel.markForDeletion(selected);
final Activity activity = getActivity();
- Shared.makeSnackbar(activity, message, Snackbar.LENGTH_LONG)
+ Snackbars.makeSnackbar(activity, message, Snackbar.LENGTH_LONG)
.setAction(
R.string.undo,
new android.view.View.OnClickListener() {
@@ -823,7 +817,7 @@
new Model.DeletionListener() {
@Override
public void onError() {
- Shared.makeSnackbar(
+ Snackbars.makeSnackbar(
activity,
R.string.toast_failed_delete,
Snackbar.LENGTH_LONG)
@@ -1244,7 +1238,7 @@
private void copyDocuments(final List<DocumentInfo> docs, final DocumentInfo destination) {
if (!canCopy(docs, destination)) {
- Shared.makeSnackbar(
+ Snackbars.makeSnackbar(
getActivity(),
R.string.clipboard_files_cannot_paste,
Snackbar.LENGTH_SHORT)
@@ -1298,7 +1292,7 @@
void onDocumentsReady(List<DocumentInfo> docs) {
mClipper.clipDocuments(docs);
Activity activity = getActivity();
- Shared.makeSnackbar(activity,
+ Snackbars.makeSnackbar(activity,
activity.getResources().getQuantityString(
R.plurals.clipboard_files_clipped, docs.size(), docs.size()),
Snackbar.LENGTH_SHORT).show();
@@ -1608,23 +1602,25 @@
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
+ boolean copyEnabled = mManaging && dirType != TYPE_RECENT_OPEN;
+ // TODO: The selection needs to be deletable.
+ boolean moveEnabled =
+ SystemProperties.getBoolean("debug.documentsui.enable_move", false);
+ menu.findItem(R.id.menu_copy_to_clipboard).setEnabled(copyEnabled);
final MenuItem open = menu.findItem(R.id.menu_open);
final MenuItem share = menu.findItem(R.id.menu_share);
final MenuItem delete = menu.findItem(R.id.menu_delete);
final MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
final MenuItem moveTo = menu.findItem(R.id.menu_move_to);
- final MenuItem copyToClipboard = menu.findItem(R.id.menu_copy_to_clipboard);
open.setVisible(!mManaging);
share.setVisible(mManaging);
delete.setVisible(mManaging && canDelete);
- // Disable copying from the Recents view.
- copyTo.setVisible(mManaging && dirType != TYPE_RECENT_OPEN);
- moveTo.setVisible(SystemProperties.getBoolean("debug.documentsui.enable_move", false));
-
- // Only shown in files mode.
- copyToClipboard.setVisible(false);
+ copyTo.setVisible(copyEnabled);
+ copyTo.setEnabled(copyEnabled);
+ moveTo.setVisible(moveEnabled);
+ moveTo.setEnabled(moveEnabled);
}
@Override
@@ -1638,13 +1634,14 @@
@Override
public void updateActionMenu(Menu menu, int dirType, boolean canDelete) {
+ menu.findItem(R.id.menu_copy_to_clipboard).setEnabled(dirType != TYPE_RECENT_OPEN);
+
menu.findItem(R.id.menu_share).setVisible(true);
menu.findItem(R.id.menu_delete).setVisible(canDelete);
- menu.findItem(R.id.menu_copy_to_clipboard).setVisible(true);
menu.findItem(R.id.menu_open).setVisible(false);
- menu.findItem(R.id.menu_copy_to).setVisible(false);
- menu.findItem(R.id.menu_move_to).setVisible(false);
+ menu.findItem(R.id.menu_copy_to).setVisible(true);
+ menu.findItem(R.id.menu_move_to).setVisible(true);
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index ced03cc..6b428f5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -89,8 +89,6 @@
setTheme(R.style.DocumentsNonDialogTheme);
}
- final Context context = this;
-
if (mShowAsDialog) {
mDrawer = DrawerController.createDummy();
@@ -314,41 +312,35 @@
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
final MenuItem grid = menu.findItem(R.id.menu_grid);
final MenuItem list = menu.findItem(R.id.menu_list);
- final MenuItem advanced = menu.findItem(R.id.menu_advanced);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- boolean fileSizeVisible = mState.showSize && !mState.forceSize;
- if (mState.action == ACTION_CREATE
+ boolean recents = cwd == null;
+ boolean picking = mState.action == ACTION_CREATE
|| mState.action == ACTION_OPEN_TREE
- || mState.action == ACTION_OPEN_COPY_DESTINATION) {
- createDir.setVisible(cwd != null && cwd.isCreateSupported());
- mSearchManager.showMenu(false);
+ || mState.action == ACTION_OPEN_COPY_DESTINATION;
- // No display options in recent directories
- if (cwd == null) {
- grid.setVisible(false);
- list.setVisible(false);
- fileSizeVisible = false;
- }
+ createDir.setVisible(picking && !recents && cwd.isCreateSupported());
+ mSearchManager.showMenu(!picking);
- if (mState.action == ACTION_CREATE) {
- final FragmentManager fm = getFragmentManager();
- SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
- }
- } else {
- createDir.setVisible(false);
+ // No display options in recent directories
+ grid.setVisible(!(picking && recents));
+ list.setVisible(!(picking && recents));
+
+ fileSize.setVisible(fileSize.isVisible() && !picking);
+ settings.setVisible(false);
+
+ if (mState.action == ACTION_CREATE) {
+ final FragmentManager fm = getFragmentManager();
+ SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
}
- advanced.setVisible(!mState.forceAdvanced);
- fileSize.setVisible(fileSizeVisible);
- settings.setVisible(false);
+ Menus.disableHiddenItems(menu);
return true;
}
@@ -611,7 +603,7 @@
if (result != null) {
onTaskFinished(result);
} else {
- Shared.makeSnackbar(
+ Snackbars.makeSnackbar(
DocumentsActivity.this, R.string.save_error, Snackbar.LENGTH_SHORT).show();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index f6a5131..70ddf59 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -225,30 +225,23 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- boolean shown = super.onPrepareOptionsMenu(menu);
-
- menu.findItem(R.id.menu_file_size).setVisible(true);
- menu.findItem(R.id.menu_advanced).setVisible(true);
+ super.onPrepareOptionsMenu(menu);
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
final MenuItem newWindow = menu.findItem(R.id.menu_new_window);
final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
- boolean canCreateDir = canCreateDirectory();
-
createDir.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- createDir.setVisible(canCreateDir);
- createDir.setEnabled(canCreateDir);
+ createDir.setVisible(true);
+ createDir.setEnabled(canCreateDirectory());
+
+ pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
newWindow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
newWindow.setVisible(mProductivityDevice);
- newWindow.setEnabled(mProductivityDevice);
- pasteFromCb.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- pasteFromCb.setVisible(true);
- pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
-
- return shown;
+ Menus.disableHiddenItems(menu, pasteFromCb);
+ return true;
}
@Override
@@ -347,7 +340,7 @@
try {
startActivity(intent);
} catch (ActivityNotFoundException ex2) {
- Shared.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
+ Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT).show();
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
index ed7333d..14a33f9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
@@ -140,6 +140,7 @@
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
+ Menus.disableHiddenItems(menu);
return true;
}
@@ -184,7 +185,7 @@
try {
startActivity(view);
} catch (ActivityNotFoundException ex2) {
- Shared.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
+ Snackbars.makeSnackbar(this, R.string.toast_no_application, Snackbar.LENGTH_SHORT)
.show();
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Menus.java b/packages/DocumentsUI/src/com/android/documentsui/Menus.java
new file mode 100644
index 0000000..3f43a3d
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/Menus.java
@@ -0,0 +1,50 @@
+/*
+ * 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.documentsui;
+
+import android.view.Menu;
+import android.view.MenuItem;
+
+final class Menus {
+
+ private Menus() {}
+
+ /**
+ * Disables hidden menu items so that they are not invokable via command shortcuts
+ */
+ static void disableHiddenItems(Menu menu, MenuItem... exclusions) {
+ for (int i = 0; i < menu.size(); i++) {
+ MenuItem item = menu.getItem(i);
+ if (item.isVisible()) {
+ continue;
+ }
+ if (contains(exclusions, item)) {
+ continue;
+ }
+ item.setEnabled(false);
+ }
+ }
+
+ private static boolean contains(MenuItem[] exclusions, MenuItem item) {
+ for (int x = 0; x < exclusions.length; x++) {
+ if (exclusions[x] == item) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index e06d6a5..a4d6dc5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -16,12 +16,7 @@
package com.android.documentsui;
-import static com.android.internal.util.Preconditions.checkNotNull;
-
-import android.app.Activity;
import android.content.Context;
-import android.support.design.widget.Snackbar;
-import android.view.View;
/** @hide */
public final class Shared {
@@ -35,14 +30,4 @@
public static final String getQuantityString(Context context, int resourceId, int quantity) {
return context.getResources().getQuantityString(resourceId, quantity, quantity);
}
-
- public static final Snackbar makeSnackbar(Activity activity, int messageId, int duration) {
- return makeSnackbar(activity, activity.getResources().getText(messageId), duration);
- }
-
- public static final Snackbar makeSnackbar(Activity activity, CharSequence message, int duration)
- {
- final View view = checkNotNull(activity.findViewById(R.id.coordinator_layout));
- return Snackbar.make(view, message, duration);
- }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
new file mode 100644
index 0000000..f48b298
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/Snackbars.java
@@ -0,0 +1,37 @@
+/*
+ * 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.documentsui;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.app.Activity;
+import android.support.design.widget.Snackbar;
+import android.view.View;
+
+final class Snackbars {
+ private Snackbars() {}
+
+ public static final Snackbar makeSnackbar(Activity activity, int messageId, int duration) {
+ return Snackbars.makeSnackbar(activity, activity.getResources().getText(messageId), duration);
+ }
+
+ public static final Snackbar makeSnackbar(Activity activity, CharSequence message, int duration)
+ {
+ final View view = checkNotNull(activity.findViewById(R.id.coordinator_layout));
+ return Snackbar.make(view, message, duration);
+ }
+}
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 47e24e8..368f9f7 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -13,3 +13,11 @@
-keep class com.android.systemui.statusbar.phone.PhoneStatusBar
-keep class com.android.systemui.statusbar.tv.TvStatusBar
-keep class com.android.systemui.recents.*
+
+-keepclassmembers class ** {
+ public void onBusEvent(**);
+ public void onInterprocessBusEvent(**);
+}
+-keepclassmembers class ** extends **.EventBus$InterprocessEvent {
+ public <init>(android.os.Bundle);
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index f8fc232..b69fc0f 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -325,8 +325,8 @@
<string name="interruption_level_priority_twoline" msgid="1564715335217164124">"Միայն\nկարևորները"</string>
<string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"Միայն\nզարթուցիչ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> մինչև լրիվ լիցքավորումը)"</string>
- <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Արագ լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>՝ մինչև լցվելը)"</string>
- <string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Դանդաղ լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>՝ մինչև լցվելը)"</string>
+ <string name="keyguard_indication_charging_time_fast" msgid="9018981952053914986">"Արագ լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>՝ մինչև ավարտ)"</string>
+ <string name="keyguard_indication_charging_time_slowly" msgid="955252797961724952">"Դանդաղ լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>՝ մինչև ավարտ)"</string>
<string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Անջատել օգտվողին"</string>
<string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Փոխել օգտվողին. ներկայիս օգտվողն է՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
<string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Ընթացիկ օգտվողը՝ <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d91335c..7323126 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -393,7 +393,7 @@
<string name="accessibility_volume_expand" msgid="5946812790999244205">"Utöka"</string>
<string name="accessibility_volume_collapse" msgid="3609549593031810875">"Komprimera"</string>
<string name="screen_pinning_title" msgid="3273740381976175811">"Skärmen har fästs"</string>
- <string name="screen_pinning_description" msgid="1346522416878235405">"Detta visar skärmen tills du lossar den. Tryck länge på bakåtknappen och Översikt samtidigt om du vill lossa skärmen."</string>
+ <string name="screen_pinning_description" msgid="1346522416878235405">"Med den här funktionen är skärmen synlig tills du lossar den. Tryck länge på Tillbaka och Översikt samtidigt om du vill lossa skärmen."</string>
<string name="screen_pinning_description_accessible" msgid="8518446209564202557">"Detta visar skärmen tills du lossar den. Tryck länge på Översikt om du vill lossa skärmen."</string>
<string name="screen_pinning_positive" msgid="3783985798366751226">"OK"</string>
<string name="screen_pinning_negative" msgid="3741602308343880268">"Nej tack"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 23cc8f0..a78351a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -74,6 +74,8 @@
public class Recents extends SystemUI
implements ActivityOptions.OnAnimationStartedListener, RecentsComponent {
+ public final static int EVENT_BUS_PRIORITY = 1;
+
final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "triggeredFromAltTab";
final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "triggeredFromHomeKey";
final public static String EXTRA_RECENTS_VISIBILITY = "recentsVisibility";
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 9ce6b2c..5c61c5ca6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -19,23 +19,32 @@
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.SearchManager;
+import android.app.TaskStackBuilder;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.Settings;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewStub;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
+import com.android.systemui.recents.events.ui.DismissTaskEvent;
+import com.android.systemui.recents.events.ui.ResizeTaskEvent;
+import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
+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;
@@ -44,16 +53,17 @@
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.recents.views.ViewAnimation;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
* The main Recents activity that is started from AlternateRecentsComponent.
*/
-public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
- RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
+public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks {
+
+ public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
RecentsConfiguration mConfig;
+ RecentsPackageMonitor mPackageMonitor;
long mLastTabKeyEventTime;
// Top level views
@@ -318,12 +328,17 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ // Register this activity with the event bus
+ EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
+
// For the non-primary user, ensure that the SystemServicesProxy and configuration is
// initialized
RecentsTaskLoader.initialize(this);
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
mConfig = RecentsConfiguration.initialize(this, ssp);
mConfig.update(this, ssp, ssp.getWindowRect());
+ mPackageMonitor = new RecentsPackageMonitor();
// Initialize the widget host (the host id is static and does not change)
mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
@@ -371,7 +386,7 @@
registerReceiver(mServiceBroadcastReceiver, filter);
// Register any broadcast receivers for the task loader
- loader.registerReceivers(this, mRecentsView);
+ mPackageMonitor.register(this);
// Update the recent tasks
updateRecentsTasks();
@@ -415,7 +430,7 @@
unregisterReceiver(mServiceBroadcastReceiver);
// Unregister any broadcast receivers for the task loader
- loader.unregisterReceivers();
+ mPackageMonitor.unregister();
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
// through SystemUI, we need to reset the config launch flags to ensure that we do not
@@ -437,6 +452,7 @@
// Stop listening for widget package changes if there was one bound
mAppWidgetHost.stopListening();
+ EventBus.getDefault().unregister(this);
}
public void onEnterAnimationTriggered() {
@@ -446,16 +462,12 @@
mRecentsView.startEnterRecentsAnimation(ctx);
if (mSearchWidgetInfo != null) {
- final WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks> cbRef =
- new WeakReference<RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks>(
- RecentsActivity.this);
ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
@Override
public void run() {
// Start listening for widget package changes if there is one bound
- RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks cb = cbRef.get();
- if (cb != null) {
- mAppWidgetHost.startListening(cb);
+ if (mAppWidgetHost != null) {
+ mAppWidgetHost.startListening();
}
}
});
@@ -530,11 +542,6 @@
return mResizeTaskDebugDialog;
}
- @Override
- public void onTaskResize(Task t) {
- getResizeTaskDebugDialog().showResizeTaskDialog(t, mRecentsView);
- }
-
/**** RecentsView.RecentsViewCallbacks Implementation ****/
@Override
@@ -572,10 +579,40 @@
mAfterPauseRunnable = r;
}
- /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
+ /**** EventBus events ****/
- @Override
- public void refreshSearchWidgetView() {
+ public final void onBusEvent(AppWidgetProviderChangedEvent event) {
+ refreshSearchWidgetView();
+ }
+
+ public final void onBusEvent(ShowApplicationInfoEvent event) {
+ // Create a new task stack with the application info details activity
+ Intent baseIntent = event.task.key.baseIntent;
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.fromParts("package", baseIntent.getComponent().getPackageName(), null));
+ intent.setComponent(intent.resolveActivity(getPackageManager()));
+ TaskStackBuilder.create(this)
+ .addNextIntentWithParentStack(intent).startActivities(null,
+ new UserHandle(event.task.key.userId));
+
+ // Keep track of app-info invocations
+ MetricsLogger.count(this, "overview_app_info", 1);
+ }
+
+ public final void onBusEvent(DismissTaskEvent event) {
+ // Remove any stored data from the loader
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ loader.deleteTaskData(event.task, false);
+
+ // Remove the task from activity manager
+ loader.getSystemServicesProxy().removeTask(event.task.key.id);
+ }
+
+ public final void onBusEvent(ResizeTaskEvent event) {
+ getResizeTaskDebugDialog().showResizeTaskDialog(event.task, mRecentsView);
+ }
+
+ private void refreshSearchWidgetView() {
if (mSearchWidgetInfo != null) {
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
int searchWidgetId = ssp.getSearchAppWidgetId(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
index 0102332..fc96c11 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -20,24 +20,19 @@
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
/** Our special app widget host for the Search widget */
public class RecentsAppWidgetHost extends AppWidgetHost {
- /* Callbacks to notify when an app package changes */
- interface RecentsAppWidgetHostCallbacks {
- void refreshSearchWidgetView();
- }
-
- RecentsAppWidgetHostCallbacks mCb;
boolean mIsListening;
public RecentsAppWidgetHost(Context context, int hostId) {
super(context, hostId);
}
- public void startListening(RecentsAppWidgetHostCallbacks cb) {
- mCb = cb;
+ public void startListening() {
if (!mIsListening) {
mIsListening = true;
super.startListening();
@@ -47,11 +42,9 @@
@Override
public void stopListening() {
if (mIsListening) {
+ mIsListening = false;
super.stopListening();
}
- // Ensure that we release any references to the callbacks
- mCb = null;
- mIsListening = false;
}
@Override
@@ -66,8 +59,8 @@
@Override
protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
super.onProviderChanged(appWidgetId, appWidgetInfo);
- if (mIsListening && mCb != null) {
- mCb.refreshSearchWidgetView();
+ if (mIsListening) {
+ EventBus.getDefault().send(new AppWidgetProviderChangedEvent());
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
new file mode 100644
index 0000000..ef543d0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -0,0 +1,844 @@
+/*
+ * 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.events;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.MutableBoolean;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Represents a subscriber, which implements various event bus handler methods.
+ */
+class Subscriber {
+ private WeakReference<Object> mSubscriber;
+
+ long registrationTime;
+
+ Subscriber(Object subscriber, long registrationTime) {
+ mSubscriber = new WeakReference<>(subscriber);
+ this.registrationTime = registrationTime;
+ }
+
+ public String toString(int priority) {
+ Object sub = mSubscriber.get();
+ String id = Integer.toHexString(System.identityHashCode(sub));
+ return sub.getClass().getSimpleName() + " [0x" + id + ", P" + priority + "]";
+ }
+
+ public Object getReference() {
+ return mSubscriber.get();
+ }
+}
+
+/**
+ * Represents an event handler with a priority.
+ */
+class EventHandler {
+ int priority;
+ Subscriber subscriber;
+ EventHandlerMethod method;
+
+ EventHandler(Subscriber subscriber, EventHandlerMethod method, int priority) {
+ this.subscriber = subscriber;
+ this.method = method;
+ this.priority = priority;
+ }
+
+ @Override
+ public String toString() {
+ return subscriber.toString(priority) + " " + method.toString();
+ }
+}
+
+/**
+ * Represents the low level method handling a particular event.
+ */
+class EventHandlerMethod {
+ private Method mMethod;
+ Class<? extends EventBus.Event> eventType;
+
+ EventHandlerMethod(Method method, Class<? extends EventBus.Event> eventType) {
+ mMethod = method;
+ mMethod.setAccessible(true);
+ this.eventType = eventType;
+ }
+
+ public void invoke(Object target, EventBus.Event event)
+ throws InvocationTargetException, IllegalAccessException {
+ mMethod.invoke(target, event);
+ }
+
+ @Override
+ public String toString() {
+ return mMethod.getName() + "(" + eventType.getSimpleName() + ")";
+ }
+}
+
+/**
+ * A simple in-process event bus. It is simple because we can make assumptions about the state of
+ * SystemUI and Recent's lifecycle.
+ *
+ * <p>
+ * Currently, there is a single EventBus that handles {@link EventBus.Event}s for each subscriber
+ * on the main application thread. Publishers can send() events to synchronously call subscribers
+ * of that event, or post() events to be processed in the next run of the {@link Looper}. In
+ * addition, the EventBus supports sending and handling {@link EventBus.InterprocessEvent}s
+ * (within the same package) implemented using standard {@link BroadcastReceiver} mechanism.
+ * Interprocess events must be posted using postInterprocess() to ensure that it is dispatched
+ * correctly across processes.
+ *
+ * <p>
+ * Subscribers must be registered with a particular EventBus before they will receive events, and
+ * handler methods must match a specific signature.
+ *
+ * <p>
+ * Event method signature:<ul>
+ * <li>Methods must be public final
+ * <li>Methods must return void
+ * <li>Methods must be called "onBusEvent"
+ * <li>Methods must take one parameter, of class type deriving from {@link EventBus.Event}
+ * </ul>
+ *
+ * <p>
+ * Interprocess-Event method signature:<ul>
+ * <li>Methods must be public final
+ * <li>Methods must return void
+ * <li>Methods must be called "onInterprocessBusEvent"
+ * <li>Methods must take one parameter, of class type deriving from {@link EventBus.InterprocessEvent}
+ * </ul>
+ * </p>
+ *
+ * </p>
+ * Each subscriber can be registered with a given priority (default 1), and events will be dispatch
+ * in decreasing order of priority. For subscribers with the same priority, events will be
+ * dispatched by latest registration time to earliest.
+ *
+ * <p>
+ * Interprocess events must extend {@link EventBus.InterprocessEvent}, have a constructor which
+ * takes a {@link Bundle} and implement toBundle(). This allows us to serialize events to be sent
+ * across processes.
+ *
+ * <p>
+ * Caveats:<ul>
+ * <li>The EventBus keeps a {@link WeakReference} to the publisher to prevent memory leaks, so
+ * there must be another strong reference to the publisher for it to not get garbage-collected and
+ * continue receiving events.
+ * <li>Because the event handlers are called back using reflection, the EventBus is not intended
+ * for use in tight, performance criticial loops. For most user input/system callback events, this
+ * is generally of low enough frequency to use the EventBus.
+ * <li>Because the event handlers are called back using reflection, there will often be no
+ * references to them from actual code. The proguard configuration will be need to be updated to
+ * keep these extra methods:
+ *
+ * -keepclassmembers class ** {
+ * public void onBusEvent(**);
+ * public void onInterprocessBusEvent(**);
+ * }
+ * -keepclassmembers class ** extends **.EventBus$InterprocessEvent {
+ * public <init>(android.os.Bundle);
+ * }
+ *
+ * <li>Subscriber registration can be expensive depending on the subscriber's {@link Class}. This
+ * is only done once per class type, but if possible, it is best to pre-register an instance of
+ * that class beforehand or when idle.
+ * <li>Each event should be sent once. Events may hold internal information about the current
+ * dispatch, or may be queued to be dispatched on another thread (if posted from a non-main thread),
+ * so it may be unsafe to edit, change, or re-send the event again.
+ * <li>Events should follow a pattern of public-final POD (plain old data) objects, where they are
+ * initialized by the constructor and read by each subscriber of that event. Subscribers should
+ * never alter events as they are processed, and this enforces that pattern.
+ * </ul>
+ *
+ * <p>
+ * Future optimizations:
+ * <li>throw exception/log when a subscriber loses the reference
+ * <li>trace cost per registration & invocation
+ * <li>trace cross-process invocation
+ * <li>register(subscriber, Class<?>...) -- pass in exact class types you want registered
+ * <li>setSubscriberEventHandlerPriority(subscriber, Class<Event>, priority)
+ * <li>allow subscribers to implement interface, ie. EventBus.Subscriber, which lets then test a
+ * message before invocation (ie. check if task id == this task id)
+ * <li>add postOnce() which automatically debounces
+ * <li>add postDelayed() which delays / postDelayedOnce() which delays and bounces
+ * <li>consolidate register() and registerInterprocess()
+ * <li>sendForResult<ReturnType>(Event) to send and get a result, but who will send the
+ * result?
+ * </p>
+ */
+public class EventBus extends BroadcastReceiver {
+
+ public static final String TAG = "EventBus";
+
+ /**
+ * An event super class that allows us to track internal event state across subscriber
+ * invocations.
+ *
+ * Events should not be edited by subscribers.
+ */
+ public static class Event {
+ // Indicates that this event's dispatch should be traced and logged to logcat
+ boolean trace;
+ // Indicates that this event must be posted on the EventBus's looper thread before invocation
+ boolean requiresPost;
+ // Not currently exposed, allows a subscriber to cancel further dispatch of this event
+ boolean cancelled;
+
+ // Only accessible from derived events
+ protected Event() {}
+ }
+
+ /**
+ * An inter-process event super class that allows us to track user state across subscriber
+ * invocations.
+ */
+ public static class InterprocessEvent extends Event {
+ private static final String EXTRA_USER = "_user";
+
+ // The user which this event originated from
+ public final int user;
+
+ // Only accessible from derived events
+ protected InterprocessEvent(int user) {
+ this.user = user;
+ }
+
+ /**
+ * Called from the event bus
+ */
+ protected InterprocessEvent(Bundle b) {
+ user = b.getInt(EXTRA_USER);
+ }
+
+ protected Bundle toBundle() {
+ Bundle b = new Bundle();
+ b.putInt(EXTRA_USER, user);
+ return b;
+ }
+ }
+
+ /**
+ * Proguard must also know, and keep, all methods matching this signature.
+ *
+ * -keepclassmembers class ** {
+ * public void onBusEvent(**);
+ * public void onInterprocessBusEvent(**);
+ * }
+ */
+ private static final String METHOD_PREFIX = "onBusEvent";
+ private static final String INTERPROCESS_METHOD_PREFIX = "onInterprocessBusEvent";
+
+ // Ensures that interprocess events can only be sent from a process holding this permission. */
+ private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
+ // Used for passing event data across process boundaries
+ private static final String EXTRA_INTERPROCESS_EVENT_BUNDLE = "interprocess_event_bundle";
+
+ // The default priority of all subscribers
+ private static final int DEFAULT_SUBSCRIBER_PRIORITY = 1;
+
+ // Used for debugging everything
+ private static final boolean DEBUG_TRACE_ALL = false;
+
+ // Orders the handlers by priority and registration time
+ private static final Comparator<EventHandler> EVENT_HANDLER_COMPARATOR = new Comparator<EventHandler>() {
+ @Override
+ public int compare(EventHandler h1, EventHandler h2) {
+ // Rank the handlers by priority descending, followed by registration time descending.
+ // aka. the later registered
+ if (h1.priority != h2.priority) {
+ return h2.priority - h1.priority;
+ } else {
+ return Long.compare(h2.subscriber.registrationTime, h1.subscriber.registrationTime);
+ }
+ }
+ };
+
+ // Used for initializing the default bus
+ private static final Object sLock = new Object();
+ private static EventBus sDefaultBus;
+
+ // The handler to post all events
+ private Handler mHandler;
+
+ // Keep track of whether we have registered a broadcast receiver already, so that we can
+ // unregister ourselves before re-registering again with a new IntentFilter.
+ private boolean mHasRegisteredReceiver;
+
+ /**
+ * Map from event class -> event handler list. Keeps track of the actual mapping from event
+ * to subscriber method.
+ */
+ private HashMap<Class<? extends Event>, ArrayList<EventHandler>> mEventTypeMap = new HashMap<>();
+
+ /**
+ * Map from subscriber class -> event handler method lists. Used to determine upon registration
+ * of a new subscriber whether we need to read all the subscriber's methods again using
+ * reflection or whether we can just add the subscriber to the event type map.
+ */
+ private HashMap<Class<? extends Object>, ArrayList<EventHandlerMethod>> mSubscriberTypeMap = new HashMap<>();
+
+ /**
+ * Map from interprocess event name -> interprocess event class. Used for mapping the event
+ * name after receiving the broadcast, to the event type. After which a new instance is created
+ * and posted in the local process.
+ */
+ private HashMap<String, Class<? extends InterprocessEvent>> mInterprocessEventNameMap = new HashMap<>();
+
+ /**
+ * Set of all currently registered subscribers
+ */
+ private ArrayList<Subscriber> mSubscribers = new ArrayList<>();
+
+ // For tracing
+ private int mCallCount;
+ private long mCallDurationMicros;
+
+ /**
+ * Private constructor to create an event bus for a given looper.
+ */
+ private EventBus(Looper looper) {
+ mHandler = new Handler(looper);
+ }
+
+ /**
+ * @return the default event bus for the application's main thread.
+ */
+ public static EventBus getDefault() {
+ if (sDefaultBus == null)
+ synchronized (sLock) {
+ if (sDefaultBus == null) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("New EventBus");
+ }
+ sDefaultBus = new EventBus(Looper.getMainLooper());
+ }
+ }
+ return sDefaultBus;
+ }
+
+ /**
+ * Registers a subscriber to receive events with the default priority.
+ *
+ * @param subscriber the subscriber to handle events. If this is the first instance of the
+ * subscriber's class type that has been registered, the class's methods will
+ * be scanned for appropriate event handler methods.
+ */
+ public void register(Object subscriber) {
+ registerSubscriber(subscriber, DEFAULT_SUBSCRIBER_PRIORITY, null);
+ }
+
+ /**
+ * Registers a subscriber to receive events with the given priority.
+ *
+ * @param subscriber the subscriber to handle events. If this is the first instance of the
+ * subscriber's class type that has been registered, the class's methods will
+ * be scanned for appropriate event handler methods.
+ * @param priority the priority that this subscriber will receive events relative to other
+ * subscribers
+ */
+ public void register(Object subscriber, int priority) {
+ registerSubscriber(subscriber, priority, null);
+ }
+
+ /**
+ * Explicitly registers a subscriber to receive interprocess events with the default priority.
+ *
+ * @param subscriber the subscriber to handle events. If this is the first instance of the
+ * subscriber's class type that has been registered, the class's methods will
+ * be scanned for appropriate event handler methods.
+ */
+ public void registerInterprocessAsCurrentUser(Context context, Object subscriber) {
+ registerInterprocessAsCurrentUser(context, subscriber, DEFAULT_SUBSCRIBER_PRIORITY);
+ }
+
+ /**
+ * Registers a subscriber to receive interprocess events with the given priority.
+ *
+ * @param subscriber the subscriber to handle events. If this is the first instance of the
+ * subscriber's class type that has been registered, the class's methods will
+ * be scanned for appropriate event handler methods.
+ * @param priority the priority that this subscriber will receive events relative to other
+ * subscribers
+ */
+ public void registerInterprocessAsCurrentUser(Context context, Object subscriber, int priority) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("registerInterprocessAsCurrentUser(" + subscriber.getClass().getSimpleName() + ")");
+ }
+
+ // Register the subscriber normally, and update the broadcast receiver filter if this is
+ // a new subscriber type with interprocess events
+ MutableBoolean hasInterprocessEventsChanged = new MutableBoolean(false);
+ registerSubscriber(subscriber, priority, hasInterprocessEventsChanged);
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("hasInterprocessEventsChanged: " + hasInterprocessEventsChanged.value);
+ }
+ if (hasInterprocessEventsChanged.value) {
+ registerReceiverForInterprocessEvents(context);
+ }
+ }
+
+ /**
+ * Remove all EventHandlers pointing to the specified subscriber. This does not remove the
+ * mapping of subscriber type to event handler method, in case new instances of this subscriber
+ * are registered.
+ */
+ public void unregister(Object subscriber) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("unregister()");
+ }
+
+ // Fail immediately if we are being called from the non-main thread
+ long callingThreadId = Thread.currentThread().getId();
+ if (callingThreadId != mHandler.getLooper().getThread().getId()) {
+ throw new RuntimeException("Can not unregister() a subscriber from a non-main thread.");
+ }
+
+ // Return early if this is not a registered subscriber
+ if (!findRegisteredSubscriber(subscriber, true /* removeFoundSubscriber */)) {
+ return;
+ }
+
+ Class<?> subscriberType = subscriber.getClass();
+ ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType);
+ if (subscriberMethods != null) {
+ // For each of the event handlers the subscriber handles, remove all references of that
+ // handler
+ for (EventHandlerMethod method : subscriberMethods) {
+ ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(method.eventType);
+ for (int i = eventHandlers.size() - 1; i >= 0; i--) {
+ if (eventHandlers.get(i).subscriber.getReference() == subscriber) {
+ eventHandlers.remove(i);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Explicit unregistration for interprocess event subscribers. This actually behaves exactly
+ * the same as unregister() since we also do not want to stop listening for specific
+ * inter-process messages in case new instances of that subscriber is registered.
+ */
+ public void unregisterInterprocess(Context context, Object subscriber) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("unregisterInterprocess()");
+ }
+ unregister(subscriber);
+ }
+
+ /**
+ * Sends an event to the subscribers of the given event type immediately. This can only be
+ * called from the same thread as the EventBus's looper thread (for the default EventBus, this
+ * is the main application thread).
+ */
+ public void send(Event event) {
+ // Fail immediately if we are being called from the non-main thread
+ long callingThreadId = Thread.currentThread().getId();
+ if (callingThreadId != mHandler.getLooper().getThread().getId()) {
+ throw new RuntimeException("Can not send() a message from a non-main thread.");
+ }
+
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("send(" + event.getClass().getSimpleName() + ")");
+ }
+
+ // Reset the event's cancelled state
+ event.requiresPost = false;
+ event.cancelled = false;
+ queueEvent(event);
+ }
+
+ /**
+ * Post a message to the subscribers of the given event type. The messages will be posted on
+ * the EventBus's looper thread (for the default EventBus, this is the main application thread).
+ */
+ public void post(Event event) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("post(" + event.getClass().getSimpleName() + ")");
+ }
+
+ // Reset the event's cancelled state
+ event.requiresPost = true;
+ event.cancelled = false;
+ queueEvent(event);
+ }
+
+ /** Prevent post()ing an InterprocessEvent */
+ @Deprecated
+ public void post(InterprocessEvent event) {
+ throw new RuntimeException("Not supported, use postInterprocess");
+ }
+
+ /** Prevent send()ing an InterprocessEvent */
+ @Deprecated
+ public void send(InterprocessEvent event) {
+ throw new RuntimeException("Not supported, use postInterprocess");
+ }
+
+ /**
+ * Posts an interprocess event.
+ */
+ public void postInterprocess(Context context, final InterprocessEvent event) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("postInterprocess(" + event.getClass().getSimpleName() + ")");
+ }
+ String eventType = event.getClass().getName();
+ Bundle eventBundle = event.toBundle();
+ Intent intent = new Intent(eventType);
+ intent.setPackage(context.getPackageName());
+ intent.putExtra(EXTRA_INTERPROCESS_EVENT_BUNDLE, eventBundle);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
+ context.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ /**
+ * Receiver for interprocess events.
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("onReceive(" + intent.getAction() + ", user " + UserHandle.myUserId() + ")");
+ }
+
+ Bundle eventBundle = intent.getBundleExtra(EXTRA_INTERPROCESS_EVENT_BUNDLE);
+ Class<? extends InterprocessEvent> eventType = mInterprocessEventNameMap.get(intent.getAction());
+ try {
+ Constructor<? extends InterprocessEvent> ctor = eventType.getConstructor(Bundle.class);
+ send((Event) ctor.newInstance(eventBundle));
+ } catch (NoSuchMethodException|
+ InvocationTargetException|
+ InstantiationException|
+ IllegalAccessException e) {
+ Log.e(TAG, "Failed to create InterprocessEvent", e);
+ }
+ }
+
+ /**
+ * @return a dump of the current state of the EventBus
+ */
+ public String dump() {
+ StringBuilder output = new StringBuilder();
+ output.append("Registered class types:");
+ output.append("\n");
+ for (Class<?> clz : mSubscriberTypeMap.keySet()) {
+ output.append("\t");
+ output.append(clz.getSimpleName());
+ output.append("\n");
+ }
+ output.append("Event map:");
+ output.append("\n");
+ for (Class<?> clz : mEventTypeMap.keySet()) {
+ output.append("\t");
+ output.append(clz.getSimpleName());
+ output.append(" -> ");
+ output.append("\n");
+ ArrayList<EventHandler> handlers = mEventTypeMap.get(clz);
+ for (EventHandler handler : handlers) {
+ Object subscriber = handler.subscriber.getReference();
+ if (subscriber != null) {
+ String id = Integer.toHexString(System.identityHashCode(subscriber));
+ output.append("\t\t");
+ output.append(subscriber.getClass().getSimpleName());
+ output.append(" [0x" + id + ", #" + handler.priority + "]");
+ output.append("\n");
+ }
+ }
+ }
+ return output.toString();
+ }
+
+ /**
+ * Registers a new subscriber.
+ *
+ * @return return whether or not this
+ */
+ private void registerSubscriber(Object subscriber, int priority,
+ MutableBoolean hasInterprocessEventsChangedOut) {
+ // Fail immediately if we are being called from the non-main thread
+ long callingThreadId = Thread.currentThread().getId();
+ if (callingThreadId != mHandler.getLooper().getThread().getId()) {
+ throw new RuntimeException("Can not register() a subscriber from a non-main thread.");
+ }
+
+ // Return immediately if this exact subscriber is already registered
+ if (findRegisteredSubscriber(subscriber, false /* removeFoundSubscriber */)) {
+ return;
+ }
+
+ long t1 = 0;
+ if (DEBUG_TRACE_ALL) {
+ t1 = SystemClock.currentTimeMicro();
+ logWithPid("registerSubscriber(" + subscriber.getClass().getSimpleName() + ")");
+ }
+ Subscriber sub = new Subscriber(subscriber, SystemClock.uptimeMillis());
+ Class<?> subscriberType = subscriber.getClass();
+ ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType);
+ if (subscriberMethods != null) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("Subscriber class type already registered");
+ }
+
+ // If we've parsed this subscriber type before, just add to the set for all the known
+ // events
+ for (EventHandlerMethod method : subscriberMethods) {
+ ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(method.eventType);
+ eventTypeHandlers.add(new EventHandler(sub, method, priority));
+ sortEventHandlersByPriority(eventTypeHandlers);
+ }
+ mSubscribers.add(sub);
+ return;
+ } else {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("Subscriber class type requires registration");
+ }
+
+ // If we are parsing this type from scratch, ensure we add it to the subscriber type
+ // map, and pull out he handler methods below
+ subscriberMethods = new ArrayList<>();
+ mSubscriberTypeMap.put(subscriberType, subscriberMethods);
+ mSubscribers.add(sub);
+ }
+
+ // Find all the valid event bus handler methods of the subscriber
+ MutableBoolean isInterprocessEvent = new MutableBoolean(false);
+ Method[] methods = subscriberType.getDeclaredMethods();
+ for (Method m : methods) {
+ Class<?>[] parameterTypes = m.getParameterTypes();
+ isInterprocessEvent.value = false;
+ if (isValidEventBusHandlerMethod(m, parameterTypes, isInterprocessEvent)) {
+ Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
+ ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(eventType);
+ if (eventTypeHandlers == null) {
+ eventTypeHandlers = new ArrayList<>();
+ mEventTypeMap.put(eventType, eventTypeHandlers);
+ }
+ if (isInterprocessEvent.value) {
+ try {
+ // Enforce that the event must have a Bundle constructor
+ eventType.getConstructor(Bundle.class);
+
+ mInterprocessEventNameMap.put(eventType.getName(),
+ (Class<? extends InterprocessEvent>) eventType);
+ if (hasInterprocessEventsChangedOut != null) {
+ hasInterprocessEventsChangedOut.value = true;
+ }
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Expected InterprocessEvent to have a Bundle constructor");
+ }
+ }
+ EventHandlerMethod method = new EventHandlerMethod(m, eventType);
+ EventHandler handler = new EventHandler(sub, method, priority);
+ eventTypeHandlers.add(handler);
+ subscriberMethods.add(method);
+ sortEventHandlersByPriority(eventTypeHandlers);
+
+ if (DEBUG_TRACE_ALL) {
+ logWithPid(" * Method: " + m.getName() +
+ " event: " + parameterTypes[0].getSimpleName() +
+ " interprocess? " + isInterprocessEvent.value);
+ }
+ }
+ }
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("Registered " + subscriber.getClass().getSimpleName() + " in " +
+ (SystemClock.currentTimeMicro() - t1) + " microseconds");
+ }
+ }
+
+ /**
+ * Adds a new message.
+ */
+ private void queueEvent(final Event event) {
+ ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
+ if (eventHandlers == null) {
+ return;
+ }
+ // We need to clone the list in case a subscriber unregisters itself during traversal
+ eventHandlers = (ArrayList<EventHandler>) eventHandlers.clone();
+ for (final EventHandler eventHandler : eventHandlers) {
+ if (eventHandler.subscriber.getReference() != null) {
+ if (event.requiresPost) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ processEvent(eventHandler, event);
+ }
+ });
+ } else {
+ processEvent(eventHandler, event);
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes and dispatches the given event to the given event handler, on the thread of whoever
+ * calls this method.
+ */
+ private void processEvent(final EventHandler eventHandler, final Event event) {
+ // Skip if the event was already cancelled
+ if (event.cancelled) {
+ if (event.trace || DEBUG_TRACE_ALL) {
+ logWithPid("Event dispatch cancelled");
+ }
+ return;
+ }
+
+ try {
+ if (event.trace || DEBUG_TRACE_ALL) {
+ logWithPid(" -> " + eventHandler.toString());
+ }
+ Object sub = eventHandler.subscriber.getReference();
+ if (sub != null) {
+ long t1 = 0;
+ if (DEBUG_TRACE_ALL) {
+ t1 = SystemClock.currentTimeMicro();
+ }
+ eventHandler.method.invoke(sub, event);
+ if (DEBUG_TRACE_ALL) {
+ long duration = (SystemClock.currentTimeMicro() - t1);
+ mCallDurationMicros += duration;
+ mCallCount++;
+ logWithPid(eventHandler.method.toString() + " duration: " + duration +
+ " microseconds, avg: " + (mCallDurationMicros / mCallCount));
+ }
+ } else {
+ Log.e(TAG, "Failed to deliver event to null subscriber");
+ }
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Failed to invoke method", e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ }
+ }
+
+ /**
+ * Re-registers the broadcast receiver for any new messages that we want to listen for.
+ */
+ private void registerReceiverForInterprocessEvents(Context context) {
+ if (DEBUG_TRACE_ALL) {
+ logWithPid("registerReceiverForInterprocessEvents()");
+ }
+ // Rebuild the receiver filter with the new interprocess events
+ IntentFilter filter = new IntentFilter();
+ for (String eventName : mInterprocessEventNameMap.keySet()) {
+ filter.addAction(eventName);
+ if (DEBUG_TRACE_ALL) {
+ logWithPid(" filter: " + eventName);
+ }
+ }
+ // Re-register the receiver with the new filter
+ if (mHasRegisteredReceiver) {
+ context.unregisterReceiver(this);
+ }
+ context.registerReceiverAsUser(this, UserHandle.ALL, filter, PERMISSION_SELF, mHandler);
+ mHasRegisteredReceiver = true;
+ }
+
+ /**
+ * Returns whether this subscriber is currently registered. If {@param removeFoundSubscriber}
+ * is true, then remove the subscriber before returning.
+ */
+ private boolean findRegisteredSubscriber(Object subscriber, boolean removeFoundSubscriber) {
+ for (int i = mSubscribers.size() - 1; i >= 0; i--) {
+ Subscriber sub = mSubscribers.get(i);
+ if (sub.getReference() == subscriber) {
+ if (removeFoundSubscriber) {
+ mSubscribers.remove(i);
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return whether {@param method} is a valid (normal or interprocess) event bus handler method
+ */
+ private boolean isValidEventBusHandlerMethod(Method method, Class<?>[] parameterTypes,
+ MutableBoolean isInterprocessEventOut) {
+ int modifiers = method.getModifiers();
+ if (Modifier.isPublic(modifiers) &&
+ Modifier.isFinal(modifiers) &&
+ method.getReturnType().equals(Void.TYPE) &&
+ parameterTypes.length == 1) {
+ if (EventBus.InterprocessEvent.class.isAssignableFrom(parameterTypes[0]) &&
+ method.getName().startsWith(INTERPROCESS_METHOD_PREFIX)) {
+ isInterprocessEventOut.value = true;
+ return true;
+ } else if (EventBus.Event.class.isAssignableFrom(parameterTypes[0]) &&
+ method.getName().startsWith(METHOD_PREFIX)) {
+ isInterprocessEventOut.value = false;
+ return true;
+ } else {
+ if (DEBUG_TRACE_ALL) {
+ if (!EventBus.Event.class.isAssignableFrom(parameterTypes[0])) {
+ logWithPid(" Expected method take an Event-based parameter: " + method.getName());
+ } else if (!method.getName().startsWith(INTERPROCESS_METHOD_PREFIX) &&
+ !method.getName().startsWith(METHOD_PREFIX)) {
+ logWithPid(" Expected method start with method prefix: " + method.getName());
+ }
+ }
+ }
+ } else {
+ if (DEBUG_TRACE_ALL) {
+ if (!Modifier.isPublic(modifiers)) {
+ logWithPid(" Expected method to be public: " + method.getName());
+ } else if (!Modifier.isFinal(modifiers)) {
+ logWithPid(" Expected method to be final: " + method.getName());
+ } else if (!method.getReturnType().equals(Void.TYPE)) {
+ logWithPid(" Expected method to return null: " + method.getName());
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sorts the event handlers by priority and registration time.
+ */
+ private void sortEventHandlersByPriority(List<EventHandler> eventHandlers) {
+ Collections.sort(eventHandlers, EVENT_HANDLER_COMPARATOR);
+ }
+
+ /**
+ * Helper method to log the given {@param text} with the current process and user id.
+ */
+ private static void logWithPid(String text) {
+ Log.d(TAG, "[" + android.os.Process.myPid() + ", u" + UserHandle.myUserId() + "] " + text);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java
new file mode 100644
index 0000000..52cfe18
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java
@@ -0,0 +1,28 @@
+/*
+ * 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.RecentsAppWidgetHost;
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent by the {@link RecentsAppWidgetHost} whenever the search provider widget changes, and
+ * subscribers can update accordingly.
+ */
+public class AppWidgetProviderChangedEvent 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
new file mode 100644
index 0000000..3b68574
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+import com.android.systemui.recents.model.RecentsPackageMonitor;
+import com.android.systemui.recents.views.TaskStackView;
+
+/**
+ * This event is sent by {@link RecentsPackageMonitor} 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;
+ this.packageName = packageName;
+ this.userId = userId;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskEvent.java
new file mode 100644
index 0000000..12e5d3d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskEvent.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.views.TaskView;
+
+/**
+ * This is sent when a {@link TaskView} has been dismissed.
+ */
+public class DismissTaskEvent extends EventBus.Event {
+
+ public final Task task;
+ public final TaskView taskView;
+
+ public DismissTaskEvent(Task task, TaskView taskView) {
+ this.task = task;
+ this.taskView = taskView;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResizeTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResizeTaskEvent.java
new file mode 100644
index 0000000..e0d83fd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResizeTaskEvent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+
+/**
+ * This is sent when a {@link Task} is resized.
+ */
+public class ResizeTaskEvent extends EventBus.Event {
+
+ public final Task task;
+
+ public ResizeTaskEvent(Task task) {
+ this.task = task;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
new file mode 100644
index 0000000..40c30b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+
+/**
+ * This is sent when a user wants to show the application info for a {@link Task}.
+ */
+public class ShowApplicationInfoEvent extends EventBus.Event {
+
+ public final Task task;
+
+ public ShowApplicationInfoEvent(Task task) {
+ this.task = task;
+ }
+}
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 b6d25f5..e0f820d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -55,10 +55,7 @@
import android.provider.Settings;
import android.util.Log;
import android.util.MutableBoolean;
-import android.util.MutableFloat;
-import android.util.MutableInt;
import android.util.Pair;
-import android.util.Size;
import android.view.Display;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
index e48e5f0..8f9a293 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
@@ -21,6 +21,8 @@
import android.os.Looper;
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.SystemServicesProxy;
import java.util.HashSet;
@@ -31,18 +33,9 @@
* Recents list.
*/
public class RecentsPackageMonitor extends PackageMonitor {
- public interface PackageCallbacks {
- public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName,
- int userId);
- }
-
- PackageCallbacks mCb;
- SystemServicesProxy mSystemServicesProxy;
/** Registers the broadcast receivers with the specified callbacks. */
- public void register(Context context, PackageCallbacks cb) {
- mSystemServicesProxy = new SystemServicesProxy(context);
- mCb = cb;
+ 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
@@ -60,17 +53,13 @@
} catch (IllegalStateException e) {
e.printStackTrace();
}
- mSystemServicesProxy = null;
- mCb = null;
}
@Override
public void onPackageRemoved(String packageName, int uid) {
- if (mCb == null) return;
-
// Notify callbacks that a package has changed
final int eventUserId = getChangingUserId();
- mCb.onPackagesChanged(this, packageName, eventUserId);
+ EventBus.getDefault().send(new PackagesChangedEvent(this, packageName, eventUserId));
}
@Override
@@ -81,11 +70,9 @@
@Override
public void onPackageModified(String packageName) {
- if (mCb == null) return;
-
// Notify callbacks that a package has changed
final int eventUserId = getChangingUserId();
- mCb.onPackagesChanged(this, packageName, eventUserId);
+ EventBus.getDefault().send(new PackagesChangedEvent(this, packageName, eventUserId));
}
/**
@@ -108,7 +95,8 @@
// If we know that the component still exists in the package, then skip
continue;
}
- if (mSystemServicesProxy.getActivityInfo(cn, userId) != null) {
+ SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+ if (ssp.getActivityInfo(cn, userId) != null) {
existingComponents.add(cn);
} else {
removedComponents.add(cn);
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 760382e..39bef81 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -262,8 +262,6 @@
TaskResourceLoadQueue mLoadQueue;
TaskResourceLoader mLoader;
- RecentsPackageMonitor mPackageMonitor;
-
int mMaxThumbnailCacheSize;
int mMaxIconCacheSize;
int mNumVisibleTasksLoaded;
@@ -293,7 +291,6 @@
// Initialize the proxy, cache and loaders
mSystemServicesProxy = new SystemServicesProxy(context);
- mPackageMonitor = new RecentsPackageMonitor();
mLoadQueue = new TaskResourceLoadQueue();
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -519,17 +516,6 @@
mLoadQueue.clearTasks();
}
- /** Registers any broadcast receivers. */
- public void registerReceivers(Context context, RecentsPackageMonitor.PackageCallbacks cb) {
- // Register the broadcast receiver to handle messages related to packages being added/removed
- mPackageMonitor.register(context, cb);
- }
-
- /** Unregisters any broadcast receivers. */
- public void unregisterReceivers() {
- mPackageMonitor.unregister();
- }
-
/**
* Handles signals from the system, trimming memory when requested to prevent us from running
* out of memory.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 20d9203..8eec87e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -18,10 +18,10 @@
import android.content.Context;
import android.graphics.Color;
+import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.misc.NamedCounter;
import com.android.systemui.recents.misc.Utilities;
-import com.android.systemui.R;
import java.util.ArrayList;
import java.util.Collections;
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 73c9be9..de8730d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -18,18 +18,13 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
-import android.app.TaskStackBuilder;
import android.content.Context;
-import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.net.Uri;
import android.os.Bundle;
import android.os.IRemoteCallback;
import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -46,8 +41,9 @@
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsAppWidgetHostView;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.ui.DismissTaskEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -59,8 +55,7 @@
* This view is the the top level layout that contains TaskStacks (which are laid out according
* to their SpaceNode bounds.
*/
-public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks,
- RecentsPackageMonitor.PackageCallbacks {
+public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks {
private static final String TAG = "RecentsView";
@@ -73,7 +68,6 @@
public void onAllTaskViewsDismissed();
public void onExitToHomeAnimationTriggered();
public void onScreenPinningRequest();
- public void onTaskResize(Task t);
public void runAfterPause(Runnable r);
}
@@ -611,7 +605,7 @@
} else {
// Dismiss the task and return the user to home if we fail to
// launch the task
- onTaskViewDismissed(task);
+ EventBus.getDefault().send(new DismissTaskEvent(task, tv));
if (mCb != null) {
mCb.onTaskLaunchFailed();
}
@@ -648,37 +642,15 @@
}
@Override
- public void onTaskViewAppInfoClicked(Task t) {
- // Create a new task stack with the application info details activity
- Intent baseIntent = t.key.baseIntent;
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
- Uri.fromParts("package", baseIntent.getComponent().getPackageName(), null));
- intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
- TaskStackBuilder.create(getContext())
- .addNextIntentWithParentStack(intent).startActivities(null,
- new UserHandle(t.key.userId));
- }
-
- @Override
- public void onTaskViewDismissed(Task t) {
- // Remove any stored data from the loader. We currently don't bother notifying the views
- // that the data has been unloaded because at the point we call onTaskViewDismissed(), the views
- // either don't need to be updated, or have already been removed.
- RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
- loader.deleteTaskData(t, false);
-
- // Remove the old task from activity manager
- loader.getSystemServicesProxy().removeTask(t.key.id);
- }
-
- @Override
public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks) {
+ /* TODO: Not currently enabled
if (removedTasks != null) {
int taskCount = removedTasks.size();
for (int i = 0; i < taskCount; i++) {
onTaskViewDismissed(removedTasks.get(i));
}
}
+ */
mCb.onAllTaskViewsDismissed();
@@ -725,21 +697,4 @@
.start();
}
}
-
- @Override
- public void onTaskResize(Task t) {
- if (mCb != null) {
- mCb.onTaskResize(t);
- }
- }
-
- /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
-
- @Override
- public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
- // Propagate this event down to each task stack view
- if (mTaskStackView != null) {
- mTaskStackView.onPackagesChanged(monitor, packageName, userId);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 7ce50d8..b28cc21 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -22,7 +22,6 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.systemui.R;
-import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
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 b5f29a0..67e3f82 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -29,15 +29,17 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
-import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.ui.DismissTaskEvent;
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.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -54,19 +56,15 @@
/* The visual representation of a task stack view */
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
TaskView.TaskViewCallbacks, TaskStackViewScroller.TaskStackViewScrollerCallbacks,
- ViewPool.ViewPoolConsumer<TaskView, Task>, RecentsPackageMonitor.PackageCallbacks {
+ ViewPool.ViewPoolConsumer<TaskView, Task> {
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
boolean lockToTask, boolean boundsValid, Rect bounds);
- public void onTaskViewAppInfoClicked(Task t);
- public void onTaskViewDismissed(Task t);
public void onAllTaskViewsDismissed(ArrayList<Task> removedTasks);
public void onTaskStackFilterTriggered();
public void onTaskStackUnfilterTriggered();
-
- public void onTaskResize(Task t);
}
RecentsConfiguration mConfig;
@@ -77,7 +75,7 @@
TaskStackViewTouchHandler mTouchHandler;
TaskStackViewCallbacks mCb;
ViewPool<TaskView, Task> mViewPool;
- ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<TaskViewTransform>();
+ ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
DozeTrigger mUIDozeTrigger;
DismissView mDismissAllButton;
boolean mDismissAllButtonAnimating;
@@ -97,9 +95,9 @@
Matrix mTmpMatrix = new Matrix();
Rect mTmpRect = new Rect();
TaskViewTransform mTmpTransform = new TaskViewTransform();
- HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<Task, TaskView>();
- ArrayList<TaskView> mTaskViews = new ArrayList<TaskView>();
- List<TaskView> mImmutableTaskViews = new ArrayList<TaskView>();
+ HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<>();
+ ArrayList<TaskView> mTaskViews = new ArrayList<>();
+ List<TaskView> mImmutableTaskViews = new ArrayList<>();
LayoutInflater mInflater;
boolean mLayersDisabled;
@@ -147,6 +145,18 @@
mCb = cb;
}
+ @Override
+ protected void onAttachedToWindow() {
+ EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ EventBus.getDefault().unregister(this);
+ }
+
/** Sets the task stack */
void setStack(TaskStack stack) {
// Set the new stack
@@ -1161,11 +1171,6 @@
// Fade the dismiss button back in
showDismissAllButton();
}
-
- // Notify the callback that we've removed the task and it can clean up after it. Note, we
- // do this after onAllTaskViewsDismissed() is called, to allow the home activity to be
- // started before the call to remove the task.
- mCb.onTaskViewDismissed(removedTask);
}
@Override
@@ -1343,27 +1348,6 @@
/**** TaskViewCallbacks Implementation ****/
@Override
- public void onTaskViewAppIconClicked(TaskView tv) {
- if (Constants.DebugFlags.App.EnableTaskFiltering) {
- if (mStack.hasFilteredTasks()) {
- mStack.unfilterTasks();
- } else {
- mStack.filterTasks(tv.getTask());
- }
- }
- }
-
- @Override
- public void onTaskViewAppInfoClicked(TaskView tv) {
- if (mCb != null) {
- mCb.onTaskViewAppInfoClicked(tv.getTask());
-
- // Keep track of app-info invocations
- MetricsLogger.count(getContext(), "overview_app_info", 1);
- }
- }
-
- @Override
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask) {
// Cancel any doze triggers
mUIDozeTrigger.stopDozing();
@@ -1374,33 +1358,6 @@
}
@Override
- public void onTaskViewDismissed(TaskView tv) {
- Task task = tv.getTask();
- int taskIndex = mStack.indexOfTask(task);
- boolean taskWasFocused = tv.isFocusedTask();
- // Announce for accessibility
- tv.announceForAccessibility(getContext().getString(R.string.accessibility_recents_item_dismissed,
- tv.getTask().activityLabel));
- // Remove the task from the view
- mStack.removeTask(task);
- // If the dismissed task was focused, then we should focus the new task in the same index
- if (taskWasFocused) {
- ArrayList<Task> tasks = mStack.getTasks();
- int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex - 1);
- if (nextTaskIndex >= 0) {
- Task nextTask = tasks.get(nextTaskIndex);
- TaskView nextTv = getChildViewForTask(nextTask);
- if (nextTv != null) {
- // Focus the next task, and only animate the visible state if we are launched
- // from Alt-Tab
- RecentsActivityLaunchState launchState = mConfig.getLaunchState();
- nextTv.setFocusedTask(launchState.launchedWithAltTab);
- }
- }
- }
- }
-
- @Override
public void onTaskViewClipStateChanged(TaskView tv) {
if (!mStackViewsDirty) {
invalidate();
@@ -1414,13 +1371,6 @@
}
}
- @Override
- public void onTaskResize(TaskView tv) {
- if (mCb != null) {
- mCb.onTaskResize(tv.getTask());
- }
- }
-
/**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
@Override
@@ -1430,13 +1380,12 @@
postInvalidateOnAnimation();
}
- /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
+ /**** EventBus Events ****/
- @Override
- public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
+ public final void onBusEvent(PackagesChangedEvent event) {
// Compute which components need to be removed
- HashSet<ComponentName> removedComponents = monitor.computeComponentsRemoved(
- mStack.getTaskKeys(), packageName, userId);
+ HashSet<ComponentName> removedComponents = event.monitor.computeComponentsRemoved(
+ mStack.getTaskKeys(), event.packageName, event.userId);
// For other tasks, just remove them directly if they no longer exist
ArrayList<Task> tasks = mStack.getTasks();
@@ -1459,4 +1408,33 @@
}
}
}
+
+ public final void onBusEvent(DismissTaskEvent event) {
+ TaskView tv = event.taskView;
+ Task task = tv.getTask();
+ int taskIndex = mStack.indexOfTask(task);
+ boolean taskWasFocused = tv.isFocusedTask();
+
+ // Announce for accessibility
+ tv.announceForAccessibility(getContext().getString(R.string.accessibility_recents_item_dismissed,
+ tv.getTask().activityLabel));
+
+ // Remove the task from the view
+ mStack.removeTask(task);
+ // If the dismissed task was focused, then we should focus the new task in the same index
+ if (taskWasFocused) {
+ ArrayList<Task> tasks = mStack.getTasks();
+ int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex - 1);
+ if (nextTaskIndex >= 0) {
+ Task nextTask = tasks.get(nextTaskIndex);
+ TaskView nextTv = getChildViewForTask(nextTask);
+ if (nextTv != null) {
+ // Focus the next task, and only animate the visible state if we are launched
+ // from Alt-Tab
+ RecentsActivityLaunchState launchState = mConfig.getLaunchState();
+ nextTv.setFocusedTask(launchState.launchedWithAltTab);
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java
index e9f6a46..a32b242 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewFilterAlgorithm.java
@@ -16,9 +16,9 @@
package com.android.systemui.recents.views;
+import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.model.Task;
-import com.android.systemui.R;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 7f4c0a5..a8e6f47 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -18,11 +18,11 @@
import android.content.Context;
import android.graphics.Rect;
+import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
-import com.android.systemui.R;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index f0ae87f..e4fbc76 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -24,8 +24,8 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.OverScroller;
-import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.R;
+import com.android.systemui.recents.misc.Utilities;
/* The scrolling logic for a TaskStackView */
public class TaskStackViewScroller {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 86eced8..48c5b46 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -24,9 +24,11 @@
import android.view.ViewConfiguration;
import android.view.ViewParent;
import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
-import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.ui.DismissTaskEvent;
import java.util.List;
@@ -435,7 +437,7 @@
// Re-enable touch events from this task view
tv.setTouchEnabled(true);
// Remove the task view from the stack
- mSv.onTaskViewDismissed(tv);
+ EventBus.getDefault().send(new DismissTaskEvent(tv.getTask(), tv));
// Keep track of deletions by keyboard
MetricsLogger.histogram(tv.getContext(), "overview_task_dismissed_source",
Constants.Metrics.DismissSourceSwipeGesture);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index bbbaccf..910db87 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -30,34 +30,29 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
-import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
-import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.ui.DismissTaskEvent;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
/* A task view */
public class TaskView extends FrameLayout implements Task.TaskCallbacks,
- View.OnClickListener, View.OnLongClickListener {
+ View.OnClickListener {
/** The TaskView callbacks */
interface TaskViewCallbacks {
- public void onTaskViewAppIconClicked(TaskView tv);
- public void onTaskViewAppInfoClicked(TaskView tv);
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
- public void onTaskViewDismissed(TaskView tv);
public void onTaskViewClipStateChanged(TaskView tv);
public void onTaskViewFocusChanged(TaskView tv, boolean focused);
-
- public void onTaskResize(TaskView tv);
}
RecentsConfiguration mConfig;
@@ -535,9 +530,7 @@
startDeleteTaskAnimation(new Runnable() {
@Override
public void run() {
- if (mCb != null) {
- mCb.onTaskViewDismissed(tv);
- }
+ EventBus.getDefault().send(new DismissTaskEvent(mTask, tv));
}
}, 0);
}
@@ -725,17 +718,7 @@
mThumbnailView.rebindToTask(mTask);
mHeaderView.rebindToTask(mTask);
// Rebind any listeners
- AccessibilityManager am = (AccessibilityManager) getContext().
- getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (Constants.DebugFlags.App.EnableTaskFiltering || (am != null && am.isEnabled())) {
- mHeaderView.mApplicationIcon.setOnClickListener(this);
- }
- mHeaderView.mDismissButton.setOnClickListener(this);
- if (mConfig.multiWindowEnabled) {
- mHeaderView.mMoveTaskButton.setOnClickListener(this);
- }
mActionButtonView.setOnClickListener(this);
- mHeaderView.mApplicationIcon.setOnLongClickListener(this);
}
mTaskDataLoaded = true;
}
@@ -748,13 +731,7 @@
mThumbnailView.unbindFromTask();
mHeaderView.unbindFromTask();
// Unbind any listeners
- mHeaderView.mApplicationIcon.setOnClickListener(null);
- mHeaderView.mDismissButton.setOnClickListener(null);
- if (mConfig.multiWindowEnabled) {
- mHeaderView.mMoveTaskButton.setOnClickListener(null);
- }
mActionButtonView.setOnClickListener(null);
- mHeaderView.mApplicationIcon.setOnLongClickListener(null);
}
mTaskDataLoaded = false;
}
@@ -768,60 +745,12 @@
@Override
public void onClick(final View v) {
- final TaskView tv = this;
- final boolean delayViewClick = (v != this) && (v != mActionButtonView);
- if (delayViewClick) {
- // We purposely post the handler delayed to allow for the touch feedback to draw
- postDelayed(new Runnable() {
- @Override
- public void run() {
- if (v == mHeaderView.mApplicationIcon) {
- if (Constants.DebugFlags.App.EnableTaskFiltering) {
- if (mCb != null) {
- mCb.onTaskViewAppIconClicked(tv);
- }
- } else {
- AccessibilityManager am = (AccessibilityManager) getContext().
- getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (am != null && am.isEnabled()) {
- if (mCb != null) {
- mCb.onTaskViewAppInfoClicked(tv);
- }
- }
- }
- } else if (v == mHeaderView.mDismissButton) {
- dismissTask();
- // Keep track of deletions by the dismiss button
- MetricsLogger.histogram(getContext(), "overview_task_dismissed_source",
- Constants.Metrics.DismissSourceHeaderButton);
- } else if (v == mHeaderView.mMoveTaskButton) {
- if (mCb != null) {
- mCb.onTaskResize(tv);
- }
- }
- }
- }, 125);
- } else {
- if (v == mActionButtonView) {
- // Reset the translation of the action button before we animate it out
- mActionButtonView.setTranslationZ(0f);
- }
- if (mCb != null) {
- mCb.onTaskViewClicked(tv, tv.getTask(), (v == mActionButtonView));
- }
+ if (v == mActionButtonView) {
+ // Reset the translation of the action button before we animate it out
+ mActionButtonView.setTranslationZ(0f);
}
- }
-
- /**** View.OnLongClickListener Implementation ****/
-
- @Override
- public boolean onLongClick(View v) {
- if (v == mHeaderView.mApplicationIcon) {
- if (mCb != null) {
- mCb.onTaskViewAppInfoClicked(this);
- return true;
- }
+ if (mCb != null) {
+ mCb.onTaskViewClicked(this, mTask, (v == mActionButtonView));
}
- return false;
}
}
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 f68dd64..7de8b7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -39,14 +39,19 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.ui.ResizeTaskEvent;
+import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsTaskLoader;
@@ -54,10 +59,12 @@
/* The task bar view */
-public class TaskViewHeader extends FrameLayout {
+public class TaskViewHeader extends FrameLayout
+ implements View.OnClickListener, View.OnLongClickListener {
RecentsConfiguration mConfig;
private SystemServicesProxy mSsp;
+ Task mTask;
// Header views
ImageView mMoveTaskButton;
@@ -144,15 +151,15 @@
protected void onFinishInflate() {
// Initialize the icon and description views
mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
+ mApplicationIcon.setOnLongClickListener(this);
mActivityDescription = (TextView) findViewById(R.id.activity_description);
mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+ mDismissButton.setOnClickListener(this);
mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
// Hide the backgrounds if they are ripple drawables
- if (!Constants.DebugFlags.App.EnableTaskFiltering) {
- if (mApplicationIcon.getBackground() instanceof RippleDrawable) {
- mApplicationIcon.setBackground(null);
- }
+ if (mApplicationIcon.getBackground() instanceof RippleDrawable) {
+ mApplicationIcon.setBackground(null);
}
mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(R.drawable
@@ -203,6 +210,8 @@
/** Binds the bar view to the task */
public void rebindToTask(Task t) {
+ mTask = t;
+
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
if (t.activityIcon != null) {
@@ -238,6 +247,25 @@
mMoveTaskButton.setVisibility((mConfig.multiWindowEnabled) ? View.VISIBLE : View.INVISIBLE);
if (mConfig.multiWindowEnabled) {
updateResizeTaskBarIcon(t);
+ mMoveTaskButton.setOnClickListener(this);
+ }
+
+ // In accessibility, a single click on the focused app info button will show it
+ AccessibilityManager am = (AccessibilityManager) getContext().
+ getSystemService(Context.ACCESSIBILITY_SERVICE);
+ if (am != null && am.isEnabled()) {
+ mApplicationIcon.setOnClickListener(this);
+ }
+ }
+
+ /** Unbinds the bar view from the task */
+ void unbindFromTask() {
+ mTask = null;
+ mApplicationIcon.setImageDrawable(null);
+ mApplicationIcon.setOnClickListener(null);
+
+ if (mConfig.multiWindowEnabled) {
+ mMoveTaskButton.setOnClickListener(null);
}
}
@@ -274,11 +302,6 @@
mMoveTaskButton.setImageResource(resId);
}
- /** Unbinds the bar view from the task */
- void unbindFromTask() {
- mApplicationIcon.setImageDrawable(null);
- }
-
/** Animates this task bar dismiss button when launching a task. */
void startLaunchTaskDismissAnimation() {
if (mDismissButton.getVisibility() == View.VISIBLE) {
@@ -441,4 +464,30 @@
}
}
}
+
+ @Override
+ public void onClick(View v) {
+ if (v == mApplicationIcon) {
+ // In accessibility, a single click on the focused app info button will show it
+ EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
+ } else if (v == mDismissButton) {
+ TaskView tv = (TaskView) getParent().getParent();
+ tv.dismissTask();
+
+ // Keep track of deletions by the dismiss button
+ MetricsLogger.histogram(getContext(), "overview_task_dismissed_source",
+ Constants.Metrics.DismissSourceHeaderButton);
+ } else if (v == mMoveTaskButton) {
+ EventBus.getDefault().send(new ResizeTaskEvent(mTask));
+ }
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ if (v == mApplicationIcon) {
+ EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
+ return true;
+ }
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 6c83bee..690c297 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -34,9 +34,9 @@
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import com.android.systemui.R;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
-import com.android.systemui.R;
/**
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index a2967e8..5a27301 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1583,9 +1583,16 @@
nContextDeinitToClient(mContext);
mMessageThread.mRun = false;
- try {
- mMessageThread.join();
- } catch(InterruptedException e) {
+
+ // Wait for mMessageThread to join. Try in a loop, in case this thread gets interrupted
+ // during the wait.
+ boolean hasJoined = false;
+ while (!hasJoined) {
+ try {
+ mMessageThread.join();
+ hasJoined = true;
+ } catch(InterruptedException e) {
+ }
}
nContextDestroy();
diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
index 3283378..892e9da 100644
--- a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java
@@ -32,6 +32,7 @@
import android.view.MotionEvent.PointerCoords;
import android.view.MotionEvent.PointerProperties;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
/**
* Implements "Automatically click on mouse stop" feature.
@@ -56,8 +57,6 @@
*/
public class AutoclickController implements EventStreamTransformation {
- public static final int DEFAULT_CLICK_DELAY_MS = 600;
-
private static final String LOG_TAG = AutoclickController.class.getSimpleName();
private EventStreamTransformation mNext;
@@ -78,7 +77,8 @@
if (event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (mClickScheduler == null) {
Handler handler = new Handler(mContext.getMainLooper());
- mClickScheduler = new ClickScheduler(handler, DEFAULT_CLICK_DELAY_MS);
+ mClickScheduler =
+ new ClickScheduler(handler, AccessibilityManager.AUTOCLICK_DELAY_DEFAULT);
mClickDelayObserver = new ClickDelayObserver(mUserId, handler);
mClickDelayObserver.start(mContext.getContentResolver(), mClickScheduler);
}
@@ -230,7 +230,7 @@
if (mAutoclickDelaySettingUri.equals(uri)) {
int delay = Settings.Secure.getIntForUser(
mContentResolver, Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
- DEFAULT_CLICK_DELAY_MS, mUserId);
+ AccessibilityManager.AUTOCLICK_DELAY_DEFAULT, mUserId);
mClickScheduler.updateDelay(delay);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index c3f5c43..f6b32f7 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -112,12 +112,6 @@
// Timeout before trying to decide what the user is trying to do.
private final int mDetermineUserIntentTimeout;
- // Timeout within which we try to detect a tap.
- private final int mTapTimeout;
-
- // Slop between the down and up tap to be a tap.
- private final int mTouchSlop;
-
// Slop between the first and second tap to be a double tap.
private final int mDoubleTapSlop;
@@ -142,9 +136,6 @@
// Command for delayed sending of touch interaction end events.
private final SendAccessibilityEventDelayed mSendTouchInteractionEndDelayed;
- // Command for delayed sending of a long press.
- private final PerformLongPressDelayed mPerformLongPressDelayed;
-
// Command for exiting gesture detection mode after a timeout.
private final ExitGestureDetectionModeDelayed mExitGestureDetectionModeDelayed;
@@ -173,9 +164,6 @@
// Handle to the accessibility manager service.
private final AccessibilityManagerService mAms;
- // Temporary rectangle to avoid instantiation.
- private final Rect mTempRect = new Rect();
-
// Temporary point to avoid instantiation.
private final Point mTempPoint = new Point();
@@ -226,12 +214,9 @@
mAms = service;
mReceivedPointerTracker = new ReceivedPointerTracker();
mInjectedPointerTracker = new InjectedPointerTracker();
- mTapTimeout = ViewConfiguration.getTapTimeout();
mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
mHandler = new Handler(context.getMainLooper());
- mPerformLongPressDelayed = new PerformLongPressDelayed();
mExitGestureDetectionModeDelayed = new ExitGestureDetectionModeDelayed();
mGestureLibrary = GestureLibraries.fromRawResource(context, R.raw.accessibility_gestures);
mGestureLibrary.setOrientationStyle(8);
@@ -299,7 +284,6 @@
// Remove all pending callbacks.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
mExitGestureDetectionModeDelayed.cancel();
mSendTouchExplorationEndDelayed.cancel();
mSendTouchInteractionEndDelayed.cancel();
@@ -437,7 +421,6 @@
// we resent the delayed callback and wait again.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -447,18 +430,7 @@
mSendTouchInteractionEndDelayed.forceSendAndRemove();
}
- // If we have the first tap, schedule a long press and break
- // since we do not want to schedule hover enter because
- // the delayed callback will kick in before the long click.
- // This would lead to a state transition resulting in long
- // pressing the item below the double taped area which is
- // not necessary where accessibility focus is.
- if (mDoubleTapDetector.firstTapDetected()) {
- // We got a tap now post a long press action.
- mPerformLongPressDelayed.post(event, policyFlags);
- break;
- }
- if (!mTouchExplorationInProgress) {
+ if (!mDoubleTapDetector.firstTapDetected() && !mTouchExplorationInProgress) {
if (!mSendHoverEnterAndMoveDelayed.isPending()) {
// Deliver hover enter with a delay to have a chance
// to detect what the user is trying to do.
@@ -478,7 +450,6 @@
// decide what we will actually do next.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
} break;
case MotionEvent.ACTION_MOVE: {
final int pointerId = receivedTracker.getPrimaryPointerId();
@@ -521,7 +492,6 @@
mVelocityTracker.clear();
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
mExitGestureDetectionModeDelayed.post();
// Send accessibility event to announce the start
// of gesture recognition.
@@ -532,28 +502,12 @@
// exploring so start sending events.
mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE,
pointerIdBits, policyFlags);
}
break;
}
} else {
- // Cancel the long press if pending and the user
- // moved more than the slop.
- if (mPerformLongPressDelayed.isPending()) {
- final float deltaX =
- receivedTracker.getReceivedPointerDownX(pointerId)
- - rawEvent.getX(pointerIndex);
- final float deltaY =
- receivedTracker.getReceivedPointerDownY(pointerId)
- - rawEvent.getY(pointerIndex);
- final double moveDelta = Math.hypot(deltaX, deltaY);
- // The user has moved enough for us to decide.
- if (moveDelta > mTouchSlop) {
- mPerformLongPressDelayed.cancel();
- }
- }
if (mTouchExplorationInProgress) {
sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits,
@@ -569,9 +523,7 @@
// scheduled sending events.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.cancel();
if (mTouchExplorationInProgress) {
// If the user is touch exploring the second pointer may be
// performing a double tap to activate an item without need
@@ -620,9 +572,7 @@
// scheduled sending events.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.cancel();
// We are sending events so send exit and gesture
// end since we transition to another state.
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
@@ -643,7 +593,6 @@
final int pointerId = event.getPointerId(event.getActionIndex());
final int pointerIdBits = (1 << pointerId);
- mPerformLongPressDelayed.cancel();
mVelocityTracker.clear();
if (mSendHoverEnterAndMoveDelayed.isPending()) {
@@ -1110,6 +1059,7 @@
private final GestureDetector mGestureDetector;
private boolean mFirstTapDetected;
private boolean mDoubleTapDetected;
+ private int mPolicyFlags;
DoubleTapDetector(Context context) {
mGestureDetector = new GestureDetector(context, this);
@@ -1117,6 +1067,7 @@
}
public void onMotionEvent(MotionEvent event, int policyFlags) {
+ mPolicyFlags = policyFlags;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mDoubleTapDetected = false;
@@ -1135,6 +1086,11 @@
}
@Override
+ public void onLongPress(MotionEvent e) {
+ maybeSendLongPress(e, mPolicyFlags);
+ }
+
+ @Override
public boolean onSingleTapUp(MotionEvent event) {
mFirstTapDetected = true;
return false;
@@ -1154,6 +1110,38 @@
return true;
}
+ private void maybeSendLongPress(MotionEvent event, int policyFlags) {
+ if (!mDoubleTapDetected) {
+ return;
+ }
+
+ clear();
+
+ // Pointers should not be zero when running this command.
+ if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) {
+ return;
+ }
+
+ final int pointerIndex = event.getActionIndex();
+ final int pointerId = event.getPointerId(pointerIndex);
+
+ Point clickLocation = mTempPoint;
+ final int result = computeClickLocation(clickLocation);
+
+ if (result == CLICK_LOCATION_NONE) {
+ return;
+ }
+
+ mLongPressingPointerId = pointerId;
+ mLongPressingPointerDeltaX = (int) event.getX(pointerIndex) - clickLocation.x;
+ mLongPressingPointerDeltaY = (int) event.getY(pointerIndex) - clickLocation.y;
+
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+
+ mCurrentState = STATE_DELEGATING;
+ sendDownForAllNotInjectedPointers(event, policyFlags);
+ }
+
private void maybeFinishDoubleTap(MotionEvent event, int policyFlags) {
if (!mDoubleTapDetected) {
return;
@@ -1169,7 +1157,6 @@
// Remove pending event deliveries.
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
- mPerformLongPressDelayed.cancel();
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -1178,8 +1165,8 @@
mSendTouchInteractionEndDelayed.forceSendAndRemove();
}
- final int pointerId = event.getPointerId(event.getActionIndex());
- final int pointerIndex = event.findPointerIndex(pointerId);
+ final int pointerIndex = event.getActionIndex();
+ final int pointerId = event.getPointerId(pointerIndex);
Point clickLocation = mTempPoint;
final int result = computeClickLocation(clickLocation);
@@ -1306,65 +1293,6 @@
}
/**
- * Class for delayed sending of long press.
- */
- private final class PerformLongPressDelayed implements Runnable {
- private MotionEvent mEvent;
- private int mPolicyFlags;
-
- public void post(MotionEvent prototype, int policyFlags) {
- mEvent = MotionEvent.obtain(prototype);
- mPolicyFlags = policyFlags;
- mHandler.postDelayed(this, ViewConfiguration.getLongPressTimeout());
- }
-
- public void cancel() {
- if (mEvent != null) {
- mHandler.removeCallbacks(this);
- clear();
- }
- }
-
- private boolean isPending() {
- return mHandler.hasCallbacks(this);
- }
-
- @Override
- public void run() {
- // Pointers should not be zero when running this command.
- if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) {
- return;
- }
-
- final int pointerId = mEvent.getPointerId(mEvent.getActionIndex());
- final int pointerIndex = mEvent.findPointerIndex(pointerId);
-
- Point clickLocation = mTempPoint;
- final int result = computeClickLocation(clickLocation);
-
- if (result == CLICK_LOCATION_NONE) {
- return;
- }
-
- mLongPressingPointerId = pointerId;
- mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocation.x;
- mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocation.y;
-
- sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
-
- mCurrentState = STATE_DELEGATING;
- sendDownForAllNotInjectedPointers(mEvent, mPolicyFlags);
- clear();
- }
-
- private void clear() {
- mEvent.recycle();
- mEvent = null;
- mPolicyFlags = 0;
- }
- }
-
- /**
* Class for delayed sending of hover enter and move events.
*/
class SendHoverEnterAndMoveDelayed implements Runnable {
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index f245985..2aa0390 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -55,7 +55,8 @@
* Time in milliseconds in which the power button must be pressed twice so it will be considered
* as a camera launch.
*/
- private static final long CAMERA_POWER_DOUBLE_TAP_TIME_MS = 300;
+ private static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300;
+ private static final long CAMERA_POWER_DOUBLE_TAP_MIN_TIME_MS = 120;
/** The listener that receives the gesture event. */
private final GestureEventListener mGestureListener = new GestureEventListener();
@@ -256,14 +257,16 @@
synchronized (this) {
doubleTapInterval = event.getEventTime() - mLastPowerDown;
if (mCameraDoubleTapPowerEnabled
- && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_TIME_MS) {
+ && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS
+ && doubleTapInterval > CAMERA_POWER_DOUBLE_TAP_MIN_TIME_MS) {
launched = true;
intercept = interactive;
}
mLastPowerDown = event.getEventTime();
}
if (launched) {
- Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
+ Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval="
+ + doubleTapInterval + "ms");
launched = handleCameraLaunchGesture(false /* useWakelock */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
if (launched) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 9dad7a1..ab1d775 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -37,6 +37,7 @@
import org.xmlpull.v1.XmlSerializer;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.AppGlobals;
@@ -280,8 +281,19 @@
boolean mSystemReady;
/**
- * Id of the currently selected input method.
+ * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method.
+ * method. This is to be synchronized with the secure settings keyed with
+ * {@link Settings.Secure#DEFAULT_INPUT_METHOD}.
+ *
+ * <p>This can be transiently {@code null} when the system is re-initializing input method
+ * settings, e.g., the system locale is just changed.</p>
+ *
+ * <p>Note that {@link #mCurId} is used to track which IME is being connected to
+ * {@link InputMethodManagerService}.</p>
+ *
+ * @see #mCurId
*/
+ @Nullable
String mCurMethodId;
/**
@@ -311,9 +323,14 @@
EditorInfo mCurAttribute;
/**
- * The input method ID of the input method service that we are currently
+ * Id obtained with {@link InputMethodInfo#getId()} for the input method that we are currently
* connected to or in the process of connecting to.
+ *
+ * <p>This can be {@code null} when no input method is connected.</p>
+ *
+ * @see #mCurMethodId
*/
+ @Nullable
String mCurId;
/**
@@ -918,7 +935,6 @@
|| (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
if (!updateOnlyWhenLocaleChanged) {
hideCurrentInputLocked(0, null);
- mCurMethodId = null;
unbindCurrentMethodLocked(true, false);
}
if (DEBUG) {
@@ -1474,7 +1490,11 @@
channel.dispose();
}
- void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
+ void unbindCurrentMethodLocked(boolean resetCurrentMethodAndClient, boolean savePosition) {
+ if (resetCurrentMethodAndClient) {
+ mCurMethodId = null;
+ }
+
if (mVisibleBound) {
mContext.unbindService(mVisibleConnection);
mVisibleBound = false;
@@ -1501,9 +1521,8 @@
mCurId = null;
clearCurMethodLocked();
- if (reportToClient && mCurClient != null) {
- executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
- MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
+ if (resetCurrentMethodAndClient) {
+ unbindCurrentClientLocked();
}
}
@@ -1857,13 +1876,11 @@
setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Unknown input method from prefs: " + id, e);
- mCurMethodId = null;
unbindCurrentMethodLocked(true, false);
}
mShortcutInputMethodsAndSubtypes.clear();
} else {
// There is no longer an input method set, so stop any current one.
- mCurMethodId = null;
unbindCurrentMethodLocked(true, false);
}
// Here is not the perfect place to reset the switching controller. Ideally
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index c3d32c2..4d32599 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -29,6 +29,7 @@
import android.Manifest;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppOpsManager;
import android.app.IActivityManager;
@@ -90,7 +91,6 @@
import libcore.util.EmptyArray;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.Zygote;
@@ -290,7 +290,7 @@
private ArrayMap<String, DiskInfo> mDisks = new ArrayMap<>();
/** Map from volume ID to disk */
@GuardedBy("mLock")
- private ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
+ private final ArrayMap<String, VolumeInfo> mVolumes = new ArrayMap<>();
/** Map from UUID to record */
@GuardedBy("mLock")
@@ -462,11 +462,7 @@
public ObbState(String rawPath, String canonicalPath, int callingUid,
IObbActionListener token, int nonce) {
this.rawPath = rawPath;
- this.canonicalPath = canonicalPath.toString();
-
- final int userId = UserHandle.getUserId(callingUid);
- this.ownerPath = buildObbPath(canonicalPath, userId, false);
- this.voldPath = buildObbPath(canonicalPath, userId, true);
+ this.canonicalPath = canonicalPath;
this.ownerGid = UserHandle.getSharedAppGid(callingUid);
this.token = token;
@@ -475,8 +471,6 @@
final String rawPath;
final String canonicalPath;
- final String ownerPath;
- final String voldPath;
final int ownerGid;
@@ -509,8 +503,6 @@
StringBuilder sb = new StringBuilder("ObbState{");
sb.append("rawPath=").append(rawPath);
sb.append(",canonicalPath=").append(canonicalPath);
- sb.append(",ownerPath=").append(ownerPath);
- sb.append(",voldPath=").append(voldPath);
sb.append(",ownerGid=").append(ownerGid);
sb.append(",token=").append(token);
sb.append(",binder=").append(getBinder());
@@ -569,6 +561,7 @@
private static final int H_VOLUME_MOUNT = 5;
private static final int H_VOLUME_BROADCAST = 6;
private static final int H_INTERNAL_BROADCAST = 7;
+ private static final int H_VOLUME_UNMOUNT = 8;
class MountServiceHandler extends Handler {
public MountServiceHandler(Looper looper) {
@@ -649,6 +642,11 @@
}
break;
}
+ case H_VOLUME_UNMOUNT: {
+ final VolumeInfo vol = (VolumeInfo) msg.obj;
+ unmount(vol.getId());
+ break;
+ }
case H_VOLUME_BROADCAST: {
final StorageVolume userVol = (StorageVolume) msg.obj;
final String envState = userVol.getState();
@@ -683,6 +681,7 @@
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ Preconditions.checkArgument(userId >= 0);
try {
if (Intent.ACTION_USER_ADDED.equals(action)) {
@@ -690,6 +689,16 @@
final int userSerialNumber = um.getUserSerialNumber(userId);
mConnector.execute("volume", "user_added", userId, userSerialNumber);
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ synchronized (mVolumes) {
+ final int size = mVolumes.size();
+ for (int i = 0; i < size; i++) {
+ final VolumeInfo vol = mVolumes.valueAt(i);
+ if (vol.mountUserId == userId) {
+ vol.mountUserId = UserHandle.USER_NULL;
+ mHandler.obtainMessage(H_VOLUME_UNMOUNT, vol).sendToTarget();
+ }
+ }
+ }
mConnector.execute("volume", "user_removed", userId);
}
} catch (NativeDaemonConnectorException e) {
@@ -757,17 +766,26 @@
* paths never changing, so we outright kill them to pick up new state.
*/
@Deprecated
- private void killMediaProvider() {
+ private void killMediaProvider(List<UserInfo> users) {
+ if (users == null) return;
+
final long token = Binder.clearCallingIdentity();
try {
- final ProviderInfo provider = mPms.resolveContentProvider(MediaStore.AUTHORITY, 0,
- UserHandle.USER_OWNER);
- if (provider != null) {
- final IActivityManager am = ActivityManagerNative.getDefault();
- try {
- am.killApplicationWithAppId(provider.applicationInfo.packageName,
- UserHandle.getAppId(provider.applicationInfo.uid), "vold reset");
- } catch (RemoteException e) {
+ for (UserInfo user : users) {
+ // System user does not have media provider, so skip.
+ if (user.isSystemOnly()) continue;
+
+ final ProviderInfo provider =
+ mPms.resolveContentProvider(MediaStore.AUTHORITY, 0, user.id);
+ if (provider != null) {
+ final IActivityManager am = ActivityManagerNative.getDefault();
+ try {
+ am.killApplicationWithAppId(provider.applicationInfo.packageName,
+ UserHandle.getAppId(provider.applicationInfo.uid), "vold reset");
+ // We only need to run this once. It will kill all users' media processes.
+ break;
+ } catch (RemoteException e) {
+ }
}
}
} finally {
@@ -788,7 +806,9 @@
Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady
+ ", mDaemonConnected=" + mDaemonConnected);
if (mSystemReady && mDaemonConnected) {
- killMediaProvider();
+ final UserManager um = UserManager.get(mContext);
+ final List<UserInfo> users = um.getUsers();
+ killMediaProvider(users);
mDisks.clear();
mVolumes.clear();
@@ -799,8 +819,6 @@
mConnector.execute("volume", "reset");
// Tell vold about all existing and started users
- final UserManager um = mContext.getSystemService(UserManager.class);
- final List<UserInfo> users = um.getUsers();
for (UserInfo user : users) {
mConnector.execute("volume", "user_added", user.id, user.serialNumber);
}
@@ -1192,7 +1210,7 @@
vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
}
- vol.mountUserId = UserHandle.USER_OWNER;
+ vol.mountUserId = ActivityManager.getCurrentUser();
mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
} else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
@@ -2285,7 +2303,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("obb", "path", state.voldPath);
+ event = mConnector.execute("obb", "path", state.canonicalPath);
event.checkCode(VoldResponseCode.AsecPathResult);
return event.getMessage();
} catch (NativeDaemonConnectorException e) {
@@ -3038,14 +3056,14 @@
protected ObbInfo getObbInfo() throws IOException {
ObbInfo obbInfo;
try {
- obbInfo = mContainerService.getObbInfo(mObbState.ownerPath);
+ obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
} catch (RemoteException e) {
Slog.d(TAG, "Couldn't call DefaultContainerService to fetch OBB info for "
- + mObbState.ownerPath);
+ + mObbState.canonicalPath);
obbInfo = null;
}
if (obbInfo == null) {
- throw new IOException("Couldn't read OBB file: " + mObbState.ownerPath);
+ throw new IOException("Couldn't read OBB file: " + mObbState.canonicalPath);
}
return obbInfo;
}
@@ -3122,7 +3140,7 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("obb", "mount", mObbState.voldPath, new SensitiveArg(hashedKey),
+ mConnector.execute("obb", "mount", mObbState.canonicalPath, new SensitiveArg(hashedKey),
mObbState.ownerGid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
@@ -3133,7 +3151,7 @@
if (rc == StorageResultCode.OperationSucceeded) {
if (DEBUG_OBB)
- Slog.d(TAG, "Successfully mounted OBB " + mObbState.voldPath);
+ Slog.d(TAG, "Successfully mounted OBB " + mObbState.canonicalPath);
synchronized (mObbMounts) {
addObbStateLocked(mObbState);
@@ -3194,7 +3212,7 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- final Command cmd = new Command("obb", "unmount", mObbState.voldPath);
+ final Command cmd = new Command("obb", "unmount", mObbState.canonicalPath);
if (mForceUnmount) {
cmd.appendArg("force");
}
@@ -3240,49 +3258,6 @@
}
}
- @VisibleForTesting
- public static String buildObbPath(final String canonicalPath, int userId, boolean forVold) {
- // TODO: allow caller to provide Environment for full testing
- // TODO: extend to support OBB mounts on secondary external storage
-
- // Only adjust paths when storage is emulated
- if (!Environment.isExternalStorageEmulated()) {
- return canonicalPath;
- }
-
- String path = canonicalPath.toString();
-
- // First trim off any external storage prefix
- final UserEnvironment userEnv = new UserEnvironment(userId);
-
- // /storage/emulated/0
- final String externalPath = userEnv.getExternalStorageDirectory().getAbsolutePath();
- // /storage/emulated_legacy
- final String legacyExternalPath = Environment.getLegacyExternalStorageDirectory()
- .getAbsolutePath();
-
- if (path.startsWith(externalPath)) {
- path = path.substring(externalPath.length() + 1);
- } else if (path.startsWith(legacyExternalPath)) {
- path = path.substring(legacyExternalPath.length() + 1);
- } else {
- return canonicalPath;
- }
-
- // Handle special OBB paths on emulated storage
- final String obbPath = "Android/obb";
- if (path.startsWith(obbPath)) {
- path = path.substring(obbPath.length() + 1);
-
- final UserEnvironment ownerEnv = new UserEnvironment(UserHandle.USER_OWNER);
- return new File(ownerEnv.buildExternalStorageAndroidObbDirs()[0], path)
- .getAbsolutePath();
- }
-
- // Handle normal external storage paths
- return new File(userEnv.getExternalStorageDirectory(), path).getAbsolutePath();
- }
-
private static class Callbacks extends Handler {
private static final int MSG_STORAGE_STATE_CHANGED = 1;
private static final int MSG_VOLUME_STATE_CHANGED = 2;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 24b90d8..d4e798f 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -477,8 +477,8 @@
}
}
- boolean isNotResolverActivity() {
- return !ResolverActivity.class.getName().equals(realActivity.getClassName());
+ boolean isResolverActivity() {
+ return ResolverActivity.class.getName().equals(realActivity.getClassName());
}
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
@@ -605,7 +605,7 @@
_intent.getData() == null &&
_intent.getType() == null &&
(intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
- isNotResolverActivity()) {
+ !isResolverActivity()) {
// This sure looks like a home activity!
mActivityType = HOME_ACTIVITY_TYPE;
} else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a796ea7..f549af8 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1153,7 +1153,7 @@
next.results = null;
next.newIntents = null;
- if (next.isHomeActivity() && next.isNotResolverActivity()) {
+ if (next.isHomeActivity()) {
ProcessRecord app = next.task.mActivities.get(0).app;
if (app != null && app != mService.mHomeProcess) {
mService.mHomeProcess = app;
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 98b6ee6..ac7b9b1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1262,7 +1262,7 @@
r.userId, System.identityHashCode(r),
task.taskId, r.shortComponentName);
}
- if (r.isHomeActivity() && r.isNotResolverActivity()) {
+ if (r.isHomeActivity()) {
// Home process is the root process of the task.
mService.mHomeProcess = task.mActivities.get(0).app;
}
@@ -2024,6 +2024,14 @@
reuseTask = inTask;
} else {
inTask = null;
+ // Launch ResolverActivity in the source task, so that it stays in the task
+ // bounds when in freeform workspace.
+ // Also put noDisplay activities in the source task. These by itself can
+ // be placed in any task/stack, however it could launch other activities
+ // like ResolverActivity, and we want those to stay in the original task.
+ if (r.isResolverActivity() || r.noDisplay) {
+ addingToTask = true;
+ }
}
if (inTask == null) {
@@ -3091,7 +3099,7 @@
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + task.taskId);
final Configuration overrideConfig = task.updateOverrideConfiguration(bounds);
- // This variable holds information whether the configuration didn't change in a signficant
+ // This variable holds information whether the configuration didn't change in a significant
// way and the activity was kept the way it was. If it's false, it means the activity had
// to be relaunched due to configuration change.
boolean kept = true;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e49a7e4..c4b57f1 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -501,7 +501,6 @@
private volatile IRingtonePlayer mRingtonePlayer;
private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
- private int mDeviceRotation = Surface.ROTATION_0;
// Request to override default use of A2DP for media.
private boolean mBluetoothA2dpEnabled;
@@ -545,8 +544,6 @@
// If absolute volume is supported in AVRCP device
private boolean mAvrcpAbsVolSupported = false;
- private AudioOrientationEventListener mOrientationListener;
-
private static Long mLastDeviceConnectMsgTime = new Long(0);
private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
@@ -669,15 +666,7 @@
}
mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
if (mMonitorRotation) {
- mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay().getRotation();
- Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation);
-
- mOrientationListener = new AudioOrientationEventListener(mContext);
- mOrientationListener.enable();
-
- // initialize rotation in AudioSystem
- setRotationForAudioSystem();
+ RotationHelper.init(mContext, mAudioHandler);
}
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
@@ -805,7 +794,7 @@
setOrientationForAudioSystem();
}
if (mMonitorRotation) {
- setRotationForAudioSystem();
+ RotationHelper.updateOrientation();
}
synchronized (mBluetoothA2dpEnabledLock) {
@@ -1058,25 +1047,6 @@
return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
}
- private class AudioOrientationEventListener
- extends OrientationEventListener {
- public AudioOrientationEventListener(Context context) {
- super(context);
- }
-
- @Override
- public void onOrientationChanged(int orientation) {
- //Even though we're responding to phone orientation events,
- //use display rotation so audio stays in sync with video/dialogs
- int newRotation = ((WindowManager) mContext.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
- if (newRotation != mDeviceRotation) {
- mDeviceRotation = newRotation;
- setRotationForAudioSystem();
- }
- }
- }
-
///////////////////////////////////////////////////////////////////////////
// IPC methods
///////////////////////////////////////////////////////////////////////////
@@ -5066,14 +5036,13 @@
}
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
if (mMonitorRotation) {
- mOrientationListener.onOrientationChanged(0); //argument is ignored anyway
- mOrientationListener.enable();
+ RotationHelper.enable();
}
AudioSystem.setParameters("screen_state=on");
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
if (mMonitorRotation) {
//reduce wakeups (save current) by only listening when display is on
- mOrientationListener.disable();
+ RotationHelper.disable();
}
AudioSystem.setParameters("screen_state=off");
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
@@ -5322,6 +5291,7 @@
}
}
+ //TODO move to an external "orientation helper" class
private void setOrientationForAudioSystem() {
switch (mDeviceOrientation) {
case Configuration.ORIENTATION_LANDSCAPE:
@@ -5345,26 +5315,6 @@
}
}
- private void setRotationForAudioSystem() {
- switch (mDeviceRotation) {
- case Surface.ROTATION_0:
- AudioSystem.setParameters("rotation=0");
- break;
- case Surface.ROTATION_90:
- AudioSystem.setParameters("rotation=90");
- break;
- case Surface.ROTATION_180:
- AudioSystem.setParameters("rotation=180");
- break;
- case Surface.ROTATION_270:
- AudioSystem.setParameters("rotation=270");
- break;
- default:
- Log.e(TAG, "Unknown device rotation");
- }
- }
-
-
// Handles request to override default use of A2DP for media.
// Must be called synchronized on mConnectedDevices
public void setBluetoothA2dpOnInt(boolean on) {
diff --git a/services/core/java/com/android/server/audio/RotationHelper.java b/services/core/java/com/android/server/audio/RotationHelper.java
new file mode 100644
index 0000000..f03e6c7
--- /dev/null
+++ b/services/core/java/com/android/server/audio/RotationHelper.java
@@ -0,0 +1,209 @@
+/*
+ * 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.server.audio;
+
+import android.content.Context;
+import android.media.AudioSystem;
+import android.os.Handler;
+import android.util.Log;
+import android.view.OrientationEventListener;
+import android.view.Surface;
+import android.view.WindowManager;
+
+import com.android.server.policy.WindowOrientationListener;
+
+/**
+ * Class to handle device rotation events for AudioService, and forward device rotation
+ * to the audio HALs through AudioSystem.
+ *
+ * The role of this class is to monitor device orientation changes, and upon rotation,
+ * verify the UI orientation. In case of a change, send the new orientation, in increments
+ * of 90deg, through AudioSystem.
+ *
+ * Note that even though we're responding to device orientation events, we always
+ * query the display rotation so audio stays in sync with video/dialogs. This is
+ * done with .getDefaultDisplay().getRotation() from WINDOW_SERVICE.
+ */
+class RotationHelper {
+
+ private static final String TAG = "AudioService.RotationHelper";
+
+ private static AudioOrientationListener sOrientationListener;
+ private static AudioWindowOrientationListener sWindowOrientationListener;
+
+ private static final Object sRotationLock = new Object();
+ private static int sDeviceRotation = Surface.ROTATION_0; // R/W synchronized on sRotationLock
+
+ private static Context sContext;
+
+ /**
+ * post conditions:
+ * - (sWindowOrientationListener != null) xor (sOrientationListener != null)
+ * - sWindowOrientationListener xor sOrientationListener is enabled
+ * - sContext != null
+ */
+ static void init(Context context, Handler handler) {
+ if (context == null) {
+ throw new IllegalArgumentException("Invalid null context");
+ }
+ sContext = context;
+ sWindowOrientationListener = new AudioWindowOrientationListener(context, handler);
+ sWindowOrientationListener.enable();
+ if (!sWindowOrientationListener.canDetectOrientation()) {
+ // cannot use com.android.server.policy.WindowOrientationListener, revert to public
+ // orientation API
+ Log.i(TAG, "Not using WindowOrientationListener, reverting to OrientationListener");
+ sWindowOrientationListener.disable();
+ sWindowOrientationListener = null;
+ sOrientationListener = new AudioOrientationListener(context);
+ sOrientationListener.enable();
+ }
+ }
+
+ static void enable() {
+ if (sWindowOrientationListener != null) {
+ sWindowOrientationListener.enable();
+ } else {
+ sOrientationListener.enable();
+ }
+ updateOrientation();
+ }
+
+ static void disable() {
+ if (sWindowOrientationListener != null) {
+ sWindowOrientationListener.disable();
+ } else {
+ sOrientationListener.disable();
+ }
+ }
+
+ /**
+ * Query current display rotation and publish the change if any.
+ */
+ static void updateOrientation() {
+ // Even though we're responding to device orientation events,
+ // use display rotation so audio stays in sync with video/dialogs
+ int newRotation = ((WindowManager) sContext.getSystemService(
+ Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
+ synchronized(sRotationLock) {
+ if (newRotation != sDeviceRotation) {
+ sDeviceRotation = newRotation;
+ publishRotation(sDeviceRotation);
+ }
+ }
+ }
+
+ private static void publishRotation(int rotation) {
+ Log.v(TAG, "publishing device rotation =" + rotation + " (x90deg)");
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ AudioSystem.setParameters("rotation=0");
+ break;
+ case Surface.ROTATION_90:
+ AudioSystem.setParameters("rotation=90");
+ break;
+ case Surface.ROTATION_180:
+ AudioSystem.setParameters("rotation=180");
+ break;
+ case Surface.ROTATION_270:
+ AudioSystem.setParameters("rotation=270");
+ break;
+ default:
+ Log.e(TAG, "Unknown device rotation");
+ }
+ }
+
+ /**
+ * Uses android.view.OrientationEventListener
+ */
+ final static class AudioOrientationListener extends OrientationEventListener {
+ AudioOrientationListener(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onOrientationChanged(int orientation) {
+ updateOrientation();
+ }
+ }
+
+ /**
+ * Uses com.android.server.policy.WindowOrientationListener
+ */
+ final static class AudioWindowOrientationListener extends WindowOrientationListener {
+ private static RotationCheckThread sRotationCheckThread;
+
+ AudioWindowOrientationListener(Context context, Handler handler) {
+ super(context, handler);
+ }
+
+ public void onProposedRotationChanged(int rotation) {
+ updateOrientation();
+ if (sRotationCheckThread != null) {
+ sRotationCheckThread.endCheck();
+ }
+ sRotationCheckThread = new RotationCheckThread();
+ sRotationCheckThread.beginCheck();
+ }
+ }
+
+ /**
+ * When com.android.server.policy.WindowOrientationListener report an orientation change,
+ * the UI may not have rotated yet. This thread polls with gradually increasing delays
+ * the new orientation.
+ */
+ final static class RotationCheckThread extends Thread {
+ // how long to wait between each rotation check
+ private final int[] WAIT_TIMES_MS = { 10, 20, 50, 100, 100, 200, 200, 500 };
+ private int mWaitCounter;
+ private final Object mCounterLock = new Object();
+
+ RotationCheckThread() {
+ super("RotationCheck");
+ }
+
+ void beginCheck() {
+ synchronized(mCounterLock) {
+ mWaitCounter = 0;
+ }
+ try {
+ start();
+ } catch (IllegalStateException e) { }
+ }
+
+ void endCheck() {
+ synchronized(mCounterLock) {
+ mWaitCounter = WAIT_TIMES_MS.length;
+ }
+ }
+
+ public void run() {
+ int newRotation;
+ while (mWaitCounter < WAIT_TIMES_MS.length) {
+ updateOrientation();
+ int waitTimeMs;
+ synchronized(mCounterLock) {
+ waitTimeMs = WAIT_TIMES_MS[mWaitCounter];
+ mWaitCounter++;
+ }
+ try {
+ sleep(waitTimeMs);
+ } catch (InterruptedException e) { }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index a441cb2..6e32e5c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -946,7 +946,7 @@
}
final int uid = mPm.getPackageUid(PackageManagerService.DEFAULT_CONTAINER_PACKAGE,
- UserHandle.USER_OWNER);
+ UserHandle.USER_SYSTEM);
final int gid = UserHandle.getSharedAppGid(uid);
if (!PackageHelper.fixSdPermissions(cid, gid, null)) {
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2009ccf..99562f3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1108,7 +1108,7 @@
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
if (mContext.bindServiceAsUser(service, mDefContainerConn,
- Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mBound = true;
return true;
@@ -1715,7 +1715,7 @@
for (PackageSetting ps : packages) {
Slog.d(TAG, "Destroying " + ps.name + " because volume was forgotten");
deletePackage(ps.name, new LegacyPackageDeleteObserver(null).getBinder(),
- UserHandle.USER_OWNER, PackageManager.DELETE_ALL_USERS);
+ UserHandle.USER_SYSTEM, PackageManager.DELETE_ALL_USERS);
}
mSettings.onVolumeForgotten(fsUuid);
@@ -1726,7 +1726,7 @@
private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int userId,
String[] grantedPermissions) {
- if (userId >= UserHandle.USER_OWNER) {
+ if (userId >= UserHandle.USER_SYSTEM) {
grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions);
} else if (userId == UserHandle.USER_ALL) {
final int[] userIds;
@@ -2276,7 +2276,7 @@
mSettings.enableSystemPackageLPw(packageName);
try {
- scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
+ scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, UserHandle.SYSTEM);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
@@ -2401,8 +2401,9 @@
private String getRequiredVerifierLPr() {
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ // We only care about verifier that's installed under system user.
final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
- PackageManager.GET_DISABLED_COMPONENTS, 0 /* TODO: Which userId? */);
+ PackageManager.GET_DISABLED_COMPONENTS, UserHandle.USER_SYSTEM);
String requiredVerifier = null;
@@ -2417,7 +2418,7 @@
final String packageName = info.activityInfo.packageName;
if (checkPermission(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- packageName, UserHandle.USER_OWNER) != PackageManager.PERMISSION_GRANTED) {
+ packageName, UserHandle.USER_SYSTEM) != PackageManager.PERMISSION_GRANTED) {
continue;
}
@@ -2437,7 +2438,7 @@
installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), PACKAGE_MIME_TYPE);
final List<ResolveInfo> installers = queryIntentActivities(installerIntent,
- PACKAGE_MIME_TYPE, 0, 0);
+ PACKAGE_MIME_TYPE, 0, UserHandle.USER_SYSTEM);
String requiredInstaller = null;
@@ -2467,7 +2468,7 @@
private ComponentName getIntentFilterVerifierComponentNameLPr() {
final Intent verification = new Intent(Intent.ACTION_INTENT_FILTER_NEEDS_VERIFICATION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
- PackageManager.GET_DISABLED_COMPONENTS, 0 /* userId */);
+ PackageManager.GET_DISABLED_COMPONENTS, UserHandle.USER_SYSTEM);
ComponentName verifierComponentName = null;
@@ -2488,7 +2489,7 @@
}
if (checkPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT,
- packageName, UserHandle.USER_OWNER) != PackageManager.PERMISSION_GRANTED) {
+ packageName, UserHandle.USER_SYSTEM) != PackageManager.PERMISSION_GRANTED) {
continue;
}
@@ -2784,8 +2785,7 @@
if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) {
return -1;
}
- p = ps.pkg;
- return p != null ? UserHandle.getUid(userId, p.applicationInfo.uid) : -1;
+ return UserHandle.getUid(userId, ps.pkg.applicationInfo.uid);
}
}
@@ -5690,7 +5690,7 @@
}
try {
scanPackageTracedLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
- scanFlags, currentTime, null);
+ scanFlags, currentTime, UserHandle.SYSTEM);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
@@ -5796,6 +5796,8 @@
*/
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
+ Preconditions.checkNotNull(user);
+
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
parseFlags |= mDefParseFlags;
PackageParser pp = new PackageParser();
@@ -5837,7 +5839,7 @@
}
boolean updatedPkgBetter = false;
// First check if this is a system package that may involve an update
- if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
+ if (updatedPkg != null && (parseFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
// If new package is not located in "/system/priv-app" (e.g. due to an OTA),
// it needs to drop FLAG_PRIVILEGED.
if (locationIsPrivileged(scanFile)) {
@@ -6932,7 +6934,7 @@
} else {
// This is a normal package, need to make its data directory.
dataPath = Environment.getDataUserPackageDirectory(pkg.volumeUuid,
- UserHandle.USER_OWNER, pkg.packageName);
+ UserHandle.USER_SYSTEM, pkg.packageName);
boolean uidError = false;
if (dataPath.exists()) {
@@ -7090,7 +7092,7 @@
// if they already exist
if (!TextUtils.isEmpty(pkg.volumeUuid)) {
for (int userId : userIds) {
- if (userId != 0) {
+ if (userId != UserHandle.USER_SYSTEM) {
mInstaller.createUserData(pkg.volumeUuid, pkg.packageName,
UserHandle.getUid(userId, pkg.applicationInfo.uid), userId,
pkg.applicationInfo.seinfo);
@@ -7218,7 +7220,6 @@
for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
if (name.equals(sysPs.pkg.libraryNames.get(j))) {
allowed = true;
- allowed = true;
break;
}
}
@@ -9603,7 +9604,7 @@
if (am != null) {
try {
am.startService(null, intent, null, mContext.getOpPackageName(),
- UserHandle.USER_OWNER);
+ UserHandle.USER_SYSTEM);
} catch (RemoteException e) {
}
}
@@ -10322,7 +10323,8 @@
+ " to BM for possible restore");
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
try {
- if (bm.isBackupServiceActive(UserHandle.USER_OWNER)) {
+ // TODO: http://b/22388012
+ if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
} else {
doRestore = false;
@@ -10803,14 +10805,11 @@
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
- /*
- * ADB installs appear as UserHandle.USER_ALL, and can only be performed by
- * UserHandle.USER_OWNER, so use the package verifier for UserHandle.USER_OWNER.
- */
- int userIdentifier = getUser().getIdentifier();
- if (userIdentifier == UserHandle.USER_ALL
- && ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0)) {
- userIdentifier = UserHandle.USER_OWNER;
+ // TODO: http://b/22976637
+ // Apps installed for "all" users use the device owner to verify the app
+ UserHandle verifierUser = getUser();
+ if (verifierUser == UserHandle.ALL) {
+ verifierUser = UserHandle.SYSTEM;
}
/*
@@ -10818,9 +10817,9 @@
* do, then we'll defer to them to verify the packages.
*/
final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, userIdentifier);
+ : getPackageUid(mRequiredVerifierPackage, verifierUser.getIdentifier());
if (!origin.existing && requiredUid != -1
- && isVerificationEnabled(userIdentifier, installFlags)) {
+ && isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) {
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -10830,7 +10829,7 @@
final List<ResolveInfo> receivers = queryIntentReceivers(verification,
PACKAGE_MIME_TYPE, PackageManager.GET_DISABLED_COMPONENTS,
- 0 /* TODO: Which userId? */);
+ verifierUser.getIdentifier());
if (DEBUG_VERIFY) {
Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
@@ -10885,12 +10884,6 @@
final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
receivers, verificationState);
- // Apps installed for "all" users use the device owner to verify the app
- UserHandle verifierUser = getUser();
- if (verifierUser == UserHandle.ALL) {
- verifierUser = UserHandle.OWNER;
- }
-
/*
* If any sufficient verifiers were listed in the package
* manifest, attempt to ask them.
@@ -12121,7 +12114,8 @@
(oldExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
int oldScanFlags = SCAN_UPDATE_SIGNATURE | SCAN_UPDATE_TIME;
try {
- scanPackageTracedLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime, null);
+ scanPackageTracedLI(restoreFile, oldParseFlags, oldScanFlags, origUpdateTime,
+ UserHandle.SYSTEM);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade: "
+ e.getMessage());
@@ -12616,7 +12610,7 @@
final int verifierUid = getPackageUid(
mIntentFilterVerifierComponent.getPackageName(),
- (userId == UserHandle.USER_ALL) ? UserHandle.USER_OWNER : userId);
+ (userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId);
mHandler.removeMessages(START_INTENT_FILTER_VERIFICATIONS);
final Message msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS);
@@ -12816,11 +12810,14 @@
Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(observer);
final int uid = Binder.getCallingUid();
- if (UserHandle.getUserId(uid) != userId) {
+ final boolean deleteAllUsers = (flags & PackageManager.DELETE_ALL_USERS) != 0;
+ final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
+ if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
mContext.enforceCallingPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"deletePackage for user " + userId);
}
+
if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
try {
observer.onPackageDeleted(packageName,
@@ -12830,25 +12827,15 @@
return;
}
- boolean uninstallBlocked = false;
- if ((flags & PackageManager.DELETE_ALL_USERS) != 0) {
- int[] users = sUserManager.getUserIds();
- for (int i = 0; i < users.length; ++i) {
- if (getBlockUninstallForUser(packageName, users[i])) {
- uninstallBlocked = true;
- break;
+ for (int currentUserId : users) {
+ if (getBlockUninstallForUser(packageName, currentUserId)) {
+ try {
+ observer.onPackageDeleted(packageName,
+ PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
+ } catch (RemoteException re) {
}
+ return;
}
- } else {
- uninstallBlocked = getBlockUninstallForUser(packageName, userId);
- }
- if (uninstallBlocked) {
- try {
- observer.onPackageDeleted(packageName, PackageManager.DELETE_FAILED_OWNER_BLOCKED,
- null);
- } catch (RemoteException re) {
- }
- return;
}
if (DEBUG_REMOVE) {
@@ -12859,13 +12846,11 @@
public void run() {
mHandler.removeCallbacks(this);
final int returnCode = deletePackageX(packageName, userId, flags);
- if (observer != null) {
- try {
- observer.onPackageDeleted(packageName, returnCode, null);
- } catch (RemoteException e) {
- Log.i(TAG, "Observer no longer exists.");
- } //end catch
- } //end if
+ try {
+ observer.onPackageDeleted(packageName, returnCode, null);
+ } catch (RemoteException e) {
+ Log.i(TAG, "Observer no longer exists.");
+ } //end catch
} //end run
});
}
@@ -13063,7 +13048,7 @@
final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
userId);
if (userIdToKill == UserHandle.USER_ALL
- || userIdToKill >= UserHandle.USER_OWNER) {
+ || userIdToKill >= UserHandle.USER_SYSTEM) {
// If gids changed for this user, kill all affected packages.
mHandler.post(new Runnable() {
@Override
@@ -13180,7 +13165,8 @@
final PackageParser.Package newPkg;
try {
- newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, SCAN_NO_PATHS, 0, null);
+ newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, SCAN_NO_PATHS, 0,
+ UserHandle.SYSTEM);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + newPs.name + ": " + e.getMessage());
return false;
@@ -13431,7 +13417,7 @@
}
final ClearStorageConnection conn = new ClearStorageConnection();
if (mContext.bindServiceAsUser(
- containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
+ containerIntent, conn, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
try {
for (int curUser : users) {
long timeout = SystemClock.uptimeMillis() + 5000;
@@ -15743,7 +15729,8 @@
synchronized (mInstallLock) {
PackageParser.Package pkg = null;
try {
- pkg = scanPackageTracedLI(new File(codePath), parseFlags, 0, 0, null);
+ pkg = scanPackageTracedLI(new File(codePath), parseFlags, 0, 0,
+ UserHandle.SYSTEM);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to scan " + codePath + ": " + e.getMessage());
}
@@ -15903,7 +15890,8 @@
synchronized (mInstallLock) {
final PackageParser.Package pkg;
try {
- pkg = scanPackageTracedLI(ps.codePath, parseFlags, SCAN_INITIAL, 0L, null);
+ pkg = scanPackageTracedLI(ps.codePath, parseFlags, SCAN_INITIAL, 0,
+ UserHandle.SYSTEM);
loaded.add(pkg.applicationInfo);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 6386a91..31fc24b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -131,6 +131,8 @@
private static final String XML_SUFFIX = ".xml";
private static final int MIN_USER_ID = 10;
+ // We need to keep process uid within Integer.MAX_VALUE.
+ private static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
private static final int USER_VERSION = 6;
@@ -844,7 +846,7 @@
int userVersion = mUserVersion;
if (userVersion < 1) {
// Assign a proper name for the owner, if not initialized correctly before
- UserInfo user = mUsers.get(UserHandle.USER_OWNER);
+ UserInfo user = mUsers.get(UserHandle.USER_SYSTEM);
if ("Primary".equals(user.name)) {
user.name = mContext.getResources().getString(com.android.internal.R.string.owner_name);
scheduleWriteUserLocked(user);
@@ -854,7 +856,7 @@
if (userVersion < 2) {
// Owner should be marked as initialized
- UserInfo user = mUsers.get(UserHandle.USER_OWNER);
+ UserInfo user = mUsers.get(UserHandle.USER_SYSTEM);
if ((user.flags & UserInfo.FLAG_INITIALIZED) == 0) {
user.flags |= UserInfo.FLAG_INITIALIZED;
scheduleWriteUserLocked(user);
@@ -1518,6 +1520,11 @@
long ident = Binder.clearCallingIdentity();
try {
final UserInfo user;
+ int currentUser = ActivityManager.getCurrentUser();
+ if (currentUser == userHandle) {
+ Log.w(LOG_TAG, "Current user cannot be removed");
+ return false;
+ }
synchronized (mPackagesLock) {
user = mUsers.get(userHandle);
if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
@@ -2005,14 +2012,14 @@
private int getNextAvailableIdLocked() {
synchronized (mPackagesLock) {
int i = MIN_USER_ID;
- while (i < Integer.MAX_VALUE) {
+ while (i < MAX_USER_ID) {
if (mUsers.indexOfKey(i) < 0 && !mRemovingUserIds.get(i)) {
- break;
+ return i;
}
i++;
}
- return i;
}
+ throw new IllegalStateException("No user id available!");
}
private String packageToRestrictionsFileName(String packageName) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c265000..4f30a15 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -778,6 +778,8 @@
private final Runnable mUpdateRotationRunnable = new Runnable() {
@Override
public void run() {
+ // send interaction hint to improve redraw performance
+ mPowerManagerInternal.powerHint(PowerManagerInternal.POWER_HINT_INTERACTION, 0);
updateRotation(false);
}
};
diff --git a/services/core/java/com/android/server/wm/DimBehindController.java b/services/core/java/com/android/server/wm/DimBehindController.java
new file mode 100644
index 0000000..c56af39
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DimBehindController.java
@@ -0,0 +1,291 @@
+package com.android.server.wm;
+
+import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
+
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.util.TypedValue;
+
+import java.io.PrintWriter;
+
+/**
+ * Centralizes the control of dim layers used for
+ * {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}.
+ */
+class DimBehindController {
+ private static final String TAG = "DimBehindController";
+
+ /** Amount of time in milliseconds to animate the dim surface from one value to another,
+ * when no window animation is driving it. */
+ private static final int DEFAULT_DIM_DURATION = 200;
+
+ // Shared dim layer for fullscreen users. {@link DimBehindState#dimLayer} will point to this
+ // instead of creating a new object per fullscreen task on a display.
+ private DimLayer mSharedFullScreenDimLayer;
+
+ private ArrayMap<DimLayer.DimLayerUser, DimBehindState> mState = new ArrayMap<>();
+
+ private DisplayContent mDisplayContent;
+
+ private Rect mTmpBounds = new Rect();
+
+ DimBehindController(DisplayContent displayContent) {
+ mDisplayContent = displayContent;
+ }
+
+ /** Updates the dim layer bounds, recreating it if needed. */
+ void updateDimLayer(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = getOrCreateDimBehindState(dimLayerUser);
+ final boolean previousFullscreen = state.dimLayer != null
+ && state.dimLayer == mSharedFullScreenDimLayer;
+ DimLayer newDimLayer;
+ final int displayId = mDisplayContent.getDisplayId();
+ if (dimLayerUser.isFullscreen()) {
+ if (previousFullscreen) {
+ // Nothing to do here...
+ return;
+ }
+ // Use shared fullscreen dim layer
+ newDimLayer = mSharedFullScreenDimLayer;
+ if (newDimLayer == null) {
+ if (state.dimLayer != null) {
+ // Re-purpose the previous dim layer.
+ newDimLayer = state.dimLayer;
+ } else {
+ // Create new full screen dim layer.
+ newDimLayer = new DimLayer(mDisplayContent.mService, dimLayerUser, displayId);
+ }
+ dimLayerUser.getBounds(mTmpBounds);
+ newDimLayer.setBounds(mTmpBounds);
+ mSharedFullScreenDimLayer = newDimLayer;
+ } else if (state.dimLayer != null) {
+ state.dimLayer. destroySurface();
+ }
+ } else {
+ newDimLayer = (state.dimLayer == null || previousFullscreen)
+ ? new DimLayer(mDisplayContent.mService, dimLayerUser, displayId)
+ : state.dimLayer;
+ dimLayerUser.getBounds(mTmpBounds);
+ newDimLayer.setBounds(mTmpBounds);
+ }
+ state.dimLayer = newDimLayer;
+ }
+
+ private DimBehindState getOrCreateDimBehindState(DimLayer.DimLayerUser dimLayerUser) {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "getDimBehindState, dimLayerUser="
+ + dimLayerUser.toShortString());
+ DimBehindState state = mState.get(dimLayerUser);
+ if (state == null) {
+ state = new DimBehindState();
+ mState.put(dimLayerUser, state);
+ }
+ return state;
+ }
+
+ private void setContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = mState.get(dimLayerUser);
+ if (state == null) {
+ if (DEBUG_DIM_LAYER) Slog.w(TAG, "setContinueDimming, no state for: "
+ + dimLayerUser.toShortString());
+ return;
+ }
+ state.continueDimming = true;
+ }
+
+ boolean isDimming() {
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimBehindState state = mState.valueAt(i);
+ if (state.dimLayer != null && state.dimLayer.isDimming()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void resetDimming() {
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ mState.valueAt(i).continueDimming = false;
+ }
+ }
+
+ private boolean getContinueDimming(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = mState.get(dimLayerUser);
+ return state != null && state.continueDimming;
+ }
+
+ void startDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser,
+ WindowStateAnimator newWinAnimator) {
+ // Only set dim params on the highest dimmed layer.
+ // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
+ DimBehindState state = getOrCreateDimBehindState(dimLayerUser);
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "startDimmingIfNeeded,"
+ + " dimLayerUser=" + dimLayerUser.toShortString()
+ + " newWinAnimator=" + newWinAnimator
+ + " state.animator=" + state.animator);
+ if (newWinAnimator.mSurfaceShown && (state.animator == null
+ || !state.animator.mSurfaceShown
+ || state.animator.mAnimLayer <= newWinAnimator.mAnimLayer)) {
+ state.animator = newWinAnimator;
+ if (state.animator.mWin.mAppToken == null && !dimLayerUser.isFullscreen()) {
+ // Dim should cover the entire screen for system windows.
+ mDisplayContent.getLogicalDisplayRect(mTmpBounds);
+ state.dimLayer.setBounds(mTmpBounds);
+ }
+ }
+ }
+
+ void stopDimmingIfNeeded() {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded, mState.size()=" + mState.size());
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimLayer.DimLayerUser dimLayerUser = mState.keyAt(i);
+ stopDimmingIfNeeded(dimLayerUser);
+ }
+ }
+
+ private void stopDimmingIfNeeded(DimLayer.DimLayerUser dimLayerUser) {
+ // No need to check if state is null, we know the key has a value.
+ DimBehindState state = mState.get(dimLayerUser);
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "stopDimmingIfNeeded,"
+ + " dimLayerUser=" + dimLayerUser.toShortString()
+ + " state.continueDimming=" + state.continueDimming
+ + " state.dimLayer.isDimming=" + state.dimLayer.isDimming());
+ if (!state.continueDimming && state.dimLayer.isDimming()) {
+ state.animator = null;
+ dimLayerUser.getBounds(mTmpBounds);
+ state.dimLayer.setBounds(mTmpBounds);
+ }
+ }
+
+ boolean animateDimLayers() {
+ int fullScreen = -1;
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimLayer.DimLayerUser dimLayerUser = mState.keyAt(i);
+ if (dimLayerUser.isFullscreen()) {
+ fullScreen = i;
+ if (mState.valueAt(i).continueDimming) {
+ break;
+ }
+ }
+ }
+ if (fullScreen != -1) {
+ return animateDimLayers(mState.keyAt(fullScreen));
+ } else {
+ boolean result = false;
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ result |= animateDimLayers(mState.keyAt(i));
+ }
+ return result;
+ }
+ }
+
+ private boolean animateDimLayers(DimLayer.DimLayerUser dimLayerUser) {
+ DimBehindState state = mState.get(dimLayerUser);
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "animateDimLayers,"
+ + " dimLayerUser=" + dimLayerUser.toShortString()
+ + " state.animator=" + state.animator
+ + " state.continueDimming=" + state.continueDimming);
+ final int dimLayer;
+ final float dimAmount;
+ if (state.animator == null) {
+ dimLayer = state.dimLayer.getLayer();
+ dimAmount = 0;
+ } else {
+ dimLayer = state.animator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
+ dimAmount = state.animator.mWin.mAttrs.dimAmount;
+ }
+ final float targetAlpha = state.dimLayer.getTargetAlpha();
+ if (targetAlpha != dimAmount) {
+ if (state.animator == null) {
+ state.dimLayer.hide(DEFAULT_DIM_DURATION);
+ } else {
+ long duration = (state.animator.mAnimating && state.animator.mAnimation != null)
+ ? state.animator.mAnimation.computeDurationHint()
+ : DEFAULT_DIM_DURATION;
+ if (targetAlpha > dimAmount) {
+ duration = getDimBehindFadeDuration(duration);
+ }
+ state.dimLayer.show(dimLayer, dimAmount, duration);
+ }
+ } else if (state.dimLayer.getLayer() != dimLayer) {
+ state.dimLayer.setLayer(dimLayer);
+ }
+ if (state.dimLayer.isAnimating()) {
+ if (!mDisplayContent.mService.okToDisplay()) {
+ // Jump to the end of the animation.
+ state.dimLayer.show();
+ } else {
+ return state.dimLayer.stepAnimation();
+ }
+ }
+ return false;
+ }
+
+ boolean isDimming(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator winAnimator) {
+ DimBehindState state = mState.get(dimLayerUser);
+ return state != null && state.animator == winAnimator && state.dimLayer.isDimming();
+ }
+
+ private long getDimBehindFadeDuration(long duration) {
+ TypedValue tv = new TypedValue();
+ mDisplayContent.mService.mContext.getResources().getValue(
+ com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
+ if (tv.type == TypedValue.TYPE_FRACTION) {
+ duration = (long) tv.getFraction(duration, duration);
+ } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
+ duration = tv.data;
+ }
+ return duration;
+ }
+
+ void close() {
+ for (int i = mState.size() - 1; i >= 0; i--) {
+ DimBehindState state = mState.valueAt(i);
+ state.dimLayer.destroySurface();
+ }
+ mState.clear();
+ mSharedFullScreenDimLayer = null;
+ }
+
+ void removeDimLayerUser(DimLayer.DimLayerUser dimLayerUser) {
+ mState.remove(dimLayerUser);
+ }
+
+ void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
+ if (dimLayerUser == null) {
+ Slog.e(TAG, "Trying to apply dim layer for: " + this
+ + ", but no dim layer user found.");
+ return;
+ }
+ if (!getContinueDimming(dimLayerUser)) {
+ setContinueDimming(dimLayerUser);
+ if (!isDimming(dimLayerUser, animator)) {
+ if (DEBUG_DIM_LAYER) Slog.v(TAG, "Win " + this + " start dimming.");
+ startDimmingIfNeeded(dimLayerUser, animator);
+ }
+ }
+ }
+
+ private static class DimBehindState {
+ // The particular window with FLAG_DIM_BEHIND set. If null, hide dimLayer.
+ WindowStateAnimator animator;
+ // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the
+ // end then stop any dimming.
+ boolean continueDimming;
+ DimLayer dimLayer;
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.println(prefix + "DimBehindController");
+ for (int i = 0, n = mState.size(); i < n; i++) {
+ pw.println(prefix + " " + mState.keyAt(i).toShortString());
+ pw.print(prefix + " ");
+ DimBehindState state = mState.valueAt(i);
+ pw.print("dimLayer=" + (state.dimLayer == mSharedFullScreenDimLayer ? "shared" :
+ state.dimLayer));
+ pw.print(", animator=" + state.animator);
+ pw.println(", continueDimming=" + state.continueDimming + "}");
+
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index 538d6b84..8c479d8 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -65,6 +65,9 @@
boolean isFullscreen();
/** Returns the display info. of the dim layer user. */
DisplayInfo getDisplayInfo();
+ /** Gets the bounds of the dim layer user. */
+ void getBounds(Rect outBounds);
+ String toShortString();
}
/** The user of this dim layer. */
final DimLayerUser mUser;
@@ -239,8 +242,9 @@
mDuration = duration;
}
}
- if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime);
mTargetAlpha = alpha;
+ if (DEBUG) Slog.v(TAG, "show: mStartAlpha=" + mStartAlpha + " mStartTime=" + mStartTime
+ + " mTargetAlpha=" + mTargetAlpha);
}
/** Immediate hide.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6b5ecdc..f13f350 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -115,6 +115,8 @@
final DockedStackDividerController mDividerControllerLocked;
+ final DimBehindController mDimBehindController;
+
/**
* @param display May not be null.
* @param service You know.
@@ -128,6 +130,7 @@
mService = service;
initializeDisplayBaseInfo();
mDividerControllerLocked = new DockedStackDividerController(service.mContext, this);
+ mDimBehindController = new DimBehindController(this);
}
int getDisplayId() {
@@ -246,6 +249,7 @@
}
void detachStack(TaskStack stack) {
+ mDimBehindController.removeDimLayerUser(stack);
mStacks.remove(stack);
}
@@ -382,54 +386,23 @@
}
boolean animateDimLayers() {
- boolean result = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final Task task = tasks.get(taskNdx);
- result |= task.animateDimLayers();
- if (task.isFullscreen()) {
- // No point in continuing as this task covers the entire screen.
- // Also, fullscreen tasks all share the same dim layer, so we don't want
- // processing of fullscreen task below this one affecting the dim layer state.
- return result;
- }
- }
- }
- return result;
+ return mDimBehindController.animateDimLayers();
}
void resetDimming() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- tasks.get(taskNdx).clearContinueDimming();
- }
- }
+ mDimBehindController.resetDimming();
}
boolean isDimming() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- if (tasks.get(taskNdx).isDimming()) {
- return true;
- }
- }
- }
- return false;
+ return mDimBehindController.isDimming();
}
void stopDimmingIfNeeded() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- tasks.get(taskNdx).stopDimmingIfNeeded();
- }
- }
+ mDimBehindController.stopDimmingIfNeeded();
}
void close() {
+ mDimBehindController.close();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).close();
}
@@ -576,6 +549,7 @@
}
}
pw.println();
+ mDimBehindController.dump(prefix + " ", pw);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 8c5d319..b9028e3 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_ID;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -25,16 +26,15 @@
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.server.wm.TaskStack.DOCKED_BOTTOM;
-import static com.android.server.wm.TaskStack.DOCKED_INVALID;
import static com.android.server.wm.TaskStack.DOCKED_LEFT;
import static com.android.server.wm.TaskStack.DOCKED_RIGHT;
import static com.android.server.wm.TaskStack.DOCKED_TOP;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.RemoteException;
-import android.util.Slog;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -58,7 +58,6 @@
private Rect mOriginalRect = new Rect();
private int mDockSide;
-
DockedStackDividerController(Context context, DisplayContent displayContent) {
mContext = context;
mDisplayContent = displayContent;
@@ -66,13 +65,16 @@
com.android.internal.R.dimen.docked_stack_divider_thickness);
}
- private void addDivider() {
+ private void addDivider(Configuration configuration) {
View view = LayoutInflater.from(mContext).inflate(
com.android.internal.R.layout.docked_stack_divider, null);
view.setOnTouchListener(this);
WindowManagerGlobal manager = WindowManagerGlobal.getInstance();
+ final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
+ final int width = landscape ? mDividerWidth : MATCH_PARENT;
+ final int height = landscape ? MATCH_PARENT : mDividerWidth;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
- mDividerWidth, MATCH_PARENT, TYPE_DOCK_DIVIDER,
+ width, height, TYPE_DOCK_DIVIDER,
FLAG_TOUCHABLE_WHEN_WAKING | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
| FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH,
PixelFormat.OPAQUE);
@@ -92,10 +94,13 @@
return mView != null;
}
- void update() {
+ void update(Configuration configuration, boolean forceUpdate) {
+ if (forceUpdate && mView != null) {
+ removeDivider();
+ }
TaskStack stack = mDisplayContent.getDockedStackLocked();
if (stack != null && mView == null) {
- addDivider();
+ addDivider(configuration);
} else if (stack == null && mView != null) {
removeDivider();
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1f986dd..c4600e0 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -29,7 +29,6 @@
import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.TypedValue;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -39,10 +38,6 @@
import java.util.ArrayList;
class Task implements DimLayer.DimLayerUser {
- /** Amount of time in milliseconds to animate the dim surface from one value to another,
- * when no window animation is driving it. */
- private static final int DEFAULT_DIM_DURATION = 200;
-
// Return value from {@link setBounds} indicating no change was made to the Task bounds.
static final int BOUNDS_CHANGE_NONE = 0;
// Return value from {@link setBounds} indicating the position of the Task bounds changed.
@@ -78,17 +73,6 @@
// Whether the task is currently being drag-resized
private boolean mDragResizing;
- // The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer.
- WindowStateAnimator mDimWinAnimator;
- // Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND}
- private DimLayer mDimLayer;
- // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end
- // then stop any dimming.
- private boolean mContinueDimming;
- // Shared dim layer for fullscreen tasks. {@link #mDimLayer} will point to this instead
- // of creating a new object per fullscreen task on a display.
- private static final SparseArray<DimLayer> sSharedFullscreenDimLayers = new SparseArray<>();
-
Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
Configuration config) {
mTaskId = taskId;
@@ -128,6 +112,10 @@
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
mDeferRemoval = false;
+ DisplayContent content = getDisplayContent();
+ if (content != null) {
+ content.mDimBehindController.removeDimLayerUser(this);
+ }
mStack.removeTask(this);
mService.mTaskIdToTask.delete(mTaskId);
}
@@ -228,7 +216,9 @@
mBounds.set(bounds);
mRotation = rotation;
- updateDimLayer();
+ if (displayContent != null) {
+ displayContent.mDimBehindController.updateDimLayer(this);
+ }
mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
return boundsChange;
}
@@ -261,7 +251,8 @@
}
/** Bounds of the task with other system factors taken into consideration. */
- void getBounds(Rect out) {
+ @Override
+ public void getBounds(Rect out) {
if (useCurrentBounds()) {
// No need to adjust the output bounds if fullscreen or the docked stack is visible
// since it is already what we want to represent to the rest of the system.
@@ -303,142 +294,12 @@
if (setBounds(mTmpRect2, mOverrideConfig) != BOUNDS_CHANGE_NONE) {
// Post message to inform activity manager of the bounds change simulating
// a one-way call. We do this to prevent a deadlock between window manager
- // lock and activity manager lock been held.
- mService.mH.sendMessage(mService.mH.obtainMessage(
- RESIZE_TASK, mTaskId, RESIZE_MODE_SYSTEM_SCREEN_ROTATION, mBounds));
- }
- }
-
- /** Updates the dim layer bounds, recreating it if needed. */
- private void updateDimLayer() {
- DimLayer newDimLayer;
- final boolean previousFullscreen =
- mDimLayer != null && sSharedFullscreenDimLayers.indexOfValue(mDimLayer) > -1;
- final int displayId = mStack.getDisplayContent().getDisplayId();
- if (mFullscreen) {
- if (previousFullscreen) {
- // Nothing to do here...
- return;
+ // lock and activity manager lock been held. Only tasks within the freeform stack
+ // are resizeable independently of their stack resizing.
+ if (mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ mService.mH.sendMessage(mService.mH.obtainMessage(
+ RESIZE_TASK, mTaskId, RESIZE_MODE_SYSTEM_SCREEN_ROTATION, mBounds));
}
- // Use shared fullscreen dim layer
- newDimLayer = sSharedFullscreenDimLayers.get(displayId);
- if (newDimLayer == null) {
- if (mDimLayer != null) {
- // Re-purpose the previous dim layer.
- newDimLayer = mDimLayer;
- } else {
- // Create new full screen dim layer.
- newDimLayer = new DimLayer(mService, this, displayId);
- }
- newDimLayer.setBounds(mBounds);
- sSharedFullscreenDimLayers.put(displayId, newDimLayer);
- } else if (mDimLayer != null) {
- mDimLayer.destroySurface();
- }
- } else {
- newDimLayer = (mDimLayer == null || previousFullscreen)
- ? new DimLayer(mService, this, displayId) : mDimLayer;
- newDimLayer.setBounds(mBounds);
- }
- mDimLayer = newDimLayer;
- }
-
- boolean animateDimLayers() {
- final int dimLayer;
- final float dimAmount;
- if (mDimWinAnimator == null) {
- dimLayer = mDimLayer.getLayer();
- dimAmount = 0;
- } else {
- dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM;
- dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount;
- }
- final float targetAlpha = mDimLayer.getTargetAlpha();
- if (targetAlpha != dimAmount) {
- if (mDimWinAnimator == null) {
- mDimLayer.hide(DEFAULT_DIM_DURATION);
- } else {
- long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null)
- ? mDimWinAnimator.mAnimation.computeDurationHint()
- : DEFAULT_DIM_DURATION;
- if (targetAlpha > dimAmount) {
- duration = getDimBehindFadeDuration(duration);
- }
- mDimLayer.show(dimLayer, dimAmount, duration);
- }
- } else if (mDimLayer.getLayer() != dimLayer) {
- mDimLayer.setLayer(dimLayer);
- }
- if (mDimLayer.isAnimating()) {
- if (!mService.okToDisplay()) {
- // Jump to the end of the animation.
- mDimLayer.show();
- } else {
- return mDimLayer.stepAnimation();
- }
- }
- return false;
- }
-
- private long getDimBehindFadeDuration(long duration) {
- TypedValue tv = new TypedValue();
- mService.mContext.getResources().getValue(
- com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true);
- if (tv.type == TypedValue.TYPE_FRACTION) {
- duration = (long)tv.getFraction(duration, duration);
- } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) {
- duration = tv.data;
- }
- return duration;
- }
-
- void clearContinueDimming() {
- mContinueDimming = false;
- }
-
- void setContinueDimming() {
- mContinueDimming = true;
- }
-
- boolean getContinueDimming() {
- return mContinueDimming;
- }
-
- boolean isDimming() {
- return mDimLayer.isDimming();
- }
-
- boolean isDimming(WindowStateAnimator winAnimator) {
- return mDimWinAnimator == winAnimator && isDimming();
- }
-
- void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) {
- // Only set dim params on the highest dimmed layer.
- // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer.
- if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null
- || !mDimWinAnimator.mSurfaceShown
- || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) {
- mDimWinAnimator = newWinAnimator;
- if (mDimWinAnimator.mWin.mAppToken == null
- && !mFullscreen && mStack.getDisplayContent() != null) {
- // Dim should cover the entire screen for system windows.
- mStack.getDisplayContent().getLogicalDisplayRect(mTmpRect);
- mDimLayer.setBounds(mTmpRect);
- }
- }
- }
-
- void stopDimmingIfNeeded() {
- if (!mContinueDimming && isDimming()) {
- mDimWinAnimator = null;
- mDimLayer.setBounds(mBounds);
- }
- }
-
- void close() {
- if (mDimLayer != null) {
- mDimLayer.destroySurface();
- mDimLayer = null;
}
}
@@ -491,16 +352,14 @@
return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
}
+ @Override
+ public String toShortString() {
+ return "Task=" + mTaskId;
+ }
+
public void printTo(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("taskId="); pw.print(mTaskId);
pw.print(prefix); pw.print("appTokens="); pw.print(mAppTokens);
pw.print(prefix); pw.print("mdr="); pw.println(mDeferRemoval);
- if (mDimLayer.isDimming()) {
- pw.print(prefix); pw.println("mDimLayer:");
- mDimLayer.printTo(prefix + " ", pw);
- pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator);
- } else {
- pw.println();
- }
}
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 9da7406..207da47 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -146,13 +146,18 @@
}
synchronized (mService.mWindowMap) {
mDragEnded = notifyMoveLocked(newX, newY);
+ mTask.getBounds(mTmpRect);
}
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.TaskPositioner.resizeTask");
- try {
- mService.mActivityManager.resizeTask(
- mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
- } catch(RemoteException e) {}
- Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ if (!mTmpRect.equals(mWindowDragBounds)) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
+ "wm.TaskPositioner.resizeTask");
+ try {
+ mService.mActivityManager.resizeTask(
+ mTask.mTaskId, mWindowDragBounds, RESIZE_MODE_USER);
+ } catch (RemoteException e) {
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
+ }
} break;
case MotionEvent.ACTION_UP: {
@@ -171,11 +176,12 @@
}
if (mDragEnded) {
+ final boolean wasResizing = mResizing;
synchronized (mService.mWindowMap) {
endDragLocked();
}
try {
- if (mResizing) {
+ if (wasResizing) {
// We were using fullscreen surface during resizing. Request
// resizeTask() one last time to restore surface to window size.
mService.mActivityManager.resizeTask(
@@ -462,6 +468,16 @@
return mTask.mStack.getDisplayInfo();
}
+ @Override
+ public void getBounds(Rect out) {
+ // This dim layer user doesn't need this.
+ }
+
+ @Override
+ public String toShortString() {
+ return TAG;
+ }
+
private int getDragLayerLocked() {
return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
* WindowManagerService.TYPE_LAYER_MULTIPLIER
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index f030b9a..a630993 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -175,6 +175,10 @@
return false;
}
+ if (mDisplayContent != null) {
+ mDisplayContent.mDimBehindController.updateDimLayer(this);
+ }
+
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
mRotation = rotation;
@@ -201,7 +205,8 @@
}
/** Bounds of the stack with other system factors taken into consideration. */
- void getBounds(Rect out) {
+ @Override
+ public void getBounds(Rect out) {
if (useCurrentBounds()) {
// No need to adjust the output bounds if fullscreen or the docked stack is visible
// since it is already what we want to represent to the rest of the system.
@@ -550,9 +555,6 @@
mAnimationBackgroundSurface.destroySurface();
mAnimationBackgroundSurface = null;
}
- for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- mTasks.get(taskNdx).close();
- }
mDisplayContent = null;
}
@@ -609,6 +611,11 @@
return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
}
+ @Override
+ public String toShortString() {
+ return "Stack=" + mStackId;
+ }
+
/**
* For docked workspace provides information which side of the screen was the dock anchored.
*/
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 74572cf..1b72876 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -216,6 +216,7 @@
static final boolean DEBUG_STACK = false;
static final boolean DEBUG_DISPLAY = false;
static final boolean DEBUG_POWER = false;
+ static final boolean DEBUG_DIM_LAYER = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -3419,12 +3420,20 @@
}
synchronized(mWindowMap) {
+ final boolean orientationChanged = mCurConfiguration.orientation != config.orientation;
mCurConfiguration = new Configuration(config);
if (mWaitingForConfig) {
mWaitingForConfig = false;
mLastFinishedFreezeSource = "new-config";
}
mWindowPlacerLocked.performSurfacePlacement();
+ if (orientationChanged) {
+ for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
+ DisplayContent content = mDisplayContents.valueAt(i);
+ Message.obtain(mH, H.UPDATE_DOCKED_STACK_DIVIDER, H.DOCK_DIVIDER_FORCE_UPDATE,
+ H.UNUSED, content).sendToTarget();
+ }
+ }
}
}
@@ -7164,6 +7173,21 @@
public static final int RESIZE_STACK = 43;
public static final int RESIZE_TASK = 44;
+ /**
+ * Used to indicate in the message that the dock divider needs to be updated only if it's
+ * necessary.
+ */
+ static final int DOCK_DIVIDER_NO_FORCE_UPDATE = 0;
+ /**
+ * Used to indicate in the message that the dock divider should be force-removed before
+ * updating, so new configuration can be applied.
+ */
+ static final int DOCK_DIVIDER_FORCE_UPDATE = 1;
+ /**
+ * Used to denote that an integer field in a message will not be used.
+ */
+ public static final int UNUSED = 0;
+
@Override
public void handleMessage(Message msg) {
if (DEBUG_WINDOW_TRACE) {
@@ -7705,8 +7729,9 @@
break;
case UPDATE_DOCKED_STACK_DIVIDER: {
DisplayContent content = (DisplayContent) msg.obj;
+ final boolean forceUpdate = msg.arg1 == DOCK_DIVIDER_FORCE_UPDATE;
synchronized (mWindowMap) {
- content.mDividerControllerLocked.update();
+ content.mDividerControllerLocked.update(mCurConfiguration, forceUpdate);
}
}
break;
@@ -8356,8 +8381,10 @@
layerChanged = true;
anyLayerChanged = true;
}
- final Task task = w.getTask();
- if (layerChanged && task != null && task.isDimming(winAnimator)) {
+ final DimLayer.DimLayerUser dimLayerUser = w.getDimLayerUser();
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (layerChanged && dimLayerUser != null && displayContent != null &&
+ displayContent.mDimBehindController.isDimming(dimLayerUser, winAnimator)) {
// Force an animation pass just to update the mDimLayer layer.
scheduleAnimationLocked();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 55ddbc0..8ace990 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -29,6 +29,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
+import static com.android.server.wm.WindowManagerService.DEBUG_DIM_LAYER;
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
@@ -698,10 +699,10 @@
final int height = Math.min(mFrame.height(), mContentFrame.height());
final int width = Math.min(mContentFrame.width(), mFrame.width());
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
- final int minVisibleHeight =
- mService.dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
- final int minVisibleWidth =
- mService.dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
+ final int minVisibleHeight = WindowManagerService.dipToPixel(
+ MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
+ final int minVisibleWidth = WindowManagerService.dipToPixel(
+ MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
final int top = Math.max(mContentFrame.top,
Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight));
final int left = Math.max(mContentFrame.left + minVisibleWidth - width,
@@ -889,7 +890,7 @@
@Override
public boolean isVoiceInteraction() {
- return mAppToken != null ? mAppToken.voiceInteraction : false;
+ return mAppToken != null && mAppToken.voiceInteraction;
}
boolean setInsetsChanged() {
@@ -934,7 +935,10 @@
return task.mStack;
}
}
- return null;
+ // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
+ // associate them with some stack to enable dimming.
+ return mAttrs.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
+ && mDisplayContent != null ? mDisplayContent.getHomeStack() : null;
}
/**
@@ -970,7 +974,8 @@
}
if (forTouch && inFreeformWorkspace()) {
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
- final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
+ final int delta = WindowManagerService.dipToPixel(
+ RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
bounds.inset(-delta, -delta);
}
}
@@ -1031,8 +1036,7 @@
return false;
}
final AppWindowToken atoken = mAppToken;
- final boolean animating = atoken != null
- ? (atoken.mAppAnimator.animation != null) : false;
+ final boolean animating = atoken != null && atoken.mAppAnimator.animation != null;
return mHasSurface && !mDestroying && !mExiting
&& (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
&& ((!mAttachedHidden && mViewVisibility == View.VISIBLE
@@ -1114,8 +1118,7 @@
* of a transition that has not yet been started.
*/
boolean isReadyForDisplay() {
- if (mRootToken.waitingToShow &&
- mService.mAppTransition.isTransitionSet()) {
+ if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
return false;
}
return mHasSurface && mPolicyVisibility && !mDestroying
@@ -1295,19 +1298,20 @@
}
void handleFlagDimBehind() {
- if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isDisplayedLw() && !mExiting) {
- final Task task = getTask();
- if (task == null) {
- return;
- }
- task.setContinueDimming();
- if (!task.isDimming(mWinAnimator)) {
- if (WindowManagerService.localLOGV) Slog.v(TAG, "Win " + this + " start dimming.");
- task.startDimmingIfNeeded(mWinAnimator);
- }
+ if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && mDisplayContent != null && !mExiting
+ && isDisplayedLw()) {
+ mDisplayContent.mDimBehindController.applyDimBehind(getDimLayerUser(), mWinAnimator);
}
}
+ DimLayer.DimLayerUser getDimLayerUser() {
+ Task task = getTask();
+ if (task != null) {
+ return task;
+ }
+ return getStack();
+ }
+
void maybeRemoveReplacedWindow() {
AppWindowToken token = mAppToken;
if (token != null && token.mReplacingWindow) {
@@ -1512,11 +1516,9 @@
@Override
public boolean isDimming() {
- Task task = getTask();
- if (task == null) {
- return false;
- }
- return task.isDimming(mWinAnimator);
+ final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
+ return dimLayerUser != null && mDisplayContent != null &&
+ mDisplayContent.mDimBehindController.isDimming(dimLayerUser, mWinAnimator);
}
public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 60bf571..ed53501 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1516,12 +1516,7 @@
mDsDy * w.mHScale, mDtDy * w.mVScale);
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
- if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
- final Task task = w.getTask();
- if (task != null) {
- task.startDimmingIfNeeded(this);
- }
- }
+ w.handleFlagDimBehind();
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index df0a1c9..112646a 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -642,9 +642,7 @@
handleNotObscuredLocked(w, innerDw, innerDh);
}
- if (task != null && !task.getContinueDimming()) {
- w.handleFlagDimBehind();
- }
+ w.handleFlagDimBehind();
if (isDefaultDisplay && obscuredChanged
&& mWallpaperControllerLocked.isWallpaperTarget(w) && w.isVisibleLw()) {
@@ -967,7 +965,8 @@
}
mService.mPolicy.finishLayoutLw();
- mService.mH.obtainMessage(UPDATE_DOCKED_STACK_DIVIDER, displayContent).sendToTarget();
+ mService.mH.obtainMessage(UPDATE_DOCKED_STACK_DIVIDER,
+ DOCK_DIVIDER_NO_FORCE_UPDATE, UNUSED, displayContent).sendToTarget();
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/MountServiceTests.java b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
index 9c88b40..ecfe0db 100644
--- a/services/tests/servicestests/src/com/android/server/MountServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
@@ -27,8 +27,6 @@
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
-import static com.android.server.MountService.buildObbPath;
-
import com.android.frameworks.servicestests.R;
import java.io.File;
@@ -42,16 +40,6 @@
private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
private static void assertStartsWith(String message, String prefix, String actual) {
if (!actual.startsWith(prefix)) {
throw new ComparisonFailure(message, prefix, actual);
@@ -195,8 +183,7 @@
final ObbObserver observer = new ObbObserver();
assertTrue("unmountObb call on test1.obb should succeed",
- sm.unmountObb(file.getPath(),
- false, observer));
+ sm.unmountObb(file.getPath(), false, observer));
assertTrue("Unmount should have completed",
observer.waitForCompletion());
@@ -284,34 +271,4 @@
unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
}
-
- public void testBuildObbPath() {
- final int userId = 10;
-
- // Paths outside external storage should remain untouched
- assertEquals("/storage/random/foo",
- buildObbPath("/storage/random/foo", userId, true));
- assertEquals("/storage/random/foo",
- buildObbPath("/storage/random/foo", userId, false));
-
- // Paths on user-specific emulated storage
- assertEquals("/mnt/shell/emulated/10/foo",
- buildObbPath("/storage/emulated_legacy/foo", userId, true));
- assertEquals("/storage/emulated/10/foo",
- buildObbPath("/storage/emulated_legacy/foo", userId, false));
- assertEquals("/mnt/shell/emulated/10/foo",
- buildObbPath("/storage/emulated/10/foo", userId, true));
- assertEquals("/storage/emulated/10/foo",
- buildObbPath("/storage/emulated/10/foo", userId, false));
-
- // Paths on shared OBB emulated storage
- assertEquals("/mnt/shell/emulated/obb/foo",
- buildObbPath("/storage/emulated_legacy/Android/obb/foo", userId, true));
- assertEquals("/storage/emulated/0/Android/obb/foo",
- buildObbPath("/storage/emulated_legacy/Android/obb/foo", userId, false));
- assertEquals("/mnt/shell/emulated/obb/foo",
- buildObbPath("/storage/emulated/10/Android/obb/foo", userId, true));
- assertEquals("/storage/emulated/0/Android/obb/foo",
- buildObbPath("/storage/emulated/10/Android/obb/foo", userId, false));
- }
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 7f813ec..3160e39 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -753,7 +753,7 @@
UsbManager.USB_FUNCTION_MTP)
|| UsbManager.containsFunction(mCurrentFunctions,
UsbManager.USB_FUNCTION_PTP);
- if (active && mCurrentUser != UserHandle.USER_NULL) {
+ if (mUsbDataUnlocked && active && mCurrentUser != UserHandle.USER_NULL) {
Slog.v(TAG, "Current user switched to " + mCurrentUser
+ "; resetting USB host stack for MTP or PTP");
setEnabledFunctions(mCurrentFunctions, true);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
index b458d9b..7628c5c 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MultiProducerActivity.java
@@ -188,7 +188,7 @@
// This call should be done while the rendernode's displaylist is produced.
// For simplicity of this test we do this before we kick off the draw.
mContent.getLocationInSurface(surfaceOrigin);
- mRenderer.setContentOverdrawProtectionBounds(surfaceOrigin[0], surfaceOrigin[1],
+ mRenderer.setContentDrawBounds(surfaceOrigin[0], surfaceOrigin[1],
surfaceOrigin[0] + mContent.getWidth(),
surfaceOrigin[1] + mContent.getHeight());
// Determine new position for frame.