Merge "Fixing issue incorrect resources being used with docked windows."
diff --git a/api/current.txt b/api/current.txt
index c9e9f9a..758851c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -45349,7 +45349,10 @@
}
public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<T> getDeclaringClass();
method public java.lang.Class<?>[] getExceptionTypes();
method public java.lang.reflect.Type[] getGenericExceptionTypes();
@@ -45359,6 +45362,7 @@
method public java.lang.annotation.Annotation[][] getParameterAnnotations();
method public java.lang.Class<?>[] getParameterTypes();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isSynthetic();
method public boolean isVarArgs();
method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
@@ -45432,7 +45436,10 @@
}
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -45446,6 +45453,7 @@
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isSynthetic();
method public boolean isVarArgs();
diff --git a/api/system-current.txt b/api/system-current.txt
index f39dc9a..2568240 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -47957,7 +47957,10 @@
}
public final class Constructor extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<T> getDeclaringClass();
method public java.lang.Class<?>[] getExceptionTypes();
method public java.lang.reflect.Type[] getGenericExceptionTypes();
@@ -47967,6 +47970,7 @@
method public java.lang.annotation.Annotation[][] getParameterAnnotations();
method public java.lang.Class<?>[] getParameterTypes();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Constructor<T>>[] getTypeParameters();
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isSynthetic();
method public boolean isVarArgs();
method public T newInstance(java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.InstantiationException, java.lang.reflect.InvocationTargetException;
@@ -48040,7 +48044,10 @@
}
public final class Method extends java.lang.reflect.AccessibleObject implements java.lang.reflect.GenericDeclaration java.lang.reflect.Member {
+ method public boolean equals(java.lang.Object);
method public A getAnnotation(java.lang.Class<A>);
+ method public java.lang.annotation.Annotation[] getAnnotations();
+ method public java.lang.annotation.Annotation[] getDeclaredAnnotations();
method public java.lang.Class<?> getDeclaringClass();
method public java.lang.Object getDefaultValue();
method public java.lang.Class<?>[] getExceptionTypes();
@@ -48054,6 +48061,7 @@
method public java.lang.Class<?> getReturnType();
method public java.lang.reflect.TypeVariable<java.lang.reflect.Method>[] getTypeParameters();
method public java.lang.Object invoke(java.lang.Object, java.lang.Object...) throws java.lang.IllegalAccessException, java.lang.IllegalArgumentException, java.lang.reflect.InvocationTargetException;
+ method public boolean isAnnotationPresent(java.lang.Class<? extends java.lang.annotation.Annotation>);
method public boolean isBridge();
method public boolean isSynthetic();
method public boolean isVarArgs();
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 20ac8d8..5c9fd51 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -163,6 +163,7 @@
" am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" +
" am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" +
" am get-config\n" +
+ " am suppress-resize-config-changes <true|false>\n" +
" am set-inactive [--user <USER_ID>] <PACKAGE> true|false\n" +
" am get-inactive [--user <USER_ID>] <PACKAGE>\n" +
" am send-trim-memory [--user <USER_ID>] <PROCESS>\n" +
@@ -326,6 +327,8 @@
"\n" +
"am get-config: retrieve the configuration and any recent configurations\n" +
" of the device.\n" +
+ "am suppress-resize-config-changes: suppresses configuration changes due to\n" +
+ " user resizing an activity/task.\n" +
"\n" +
"am set-inactive: sets the inactive state of an app.\n" +
"\n" +
@@ -453,6 +456,8 @@
runTask();
} else if (op.equals("get-config")) {
runGetConfig();
+ } else if (op.equals("suppress-resize-config-changes")) {
+ runSuppressResizeConfigChanges();
} else if (op.equals("set-inactive")) {
runSetInactive();
} else if (op.equals("get-inactive")) {
@@ -2606,6 +2611,16 @@
}
}
+ private void runSuppressResizeConfigChanges() throws Exception {
+ boolean suppress = Boolean.valueOf(nextArgRequired());
+
+ try {
+ mAm.suppressResizeConfigChanges(suppress);
+ } catch (RemoteException e) {
+ System.err.println("Error suppressing resize config changes: " + e);
+ }
+ }
+
private void runSetInactive() throws Exception {
int userId = UserHandle.USER_CURRENT;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3864a4b..cb1a89f 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2682,6 +2682,13 @@
reportSizeConfigurations(token, horizontal, vertical);
return true;
}
+ case SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final boolean suppress = data.readInt() == 1;
+ suppressResizeConfigChanges(suppress);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -6216,5 +6223,17 @@
reply.recycle();
}
+ @Override
+ public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(suppress ? 1 : 0);
+ mRemote.transact(SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2180bcc..478fdd1 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -535,6 +535,8 @@
public int getActivityStackId(IBinder token) throws RemoteException;
public void moveActivityToStack(IBinder token, int stackId) throws RemoteException;
+ public void suppressResizeConfigChanges(boolean suppress) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -891,4 +893,5 @@
int MOVE_ACTIVITY_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 344;
int REPORT_SIZE_CONFIGURATIONS = IBinder.FIRST_CALL_TRANSACTION + 345;
int MOVE_TASK_TO_DOCKED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 346;
+ int SUPPRESS_RESIZE_CONFIG_CHANGES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 347;
}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 31d1ab7..5e8ad68 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -90,6 +90,9 @@
public static final int WINDOW_STATE_HIDING = 1;
public static final int WINDOW_STATE_HIDDEN = 2;
+ public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0;
+ public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1;
+
private Context mContext;
private IStatusBarService mService;
private IBinder mToken = new Binder();
diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java
new file mode 100644
index 0000000..b1d28e0
--- /dev/null
+++ b/core/java/android/view/BatchedInputEventReceiver.java
@@ -0,0 +1,82 @@
+/*
+ * 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.os.Looper;
+
+/**
+ * Similar to {@link InputEventReceiver}, but batches events to vsync boundaries when possible.
+ * @hide
+ */
+public class BatchedInputEventReceiver extends InputEventReceiver {
+ Choreographer mChoreographer;
+ private boolean mBatchedInputScheduled;
+
+ public BatchedInputEventReceiver(
+ InputChannel inputChannel, Looper looper, Choreographer choreographer) {
+ super(inputChannel, looper);
+ mChoreographer = choreographer;
+ }
+
+ @Override
+ public void onBatchedInputEventPending() {
+ scheduleBatchedInput();
+ }
+
+ @Override
+ public void dispose() {
+ unscheduleBatchedInput();
+ super.dispose();
+ }
+
+ void doConsumeBatchedInput(long frameTimeNanos) {
+ if (mBatchedInputScheduled) {
+ mBatchedInputScheduled = false;
+ if (consumeBatchedInputEvents(frameTimeNanos) && frameTimeNanos != -1) {
+ // If we consumed a batch here, we want to go ahead and schedule the
+ // consumption of batched input events on the next frame. Otherwise, we would
+ // wait until we have more input events pending and might get starved by other
+ // things occurring in the process. If the frame time is -1, however, then
+ // we're in a non-batching mode, so there's no need to schedule this.
+ scheduleBatchedInput();
+ }
+ }
+ }
+
+ private void scheduleBatchedInput() {
+ if (!mBatchedInputScheduled) {
+ mBatchedInputScheduled = true;
+ mChoreographer.postCallback(Choreographer.CALLBACK_INPUT, mBatchedInputRunnable, null);
+ }
+ }
+
+ private void unscheduleBatchedInput() {
+ if (mBatchedInputScheduled) {
+ mBatchedInputScheduled = false;
+ mChoreographer.removeCallbacks(
+ Choreographer.CALLBACK_INPUT, mBatchedInputRunnable, null);
+ }
+ }
+
+ private final class BatchedInputRunnable implements Runnable {
+ @Override
+ public void run() {
+ doConsumeBatchedInput(mChoreographer.getFrameTimeNanos());
+ }
+ }
+ private final BatchedInputRunnable mBatchedInputRunnable = new BatchedInputRunnable();
+}
diff --git a/core/java/android/widget/MenuPopupWindow.java b/core/java/android/widget/MenuPopupWindow.java
index ba77b1b..eac3a0b 100644
--- a/core/java/android/widget/MenuPopupWindow.java
+++ b/core/java/android/widget/MenuPopupWindow.java
@@ -124,8 +124,8 @@
}
return true;
} else if (selectedItem != null && keyCode == mRetreatKey) {
- setSelectedPositionInt(-1);
- setNextSelectedPositionInt(-1);
+ setSelectedPositionInt(INVALID_POSITION);
+ setNextSelectedPositionInt(INVALID_POSITION);
((MenuAdapter) getAdapter()).getAdapterMenu().close();
return true;
@@ -159,6 +159,4 @@
return superVal;
}
}
-
-
}
\ No newline at end of file
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7ca3339..ca1b211 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -31,6 +31,7 @@
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.Rect;
@@ -55,6 +56,8 @@
import android.widget.AdapterView.OnItemClickListener;
import libcore.util.Objects;
+import com.android.internal.R;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -206,14 +209,22 @@
/** @hide */
public static class OnClickHandler {
+
+ private int mEnterAnimationId;
+
public boolean onClickHandler(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
Context context = view.getContext();
- ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
- 0, 0,
- view.getMeasuredWidth(), view.getMeasuredHeight());
+ ActivityOptions opts;
+ if (mEnterAnimationId != 0) {
+ opts = ActivityOptions.makeCustomAnimation(context, mEnterAnimationId, 0);
+ } else {
+ opts = ActivityOptions.makeScaleUpAnimation(view,
+ 0, 0,
+ view.getMeasuredWidth(), view.getMeasuredHeight());
+ }
context.startIntentSender(
pendingIntent.getIntentSender(), fillInIntent,
Intent.FLAG_ACTIVITY_NEW_TASK,
@@ -228,6 +239,10 @@
}
return true;
}
+
+ public void setEnterAnimationId(int enterAnimationId) {
+ mEnterAnimationId = enterAnimationId;
+ }
}
/**
@@ -2761,11 +2776,31 @@
inflater.setFilter(this);
result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
+ loadTransitionOverride(context, handler);
+
rvToApply.performApply(result, parent, handler);
return result;
}
+ private static void loadTransitionOverride(Context context,
+ RemoteViews.OnClickHandler handler) {
+ if (handler != null && context.getResources().getBoolean(
+ com.android.internal.R.bool.config_overrideRemoteViewsActivityTransition)) {
+ TypedArray windowStyle = context.getTheme().obtainStyledAttributes(
+ com.android.internal.R.styleable.Window);
+ int windowAnimations = windowStyle.getResourceId(
+ com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
+ TypedArray windowAnimationStyle = context.obtainStyledAttributes(
+ windowAnimations, com.android.internal.R.styleable.WindowAnimation);
+ handler.setEnterAnimationId(windowAnimationStyle.getResourceId(
+ com.android.internal.R.styleable.
+ WindowAnimation_activityOpenRemoteViewsEnterAnimation, 0));
+ windowStyle.recycle();
+ windowAnimationStyle.recycle();
+ }
+ }
+
/**
* Applies all of the actions to the provided view.
*
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index ec41447..3353d16 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2292,7 +2292,7 @@
}
}
- private static final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
+ private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
/* package */int mDefaultOpacity = PixelFormat.OPAQUE;
@@ -2362,8 +2362,6 @@
private int mRootScrollY = 0;
- private PhoneWindow mWindow;
-
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
@@ -2385,7 +2383,7 @@
@Override
public void onDraw(Canvas c) {
super.onDraw(c);
- mBackgroundFallback.draw(mWindow.mContentRoot, c, mWindow.mContentParent);
+ mBackgroundFallback.draw(mContentRoot, c, mContentParent);
}
@Override
@@ -2397,7 +2395,7 @@
if (isDown && (event.getRepeatCount() == 0)) {
// First handle chording of panel key: if a panel key is held
// but not released, try to execute a shortcut in it.
- if ((mWindow.mPanelChordingKey > 0) && (mWindow.mPanelChordingKey != keyCode)) {
+ if ((mPanelChordingKey > 0) && (mPanelChordingKey != keyCode)) {
boolean handled = dispatchKeyShortcutEvent(event);
if (handled) {
return true;
@@ -2406,15 +2404,15 @@
// If a panel is open, perform a shortcut on it without the
// chorded panel key
- if ((mWindow.mPreparedPanel != null) && mWindow.mPreparedPanel.isOpen) {
- if (mWindow.performPanelShortcut(mWindow.mPreparedPanel, keyCode, event, 0)) {
+ if ((mPreparedPanel != null) && mPreparedPanel.isOpen) {
+ if (performPanelShortcut(mPreparedPanel, keyCode, event, 0)) {
return true;
}
}
}
- if (!mWindow.isDestroyed()) {
- final Callback cb = mWindow.getCallback();
+ if (!isDestroyed()) {
+ final Callback cb = getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
@@ -2422,28 +2420,28 @@
}
}
- return isDown ? mWindow.onKeyDown(mFeatureId, event.getKeyCode(), event)
- : mWindow.onKeyUp(mFeatureId, event.getKeyCode(), event);
+ return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)
+ : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent ev) {
// If the panel is already prepared, then perform the shortcut using it.
boolean handled;
- if (mWindow.mPreparedPanel != null) {
- handled = mWindow.performPanelShortcut(mWindow.mPreparedPanel, ev.getKeyCode(), ev,
+ if (mPreparedPanel != null) {
+ handled = performPanelShortcut(mPreparedPanel, ev.getKeyCode(), ev,
Menu.FLAG_PERFORM_NO_CLOSE);
if (handled) {
- if (mWindow.mPreparedPanel != null) {
- mWindow.mPreparedPanel.isHandled = true;
+ if (mPreparedPanel != null) {
+ mPreparedPanel.isHandled = true;
}
return true;
}
}
// Shortcut not handled by the panel. Dispatch to the view hierarchy.
- final Callback cb = mWindow.getCallback();
- handled = cb != null && !mWindow.isDestroyed() && mFeatureId < 0
+ final Callback cb = getCallback();
+ handled = cb != null && !isDestroyed() && mFeatureId < 0
? cb.dispatchKeyShortcutEvent(ev) : super.dispatchKeyShortcutEvent(ev);
if (handled) {
return true;
@@ -2453,10 +2451,10 @@
// combination such as Control+C. Temporarily prepare the panel then mark it
// unprepared again when finished to ensure that the panel will again be prepared
// the next time it is shown for real.
- PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (st != null && mWindow.mPreparedPanel == null) {
- mWindow.preparePanel(st, ev);
- handled = mWindow.performPanelShortcut(st, ev.getKeyCode(), ev,
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (st != null && mPreparedPanel == null) {
+ preparePanel(st, ev);
+ handled = performPanelShortcut(st, ev.getKeyCode(), ev,
Menu.FLAG_PERFORM_NO_CLOSE);
st.isPrepared = false;
if (handled) {
@@ -2468,23 +2466,23 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
- final Callback cb = mWindow.getCallback();
- return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev);
+ final Callback cb = getCallback();
+ return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)
+ : super.dispatchTouchEvent(ev);
}
@Override
public boolean dispatchTrackballEvent(MotionEvent ev) {
- final Callback cb = mWindow.getCallback();
- return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchTrackballEvent(ev) : super.dispatchTrackballEvent(ev);
+ final Callback cb = getCallback();
+ return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTrackballEvent(ev)
+ : super.dispatchTrackballEvent(ev);
}
@Override
public boolean dispatchGenericMotionEvent(MotionEvent ev) {
- final Callback cb = mWindow.getCallback();
- return cb != null && !mWindow.isDestroyed() && mFeatureId < 0
- ? cb.dispatchGenericMotionEvent(ev) : super.dispatchGenericMotionEvent(ev);
+ final Callback cb = getCallback();
+ return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchGenericMotionEvent(ev)
+ : super.dispatchGenericMotionEvent(ev);
}
public boolean superDispatchKeyEvent(KeyEvent event) {
@@ -2536,7 +2534,7 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
- if (mHasNonClientDecor && mWindow.mNonClientDecorView.mVisible) {
+ if (mHasNonClientDecor && mNonClientDecorView.mVisible) {
// Don't dispatch ACTION_DOWN to the non client decor if the window is
// resizable and the event was (starting) outside the window.
// Window resizing events should be handled by WindowManager.
@@ -2559,7 +2557,7 @@
int x = (int)event.getX();
int y = (int)event.getY();
if (isOutOfBounds(x, y)) {
- mWindow.closePanel(mFeatureId);
+ closePanel(mFeatureId);
return true;
}
}
@@ -2585,7 +2583,7 @@
if (action == MotionEvent.ACTION_MOVE) {
if (y > (mDownY+30)) {
Log.i(TAG, "Closing!");
- mWindow.closePanel(mFeatureId);
+ closePanel(mFeatureId);
mWatchingForMenu = false;
return true;
}
@@ -2601,7 +2599,7 @@
if (action == MotionEvent.ACTION_DOWN) {
int y = (int)event.getY();
- if (y >= (getHeight()-5) && !mWindow.hasChildren()) {
+ if (y >= (getHeight()-5) && !hasChildren()) {
Log.i(TAG, "Watchiing!");
mWatchingForMenu = true;
}
@@ -2616,7 +2614,7 @@
if (action == MotionEvent.ACTION_MOVE) {
if (y < (getHeight()-30)) {
Log.i(TAG, "Opening!");
- mWindow.openPanel(FEATURE_OPTIONS_PANEL, new KeyEvent(
+ openPanel(FEATURE_OPTIONS_PANEL, new KeyEvent(
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU));
mWatchingForMenu = false;
return true;
@@ -2650,8 +2648,8 @@
@Override
public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
- final Callback cb = mWindow.getCallback();
- if (cb != null && !mWindow.isDestroyed()) {
+ final Callback cb = getCallback();
+ if (cb != null && !isDestroyed()) {
if (cb.dispatchPopulateAccessibilityEvent(event)) {
return true;
}
@@ -2688,7 +2686,7 @@
if (SWEEP_OPEN_MENU) {
if (mMenuBackground == null && mFeatureId < 0
- && mWindow.getAttributes().height
+ && getAttributes().height
== WindowManager.LayoutParams.MATCH_PARENT) {
mMenuBackground = getContext().getDrawable(
R.drawable.menu_background);
@@ -2713,8 +2711,7 @@
boolean fixedWidth = false;
if (widthMode == AT_MOST) {
- final TypedValue tvw = isPortrait ? mWindow.mFixedWidthMinor
- : mWindow.mFixedWidthMajor;
+ final TypedValue tvw = isPortrait ? mFixedWidthMinor : mFixedWidthMajor;
if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
final int w;
if (tvw.type == TypedValue.TYPE_DIMENSION) {
@@ -2735,8 +2732,7 @@
}
if (heightMode == AT_MOST) {
- final TypedValue tvh = isPortrait ? mWindow.mFixedHeightMajor
- : mWindow.mFixedHeightMinor;
+ final TypedValue tvh = isPortrait ? mFixedHeightMajor : mFixedHeightMinor;
if (tvh != null && tvh.type != TypedValue.TYPE_NULL) {
final int h;
if (tvh.type == TypedValue.TYPE_DIMENSION) {
@@ -2754,21 +2750,21 @@
}
}
- getOutsets(mWindow.mOutsets);
- if (mWindow.mOutsets.top > 0 || mWindow.mOutsets.bottom > 0) {
+ getOutsets(mOutsets);
+ if (mOutsets.top > 0 || mOutsets.bottom > 0) {
int mode = MeasureSpec.getMode(heightMeasureSpec);
if (mode != MeasureSpec.UNSPECIFIED) {
int height = MeasureSpec.getSize(heightMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- height + mWindow.mOutsets.top + mWindow.mOutsets.bottom, mode);
+ height + mOutsets.top + mOutsets.bottom, mode);
}
}
- if (mWindow.mOutsets.left > 0 || mWindow.mOutsets.right > 0) {
+ if (mOutsets.left > 0 || mOutsets.right > 0) {
int mode = MeasureSpec.getMode(widthMeasureSpec);
if (mode != MeasureSpec.UNSPECIFIED) {
int width = MeasureSpec.getSize(widthMeasureSpec);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- width + mWindow.mOutsets.left + mWindow.mOutsets.right, mode);
+ width + mOutsets.left + mOutsets.right, mode);
}
}
@@ -2780,7 +2776,7 @@
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY);
if (!fixedWidth && widthMode == AT_MOST) {
- final TypedValue tv = isPortrait ? mWindow.mMinWidthMinor : mWindow.mMinWidthMajor;
+ final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor;
if (tv.type != TypedValue.TYPE_NULL) {
final int min;
if (tv.type == TypedValue.TYPE_DIMENSION) {
@@ -2808,12 +2804,12 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- getOutsets(mWindow.mOutsets);
- if (mWindow.mOutsets.left > 0) {
- offsetLeftAndRight(-mWindow.mOutsets.left);
+ getOutsets(mOutsets);
+ if (mOutsets.left > 0) {
+ offsetLeftAndRight(-mOutsets.left);
}
- if (mWindow.mOutsets.top > 0) {
- offsetTopAndBottom(-mWindow.mOutsets.top);
+ if (mOutsets.top > 0) {
+ offsetTopAndBottom(-mOutsets.top);
}
}
@@ -2829,23 +2825,23 @@
@Override
public boolean showContextMenuForChild(View originalView) {
// Reuse the context menu builder
- if (mWindow.mContextMenu == null) {
- mWindow.mContextMenu = new ContextMenuBuilder(getContext());
- mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
+ if (mContextMenu == null) {
+ mContextMenu = new ContextMenuBuilder(getContext());
+ mContextMenu.setCallback(mContextMenuCallback);
} else {
- mWindow.mContextMenu.clearAll();
+ mContextMenu.clearAll();
}
- final MenuDialogHelper helper = mWindow.mContextMenu.show(originalView,
+ final MenuDialogHelper helper = mContextMenu.show(originalView,
originalView.getWindowToken());
if (helper != null) {
- helper.setPresenterCallback(mWindow.mContextMenuCallback);
- } else if (mWindow.mContextMenuHelper != null) {
+ helper.setPresenterCallback(mContextMenuCallback);
+ } else if (mContextMenuHelper != null) {
// No menu to show, but if we have a menu currently showing it just became blank.
// Close it.
- mWindow.mContextMenuHelper.dismiss();
+ mContextMenuHelper.dismiss();
}
- mWindow.mContextMenuHelper = helper;
+ mContextMenuHelper = helper;
return helper != null;
}
@@ -2875,15 +2871,14 @@
View originatingView, ActionMode.Callback callback, int type) {
ActionMode.Callback2 wrappedCallback = new ActionModeCallback2Wrapper(callback);
ActionMode mode = null;
- if (mWindow.getCallback() != null && !mWindow.isDestroyed()) {
+ if (getCallback() != null && !isDestroyed()) {
try {
- mode = mWindow.getCallback().onWindowStartingActionMode(wrappedCallback, type);
+ mode = getCallback().onWindowStartingActionMode(wrappedCallback, type);
} catch (AbstractMethodError ame) {
// Older apps might not implement the typed version of this method.
if (type == ActionMode.TYPE_PRIMARY) {
try {
- mode = mWindow.getCallback().onWindowStartingActionMode(
- wrappedCallback);
+ mode = getCallback().onWindowStartingActionMode(wrappedCallback);
} catch (AbstractMethodError ame2) {
// Older apps might not implement this callback method at all.
}
@@ -2908,9 +2903,9 @@
mode = null;
}
}
- if (mode != null && mWindow.getCallback() != null && !mWindow.isDestroyed()) {
+ if (mode != null && getCallback() != null && !isDestroyed()) {
try {
- mWindow.getCallback().onActionModeStarted(mode);
+ getCallback().onActionModeStarted(mode);
} catch (AbstractMethodError ame) {
// Older apps might not implement this callback method.
}
@@ -2999,10 +2994,10 @@
}
private WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
- WindowManager.LayoutParams attrs = mWindow.getAttributes();
+ WindowManager.LayoutParams attrs = getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
- if (!mWindow.mIsFloating && ActivityManager.isHighEndGfx()) {
+ if (!mIsFloating && ActivityManager.isHighEndGfx()) {
boolean disallowAnimate = !isLaidOut();
disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
& FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
@@ -3034,14 +3029,14 @@
boolean navBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0;
int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
- updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
- mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
- 0 /* rightInset */, animate && !disallowAnimate);
+ updateColorViewInt(mNavigationColorViewState, sysUiVisibility, mNavigationBarColor,
+ navBarSize, navBarToRightEdge, 0 /* rightInset */,
+ animate && !disallowAnimate);
boolean statusBarNeedsRightInset = navBarToRightEdge
&& mNavigationColorViewState.present;
int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0;
- updateColorViewInt(mStatusColorViewState, sysUiVisibility, mWindow.mStatusBarColor,
+ updateColorViewInt(mStatusColorViewState, sysUiVisibility, mStatusBarColor,
mLastTopInset, false /* matchVertical */, statusBarRightInset,
animate && !disallowAnimate);
}
@@ -3058,13 +3053,13 @@
int consumedRight = consumingNavBar ? mLastRightInset : 0;
int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
- if (mWindow.mContentRoot != null
- && mWindow.mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {
- MarginLayoutParams lp = (MarginLayoutParams) mWindow.mContentRoot.getLayoutParams();
+ if (mContentRoot != null
+ && mContentRoot.getLayoutParams() instanceof MarginLayoutParams) {
+ MarginLayoutParams lp = (MarginLayoutParams) mContentRoot.getLayoutParams();
if (lp.rightMargin != consumedRight || lp.bottomMargin != consumedBottom) {
lp.rightMargin = consumedRight;
lp.bottomMargin = consumedBottom;
- mWindow.mContentRoot.setLayoutParams(lp);
+ mContentRoot.setLayoutParams(lp);
if (insets == null) {
// The insets have changed, but we're not currently in the process
@@ -3102,11 +3097,11 @@
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
int size, boolean verticalBar, int rightMargin, boolean animate) {
state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
- && (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
- && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ && (getAttributes().flags & state.hideWindowFlag) == 0
+ && (getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
boolean show = state.present
&& (color & Color.BLACK) != 0
- && (mWindow.getAttributes().flags & state.translucentFlag) == 0;
+ && (getAttributes().flags & state.translucentFlag) == 0;
boolean visibilityChanged = false;
View view = state.view;
@@ -3198,14 +3193,14 @@
mPrimaryActionModeView.getLayoutParams();
boolean mlpChanged = false;
if (mPrimaryActionModeView.isShown()) {
- if (mWindow.mTempRect == null) {
- mWindow.mTempRect = new Rect();
+ if (mTempRect == null) {
+ mTempRect = new Rect();
}
- final Rect rect = mWindow.mTempRect;
+ final Rect rect = mTempRect;
// If the parent doesn't consume the insets, manually
// apply the default system window insets.
- mWindow.mContentParent.computeSystemWindowInsets(insets, rect);
+ mContentParent.computeSystemWindowInsets(insets, rect);
final int newMargin = rect.top == 0 ? insets.getSystemWindowInsetTop() : 0;
if (mlp.topMargin != newMargin) {
mlpChanged = true;
@@ -3236,7 +3231,7 @@
// mode is overlaid on the app content (e.g. it's
// sitting in a FrameLayout, see
// screen_simple_overlay_action_mode.xml).
- final boolean nonOverlay = (mWindow.getLocalFeatures()
+ final boolean nonOverlay = (getLocalFeatures()
& (1 << FEATURE_ACTION_MODE_OVERLAY)) == 0;
insets = insets.consumeSystemWindowInsets(
false, nonOverlay && showStatusGuard /* top */, false, false);
@@ -3260,14 +3255,14 @@
private void updateNavigationGuard(WindowInsets insets) {
// IMEs lay out below the nav bar, but the content view must not (for back compat)
- if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD) {
+ if (getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD) {
// prevent the content view from including the nav bar height
- if (mWindow.mContentParent != null) {
- if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
+ if (mContentParent != null) {
+ if (mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
MarginLayoutParams mlp =
- (MarginLayoutParams) mWindow.mContentParent.getLayoutParams();
+ (MarginLayoutParams) mContentParent.getLayoutParams();
mlp.bottomMargin = insets.getSystemWindowInsetBottom();
- mWindow.mContentParent.setLayoutParams(mlp);
+ mContentParent.setLayoutParams(mlp);
}
}
// position the navigation guard view, creating it if necessary
@@ -3349,7 +3344,7 @@
mDefaultOpacity = opacity;
if (mFeatureId < 0) {
- mWindow.setDefaultWindowFormat(opacity);
+ setDefaultWindowFormat(opacity);
}
}
@@ -3359,13 +3354,12 @@
// If the user is chording a menu shortcut, release the chord since
// this window lost focus
- if (mWindow.hasFeature(FEATURE_OPTIONS_PANEL) && !hasWindowFocus
- && mWindow.mPanelChordingKey != 0) {
- mWindow.closePanel(FEATURE_OPTIONS_PANEL);
+ if (hasFeature(FEATURE_OPTIONS_PANEL) && !hasWindowFocus && mPanelChordingKey != 0) {
+ closePanel(FEATURE_OPTIONS_PANEL);
}
- final Callback cb = mWindow.getCallback();
- if (cb != null && !mWindow.isDestroyed() && mFeatureId < 0) {
+ final Callback cb = getCallback();
+ if (cb != null && !isDestroyed() && mFeatureId < 0) {
cb.onWindowFocusChanged(hasWindowFocus);
}
@@ -3381,8 +3375,8 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- final Callback cb = mWindow.getCallback();
- if (cb != null && !mWindow.isDestroyed() && mFeatureId < 0) {
+ final Callback cb = getCallback();
+ if (cb != null && !isDestroyed() && mFeatureId < 0) {
cb.onAttachedToWindow();
}
@@ -3394,7 +3388,7 @@
* menu was open. When the activity is recreated, the menu
* should be shown again.
*/
- mWindow.openPanelsAfterRestore();
+ openPanelsAfterRestore();
}
}
@@ -3402,13 +3396,13 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- final Callback cb = mWindow.getCallback();
+ final Callback cb = getCallback();
if (cb != null && mFeatureId < 0) {
cb.onDetachedFromWindow();
}
- if (mWindow.mDecorContentParent != null) {
- mWindow.mDecorContentParent.dismissPopups();
+ if (mDecorContentParent != null) {
+ mDecorContentParent.dismissPopups();
}
if (mPrimaryActionModePopup != null) {
@@ -3423,7 +3417,7 @@
mFloatingToolbar = null;
}
- PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
if (st != null && st.menu != null && mFeatureId < 0) {
st.menu.close();
}
@@ -3432,29 +3426,29 @@
@Override
public void onCloseSystemDialogs(String reason) {
if (mFeatureId >= 0) {
- mWindow.closeAllPanels();
+ closeAllPanels();
}
}
public android.view.SurfaceHolder.Callback2 willYouTakeTheSurface() {
- return mFeatureId < 0 ? mWindow.mTakeSurfaceCallback : null;
+ return mFeatureId < 0 ? mTakeSurfaceCallback : null;
}
public InputQueue.Callback willYouTakeTheInputQueue() {
- return mFeatureId < 0 ? mWindow.mTakeInputQueueCallback : null;
+ return mFeatureId < 0 ? mTakeInputQueueCallback : null;
}
public void setSurfaceType(int type) {
- mWindow.setType(type);
+ PhoneWindow.this.setType(type);
}
public void setSurfaceFormat(int format) {
- mWindow.setFormat(format);
+ PhoneWindow.this.setFormat(format);
}
public void setSurfaceKeepScreenOn(boolean keepOn) {
- if (keepOn) mWindow.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- else mWindow.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ if (keepOn) PhoneWindow.this.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
@Override
@@ -3486,7 +3480,7 @@
endOnGoingFadeAnimation();
cleanupPrimaryActionMode();
if (mPrimaryActionModeView == null) {
- if (mWindow.isFloating()) {
+ if (isFloating()) {
// Use the action bar theme.
final TypedValue outValue = new TypedValue();
final Theme baseTheme = mContext.getTheme();
@@ -3633,7 +3627,7 @@
private void setHandledFloatingActionMode(ActionMode mode) {
mFloatingActionMode = mode;
- mFloatingToolbar = new FloatingToolbar(mContext, mWindow);
+ mFloatingToolbar = new FloatingToolbar(mContext, PhoneWindow.this);
((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
mFloatingActionMode.invalidate(); // Will show the floating toolbar if necessary.
mFloatingActionModeOriginatingView.getViewTreeObserver()
@@ -3672,10 +3666,6 @@
return windowHasNonClientDecor() && getElevation() > 0;
}
- void setWindow(PhoneWindow phoneWindow) {
- mWindow = phoneWindow;
- }
-
/**
* Clears out internal references when the action mode is destroyed.
*/
@@ -3764,9 +3754,9 @@
cleanupFloatingActionModeViews();
mFloatingActionMode = null;
}
- if (mWindow.getCallback() != null && !mWindow.isDestroyed()) {
+ if (getCallback() != null && !isDestroyed()) {
try {
- mWindow.getCallback().onActionModeFinished(mode);
+ getCallback().onActionModeFinished(mode);
} catch (AbstractMethodError ame) {
// Older apps might not implement this callback method.
}
@@ -3786,14 +3776,7 @@
}
protected DecorView generateDecor(int featureId) {
- // System process doesn't have application context and in that case we need to directly use
- // the context we have. Otherwise we want the application context, so we don't cling to the
- // activity.
- Context context = getContext().getApplicationContext();
- if (context == null) {
- context = getContext();
- }
- return new DecorView(context, featureId);
+ return new DecorView(getContext(), featureId);
}
protected void setFeatureFromAttrs(int featureId, TypedArray attrs,
@@ -4164,17 +4147,11 @@
if (nonClientDecorView == null) {
TypedValue value = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
- // We can't use the application context inside the general inflater, because some
- // views might depend on the fact that they get Activity or even specific activity.
- // We control the NonClientDecor, so we know that application context should be
- // safe enough.
- LayoutInflater inflater =
- mLayoutInflater.cloneInContext(getContext().getApplicationContext());
if (Color.luminance(value.data) < 0.5) {
- nonClientDecorView = (NonClientDecorView) inflater.inflate(
+ nonClientDecorView = (NonClientDecorView) mLayoutInflater.inflate(
R.layout.non_client_decor_dark, null);
} else {
- nonClientDecorView = (NonClientDecorView) inflater.inflate(
+ nonClientDecorView = (NonClientDecorView) mLayoutInflater.inflate(
R.layout.non_client_decor_light, null);
}
}
@@ -4196,14 +4173,12 @@
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
- mDecor.setWindow(this);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
- mDecor.setWindow(this);
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index ab3ec98..11ef18b 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -74,7 +74,9 @@
/**
* Notifies the status bar that a camera launch gesture has been detected.
+ *
+ * @param source the identifier for the gesture, see {@link StatusBarManager}
*/
- void onCameraLaunchGestureDetected();
+ void onCameraLaunchGestureDetected(int source);
}
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 415f325..aa7b34b 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -153,8 +153,6 @@
(MenuDropDownListView) mListViews.get(menuIndex + 1);
final MenuAdapter nextAdapter = (MenuAdapter) nextView.getAdapter();
- view.clearSelection();
-
mSubMenuHoverHandler.removeCallbacksAndMessages(null);
mSubMenuHoverHandler.postDelayed(new Runnable() {
@Override
@@ -162,9 +160,14 @@
// Make sure the menu wasn't already closed by something else and that
// it wasn't re-hovered by the user since this was scheduled.
int nextMenuIndex = mListViews.indexOf(nextView);
+
if (nextMenuIndex != -1 && nextView.getSelectedView() == null) {
// Disable exit animation, to prevent overlapping fading out submenus.
- mPopupWindows.get(nextMenuIndex).setExitTransition(null);
+ for (int i = nextMenuIndex; i < mPopupWindows.size(); i++) {
+ final MenuPopupWindow popupWindow = mPopupWindows.get(i);
+ popupWindow.setExitTransition(null);
+ popupWindow.setAnimationStyle(0);
+ }
nextAdapter.getAdapterMenu().close();
}
}
@@ -178,8 +181,9 @@
private View mShownAnchorView;
private List<DropDownListView> mListViews;
private List<MenuPopupWindow> mPopupWindows;
+ private int mLastPosition;
+ private List<Integer> mPositions;
private List<int[]> mOffsets;
- private int mPreferredPosition;
private boolean mForceShowIcon;
private Callback mPresenterCallback;
private ViewTreeObserver mTreeObserver;
@@ -203,14 +207,14 @@
final Resources res = context.getResources();
final Configuration config = res.getConfiguration();
mLayoutDirection = config.getLayoutDirection();
- mPreferredPosition = mLayoutDirection == View.LAYOUT_DIRECTION_RTL ? HORIZ_POSITION_LEFT :
- HORIZ_POSITION_RIGHT;
+ mLastPosition = getInitialMenuPosition();
mMenuMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
res.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
mPopupWindows = new ArrayList<MenuPopupWindow>();
mListViews = new ArrayList<DropDownListView>();
mOffsets = new ArrayList<int[]>();
+ mPositions = new ArrayList<Integer>();
mSubMenuHoverHandler = new Handler();
}
@@ -286,6 +290,16 @@
}
/**
+ * Determines the proper initial menu position for the current LTR/RTL configuration.
+ * @return The initial position.
+ */
+ @HorizPosition
+ private int getInitialMenuPosition() {
+ return mLayoutDirection == View.LAYOUT_DIRECTION_RTL ? HORIZ_POSITION_LEFT :
+ HORIZ_POSITION_RIGHT;
+ }
+
+ /**
* Determines whether the next submenu (of the given width) should display on the right or on
* the left of the most recent menu.
*
@@ -302,7 +316,7 @@
final Rect displayFrame = new Rect();
mShownAnchorView.getWindowVisibleDisplayFrame(displayFrame);
- if (mPreferredPosition == HORIZ_POSITION_RIGHT) {
+ if (mLastPosition == HORIZ_POSITION_RIGHT) {
final int right = screenLocation[0] + lastListView.getWidth() + nextMenuWidth;
if (right > displayFrame.right) {
return HORIZ_POSITION_LEFT;
@@ -342,7 +356,7 @@
ListView lastListView = mListViews.get(mListViews.size() - 1);
@HorizPosition int nextMenuPosition = getNextMenuPosition(menuWidth);
boolean showOnRight = nextMenuPosition == HORIZ_POSITION_RIGHT;
- mPreferredPosition = nextMenuPosition;
+ mLastPosition = nextMenuPosition;
int[] lastLocation = new int[2];
lastListView.getLocationOnScreen(lastLocation);
@@ -384,6 +398,7 @@
int[] offsets = {x, y};
mOffsets.add(offsets);
+ mPositions.add(mLastPosition);
}
/**
@@ -479,9 +494,11 @@
mListViews.subList(menuIndex, mListViews.size()).clear();
mOffsets.subList(menuIndex, mOffsets.size()).clear();
- // If there's still a menu open, refocus the new leaf [sub]menu.
- if (mListViews.size() > 0) {
- mListViews.get(mListViews.size() - 1).requestFocus();
+ mPositions.subList(menuIndex, mPositions.size()).clear();
+ if (mPositions.size() > 0) {
+ mLastPosition = mPositions.get(mPositions.size() - 1);
+ } else {
+ mLastPosition = getInitialMenuPosition();
}
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e4bc800..ffc69a9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -217,7 +217,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeZygoteInit", "()V",
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index fbe3ece..e6c7c2b 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1348,7 +1348,7 @@
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gBitmapMethods[] = {
+static const JNINativeMethod gBitmapMethods[] = {
{ "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
(void*)Bitmap_creator },
{ "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 20a54e5..28bc7fe 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -542,7 +542,7 @@
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeDecodeStream",
"(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
(void*)nativeDecodeStream
@@ -569,7 +569,7 @@
},
};
-static JNINativeMethod gOptionsMethods[] = {
+static const JNINativeMethod gOptionsMethods[] = {
{ "requestCancel", "()V", (void*)nativeRequestCancel }
};
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 1bbbb08..2df3a46 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -261,7 +261,7 @@
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gBitmapRegionDecoderMethods[] = {
+static const JNINativeMethod gBitmapRegionDecoderMethods[] = {
{ "nativeDecodeRegion",
"(JIIIILandroid/graphics/BitmapFactory$Options;)Landroid/graphics/Bitmap;",
(void*)nativeDecodeRegion},
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 036ece1..6fcf689 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -115,7 +115,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gCameraMethods[] = {
+static const JNINativeMethod gCameraMethods[] = {
/* name, signature, funcPtr */
{ "nativeConstructor", "()V", (void*)Camera_constructor },
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
index deb4971..728bc1c 100644
--- a/core/jni/android/graphics/CanvasProperty.cpp
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -39,7 +39,7 @@
// JNI Glue
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateFloat", "(F)J", (void*) createFloat },
{ "nCreatePaint", "(J)J", (void*) createPaint },
};
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index d03bcf0..83fd073 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -57,19 +57,19 @@
}
};
-static JNINativeMethod colorfilter_methods[] = {
+static const JNINativeMethod colorfilter_methods[] = {
{"destroyFilter", "(J)V", (void*) SkColorFilterGlue::finalizer}
};
-static JNINativeMethod porterduff_methods[] = {
+static const JNINativeMethod porterduff_methods[] = {
{ "native_CreatePorterDuffFilter", "(II)J", (void*) SkColorFilterGlue::CreatePorterDuffFilter },
};
-static JNINativeMethod lighting_methods[] = {
+static const JNINativeMethod lighting_methods[] = {
{ "native_CreateLightingFilter", "(II)J", (void*) SkColorFilterGlue::CreateLightingFilter },
};
-static JNINativeMethod colormatrix_methods[] = {
+static const JNINativeMethod colormatrix_methods[] = {
{ "nativeColorMatrixFilter", "([F)J", (void*) SkColorFilterGlue::CreateColorMatrixFilter },
};
diff --git a/core/jni/android/graphics/DrawFilter.cpp b/core/jni/android/graphics/DrawFilter.cpp
index 90ef6c0..c1dc0dd 100644
--- a/core/jni/android/graphics/DrawFilter.cpp
+++ b/core/jni/android/graphics/DrawFilter.cpp
@@ -97,11 +97,11 @@
}
};
-static JNINativeMethod drawfilter_methods[] = {
+static const JNINativeMethod drawfilter_methods[] = {
{"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer}
};
-static JNINativeMethod paintflags_methods[] = {
+static const JNINativeMethod paintflags_methods[] = {
{"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF}
};
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 38db76b..dac6d96 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -124,7 +124,7 @@
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gFontFamilyMethods[] = {
+static const JNINativeMethod gFontFamilyMethods[] = {
{ "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create },
{ "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
{ "nAddFont", "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
diff --git a/core/jni/android/graphics/Interpolator.cpp b/core/jni/android/graphics/Interpolator.cpp
index 3593d1a..fa28359 100644
--- a/core/jni/android/graphics/Interpolator.cpp
+++ b/core/jni/android/graphics/Interpolator.cpp
@@ -71,7 +71,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gInterpolatorMethods[] = {
+static const JNINativeMethod gInterpolatorMethods[] = {
{ "nativeConstructor", "(II)J", (void*)Interpolator_constructor },
{ "nativeDestructor", "(J)V", (void*)Interpolator_destructor },
{ "nativeReset", "(JII)V", (void*)Interpolator_reset },
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index d658643..2b4a1ab 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -61,19 +61,19 @@
}
};
-static JNINativeMethod gMaskFilterMethods[] = {
+static const JNINativeMethod gMaskFilterMethods[] = {
{ "nativeDestructor", "(J)V", (void*)SkMaskFilterGlue::destructor }
};
-static JNINativeMethod gBlurMaskFilterMethods[] = {
+static const JNINativeMethod gBlurMaskFilterMethods[] = {
{ "nativeConstructor", "(FI)J", (void*)SkMaskFilterGlue::createBlur }
};
-static JNINativeMethod gEmbossMaskFilterMethods[] = {
+static const JNINativeMethod gEmbossMaskFilterMethods[] = {
{ "nativeConstructor", "([FFFF)J", (void*)SkMaskFilterGlue::createEmboss }
};
-static JNINativeMethod gTableMaskFilterMethods[] = {
+static const JNINativeMethod gTableMaskFilterMethods[] = {
{ "nativeNewTable", "([B)J", (void*)SkMaskFilterGlue::createTable },
{ "nativeNewClip", "(II)J", (void*)SkMaskFilterGlue::createClipTable },
{ "nativeNewGamma", "(F)J", (void*)SkMaskFilterGlue::createGammaTable }
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index 101e2ba..b0f3bb4 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -302,7 +302,7 @@
}
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"finalizer", "(J)V", (void*) SkMatrixGlue::finalizer},
{"native_create","(J)J", (void*) SkMatrixGlue::create},
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index d67ed10..498c590 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -135,7 +135,7 @@
//////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "width", "()I", (void*)movie_width },
{ "height", "()I", (void*)movie_height },
{ "isOpaque", "()Z", (void*)movie_isOpaque },
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 1c28262..3ccbb35 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -108,7 +108,7 @@
/////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gNinePatchMethods[] = {
+static const JNINativeMethod gNinePatchMethods[] = {
{ "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk },
{ "validateNinePatchChunk", "([B)J",
(void*) SkNinePatchGlue::validateNinePatchChunk },
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 988d13a..520dc4f 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -1095,7 +1095,7 @@
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"finalizer", "(J)V", (void*) PaintGlue::finalizer},
{"native_init","()J", (void*) PaintGlue::init},
{"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index dbd7c89..2998c99 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -475,7 +475,7 @@
}
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"finalizer", "(J)V", (void*) SkPathGlue::finalizer},
{"init1","()J", (void*) SkPathGlue::init1},
{"init2","(J)J", (void*) SkPathGlue::init2},
diff --git a/core/jni/android/graphics/PathEffect.cpp b/core/jni/android/graphics/PathEffect.cpp
index 265944e..b289b21 100644
--- a/core/jni/android/graphics/PathEffect.cpp
+++ b/core/jni/android/graphics/PathEffect.cpp
@@ -69,31 +69,31 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gPathEffectMethods[] = {
+static const JNINativeMethod gPathEffectMethods[] = {
{ "nativeDestructor", "(J)V", (void*)SkPathEffectGlue::destructor }
};
-static JNINativeMethod gComposePathEffectMethods[] = {
+static const JNINativeMethod gComposePathEffectMethods[] = {
{ "nativeCreate", "(JJ)J", (void*)SkPathEffectGlue::Compose_constructor }
};
-static JNINativeMethod gSumPathEffectMethods[] = {
+static const JNINativeMethod gSumPathEffectMethods[] = {
{ "nativeCreate", "(JJ)J", (void*)SkPathEffectGlue::Sum_constructor }
};
-static JNINativeMethod gDashPathEffectMethods[] = {
+static const JNINativeMethod gDashPathEffectMethods[] = {
{ "nativeCreate", "([FF)J", (void*)SkPathEffectGlue::Dash_constructor }
};
-static JNINativeMethod gPathDashPathEffectMethods[] = {
+static const JNINativeMethod gPathDashPathEffectMethods[] = {
{ "nativeCreate", "(JFFI)J", (void*)SkPathEffectGlue::OneD_constructor }
};
-static JNINativeMethod gCornerPathEffectMethods[] = {
+static const JNINativeMethod gCornerPathEffectMethods[] = {
{ "nativeCreate", "(F)J", (void*)SkPathEffectGlue::Corner_constructor }
};
-static JNINativeMethod gDiscretePathEffectMethods[] = {
+static const JNINativeMethod gDiscretePathEffectMethods[] = {
{ "nativeCreate", "(FF)J", (void*)SkPathEffectGlue::Discrete_constructor }
};
diff --git a/core/jni/android/graphics/PathMeasure.cpp b/core/jni/android/graphics/PathMeasure.cpp
index fec5d9d..70e528d 100644
--- a/core/jni/android/graphics/PathMeasure.cpp
+++ b/core/jni/android/graphics/PathMeasure.cpp
@@ -143,7 +143,7 @@
}
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"native_create", "(JZ)J", (void*) SkPathMeasureGlue::create },
{"native_setPath", "(JJZ)V", (void*) SkPathMeasureGlue::setPath },
{"native_getLength", "(J)F", (void*) SkPathMeasureGlue::getLength },
diff --git a/core/jni/android/graphics/PorterDuff.cpp b/core/jni/android/graphics/PorterDuff.cpp
index fed90a5..dfc3c9d 100644
--- a/core/jni/android/graphics/PorterDuff.cpp
+++ b/core/jni/android/graphics/PorterDuff.cpp
@@ -58,7 +58,7 @@
};
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"nativeCreateXfermode","(I)J", (void*) SkPorterDuffGlue::CreateXfermode},
};
diff --git a/core/jni/android/graphics/Rasterizer.cpp b/core/jni/android/graphics/Rasterizer.cpp
index cfc23ac8..a106ecf 100644
--- a/core/jni/android/graphics/Rasterizer.cpp
+++ b/core/jni/android/graphics/Rasterizer.cpp
@@ -61,7 +61,7 @@
}
};
-static JNINativeMethod gRasterizerMethods[] = {
+static const JNINativeMethod gRasterizerMethods[] = {
{"finalizer", "(J)V", (void*) SkRasterizerGlue::finalizer}
};
@@ -85,7 +85,7 @@
}
};
-static JNINativeMethod gLayerRasterizerMethods[] = {
+static const JNINativeMethod gLayerRasterizerMethods[] = {
{ "nativeConstructor", "()J", (void*)SkLayerRasterizerGlue::create },
{ "nativeAddLayer", "(JJFF)V", (void*)SkLayerRasterizerGlue::addLayer }
};
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index e99bdfc..bcd0b60 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -306,13 +306,13 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gRegionIterMethods[] = {
+static const JNINativeMethod gRegionIterMethods[] = {
{ "nativeConstructor", "(J)J", (void*)RegionIter_constructor },
{ "nativeDestructor", "(J)V", (void*)RegionIter_destructor },
{ "nativeNext", "(JLandroid/graphics/Rect;)Z", (void*)RegionIter_next }
};
-static JNINativeMethod gRegionMethods[] = {
+static const JNINativeMethod gRegionMethods[] = {
// these are static methods
{ "nativeConstructor", "()J", (void*)Region_constructor },
{ "nativeDestructor", "(J)V", (void*)Region_destructor },
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 49c377e..799ed83 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -240,36 +240,36 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gColorMethods[] = {
+static const JNINativeMethod gColorMethods[] = {
{ "nativeRGBToHSV", "(III[F)V", (void*)Color_RGBToHSV },
{ "nativeHSVToColor", "(I[F)I", (void*)Color_HSVToColor }
};
-static JNINativeMethod gShaderMethods[] = {
+static const JNINativeMethod gShaderMethods[] = {
{ "nativeDestructor", "(J)V", (void*)Shader_destructor },
{ "nativeSetLocalMatrix", "(JJ)J", (void*)Shader_setLocalMatrix }
};
-static JNINativeMethod gBitmapShaderMethods[] = {
+static const JNINativeMethod gBitmapShaderMethods[] = {
{ "nativeCreate", "(Landroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor },
};
-static JNINativeMethod gLinearGradientMethods[] = {
+static const JNINativeMethod gLinearGradientMethods[] = {
{ "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
{ "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
};
-static JNINativeMethod gRadialGradientMethods[] = {
+static const JNINativeMethod gRadialGradientMethods[] = {
{ "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
{ "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
};
-static JNINativeMethod gSweepGradientMethods[] = {
+static const JNINativeMethod gSweepGradientMethods[] = {
{ "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
{ "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
};
-static JNINativeMethod gComposeShaderMethods[] = {
+static const JNINativeMethod gComposeShaderMethods[] = {
{ "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 },
{ "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 },
};
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 80de526..61dc6e4 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -359,7 +359,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gSurfaceTextureMethods[] = {
+static const JNINativeMethod gSurfaceTextureMethods[] = {
{"nativeClassInit", "()V", (void*)SurfaceTexture_classInit },
{"nativeInit", "(ZIZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init },
{"nativeFinalize", "()V", (void*)SurfaceTexture_finalize },
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index e0cbc9e..e97b768 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -68,7 +68,7 @@
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gTypefaceMethods[] = {
+static const JNINativeMethod gTypefaceMethods[] = {
{ "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
{ "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias },
{ "nativeUnref", "(J)V", (void*)Typeface_unref },
diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp
index 4a424ae..7441acc 100644
--- a/core/jni/android/graphics/Xfermode.cpp
+++ b/core/jni/android/graphics/Xfermode.cpp
@@ -47,15 +47,15 @@
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gXfermodeMethods[] = {
+static const JNINativeMethod gXfermodeMethods[] = {
{"finalizer", "(J)V", (void*) SkXfermodeGlue::finalizer}
};
-static JNINativeMethod gAvoidMethods[] = {
+static const JNINativeMethod gAvoidMethods[] = {
{"nativeCreate", "(III)J", (void*) SkXfermodeGlue::avoid_create}
};
-static JNINativeMethod gPixelXorMethods[] = {
+static const JNINativeMethod gPixelXorMethods[] = {
{"nativeCreate", "(I)J", (void*) SkXfermodeGlue::pixelxor_create}
};
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 5eede2a..7d0c39c 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -243,7 +243,7 @@
}
///////////////////////////////////////////////////////////////////////////////
-static JNINativeMethod gYuvImageMethods[] = {
+static const JNINativeMethod gYuvImageMethods[] = {
{ "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z",
(void*)YuvImage_compressToJpeg }
};
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index a91b15b..7a13fe4 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -150,7 +150,7 @@
document->close();
}
-static JNINativeMethod gPdfDocument_Methods[] = {
+static const JNINativeMethod gPdfDocument_Methods[] = {
{"nativeCreateDocument", "()J", (void*) nativeCreateDocument},
{"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage},
{"nativeFinishPage", "(J)V", (void*) nativeFinishPage},
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
index 52b69e0..0177635 100644
--- a/core/jni/android/graphics/pdf/PdfEditor.cpp
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -343,7 +343,7 @@
nativeSetPageBox(env, thiz, documentPtr, pageIndex, PAGE_BOX_CROP, mediaBox);
}
-static JNINativeMethod gPdfEditor_Methods[] = {
+static const JNINativeMethod gPdfEditor_Methods[] = {
{"nativeOpen", "(IJ)J", (void*) nativeOpen},
{"nativeClose", "(J)V", (void*) nativeClose},
{"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
diff --git a/core/jni/android/graphics/pdf/PdfRenderer.cpp b/core/jni/android/graphics/pdf/PdfRenderer.cpp
index 006eef8..6ddfacf 100644
--- a/core/jni/android/graphics/pdf/PdfRenderer.cpp
+++ b/core/jni/android/graphics/pdf/PdfRenderer.cpp
@@ -283,7 +283,7 @@
skBitmap.notifyPixelsChanged();
}
-static JNINativeMethod gPdfRenderer_Methods[] = {
+static const JNINativeMethod gPdfRenderer_Methods[] = {
{"nativeCreate", "(IJ)J", (void*) nativeCreate},
{"nativeClose", "(J)V", (void*) nativeClose},
{"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 40029bb..e045f5f 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -1087,18 +1087,18 @@
* JNI registration
*/
-static JNINativeMethod gMatrixMethods[] = {
+static const JNINativeMethod gMatrixMethods[] = {
{ "multiplyMM", "([FI[FI[FI)V", (void*)util_multiplyMM },
{ "multiplyMV", "([FI[FI[FI)V", (void*)util_multiplyMV },
};
-static JNINativeMethod gVisibilityMethods[] = {
+static const JNINativeMethod gVisibilityMethods[] = {
{ "computeBoundingSphere", "([FII[FI)V", (void*)util_computeBoundingSphere },
{ "frustumCullSpheres", "([FI[FII[III)I", (void*)util_frustumCullSpheres },
{ "visibilityTest", "([FI[FI[CII)I", (void*)util_visibilityTest },
};
-static JNINativeMethod gUtilsMethods[] = {
+static const JNINativeMethod gUtilsMethods[] = {
{ "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat },
{ "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
{ "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
@@ -1106,7 +1106,7 @@
{ "setTracingLevel", "(I)V", (void*)setTracingLevel },
};
-static JNINativeMethod gEtc1Methods[] = {
+static const JNINativeMethod gEtc1Methods[] = {
{ "encodeBlock", "(Ljava/nio/Buffer;ILjava/nio/Buffer;)V", (void*) etc1_encodeBlock },
{ "decodeBlock", "(Ljava/nio/Buffer;Ljava/nio/Buffer;)V", (void*) etc1_decodeBlock },
{ "getEncodedDataSize", "(II)I", (void*) etc1_getEncodedDataSize },
@@ -1120,11 +1120,11 @@
typedef struct _ClassRegistrationInfo {
const char* classPath;
- JNINativeMethod* methods;
+ const JNINativeMethod* methods;
size_t methodCount;
} ClassRegistrationInfo;
-static ClassRegistrationInfo gClasses[] = {
+static const ClassRegistrationInfo gClasses[] = {
{"android/opengl/Matrix", gMatrixMethods, NELEM(gMatrixMethods)},
{"android/opengl/Visibility", gVisibilityMethods, NELEM(gVisibilityMethods)},
{"android/opengl/GLUtils", gUtilsMethods, NELEM(gUtilsMethods)},
@@ -1136,7 +1136,7 @@
nativeClassInitBuffer(env);
int result = 0;
for (int i = 0; i < NELEM(gClasses); i++) {
- ClassRegistrationInfo* cri = &gClasses[i];
+ const ClassRegistrationInfo* cri = &gClasses[i];
result = RegisterMethodsOrDie(env, cri->classPath, cri->methods, cri->methodCount);
}
return result;
diff --git a/core/jni/android_animation_PropertyValuesHolder.cpp b/core/jni/android_animation_PropertyValuesHolder.cpp
index d117741..6065c24 100644
--- a/core/jni/android_animation_PropertyValuesHolder.cpp
+++ b/core/jni/android_animation_PropertyValuesHolder.cpp
@@ -139,7 +139,7 @@
env->ReleaseIntArrayElements(arg, intValues, JNI_ABORT);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nGetIntMethod", "(Ljava/lang/Class;Ljava/lang/String;)J",
(void*)android_animation_PropertyValuesHolder_getIntMethod },
{ "nGetFloatMethod", "(Ljava/lang/Class;Ljava/lang/String;)J",
diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp
index ef17db6..36d78cf 100644
--- a/core/jni/android_content_res_ObbScanner.cpp
+++ b/core/jni/android_content_res_ObbScanner.cpp
@@ -76,7 +76,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "getObbInfo_native", "(Ljava/lang/String;Landroid/content/res/ObbInfo;)V",
(void*) android_content_res_ObbScanner_getObbInfo },
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 580ac02..bb09d00 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -477,7 +477,7 @@
return true;
}
-static JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
{ "nativeCreate", "(Ljava/lang/String;I)J",
diff --git a/core/jni/android_database_SQLiteConnection.cpp b/core/jni/android_database_SQLiteConnection.cpp
index 7a3cdf6..bcc3bb0 100644
--- a/core/jni/android_database_SQLiteConnection.cpp
+++ b/core/jni/android_database_SQLiteConnection.cpp
@@ -786,7 +786,7 @@
}
-static JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
{ "nativeOpen", "(Ljava/lang/String;ILjava/lang/String;ZZ)J",
diff --git a/core/jni/android_database_SQLiteDebug.cpp b/core/jni/android_database_SQLiteDebug.cpp
index 26e13cf..4e4c36c 100644
--- a/core/jni/android_database_SQLiteDebug.cpp
+++ b/core/jni/android_database_SQLiteDebug.cpp
@@ -58,7 +58,7 @@
* JNI registration.
*/
-static JNINativeMethod gMethods[] =
+static const JNINativeMethod gMethods[] =
{
{ "nativeGetPagerStats", "(Landroid/database/sqlite/SQLiteDebug$PagerStats;)V",
(void*) nativeGetPagerStats },
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index 0a1c9f7..03e2387 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -75,7 +75,7 @@
return sqlite3_release_memory(SOFT_HEAP_LIMIT);
}
-static JNINativeMethod sMethods[] =
+static const JNINativeMethod sMethods[] =
{
/* name, signature, funcPtr */
{ "nativeReleaseMemory", "()I", (void*)nativeReleaseMemory },
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index ae96936..3e7a04e 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -105,7 +105,7 @@
return array;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "getLeakInfo", "()[B", (void*) DdmHandleNativeHeap_getLeakInfo },
};
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 5ddf235..32a877a 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -746,7 +746,7 @@
}; // namespace CanvasJNI
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
{"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
{"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
index fd42ddb..03fcdef 100644
--- a/core/jni/android_graphics_Picture.cpp
+++ b/core/jni/android_graphics_Picture.cpp
@@ -91,7 +91,7 @@
pict->endRecording();
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth},
{"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight},
{"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture},
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 4f44c262..414eba7 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -949,7 +949,7 @@
//-------------------------------------------------
-static JNINativeMethod camMethods[] = {
+static const JNINativeMethod camMethods[] = {
{ "getNumberOfCameras",
"()I",
(void *)android_hardware_Camera_getNumberOfCameras },
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 7d0afdc..2e5cda0 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -343,7 +343,7 @@
}
//----------------------------------------------------------------------------
-static JNINativeMethod gSystemSensorManagerMethods[] = {
+static const JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeClassInit",
"()V",
(void*)nativeClassInit },
@@ -360,7 +360,7 @@
(void*)nativeIsDataInjectionEnabled},
};
-static JNINativeMethod gBaseEventQueueMethods[] = {
+static const JNINativeMethod gBaseEventQueueMethods[] = {
{"nativeInitBaseEventQueue",
"(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;ILjava/lang/String;)J",
(void*)nativeInitSensorEventQueue },
diff --git a/core/jni/android_hardware_SerialPort.cpp b/core/jni/android_hardware_SerialPort.cpp
index 2d2ff4d..393dc7b 100644
--- a/core/jni/android_hardware_SerialPort.cpp
+++ b/core/jni/android_hardware_SerialPort.cpp
@@ -243,7 +243,7 @@
tcsendbreak(fd, 0);
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{"native_open", "(Ljava/io/FileDescriptor;I)V",
(void *)android_hardware_SerialPort_open},
{"native_close", "()V", (void *)android_hardware_SerialPort_close},
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 1c4c9ec..048b3c7 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -768,14 +768,14 @@
return status;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"listModules",
"(Ljava/util/ArrayList;)I",
(void *)android_hardware_SoundTrigger_listModules},
};
-static JNINativeMethod gModuleMethods[] = {
+static const JNINativeMethod gModuleMethods[] = {
{"native_setup",
"(Ljava/lang/Object;)V",
(void *)android_hardware_SoundTrigger_setup},
diff --git a/core/jni/android_hardware_UsbDevice.cpp b/core/jni/android_hardware_UsbDevice.cpp
index ef3b646..89d33e2 100644
--- a/core/jni/android_hardware_UsbDevice.cpp
+++ b/core/jni/android_hardware_UsbDevice.cpp
@@ -44,7 +44,7 @@
return result;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
// static methods
{ "native_get_device_id", "(Ljava/lang/String;)I",
(void*)android_hardware_UsbDevice_get_device_id },
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index e0cae6f..1ba9fc5 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -246,7 +246,7 @@
return result;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{"native_open", "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z",
(void *)android_hardware_UsbDeviceConnection_open},
{"native_close", "()V", (void *)android_hardware_UsbDeviceConnection_close},
diff --git a/core/jni/android_hardware_UsbRequest.cpp b/core/jni/android_hardware_UsbRequest.cpp
index ce99e15..399e7b1 100644
--- a/core/jni/android_hardware_UsbRequest.cpp
+++ b/core/jni/android_hardware_UsbRequest.cpp
@@ -190,7 +190,7 @@
return (usb_request_cancel(request) == 0);
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{"native_init", "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
(void *)android_hardware_UsbRequest_init},
{"native_close", "()V", (void *)android_hardware_UsbRequest_close},
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index fb22689..7930027 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -529,7 +529,7 @@
//-------------------------------------------------
-static JNINativeMethod gCameraMetadataMethods[] = {
+static const JNINativeMethod gCameraMetadataMethods[] = {
// static methods
{ "nativeClassInit",
"()V",
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 8b69bbd..738a62a 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -2280,7 +2280,7 @@
} /*extern "C" */
-static JNINativeMethod gDngCreatorMethods[] = {
+static const JNINativeMethod gDngCreatorMethods[] = {
{"nativeClassInit", "()V", (void*) DngCreator_nativeClassInit},
{"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;"
"Landroid/hardware/camera2/impl/CameraMetadataNative;Ljava/lang/String;)V",
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 63915ed..f1ea7ec 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -730,7 +730,7 @@
} // extern "C"
-static JNINativeMethod gCameraDeviceMethods[] = {
+static const JNINativeMethod gCameraDeviceMethods[] = {
{ "nativeDetectSurfaceType",
"(Landroid/view/Surface;)I",
(void *)LegacyCameraDevice_nativeDetectSurfaceType },
diff --git a/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp b/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp
index 7257597..f042058 100644
--- a/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp
+++ b/core/jni/android_hardware_camera2_legacy_PerfMeasurement.cpp
@@ -302,7 +302,7 @@
} // extern "C"
-static JNINativeMethod gPerfMeasurementMethods[] = {
+static const JNINativeMethod gPerfMeasurementMethods[] = {
{ "nativeCreateContext",
"(I)J",
(jlong *)PerfMeasurement_nativeCreateContext },
diff --git a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
index 470c5ba..4b279f63 100644
--- a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
+++ b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp
@@ -275,7 +275,7 @@
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
// {"name", "signature", (void*) functionPointer },
{ "nativeClassInit", "()V", (void*) class_init },
{ "nativeInitialize", "()V", (void*) initialize },
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 6c2bbd4..b977e37 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -682,7 +682,7 @@
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "(II)I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 91b3278..6d3c7d7 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1616,7 +1616,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
{"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
{"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
@@ -1663,7 +1663,7 @@
};
-static JNINativeMethod gEventHandlerMethods[] = {
+static const JNINativeMethod gEventHandlerMethods[] = {
{"native_setup",
"(Ljava/lang/Object;)V",
(void *)android_media_AudioSystem_eventHandlerSetup},
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 5faa150..7860b74 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1052,7 +1052,7 @@
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "()V", (void *)android_media_AudioTrack_start},
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp
index d441f10..873c3f2 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/core/jni/android_media_JetPlayer.cpp
@@ -488,7 +488,7 @@
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_setup", "(Ljava/lang/Object;II)Z", (void *)android_media_JetPlayer_setup},
{"native_finalize", "()V", (void *)android_media_JetPlayer_finalize},
diff --git a/core/jni/android_media_RemoteDisplay.cpp b/core/jni/android_media_RemoteDisplay.cpp
index 9bc223b..bd1a6ec 100644
--- a/core/jni/android_media_RemoteDisplay.cpp
+++ b/core/jni/android_media_RemoteDisplay.cpp
@@ -177,7 +177,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeListen", "(Ljava/lang/String;Ljava/lang/String;)J",
(void*)nativeListen },
{"nativeDispose", "(J)V",
diff --git a/core/jni/android_media_ToneGenerator.cpp b/core/jni/android_media_ToneGenerator.cpp
index 243f040..aec6263 100644
--- a/core/jni/android_media_ToneGenerator.cpp
+++ b/core/jni/android_media_ToneGenerator.cpp
@@ -123,7 +123,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone },
{ "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone },
{ "getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index c137b17..d6d4310 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -495,7 +495,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{"connectLocal", "(Ljava/io/FileDescriptor;Ljava/lang/String;I)V",
(void*)socket_connect_local},
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index fada7ac2..ba0876d 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -302,7 +302,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gNetworkUtilMethods[] = {
+static const JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
{ "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections },
{ "startDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_startDhcp },
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index 7354417..7b7d0cf 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -185,7 +185,7 @@
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
{"nativeGetUidStat", "(II)J", (void*) getUidStat},
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 9f5b3bc..568473c 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -1231,7 +1231,7 @@
static const char *classPathName = "android/opengl/EGL14";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"eglGetError", "()I", (void *) android_eglGetError },
{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplayInt },
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index 60a3bf6..62ccad4 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -149,7 +149,7 @@
static const char *classPathName = "android/opengl/EGLExt";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"eglPresentationTimeANDROID", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;J)Z", (void *) android_eglPresentationTimeANDROID },
};
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index dac98de..f4135c2 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -3184,7 +3184,7 @@
static const char *classPathName = "android/opengl/GLES10";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
{"glAlphaFunc", "(IF)V", (void *) android_glAlphaFunc__IF },
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 95be11b..4dc4233 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -582,7 +582,7 @@
static const char *classPathName = "android/opengl/GLES10Ext";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glQueryMatrixxOES", "([II[II)I", (void *) android_glQueryMatrixxOES___3II_3II },
{"glQueryMatrixxOES", "(Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)I", (void *) android_glQueryMatrixxOES__Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 6970a3c..2625e03 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -3065,7 +3065,7 @@
static const char *classPathName = "android/opengl/GLES11";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glBindBuffer", "(II)V", (void *) android_glBindBuffer__II },
{"glBufferData", "(IILjava/nio/Buffer;I)V", (void *) android_glBufferData__IILjava_nio_Buffer_2I },
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 6422ff2..fb85cb0 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -3573,7 +3573,7 @@
static const char *classPathName = "android/opengl/GLES11Ext";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glBlendEquationSeparateOES", "(II)V", (void *) android_glBlendEquationSeparateOES__II },
{"glBlendFuncSeparateOES", "(IIII)V", (void *) android_glBlendFuncSeparateOES__IIII },
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index f9a0dfe..b9f61a9 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -6152,7 +6152,7 @@
static const char *classPathName = "android/opengl/GLES20";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
{"glAttachShader", "(II)V", (void *) android_glAttachShader__II },
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 1d92cd4..8eb5044 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -5167,7 +5167,7 @@
static const char *classPathName = "android/opengl/GLES30";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glReadBuffer", "(I)V", (void *) android_glReadBuffer__I },
{"glDrawRangeElements", "(IIIIILjava/nio/Buffer;)V", (void *) android_glDrawRangeElements__IIIIILjava_nio_Buffer_2 },
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 92ecbe0..e427388 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -3175,7 +3175,7 @@
static const char *classPathName = "android/opengl/GLES31";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glDispatchCompute", "(III)V", (void *) android_glDispatchCompute__III },
{"glDispatchComputeIndirect", "(J)V", (void *) android_glDispatchComputeIndirect },
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 2856308..180c693 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -1443,7 +1443,7 @@
static const char *classPathName = "android/opengl/GLES31Ext";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glBlendBarrierKHR", "()V", (void *) android_glBlendBarrierKHR__ },
{"glDebugMessageControlKHR", "(IIII[IIZ)V", (void *) android_glDebugMessageControlKHR__IIII_3IIZ },
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index b969477..097bbac 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -973,7 +973,7 @@
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "getNativeHeapSize", "()J",
(void*) android_os_Debug_getNativeHeapSize },
{ "getNativeHeapAllocatedSize", "()J",
diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp
index d2db3c9..e57a719 100644
--- a/core/jni/android_os_MessageQueue.cpp
+++ b/core/jni/android_os_MessageQueue.cpp
@@ -209,7 +209,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMessageQueueMethods[] = {
+static const JNINativeMethod gMessageQueueMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },
{ "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 762b88f..8ba77ae 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -320,7 +320,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
/* name, signature, funcPtr */
{ "checkSELinuxAccess" , "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z" , (void*)checkSELinuxAccess },
{ "getContext" , "()Ljava/lang/String;" , (void*)getCon },
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index dfe024e..d98407d 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -104,7 +104,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "uptimeMillis", "()J",
(void*) android_os_SystemClock_uptimeMillis },
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index 554d304..5dace6b 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -220,7 +220,7 @@
}
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
(void*) SystemProperties_getS },
{ "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 3fd3b3c..30fc47b 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -105,7 +105,7 @@
atrace_set_tracing_enabled(enabled);
}
-static JNINativeMethod gTraceMethods[] = {
+static const JNINativeMethod gTraceMethods[] = {
/* name, signature, funcPtr */
{ "nativeGetEnabledTags",
"()J",
diff --git a/core/jni/android_os_UEventObserver.cpp b/core/jni/android_os_UEventObserver.cpp
index eb36f85..30d40a2 100644
--- a/core/jni/android_os_UEventObserver.cpp
+++ b/core/jni/android_os_UEventObserver.cpp
@@ -103,7 +103,7 @@
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeSetup", "()V",
(void *)nativeSetup },
{ "nativeWaitForNextEvent", "()Ljava/lang/String;",
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
index ca21fd7..818bf53 100644
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ b/core/jni/android_server_NetworkManagementSocketTagger.cpp
@@ -83,7 +83,7 @@
return (jint)res;
}
-static JNINativeMethod gQTagUidMethods[] = {
+static const JNINativeMethod gQTagUidMethods[] = {
{ "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)QTagUid_tagSocketFd},
{ "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)QTagUid_untagSocketFd},
{ "native_setCounterSet", "(II)I", (void*)QTagUid_setCounterSet},
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index 3285429..2a3f036 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -56,7 +56,7 @@
return result;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "runBidi", "(I[C[BIZ)I", (void*) runBidi }
};
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 9258248..474a74e 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -178,7 +178,7 @@
return u_charMirror(c);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "getDirectionalities", "([C[BI)V",
(void*) getDirectionalities },
{ "getEastAsianWidth", "(C)I",
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index 90e4bb6..a151e00 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -172,7 +172,7 @@
env->SetFloatArrayRegion(widths, 0, b->size(), b->charWidths());
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
// TODO performance: many of these are candidates for fast jni, awaiting guidance
{"nNewBuilder", "()J", (void*) nNewBuilder},
{"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 7ca0654..614e82f 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -2112,7 +2112,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gAssetManagerMethods[] = {
+static const JNINativeMethod gAssetManagerMethods[] = {
/* name, signature, funcPtr */
// Basic asset stuff.
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 05bc125..4f8a2cb 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -249,7 +249,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gRegisterMethods[] = {
+static const JNINativeMethod gRegisterMethods[] = {
/* name, signature, funcPtr */
{ "writeEvent", "(II)I", (void*) android_util_EventLog_writeEvent_Integer },
{ "writeEvent", "(IJ)I", (void*) android_util_EventLog_writeEvent_Long },
diff --git a/core/jni/android_util_FileObserver.cpp b/core/jni/android_util_FileObserver.cpp
index 067d298..2b93b6d 100644
--- a/core/jni/android_util_FileObserver.cpp
+++ b/core/jni/android_util_FileObserver.cpp
@@ -127,7 +127,7 @@
#endif
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "init", "()I", (void*)android_os_fileobserver_init },
{ "observe", "(I)V", (void*)android_os_fileobserver_observe },
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 2b1067b..2d23cda 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -111,7 +111,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "isLoggable", "(Ljava/lang/String;I)Z", (void*) android_util_Log_isLoggable },
{ "println_native", "(IILjava/lang/String;Ljava/lang/String;)I", (void*) android_util_Log_println_native },
diff --git a/core/jni/android_util_StringBlock.cpp b/core/jni/android_util_StringBlock.cpp
index f83eaec..b396afe 100644
--- a/core/jni/android_util_StringBlock.cpp
+++ b/core/jni/android_util_StringBlock.cpp
@@ -155,7 +155,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gStringBlockMethods[] = {
+static const JNINativeMethod gStringBlockMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "([BII)J",
(void*) android_content_StringBlock_nativeCreate },
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index 375710e..7ae51c8 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -364,7 +364,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gXmlBlockMethods[] = {
+static const JNINativeMethod gXmlBlockMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "([BII)J",
(void*) android_content_XmlBlock_nativeCreate },
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 0e2ec6b..437bd19 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -259,7 +259,7 @@
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/os/MessageQueue;)J",
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index 17d2a5e..7682dd6 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -268,7 +268,7 @@
const char* const kClassPathName = "android/view/GraphicBuffer";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateGraphicBuffer", "(IIII)J", (void*) android_view_GraphiceBuffer_create },
{ "nDestroyGraphicBuffer", "(J)V", (void*) android_view_GraphiceBuffer_destroy },
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 36ba892..3a0ddc9 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -85,7 +85,7 @@
const char* const kClassPathName = "android/view/HardwareLayer";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare },
{ "nSetLayerPaint", "(JJ)V", (void*) android_view_HardwareLayer_setLayerPaint },
{ "nSetTransform", "(JJ)V", (void*) android_view_HardwareLayer_setTransform },
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 4b42ab5..092ac27 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -259,7 +259,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gInputChannelMethods[] = {
+static const JNINativeMethod gInputChannelMethods[] = {
/* name, signature, funcPtr */
{ "nativeOpenInputChannelPair", "(Ljava/lang/String;)[Landroid/view/InputChannel;",
(void*)android_view_InputChannel_nativeOpenInputChannelPair },
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 43b8471..8293cd8 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -395,7 +395,7 @@
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index d61dee7..3bd6917 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -289,7 +289,7 @@
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Ljava/lang/ref/WeakReference;Landroid/view/InputChannel;Landroid/os/MessageQueue;)J",
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index 7653f58..e5519a7 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -203,7 +203,7 @@
* JNI registration.
*/
-static JNINativeMethod g_methods[] = {
+static const JNINativeMethod g_methods[] = {
/* name, signature, funcPtr */
{ "nativeReadFromParcel", "(Landroid/os/Parcel;)J",
(void*)nativeReadFromParcel },
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 98c17c0..81d46c3 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -752,7 +752,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMotionEventMethods[] = {
+static const JNINativeMethod gMotionEventMethods[] = {
/* name, signature, funcPtr */
{ "nativeInitialize",
"(JIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index a3b3700..388d365 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -467,7 +467,7 @@
const char* const kClassPathName = "android/view/RenderNode";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreate", "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
{ "nDestroyRenderNode", "(J)V", (void*) android_view_RenderNode_destroyRenderNode },
{ "nSetDisplayListData", "(JJ)V", (void*) android_view_RenderNode_setDisplayListData },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 4177ee2..0926e9b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -193,7 +193,7 @@
const char* const kClassPathName = "android/view/RenderNodeAnimator";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateAnimator", "(IF)J", (void*) createAnimator },
{ "nCreateCanvasPropertyFloatAnimator", "(JF)J", (void*) createCanvasPropertyFloatAnimator },
{ "nCreateCanvasPropertyPaintAnimator", "(JIF)J", (void*) createCanvasPropertyPaintAnimator },
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 4a311d31..24055e7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -514,7 +514,7 @@
namespace hwui = android::uirenderer;
-static JNINativeMethod gSurfaceMethods[] = {
+static const JNINativeMethod gSurfaceMethods[] = {
{"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
(void*)nativeCreateFromSurfaceTexture },
{"nativeRelease", "(J)V",
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d1acb59..65ebb663 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -572,7 +572,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod sSurfaceControlMethods[] = {
+static const JNINativeMethod sSurfaceControlMethods[] = {
{"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J",
(void*)nativeCreate },
{"nativeRelease", "(J)V",
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
index 609c565..dad6958 100644
--- a/core/jni/android_view_SurfaceSession.cpp
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -56,7 +56,7 @@
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "nativeCreate", "()J",
(void*)nativeCreate },
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index beb83b1..b736a17 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -197,7 +197,7 @@
const char* const kClassPathName = "android/view/TextureView";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V",
(void*) android_view_TextureView_createNativeWindow },
{ "nDestroyNativeWindow", "()V",
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 9a2703b..c79f833 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -484,7 +484,7 @@
const char* const kClassPathName = "android/view/ThreadedRenderer";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas },
{ "nSetProcessStatsBuffer", "(JI)V", (void*) android_view_ThreadedRenderer_setProcessStatsBuffer },
{ "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
diff --git a/core/jni/android_view_VelocityTracker.cpp b/core/jni/android_view_VelocityTracker.cpp
index ddd5fc8..04ec705 100644
--- a/core/jni/android_view_VelocityTracker.cpp
+++ b/core/jni/android_view_VelocityTracker.cpp
@@ -215,7 +215,7 @@
// --- JNI Registration ---
-static JNINativeMethod gVelocityTrackerMethods[] = {
+static const JNINativeMethod gVelocityTrackerMethods[] = {
/* name, signature, funcPtr */
{ "nativeInitialize",
"(Ljava/lang/String;)J",
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index daa6f82..364ac44 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -561,7 +561,7 @@
delete reinterpret_cast<ZipFileRO*>(apkHandle);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"nativeOpenApk",
"(Ljava/lang/String;)J",
(void *)com_android_internal_content_NativeLibraryHelper_openApk},
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 6c0b756..70134ab 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -284,7 +284,7 @@
return 0;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeReadNetworkStatsDetail",
"(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I",
(void*) readNetworkStatsDetail }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aef70be..3f1be45 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -647,7 +647,7 @@
return pid;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
diff --git a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
index 7a18c2d..d20bae2 100644
--- a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
+++ b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
@@ -36,7 +36,7 @@
const char* const kClassPathName = "com/android/internal/util/VirtualRefBasePtr";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nIncStrong", "(J)V", (void*) incStrong },
{ "nDecStrong", "(J)V", (void*) decStrong },
};
diff --git a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
index 2c65d62..6781e13 100644
--- a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
+++ b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
@@ -78,7 +78,7 @@
const char* const kClassPathName = "com/android/internal/view/animation/NativeInterpolatorFactoryHelper";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "createAccelerateDecelerateInterpolator", "()J", (void*) createAccelerateDecelerateInterpolator },
{ "createAccelerateInterpolator", "(F)J", (void*) createAccelerateInterpolator },
{ "createAnticipateInterpolator", "(F)J", (void*) createAnticipateInterpolator },
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index baeb7dd..3d63b01 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -532,7 +532,7 @@
#define OBJECT "Ljava/lang/Object;"
#define STRING "Ljava/lang/String;"
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit","()V", (void*)nativeClassInit },
{"eglWaitGL", "()Z", (void*)jni_eglWaitGL },
{"eglInitialize", "(" DISPLAY "[I)Z", (void*)jni_eglInitialize },
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index f15f957..ad7d744 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -8490,7 +8490,7 @@
static const char *classPathName = "com/google/android/gles_jni/GLImpl";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nativeClassInit", "()V", (void*)nativeClassInit },
{"glActiveTexture", "(I)V", (void *) android_glActiveTexture__I },
{"glAlphaFunc", "(IF)V", (void *) android_glAlphaFunc__IF },
diff --git a/core/res/res/color/btn_colored_material.xml b/core/res/res/color/btn_colored_background_material.xml
similarity index 87%
rename from core/res/res/color/btn_colored_material.xml
rename to core/res/res/color/btn_colored_background_material.xml
index b45f824..b7f0ef5 100644
--- a/core/res/res/color/btn_colored_material.xml
+++ b/core/res/res/color/btn_colored_background_material.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -14,6 +14,7 @@
limitations under the License.
-->
+<!-- Used for tha background of a bordered colored button. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:alpha="?attr/disabledAlpha"
diff --git a/core/res/res/color/btn_colored_material.xml b/core/res/res/color/btn_colored_borderless_text_material.xml
similarity index 78%
copy from core/res/res/color/btn_colored_material.xml
copy to core/res/res/color/btn_colored_borderless_text_material.xml
index b45f824..ee5a90c 100644
--- a/core/res/res/color/btn_colored_material.xml
+++ b/core/res/res/color/btn_colored_borderless_text_material.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -14,9 +14,10 @@
limitations under the License.
-->
+<!-- Used for the text of a borderless colored button. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:alpha="?attr/disabledAlpha"
- android:color="?attr/colorButtonNormal" />
- <item android:color="?attr/colorAccent" />
+ android:color="?attr/textColorSecondary" />
+ <item android:color="?attr/colorAccent"/>
</selector>
diff --git a/core/res/res/color/btn_colored_text_material.xml b/core/res/res/color/btn_colored_text_material.xml
index 950d04a..23d05a9 100644
--- a/core/res/res/color/btn_colored_text_material.xml
+++ b/core/res/res/color/btn_colored_text_material.xml
@@ -14,9 +14,10 @@
limitations under the License.
-->
+<!-- Used for the text of a bordered colored button. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:alpha="?attr/disabledAlpha"
android:color="?attr/textColorSecondary" />
- <item android:color="?attr/colorAccent"/>
+ <item android:color="?attr/textColorSecondaryInverse" />
</selector>
diff --git a/core/res/res/drawable/btn_colored_material.xml b/core/res/res/drawable/btn_colored_material.xml
index 81cbe39..c3c5760 100644
--- a/core/res/res/drawable/btn_colored_material.xml
+++ b/core/res/res/drawable/btn_colored_material.xml
@@ -22,7 +22,7 @@
<ripple android:color="?attr/colorControlHighlight">
<item>
<shape android:shape="rectangle"
- android:tint="@color/btn_colored_material">
+ android:tint="@color/btn_colored_background_material">
<corners android:radius="@dimen/control_corner_material" />
<solid android:color="@color/white" />
<padding android:left="@dimen/button_padding_horizontal_material"
diff --git a/core/res/res/layout/number_picker_material.xml b/core/res/res/layout/number_picker_material.xml
index 47edec4..b045585 100644
--- a/core/res/res/layout/number_picker_material.xml
+++ b/core/res/res/layout/number_picker_material.xml
@@ -22,4 +22,4 @@
android:gravity="center"
android:singleLine="true"
android:background="@null"
- android:textAppearance="@style/TextAppearance.Material.Caption" />
+ android:textAppearance="@style/TextAppearance.Material.Body1" />
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 41b05ea..919519e 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -54,4 +54,7 @@
<!-- Do not show the message saying USB is connected in charging mode. -->
<bool name="config_usbChargingMessage">false</bool>
+
+ <!-- Use a custom transition for RemoteViews. -->
+ <bool name="config_overrideRemoteViewsActivityTransition">true</bool>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index dc96df4..83d9a3c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2150,6 +2150,13 @@
(which is exiting the screen). The wallpaper remains
static behind the animation. -->
<attr name="wallpaperIntraCloseExitAnimation" format="reference" />
+
+ <!-- When opening a new activity from a RemoteViews, this is the
+ animation that is run on the next activity (which is entering the
+ screen). Requires config_overrideRemoteViewsActivityTransition to
+ be true. -->
+ <attr name="activityOpenRemoteViewsEnterAnimation" format="reference" />
+
</declare-styleable>
<!-- ============================= -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9b1a613..24d760f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2214,6 +2214,10 @@
<bool name="config_defaultWindowFeatureOptionsPanel">true</bool>
<bool name="config_defaultWindowFeatureContextMenu">true</bool>
+ <!-- If true, the transition for a RemoteViews is read from a resource instead of using the
+ default scale-up transition. -->
+ <bool name="config_overrideRemoteViewsActivityTransition">false</bool>
+
<!-- This config is used to check if the carrier requires converting destination
number before sending out a SMS.
Formats for this configuration as below:
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 5dc14e3..611b171 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -471,6 +471,7 @@
<style name="Widget.Material.Button.Colored">
<item name="background">@drawable/btn_colored_material</item>
<item name="textAppearance">@style/TextAppearance.Material.Widget.Button.Inverse</item>
+ <item name="textColor">@color/btn_colored_text_material</item>
</style>
<!-- Small bordered ink button -->
@@ -487,7 +488,7 @@
<!-- Colored borderless ink button -->
<style name="Widget.Material.Button.Borderless.Colored">
- <item name="textColor">@color/btn_colored_text_material</item>
+ <item name="textColor">@color/btn_colored_borderless_text_material</item>
</style>
<!-- Alert dialog button bar button -->
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index c6052ff..05835e7 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -18,6 +18,7 @@
<style name="Animation.Micro.Activity" parent="Animation.Material.Activity">
<item name="activityOpenEnterAnimation">@anim/slide_in_micro</item>
+ <item name="activityOpenRemoteViewsEnterAnimation">@anim/slide_in_micro</item>
<item name="activityOpenExitAnimation">@null</item>
<item name="activityCloseEnterAnimation">@null</item>
<item name="activityCloseExitAnimation">@anim/slide_out_micro</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b5efbfd..028b95d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2191,6 +2191,7 @@
<java-symbol type="bool" name="config_sms_force_7bit_encoding" />
<java-symbol type="bool" name="config_defaultWindowFeatureOptionsPanel" />
<java-symbol type="bool" name="config_defaultWindowFeatureContextMenu" />
+ <java-symbol type="bool" name="config_overrideRemoteViewsActivityTransition" />
<java-symbol type="layout" name="simple_account_item" />
<java-symbol type="array" name="config_sms_convert_destination_number_support" />
diff --git a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
index e0b616c..3e83010 100644
--- a/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
+++ b/core/tests/coretests/apks/install_jni_lib/com_android_frameworks_coretests_JNITest.cpp
@@ -22,7 +22,7 @@
return 1;
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "checkFunction", "()I", (void*) checkFunction },
};
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index b37688f..ce9ae02 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -17,6 +17,9 @@
package android.widget;
import static android.widget.espresso.TextViewActions.clickOnTextAtIndex;
+import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
+import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
+import static android.widget.espresso.TextViewAssertions.hasSelection;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.pressKey;
@@ -63,4 +66,28 @@
onView(withId(R.id.textview)).perform(pressKey(KeyEvent.KEYCODE_FORWARD_DEL));
onView(withId(R.id.textview)).check(matches(withText("Hello orld!")));
}
+
+ @SmallTest
+ public void testLongPressAndDragToSelect() throws Exception {
+ getActivity();
+
+ final String helloWorld = "Hello little handsome boy!";
+ onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld));
+ onView(withId(R.id.textview)).perform(
+ longPressAndDragOnText(helloWorld.indexOf("little"), helloWorld.indexOf(" boy!")));
+
+ onView(withId(R.id.textview)).check(hasSelection("little handsome"));
+ }
+
+ @SmallTest
+ public void testDoubleTapAndDragToSelect() throws Exception {
+ getActivity();
+
+ final String helloWorld = "Hello young beautiful girl!";
+ onView(withId(R.id.textview)).perform(typeTextIntoFocusedView(helloWorld));
+ onView(withId(R.id.textview)).perform(
+ doubleTapAndDragOnText(helloWorld.indexOf("young"), helloWorld.indexOf(" girl!")));
+
+ onView(withId(R.id.textview)).check(hasSelection("young beautiful"));
+ }
}
diff --git a/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java b/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java
new file mode 100644
index 0000000..a0cd848
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/DragOnTextViewActions.java
@@ -0,0 +1,281 @@
+/*
+ * 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.widget.espresso;
+
+import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static org.hamcrest.Matchers.allOf;
+
+import android.annotation.Nullable;
+import android.os.SystemClock;
+import android.support.test.espresso.UiController;
+import android.support.test.espresso.PerformException;
+import android.support.test.espresso.ViewAction;
+import android.support.test.espresso.action.CoordinatesProvider;
+import android.support.test.espresso.action.GeneralClickAction;
+import android.support.test.espresso.action.MotionEvents;
+import android.support.test.espresso.action.PrecisionDescriber;
+import android.support.test.espresso.action.Press;
+import android.support.test.espresso.action.Swiper;
+import android.support.test.espresso.action.Tap;
+import android.support.test.espresso.util.HumanReadables;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.TextView;
+import org.hamcrest.Matcher;
+
+
+/**
+ * Drags on text in a TextView using touch events.<br>
+ * <br>
+ * View constraints:
+ * <ul>
+ * <li>must be a TextView displayed on screen
+ * <ul>
+ */
+public final class DragOnTextViewActions implements ViewAction {
+
+ /**
+ * Executes different "drag on text" types to given positions.
+ */
+ public enum Drag implements Swiper {
+
+ /**
+ * Starts a drag with a long-press.
+ */
+ LONG_PRESS {
+ private DownMotionPerformer downMotion = new DownMotionPerformer() {
+ @Override
+ public MotionEvent perform(
+ UiController uiController, float[] coordinates, float[] precision) {
+ MotionEvent downEvent = MotionEvents.sendDown(
+ uiController, coordinates, precision)
+ .down;
+ // Duration before a press turns into a long press.
+ // Factor 1.5 is needed, otherwise a long press is not safely detected.
+ // See android.test.TouchUtils longClickView
+ long longPressTimeout = (long) (ViewConfiguration.getLongPressTimeout() * 1.5f);
+ uiController.loopMainThreadForAtLeast(longPressTimeout);
+ return downEvent;
+ }
+ };
+
+ @Override
+ public Status sendSwipe(
+ UiController uiController,
+ float[] startCoordinates, float[] endCoordinates, float[] precision) {
+ return sendLinearDrag(
+ uiController, downMotion, startCoordinates, endCoordinates, precision);
+ }
+
+ @Override
+ public String toString() {
+ return "long press and drag to select";
+ }
+ },
+
+ /**
+ * Starts a drag with a double-tap.
+ */
+ DOUBLE_TAP {
+ private DownMotionPerformer downMotion = new DownMotionPerformer() {
+ @Override
+ @Nullable
+ public MotionEvent perform(
+ UiController uiController, float[] coordinates, float[] precision) {
+ MotionEvent downEvent = MotionEvents.sendDown(
+ uiController, coordinates, precision)
+ .down;
+ try {
+ if (!MotionEvents.sendUp(uiController, downEvent)) {
+ String logMessage = "Injection of up event as part of the double tap " +
+ "failed. Sending cancel event.";
+ Log.d(TAG, logMessage);
+ MotionEvents.sendCancel(uiController, downEvent);
+ return null;
+ }
+
+ long doubleTapMinimumTimeout = ViewConfiguration.getDoubleTapMinTime();
+ uiController.loopMainThreadForAtLeast(doubleTapMinimumTimeout);
+
+ return MotionEvents.sendDown(uiController, coordinates, precision).down;
+ } finally {
+ downEvent.recycle();
+ }
+ }
+ };
+
+ @Override
+ public Status sendSwipe(
+ UiController uiController,
+ float[] startCoordinates, float[] endCoordinates, float[] precision) {
+ return sendLinearDrag(
+ uiController, downMotion, startCoordinates, endCoordinates, precision);
+ }
+
+ @Override
+ public String toString() {
+ return "double-tap and drag to select";
+ }
+ };
+
+ private static final String TAG = Drag.class.getSimpleName();
+
+ /** The number of move events to send for each drag. */
+ private static final int DRAG_STEP_COUNT = 10;
+
+ /** Length of time a drag should last for, in milliseconds. */
+ private static final int DRAG_DURATION = 1500;
+
+ private static Status sendLinearDrag(
+ UiController uiController, DownMotionPerformer downMotion,
+ float[] startCoordinates, float[] endCoordinates, float[] precision) {
+ float[][] steps = interpolate(startCoordinates, endCoordinates);
+ final int delayBetweenMovements = DRAG_DURATION / steps.length;
+
+ MotionEvent downEvent = downMotion.perform(uiController, startCoordinates, precision);
+ if (downEvent == null) {
+ return Status.FAILURE;
+ }
+
+ try {
+ for (int i = 0; i < steps.length; i++) {
+ if (!MotionEvents.sendMovement(uiController, downEvent, steps[i])) {
+ String logMessage = "Injection of move event as part of the drag failed. " +
+ "Sending cancel event.";
+ Log.e(TAG, logMessage);
+ MotionEvents.sendCancel(uiController, downEvent);
+ return Status.FAILURE;
+ }
+
+ long desiredTime = downEvent.getDownTime() + delayBetweenMovements * i;
+ long timeUntilDesired = desiredTime - SystemClock.uptimeMillis();
+ if (timeUntilDesired > 10) {
+ // If the wait time until the next event isn't long enough, skip the wait
+ // and execute the next event.
+ uiController.loopMainThreadForAtLeast(timeUntilDesired);
+ }
+ }
+
+ if (!MotionEvents.sendUp(uiController, downEvent, endCoordinates)) {
+ String logMessage = "Injection of up event as part of the drag failed. " +
+ "Sending cancel event.";
+ Log.e(TAG, logMessage);
+ MotionEvents.sendCancel(uiController, downEvent);
+ return Status.FAILURE;
+ }
+ } finally {
+ downEvent.recycle();
+ }
+ return Status.SUCCESS;
+ }
+
+ private static float[][] interpolate(float[] start, float[] end) {
+ float[][] res = new float[DRAG_STEP_COUNT][2];
+
+ for (int i = 1; i < DRAG_STEP_COUNT + 1; i++) {
+ res[i - 1][0] = start[0] + (end[0] - start[0]) * i / (DRAG_STEP_COUNT + 2f);
+ res[i - 1][1] = start[1] + (end[1] - start[1]) * i / (DRAG_STEP_COUNT + 2f);
+ }
+
+ return res;
+ }
+ }
+
+ /**
+ * Interface to implement different "down motion" types.
+ */
+ private interface DownMotionPerformer {
+ /**
+ * Performs and returns a down motion.
+ *
+ * @param uiController a UiController to use to send MotionEvents to the screen.
+ * @param coordinates a float[] with x and y values of center of the tap.
+ * @param precision a float[] with x and y values of precision of the tap.
+ * @return the down motion event or null if the down motion event failed.
+ */
+ @Nullable
+ MotionEvent perform(UiController uiController, float[] coordinates, float[] precision);
+ }
+
+ private final Swiper mDragger;
+ private final CoordinatesProvider mStartCoordinatesProvider;
+ private final CoordinatesProvider mEndCoordinatesProvider;
+ private final PrecisionDescriber mPrecisionDescriber;
+
+ public DragOnTextViewActions(
+ Swiper dragger,
+ CoordinatesProvider startCoordinatesProvider,
+ CoordinatesProvider endCoordinatesProvider,
+ PrecisionDescriber precisionDescriber) {
+ mDragger = checkNotNull(dragger);
+ mStartCoordinatesProvider = checkNotNull(startCoordinatesProvider);
+ mEndCoordinatesProvider = checkNotNull(endCoordinatesProvider);
+ mPrecisionDescriber = checkNotNull(precisionDescriber);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Matcher<View> getConstraints() {
+ return allOf(isCompletelyDisplayed(), isAssignableFrom(TextView.class));
+ }
+
+ @Override
+ public void perform(UiController uiController, View view) {
+ checkNotNull(uiController);
+ checkNotNull(view);
+
+ float[] startCoordinates = mStartCoordinatesProvider.calculateCoordinates(view);
+ float[] endCoordinates = mEndCoordinatesProvider.calculateCoordinates(view);
+ float[] precision = mPrecisionDescriber.describePrecision();
+
+ Swiper.Status status;
+
+ try {
+ status = mDragger.sendSwipe(
+ uiController, startCoordinates, endCoordinates, precision);
+ } catch (RuntimeException re) {
+ throw new PerformException.Builder()
+ .withActionDescription(this.getDescription())
+ .withViewDescription(HumanReadables.describe(view))
+ .withCause(re)
+ .build();
+ }
+
+ int duration = ViewConfiguration.getPressedStateDuration();
+ // ensures that all work enqueued to process the swipe has been run.
+ if (duration > 0) {
+ uiController.loopMainThreadForAtLeast(duration);
+ }
+
+ if (status == Swiper.Status.FAILURE) {
+ throw new PerformException.Builder()
+ .withActionDescription(getDescription())
+ .withViewDescription(HumanReadables.describe(view))
+ .withCause(new RuntimeException(getDescription() + " failed"))
+ .build();
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return mDragger.toString();
+ }
+}
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
index 425dccd..7e4735b 100644
--- a/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewActions.java
@@ -18,7 +18,6 @@
import static android.support.test.espresso.action.ViewActions.actionWithAssertions;
-import android.content.res.Resources;
import android.support.test.espresso.PerformException;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.action.CoordinatesProvider;
@@ -27,8 +26,6 @@
import android.support.test.espresso.action.Tap;
import android.support.test.espresso.util.HumanReadables;
import android.text.Layout;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
import android.view.View;
import android.widget.TextView;
@@ -40,12 +37,14 @@
private TextViewActions() {}
/**
- * Returns an action that clicks on text at an index on the text view.<br>
+ * Returns an action that clicks on text at an index on the TextView.<br>
* <br>
* View constraints:
* <ul>
- * <li>must be a text view displayed on screen
+ * <li>must be a TextView displayed on screen
* <ul>
+ *
+ * @param index The index of the TextView's text to click on.
*/
public static ViewAction clickOnTextAtIndex(int index) {
return actionWithAssertions(
@@ -53,6 +52,48 @@
}
/**
+ * Returns an action that long presses then drags on text from startIndex to endIndex on the
+ * TextView.<br>
+ * <br>
+ * View constraints:
+ * <ul>
+ * <li>must be a TextView displayed on screen
+ * <ul>
+ *
+ * @param startIndex The index of the TextView's text to start a drag from
+ * @param endIndex The index of the TextView's text to end the drag at
+ */
+ public static ViewAction longPressAndDragOnText(int startIndex, int endIndex) {
+ return actionWithAssertions(
+ new DragOnTextViewActions(
+ DragOnTextViewActions.Drag.LONG_PRESS,
+ new TextCoordinates(startIndex),
+ new TextCoordinates(endIndex),
+ Press.FINGER));
+ }
+
+ /**
+ * Returns an action that double taps then drags on text from startIndex to endIndex on the
+ * TextView.<br>
+ * <br>
+ * View constraints:
+ * <ul>
+ * <li>must be a TextView displayed on screen
+ * <ul>
+ *
+ * @param startIndex The index of the TextView's text to start a drag from
+ * @param endIndex The index of the TextView's text to end the drag at
+ */
+ public static ViewAction doubleTapAndDragOnText(int startIndex, int endIndex) {
+ return actionWithAssertions(
+ new DragOnTextViewActions(
+ DragOnTextViewActions.Drag.DOUBLE_TAP,
+ new TextCoordinates(startIndex),
+ new TextCoordinates(endIndex),
+ Press.FINGER));
+ }
+
+ /**
* A provider of the x, y coordinates of the text at the specified index in a text view.
*/
private static final class TextCoordinates implements CoordinatesProvider {
diff --git a/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
new file mode 100644
index 0000000..dce3182
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/espresso/TextViewAssertions.java
@@ -0,0 +1,98 @@
+/*
+ * 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.widget.espresso;
+
+import static android.support.test.espresso.matcher.ViewMatchers.assertThat;
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static org.hamcrest.Matchers.is;
+
+import android.support.test.espresso.NoMatchingViewException;
+import android.support.test.espresso.ViewAssertion;
+import android.view.View;
+import android.widget.TextView;
+
+import junit.framework.AssertionFailedError;
+import org.hamcrest.Matcher;
+
+/**
+ * A collection of assertions on a {@link android.widget.TextView}.
+ */
+public final class TextViewAssertions {
+
+ private TextViewAssertions() {}
+
+ /**
+ * Returns a {@link ViewAssertion} that asserts that the text view has a specified
+ * selection.<br>
+ * <br>
+ * View constraints:
+ * <ul>
+ * <li>must be a text view displayed on screen
+ * <ul>
+ *
+ * @param selection The expected selection.
+ */
+ public static ViewAssertion hasSelection(String selection) {
+ return new TextSelectionAssertion(is(selection));
+ }
+
+ /**
+ * Returns a {@link ViewAssertion} that asserts that the text view has a specified
+ * selection.<br>
+ * <br>
+ * View constraints:
+ * <ul>
+ * <li>must be a text view displayed on screen
+ * <ul>
+ *
+ * @param selection A matcher representing the expected selection.
+ */
+ public static ViewAssertion hasSelection(Matcher<String> selection) {
+ return new TextSelectionAssertion(selection);
+ }
+
+ /**
+ * A {@link ViewAssertion} to check the selected text in a {@link TextView}.
+ */
+ private static final class TextSelectionAssertion implements ViewAssertion {
+
+ private final Matcher<String> mSelection;
+
+ public TextSelectionAssertion(Matcher<String> selection) {
+ mSelection = checkNotNull(selection);
+ }
+
+ @Override
+ public void check(View view, NoMatchingViewException exception) {
+ if (view instanceof TextView) {
+ TextView textView = (TextView) view;
+ int selectionStart = textView.getSelectionStart();
+ int selectionEnd = textView.getSelectionEnd();
+ try {
+ String selectedText = textView.getText()
+ .subSequence(selectionStart, selectionEnd)
+ .toString();
+ assertThat(selectedText, mSelection);
+ } catch (IndexOutOfBoundsException e) {
+ throw new AssertionFailedError(e.getMessage());
+ }
+ } else {
+ throw new AssertionFailedError("TextView not found");
+ }
+ }
+ }
+}
diff --git a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
index 4c16154..67b12d7 100644
--- a/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/32/jni/native.cpp
@@ -30,7 +30,7 @@
static const char *classPathName = "com/framework/shareduid/bit32/Native";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"add", "(II)I", (void*)add },
};
@@ -38,7 +38,7 @@
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
- JNINativeMethod* gMethods, int numMethods)
+ const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
diff --git a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
index c2f9f52..342b3bc 100644
--- a/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/64/jni/native.cpp
@@ -30,7 +30,7 @@
static const char *classPathName = "com/framework/shareduid/bit64/Native";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"add", "(II)I", (void*)add },
};
@@ -38,7 +38,7 @@
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
- JNINativeMethod* gMethods, int numMethods)
+ const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
diff --git a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
index 5d3ca06..9b38e3e 100644
--- a/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
+++ b/core/tests/hosttests/test-apps/SharedUid/dual/jni/native.cpp
@@ -30,7 +30,7 @@
static const char *classPathName = "com/framework/shareduid/dual/Native";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"add", "(II)I", (void*)add },
};
@@ -38,7 +38,7 @@
* Register several native methods for one class.
*/
static int registerNativeMethods(JNIEnv* env, const char* className,
- JNINativeMethod* gMethods, int numMethods)
+ const JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index 52597e1..63fe8ac 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -702,7 +702,7 @@
return status;
}
-static JNINativeMethod nativeMethods[] = {
+static const JNINativeMethod nativeMethods[] = {
{"_initialize", "()I",
(void*)android_drm_DrmManagerClient_initialize},
diff --git a/media/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
index afb5d5c..b56a364 100644
--- a/media/jni/android_media_AmrInputStream.cpp
+++ b/media/jni/android_media_AmrInputStream.cpp
@@ -119,7 +119,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"GsmAmrEncoderNew", "()J", (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
{"GsmAmrEncoderInitialize", "(J)V", (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
{"GsmAmrEncoderEncode", "(J[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 0034b07..3ffdb17 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -1253,7 +1253,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gImageReaderMethods[] = {
+static const JNINativeMethod gImageReaderMethods[] = {
{"nativeClassInit", "()V", (void*)ImageReader_classInit },
{"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
{"nativeClose", "()V", (void*)ImageReader_close },
@@ -1263,7 +1263,7 @@
{"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage },
};
-static JNINativeMethod gImageMethods[] = {
+static const JNINativeMethod gImageMethods[] = {
{"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
{"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
(void*)Image_createSurfacePlane },
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 93a4426..e8f680f 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1798,7 +1798,7 @@
android_media_MediaCodec_release(env, thiz);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "native_release", "()V", (void *)android_media_MediaCodec_release },
{ "native_reset", "()V", (void *)android_media_MediaCodec_reset },
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index 82dd48d..de9bf1f 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -286,7 +286,7 @@
static void android_media_MediaCodecList_native_init(JNIEnv* /* env */) {
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
{ "getCodecName", "(I)Ljava/lang/String;",
(void *)android_media_MediaCodecList_getCodecName },
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index d7968d2..e414f48 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -316,7 +316,7 @@
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaCrypto_release },
{ "native_init", "()V", (void *)android_media_MediaCrypto_native_init },
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 9ec0312..275de1ad 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -1455,7 +1455,7 @@
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaDrm_release },
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 4e9b726..96c12dd 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -769,7 +769,7 @@
android_media_MediaExtractor_release(env, thiz);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaExtractor_release },
{ "getTrackCount", "()I", (void *)android_media_MediaExtractor_getTrackCount },
diff --git a/media/jni/android_media_MediaHTTPConnection.cpp b/media/jni/android_media_MediaHTTPConnection.cpp
index 393003d..fa0b43f 100644
--- a/media/jni/android_media_MediaHTTPConnection.cpp
+++ b/media/jni/android_media_MediaHTTPConnection.cpp
@@ -154,7 +154,7 @@
return n;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "native_getIMemory", "()Landroid/os/IBinder;",
(void *)android_media_MediaHTTPConnection_native_getIMemory },
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 59fb6d6..f4e940d 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -467,7 +467,7 @@
}
// JNI mapping between Java methods and native methods
-static JNINativeMethod nativeMethods[] = {
+static const JNINativeMethod nativeMethods[] = {
{
"_setDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index ecb2ac8..216624e 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -219,7 +219,7 @@
}
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nativeAddTrack", "(J[Ljava/lang/String;[Ljava/lang/Object;)I",
(void *)android_media_MediaMuxer_addTrack },
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d8041f4..be36729 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1033,7 +1033,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{
"nativeSetDataSource",
"(Landroid/os/IBinder;Ljava/lang/String;[Ljava/lang/String;"
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index ca9db91..5800043 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -301,7 +301,7 @@
}
return static_cast<jint>(levels[index]);
}
-static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
+static const JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_file_formats", "()I", (void *)android_media_MediaProfiles_native_get_num_file_formats},
{"native_get_file_format", "(I)I", (void *)android_media_MediaProfiles_native_get_file_format},
@@ -315,7 +315,7 @@
(void *)android_media_MediaProfiles_native_get_audio_encoder_cap},
};
-static JNINativeMethod gMethodsForCamcorderProfileClass[] = {
+static const JNINativeMethod gMethodsForCamcorderProfileClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_camcorder_profile", "(II)Landroid/media/CamcorderProfile;",
(void *)android_media_MediaProfiles_native_get_camcorder_profile},
@@ -323,7 +323,7 @@
(void *)android_media_MediaProfiles_native_has_camcorder_profile},
};
-static JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = {
+static const JNINativeMethod gMethodsForDecoderCapabilitiesClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_video_decoders", "()I", (void *)android_media_MediaProfiles_native_get_num_video_decoders},
{"native_get_num_audio_decoders", "()I", (void *)android_media_MediaProfiles_native_get_num_audio_decoders},
@@ -331,7 +331,7 @@
{"native_get_audio_decoder_type", "(I)I", (void *)android_media_MediaProfiles_native_get_audio_decoder_type},
};
-static JNINativeMethod gMethodsForCameraProfileClass[] = {
+static const JNINativeMethod gMethodsForCameraProfileClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_image_encoding_quality_levels",
"(I)I", (void *)android_media_MediaProfiles_native_get_num_image_encoding_quality_levels},
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index f60af63..e05b348 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -510,7 +510,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"setCamera", "(Landroid/hardware/Camera;)V", (void *)android_media_MediaRecorder_setCamera},
{"setVideoSource", "(I)V", (void *)android_media_MediaRecorder_setVideoSource},
{"setAudioSource", "(I)V", (void *)android_media_MediaRecorder_setAudioSource},
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 1a9384e..0f3c61f 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -412,7 +412,7 @@
setNativeScanner_l(env, thiz, 0);
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{
"processDirectory",
"(Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
diff --git a/media/jni/android_media_ResampleInputStream.cpp b/media/jni/android_media_ResampleInputStream.cpp
index 1549a30..d06baa5 100644
--- a/media/jni/android_media_ResampleInputStream.cpp
+++ b/media/jni/android_media_ResampleInputStream.cpp
@@ -107,7 +107,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"fir21", "([BI[BII)V", (void*)android_media_ResampleInputStream_fir21},
};
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 713f28c..ec2f98a 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -1173,12 +1173,12 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMtpDatabaseMethods[] = {
+static const JNINativeMethod gMtpDatabaseMethods[] = {
{"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
{"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
};
-static JNINativeMethod gMtpPropertyGroupMethods[] = {
+static const JNINativeMethod gMtpPropertyGroupMethods[] = {
{"format_date_time", "(J)Ljava/lang/String;",
(void *)android_mtp_MtpPropertyGroup_format_date_time},
};
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 2a46ee7..f11329c 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -490,7 +490,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_open", "(Ljava/lang/String;I)Z",
(void *)android_mtp_MtpDevice_open},
{"native_close", "()V", (void *)android_mtp_MtpDevice_close},
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 2ce2a90..d13187c 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -179,7 +179,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_setup", "(Landroid/mtp/MtpDatabase;Z)V",
(void *)android_mtp_MtpServer_setup},
{"native_run", "()V", (void *)android_mtp_MtpServer_run},
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index aba4bbe..fa69135 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -879,7 +879,7 @@
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
{"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;II[I[Ljava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioEffect_native_setup},
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 0557019..3d3adba 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -677,7 +677,7 @@
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_visualizer_native_init},
{"native_setup", "(Ljava/lang/Object;I[ILjava/lang/String;)I",
(void *)android_media_visualizer_native_setup},
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index b02349a..45cb34d 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -17,61 +17,70 @@
<com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/material_grey_50">
+ android:background="@color/material_grey_50"
+ android:orientation="vertical"
+ android:animateLayoutChanges="true">
- <TextView
- android:id="@android:id/empty"
+ <ProgressBar
+ android:id="@+id/progressbar"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:text="@string/empty"
- android:visibility="gone"
- style="@android:style/TextAppearance.Material.Subhead" />
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ style="@style/TrimmedHorizontalProgressBar"
+ android:visibility="gone"/>
+
+ <FrameLayout
+ android:id="@+id/container_message_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:elevation="8dp"
+ android:background="@color/material_grey_50"
+ android:visibility="gone"/>
+ <!-- The empty directory view -->
<LinearLayout
- android:id="@+id/content"
+ android:id="@android:id/empty"
+ android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:animateLayoutChanges="true">
-
- <ProgressBar
- android:id="@+id/progressbar"
- android:layout_width="match_parent"
+ android:visibility="gone">
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:indeterminate="true"
- style="@style/TrimmedHorizontalProgressBar"
- android:visibility="gone"/>
+ android:text="@string/empty"
+ style="@android:style/TextAppearance.Material.Subhead" />
- <FrameLayout
- android:id="@+id/container_message_bar"
- android:layout_width="match_parent"
+ <Button
+ android:id="@+id/button_retry"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:elevation="8dp"
- android:background="@color/material_grey_50"
- android:visibility="gone"/>
-
- <!-- This FrameLayout works around b/24189541 -->
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <android.support.v7.widget.RecyclerView
- android:id="@+id/recyclerView"
- android:scrollbars="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="@dimen/grid_padding_horiz"
- android:paddingEnd="@dimen/grid_padding_horiz"
- android:paddingTop="@dimen/grid_padding_vert"
- android:paddingBottom="@dimen/grid_padding_vert"
- android:clipToPadding="false"
- android:scrollbarStyle="outsideOverlay"
- android:drawSelectorOnTop="true"
- android:background="@color/directory_background" />
-
- </FrameLayout>
-
+ android:text="@string/button_retry"
+ style="?android:attr/buttonBarPositiveButtonStyle" />
+
</LinearLayout>
+
+ <!-- This FrameLayout works around b/24189541 -->
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/recyclerView"
+ android:scrollbars="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="@dimen/grid_padding_horiz"
+ android:paddingEnd="@dimen/grid_padding_horiz"
+ android:paddingTop="@dimen/grid_padding_vert"
+ android:paddingBottom="@dimen/grid_padding_vert"
+ android:clipToPadding="false"
+ android:scrollbarStyle="outsideOverlay"
+ android:drawSelectorOnTop="true"
+ android:background="@color/directory_background" />
+
+ </FrameLayout>
</com.android.documentsui.DirectoryView>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 28018f8e..a12edf3 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -81,7 +81,8 @@
<string name="button_move">Move</string>
<!-- Button label that hides the error bar [CHAR LIMIT=24] -->
<string name="button_dismiss">Dismiss</string>
-
+ <string name="button_retry">Try Again</string>
+
<!-- Mode that sorts documents by their display name alphabetically [CHAR LIMIT=24] -->
<string name="sort_name">By name</string>
<!-- Mode that sorts documents by their last modified time in descending order; most recent first [CHAR LIMIT=24] -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 1585908..c8ec4dc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -33,14 +33,11 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.util.Log;
-import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -67,7 +64,6 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executor;
@@ -367,129 +363,6 @@
public static String EXTRA_DIRECTORY_COPY = "com.android.documentsui.DIRECTORY_COPY";
}
- public static class State implements android.os.Parcelable {
- public int action;
- public String[] acceptMimes;
-
- /** Explicit user choice */
- public int userMode = MODE_UNKNOWN;
- /** Derived after loader */
- public int derivedMode = MODE_LIST;
-
- /** Explicit user choice */
- public int userSortOrder = SORT_ORDER_UNKNOWN;
- /** Derived after loader */
- public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
-
- public boolean allowMultiple;
- public boolean forceSize ;
- public boolean showSize;
- public boolean localOnly ;
- public boolean forceAdvanced ;
- public boolean showAdvanced ;
- public boolean stackTouched ;
- public boolean restored ;
- public boolean directoryCopy ;
- /** Transfer mode for file copy/move operations. */
- public int transferMode;
-
- /** Current user navigation stack; empty implies recents. */
- public DocumentStack stack = new DocumentStack();
- /** Currently active search, overriding any stack. */
- public String currentSearch;
-
- /** Instance state for every shown directory */
- public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
-
- /** Currently copying file */
- public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<DocumentInfo>();
-
- /** Name of the package that started DocsUI */
- public List<String> excludedAuthorities = new ArrayList<>();
-
- public static final int ACTION_OPEN = 1;
- public static final int ACTION_CREATE = 2;
- public static final int ACTION_GET_CONTENT = 3;
- public static final int ACTION_OPEN_TREE = 4;
- public static final int ACTION_MANAGE = 5;
- public static final int ACTION_BROWSE = 6;
- public static final int ACTION_OPEN_COPY_DESTINATION = 8;
-
- public static final int MODE_UNKNOWN = 0;
- public static final int MODE_LIST = 1;
- public static final int MODE_GRID = 2;
-
- public static final int SORT_ORDER_UNKNOWN = 0;
- public static final int SORT_ORDER_DISPLAY_NAME = 1;
- public static final int SORT_ORDER_LAST_MODIFIED = 2;
- public static final int SORT_ORDER_SIZE = 3;
-
- public void initAcceptMimes(Intent intent) {
- if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
- acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
- } else {
- String glob = intent.getType();
- acceptMimes = new String[] { glob != null ? glob : "*/*" };
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(action);
- out.writeInt(userMode);
- out.writeStringArray(acceptMimes);
- out.writeInt(userSortOrder);
- out.writeInt(allowMultiple ? 1 : 0);
- out.writeInt(forceSize ? 1 : 0);
- out.writeInt(showSize ? 1 : 0);
- out.writeInt(localOnly ? 1 : 0);
- out.writeInt(forceAdvanced ? 1 : 0);
- out.writeInt(showAdvanced ? 1 : 0);
- out.writeInt(stackTouched ? 1 : 0);
- out.writeInt(restored ? 1 : 0);
- DurableUtils.writeToParcel(out, stack);
- out.writeString(currentSearch);
- out.writeMap(dirState);
- out.writeList(selectedDocumentsForCopy);
- out.writeList(excludedAuthorities);
- }
-
- public static final Creator<State> CREATOR = new Creator<State>() {
- @Override
- public State createFromParcel(Parcel in) {
- final State state = new State();
- state.action = in.readInt();
- state.userMode = in.readInt();
- state.acceptMimes = in.readStringArray();
- state.userSortOrder = in.readInt();
- state.allowMultiple = in.readInt() != 0;
- state.forceSize = in.readInt() != 0;
- state.showSize = in.readInt() != 0;
- state.localOnly = in.readInt() != 0;
- state.forceAdvanced = in.readInt() != 0;
- state.showAdvanced = in.readInt() != 0;
- state.stackTouched = in.readInt() != 0;
- state.restored = in.readInt() != 0;
- DurableUtils.readFromParcel(in, state.stack);
- state.currentSearch = in.readString();
- in.readMap(state.dirState, null);
- in.readList(state.selectedDocumentsForCopy, null);
- in.readList(state.excludedAuthorities, null);
- return state;
- }
-
- @Override
- public State[] newArray(int size) {
- return new State[size];
- }
- };
- }
-
void setDisplayAdvancedDevices(boolean display) {
State state = getDisplayState();
LocalPreferences.setDisplayAdvancedDevices(this, display);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index f8ec8f1..f1492dc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -16,6 +16,7 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
@@ -56,7 +57,6 @@
public class CopyService extends IntentService {
public static final String TAG = "CopyService";
- public static final boolean DEBUG = false;
private static final String EXTRA_CANCEL = "com.android.documentsui.CANCEL";
public static final String EXTRA_SRC_LIST = "com.android.documentsui.SRC_LIST";
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index ea8ecf5..5eacf21 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -16,14 +16,15 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_BROWSE;
-import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
-import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
-import static com.android.documentsui.BaseActivity.State.MODE_GRID;
-import static com.android.documentsui.BaseActivity.State.MODE_LIST;
-import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.Shared.TAG;
+import static com.android.documentsui.State.ACTION_BROWSE;
+import static com.android.documentsui.State.ACTION_CREATE;
+import static com.android.documentsui.State.ACTION_MANAGE;
+import static com.android.documentsui.State.MODE_GRID;
+import static com.android.documentsui.State.MODE_LIST;
+import static com.android.documentsui.State.MODE_UNKNOWN;
+import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
@@ -93,7 +94,6 @@
import android.widget.Toast;
import com.android.documentsui.BaseActivity.DocumentContext;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.MultiSelectManager.Selection;
import com.android.documentsui.ProviderExecutor.Preemptable;
import com.android.documentsui.RecentsProvider.StateColumns;
@@ -124,7 +124,6 @@
public static final int REQUEST_COPY_DESTINATION = 1;
private static final int LOADER_ID = 42;
- private static final boolean DEBUG = false;
private static final boolean DEBUG_ENABLE_DND = false;
private static final String EXTRA_TYPE = "type";
@@ -367,21 +366,6 @@
@Override
public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
- if (result == null || result.exception != null) {
- // onBackPressed does a fragment transaction, which can't be done inside
- // onLoadFinished
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- final Activity activity = getActivity();
- if (activity != null) {
- activity.onBackPressed();
- }
- }
- });
- return;
- }
-
if (!isAdded()) return;
mModel.update(result);
@@ -629,7 +613,6 @@
@Override
public void onItemStateChanged(int position, boolean selected) {
-
final Cursor cursor = mModel.getItem(position);
checkNotNull(cursor, "Cursor cannot be null.");
@@ -715,8 +698,9 @@
return true;
} else if (id == R.id.menu_delete) {
- deleteDocuments(selection);
+ // Exit selection mode first, so we avoid deselecting deleted documents.
mode.finish();
+ deleteDocuments(selection);
return true;
} else if (id == R.id.menu_copy_to) {
@@ -725,8 +709,9 @@
return true;
} else if (id == R.id.menu_move_to) {
- transferDocuments(selection, CopyService.TRANSFER_MODE_MOVE);
+ // Exit selection mode first, so we avoid deselecting deleted documents.
mode.finish();
+ transferDocuments(selection, CopyService.TRANSFER_MODE_MOVE);
return true;
} else if (id == R.id.menu_copy_to_clipboard) {
@@ -898,6 +883,29 @@
}
}
+ void showEmptyView() {
+ mEmptyView.setVisibility(View.VISIBLE);
+ mRecView.setVisibility(View.GONE);
+ TextView msg = (TextView) mEmptyView.findViewById(R.id.message);
+ msg.setText(R.string.empty);
+ // No retry button for the empty view.
+ mEmptyView.findViewById(R.id.button_retry).setVisibility(View.GONE);
+ }
+
+ void showErrorView() {
+ mEmptyView.setVisibility(View.VISIBLE);
+ mRecView.setVisibility(View.GONE);
+ TextView msg = (TextView) mEmptyView.findViewById(R.id.message);
+ msg.setText(R.string.query_error);
+ // TODO: Enable this once the retry button does something.
+ mEmptyView.findViewById(R.id.button_retry).setVisibility(View.GONE);
+ }
+
+ void showRecyclerView() {
+ mEmptyView.setVisibility(View.GONE);
+ mRecView.setVisibility(View.VISIBLE);
+ }
+
private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> {
private final Context mContext;
@@ -1950,21 +1958,16 @@
mProgressBar.setVisibility(model.isLoading() ? View.VISIBLE : View.GONE);
if (model.isEmpty()) {
- mEmptyView.setVisibility(View.VISIBLE);
- mRecView.setVisibility(View.GONE);
+ showEmptyView();
} else {
- mEmptyView.setVisibility(View.GONE);
- mRecView.setVisibility(View.VISIBLE);
+ showRecyclerView();
+ mAdapter.notifyDataSetChanged();
}
-
- mAdapter.notifyDataSetChanged();
}
@Override
public void onModelUpdateFailed(Exception e) {
- // TODO: deal with catastrophic update failures
- String error = getString(R.string.query_error);
- mAdapter.notifyDataSetChanged();
+ showErrorView();
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 0edb241..bb82b38 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -16,12 +16,12 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.MODE_UNKNOWN;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_DISPLAY_NAME;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_SIZE;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_UNKNOWN;
import static com.android.documentsui.Shared.TAG;
+import static com.android.documentsui.State.MODE_UNKNOWN;
+import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
+import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.State.SORT_ORDER_UNKNOWN;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import android.content.AsyncTaskLoader;
@@ -37,7 +37,6 @@
import android.provider.DocumentsContract.Document;
import android.util.Log;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.RecentsProvider.StateColumns;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
index 4893652..000b92a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
@@ -18,9 +18,9 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.widget.FrameLayout;
+import android.widget.LinearLayout;
-public class DirectoryView extends FrameLayout {
+public class DirectoryView extends LinearLayout {
private float mPosition = 0f;
private int mWidth;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index dbfcf40..4658fe3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,13 +16,12 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_CREATE;
-import static com.android.documentsui.BaseActivity.State.ACTION_GET_CONTENT;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_COPY_DESTINATION;
-import static com.android.documentsui.BaseActivity.State.ACTION_OPEN_TREE;
-import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+import static com.android.documentsui.State.ACTION_CREATE;
+import static com.android.documentsui.State.ACTION_GET_CONTENT;
+import static com.android.documentsui.State.ACTION_OPEN;
+import static com.android.documentsui.State.ACTION_OPEN_COPY_DESTINATION;
+import static com.android.documentsui.State.ACTION_OPEN_TREE;
import android.app.Activity;
import android.app.Fragment;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
index ec1cb1d..a1213d2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/IconUtils.java
@@ -222,7 +222,7 @@
return context.getDrawable(R.drawable.ic_doc_album);
}
- if (mode == BaseActivity.State.MODE_GRID) {
+ if (mode == State.MODE_GRID) {
return context.getDrawable(R.drawable.ic_grid_folder);
} else {
return context.getDrawable(R.drawable.ic_doc_folder);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
index f5b1d8e..4754899 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/ManageRootActivity.java
@@ -16,9 +16,8 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.ACTION_MANAGE;
-import static com.android.documentsui.DirectoryFragment.ANIM_DOWN;
import static com.android.documentsui.DirectoryFragment.ANIM_NONE;
+import static com.android.documentsui.State.ACTION_MANAGE;
import android.app.Activity;
import android.app.Fragment;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index 5839943..858fb42 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -365,8 +365,8 @@
// To make this more correct, we'd need to update the Ranger class to return
// information about what has changed.
notifySelectionChanged();
- } else if (toggleSelection(input.getItemPosition())) {
- notifySelectionChanged();
+ } else {
+ toggleSelection(input.getItemPosition());
}
}
@@ -375,14 +375,13 @@
* a new Ranger (range selection manager) at that point is created.
*
* @param position
- * @return True if state changed.
*/
- private boolean toggleSelection(int position) {
+ private void toggleSelection(int position) {
// Position may be special "no position" during certain
// transitional phases. If so, skip handling of the event.
if (position == RecyclerView.NO_POSITION) {
if (DEBUG) Log.d(TAG, "Ignoring toggle for element with no position.");
- return false;
+ return;
}
boolean changed = false;
@@ -391,7 +390,7 @@
} else {
boolean canSelect = notifyBeforeItemStateChange(position, true);
if (!canSelect) {
- return false;
+ return;
}
if (mSingleSelect && !mSelection.isEmpty()) {
clearSelectionQuietly();
@@ -407,7 +406,9 @@
changed = true;
}
- return changed;
+ if (changed) {
+ notifySelectionChanged();
+ }
}
/**
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
index 5f6a5e9..48e28dc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -21,7 +21,6 @@
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
-import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -29,8 +28,6 @@
import com.android.documentsui.model.DocumentInfo;
-import java.util.Locale;
-
/**
* Display pick confirmation bar, usually for selecting a directory.
*/
@@ -93,7 +90,7 @@
};
/**
- * @param action Which action defined in BaseActivity.State is the picker shown for.
+ * @param action Which action defined in State is the picker shown for.
*/
public void setPickTarget(int action, int transferMode, DocumentInfo pickTarget) {
mAction = action;
@@ -109,11 +106,11 @@
*/
private void updateView() {
switch (mAction) {
- case BaseActivity.State.ACTION_OPEN_TREE:
+ case State.ACTION_OPEN_TREE:
mPick.setText(R.string.button_select);
mCancel.setVisibility(View.GONE);
break;
- case BaseActivity.State.ACTION_OPEN_COPY_DESTINATION:
+ case State.ACTION_OPEN_COPY_DESTINATION:
mPick.setText(R.string.button_copy);
mCancel.setVisibility(View.VISIBLE);
break;
@@ -123,7 +120,7 @@
}
if (mPickTarget != null && (
- mAction == BaseActivity.State.ACTION_OPEN_TREE ||
+ mAction == State.ACTION_OPEN_TREE ||
mPickTarget.isCreateSupported())) {
mContainer.setVisibility(View.VISIBLE);
} else {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
index 4685c41..607cb95 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/QuickViewIntentBuilder.java
@@ -16,6 +16,8 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.content.ClipData;
@@ -38,9 +40,6 @@
*/
final class QuickViewIntentBuilder {
- private static final String TAG = "QvIntentBuilder";
- private static final boolean DEBUG = false;
-
private final DocumentInfo mDocument;
private final DocumentContext mContext;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index 1a7095a..c2b64fb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -16,8 +16,9 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.Shared.TAG;
+import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
import android.app.ActivityManager;
import android.content.AsyncTaskLoader;
@@ -34,7 +35,6 @@
import android.text.format.DateUtils;
import android.util.Log;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
import com.google.common.util.concurrent.AbstractFuture;
@@ -53,8 +53,6 @@
import java.util.concurrent.TimeUnit;
public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
- private static final boolean DEBUG = false;
-
// TODO: clean up cursor ownership so background thread doesn't traverse
// previously returned cursors for filtering/sorting; this currently races
// with the UI thread.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 6811331..cf682fa 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -45,7 +45,6 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.RecentsProvider.RecentColumns;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index f6e4349..82eb732 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -39,6 +39,7 @@
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
import com.android.internal.util.Predicate;
+
import com.google.android.collect.Sets;
import libcore.io.IoUtils;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index cb46bca..de35cef 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -16,8 +16,8 @@
package com.android.documentsui;
-import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.Shared.TAG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -35,12 +35,11 @@
import android.os.SystemClock;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
import com.android.internal.annotations.GuardedBy;
-import android.support.annotation.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
@@ -372,10 +371,8 @@
if (state.directoryCopy && root.isDownloads()) continue;
// Only show empty roots when creating, or in browse mode.
- if (empty && (state.action != State.ACTION_BROWSE ||
- state.action != State.ACTION_CREATE ||
- state.action != State.ACTION_OPEN_TREE ||
- state.action != State.ACTION_OPEN_COPY_DESTINATION)) {
+ if (empty && (state.action == State.ACTION_OPEN
+ || state.action == State.ACTION_GET_CONTENT)) {
if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
continue;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index c02184b..c98da47 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -41,7 +41,6 @@
import android.widget.ListView;
import android.widget.TextView;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
index 49651b4..c81377a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsLoader.java
@@ -19,7 +19,6 @@
import android.content.AsyncTaskLoader;
import android.content.Context;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
import java.util.Collection;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java
index 3ec3d1c..6698ff1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SortingCursorWrapper.java
@@ -16,9 +16,9 @@
package com.android.documentsui;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_DISPLAY_NAME;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_LAST_MODIFIED;
-import static com.android.documentsui.BaseActivity.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.State.SORT_ORDER_DISPLAY_NAME;
+import static com.android.documentsui.State.SORT_ORDER_LAST_MODIFIED;
+import static com.android.documentsui.State.SORT_ORDER_SIZE;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
new file mode 100644
index 0000000..bbffad3
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2013 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.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.DocumentStack;
+import com.android.documentsui.model.DurableUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class State implements android.os.Parcelable {
+ public int action;
+ public String[] acceptMimes;
+
+ /** Explicit user choice */
+ public int userMode = MODE_UNKNOWN;
+ /** Derived after loader */
+ public int derivedMode = MODE_LIST;
+
+ /** Explicit user choice */
+ public int userSortOrder = SORT_ORDER_UNKNOWN;
+ /** Derived after loader */
+ public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
+
+ public boolean allowMultiple;
+ public boolean forceSize ;
+ public boolean showSize;
+ public boolean localOnly ;
+ public boolean forceAdvanced ;
+ public boolean showAdvanced ;
+ public boolean stackTouched ;
+ public boolean restored ;
+ public boolean directoryCopy ;
+ /** Transfer mode for file copy/move operations. */
+ public int transferMode;
+
+ /** Current user navigation stack; empty implies recents. */
+ public DocumentStack stack = new DocumentStack();
+ /** Currently active search, overriding any stack. */
+ public String currentSearch;
+
+ /** Instance state for every shown directory */
+ public HashMap<String, SparseArray<Parcelable>> dirState = new HashMap<>();
+
+ /** Currently copying file */
+ public List<DocumentInfo> selectedDocumentsForCopy = new ArrayList<DocumentInfo>();
+
+ /** Name of the package that started DocsUI */
+ public List<String> excludedAuthorities = new ArrayList<>();
+
+ public static final int ACTION_OPEN = 1;
+ public static final int ACTION_CREATE = 2;
+ public static final int ACTION_GET_CONTENT = 3;
+ public static final int ACTION_OPEN_TREE = 4;
+ public static final int ACTION_MANAGE = 5;
+ public static final int ACTION_BROWSE = 6;
+ public static final int ACTION_OPEN_COPY_DESTINATION = 8;
+
+ public static final int MODE_UNKNOWN = 0;
+ public static final int MODE_LIST = 1;
+ public static final int MODE_GRID = 2;
+
+ public static final int SORT_ORDER_UNKNOWN = 0;
+ public static final int SORT_ORDER_DISPLAY_NAME = 1;
+ public static final int SORT_ORDER_LAST_MODIFIED = 2;
+ public static final int SORT_ORDER_SIZE = 3;
+
+ public void initAcceptMimes(Intent intent) {
+ if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
+ acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
+ } else {
+ String glob = intent.getType();
+ acceptMimes = new String[] { glob != null ? glob : "*/*" };
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(action);
+ out.writeInt(userMode);
+ out.writeStringArray(acceptMimes);
+ out.writeInt(userSortOrder);
+ out.writeInt(allowMultiple ? 1 : 0);
+ out.writeInt(forceSize ? 1 : 0);
+ out.writeInt(showSize ? 1 : 0);
+ out.writeInt(localOnly ? 1 : 0);
+ out.writeInt(forceAdvanced ? 1 : 0);
+ out.writeInt(showAdvanced ? 1 : 0);
+ out.writeInt(stackTouched ? 1 : 0);
+ out.writeInt(restored ? 1 : 0);
+ DurableUtils.writeToParcel(out, stack);
+ out.writeString(currentSearch);
+ out.writeMap(dirState);
+ out.writeList(selectedDocumentsForCopy);
+ out.writeList(excludedAuthorities);
+ }
+
+ public static final Creator<State> CREATOR = new Creator<State>() {
+ @Override
+ public State createFromParcel(Parcel in) {
+ final State state = new State();
+ state.action = in.readInt();
+ state.userMode = in.readInt();
+ state.acceptMimes = in.readStringArray();
+ state.userSortOrder = in.readInt();
+ state.allowMultiple = in.readInt() != 0;
+ state.forceSize = in.readInt() != 0;
+ state.showSize = in.readInt() != 0;
+ state.localOnly = in.readInt() != 0;
+ state.forceAdvanced = in.readInt() != 0;
+ state.showAdvanced = in.readInt() != 0;
+ state.stackTouched = in.readInt() != 0;
+ state.restored = in.readInt() != 0;
+ DurableUtils.readFromParcel(in, state.stack);
+ state.currentSearch = in.readString();
+ in.readMap(state.dirState, null);
+ in.readList(state.selectedDocumentsForCopy, null);
+ in.readList(state.excludedAuthorities, null);
+ return state;
+ }
+
+ @Override
+ public State[] newArray(int size) {
+ return new State[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 1325706..7d3498e 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -19,7 +19,6 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.documentsui.BaseActivity.State;
import com.android.documentsui.model.RootInfo;
import com.google.common.collect.Lists;
diff --git a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
index b5d9138..1530a02 100644
--- a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
+++ b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
@@ -166,7 +166,7 @@
}
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
{"nativeReadBitmapPixels", "(Landroid/graphics/Bitmap;I)V", (void *) readBitmapPixels},
{"nativeWriteBitmapPixels", "(Landroid/graphics/Bitmap;I)V", (void *) writeBitmapPixels},
};
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 93dc889..8fc7ad0 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -206,7 +206,7 @@
android:resumeWhilePausing="true"
android:screenOrientation="behind"
android:resizeableActivity="true"
- android:theme="@style/config_recents_activity_theme">
+ android:theme="@style/RecentsTheme.Wallpaper">
<intent-filter>
<action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
</intent-filter>
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 8140dd6..064d225 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -39,12 +39,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <!-- Debug Overlay View -->
- <ViewStub android:id="@+id/debug_overlay_stub"
- android:layout="@layout/recents_debug_overlay"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
<!-- Nav Bar Scrim View -->
<ImageView
android:id="@+id/nav_bar_scrim"
diff --git a/packages/SystemUI/res/layout/recents_debug_overlay.xml b/packages/SystemUI/res/layout/recents_debug_overlay.xml
deleted file mode 100644
index d23495e..0000000
--- a/packages/SystemUI/res/layout/recents_debug_overlay.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<com.android.systemui.recents.views.DebugOverlayView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:focusable="false">
- <SeekBar
- android:id="@+id/debug_seek_bar_1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top"
- android:layout_marginTop="25dp" />
- <SeekBar
- android:id="@+id/debug_seek_bar_2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top"
- android:layout_marginTop="50dp" />
-</com.android.systemui.recents.views.DebugOverlayView>
-
-
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index d608e25..f7e2344 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -20,10 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
- <!-- Whether we're using the tablet-optimized recents interface (we use this
- value at runtime for some things) -->
- <integer name="status_bar_recents_bg_gradient_degrees">90</integer>
-
<!-- The maximum number of rows in the QuickSettings -->
<integer name="quick_settings_max_rows">2</integer>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index a9e7735..2893b99 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -19,25 +19,6 @@
<!-- thickness (width) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">@*android:dimen/navigation_bar_width</dimen>
- <!-- Recent Applications parameters -->
- <!-- How far the thumbnail for a recent app appears from left edge -->
- <dimen name="status_bar_recents_thumbnail_left_margin">0dp</dimen>
- <!-- How far the thumbnail for a recent app appears from top edge -->
- <dimen name="status_bar_recents_thumbnail_top_margin">28dp</dimen>
- <!-- Padding for text descriptions -->
- <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
- <!-- Width of application label text -->
- <dimen name="status_bar_recents_app_label_width">156dip</dimen>
- <!-- Left margin of application label text -->
- <dimen name="status_bar_recents_app_label_left_margin">12dip</dimen>
- <!-- Margin between recents container and glow on the right -->
- <dimen name="status_bar_recents_right_glow_margin">0dip</dimen>
- <!-- Padding between recents items -->
- <dimen name="status_bar_recents_item_padding">2dip</dimen>
- <!-- Where to place the app icon over the thumbnail -->
- <dimen name="status_bar_recents_app_icon_left_margin">8dp</dimen>
- <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
-
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.26</item>
diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
index 3a62ad9..81ca86b 100644
--- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml
@@ -17,8 +17,6 @@
-->
<resources>
<!-- Recent Applications parameters -->
- <dimen name="status_bar_recents_app_label_width">190dip</dimen>
-
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.25</item>
diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
deleted file mode 100644
index 7dc91d1..0000000
--- a/packages/SystemUI/res/values-sw600dp-port/dimens.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-*/
--->
-<resources>
- <!-- Recent Applications parameters -->
- <dimen name="status_bar_recents_app_label_width">140dip</dimen>
-</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 1af4ab1..6deb818 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -32,10 +32,6 @@
<!-- The width of the view containing the menu/ime navigation bar icons -->
<dimen name="navigation_extra_key_width">48dip</dimen>
- <!-- Size of application thumbnail -->
- <dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
- <dimen name="status_bar_recents_thumbnail_height">177dp</dimen>
-
<!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
<item type="dimen" name="notification_panel_min_height_frac">40%</item>
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index fbeadcd..1efae42 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -22,20 +22,6 @@
<resources>
<integer name="status_bar_config_maxNotificationIcons">5</integer>
- <!-- Whether we're using the tablet-optimized recents interface (we use this
- value at runtime for some things) -->
- <bool name="config_recents_interface_for_tablets">true</bool>
-
- <!-- Whether recents thumbnails should stretch in both x and y to fill their
- ImageView -->
- <bool name="config_recents_thumbnail_image_fits_to_xy">true</bool>
-
- <!-- Min alpha % that recent items will fade to while being dismissed -->
- <integer name="config_recent_item_min_alpha">0</integer>
-
- <!-- Transposes the search bar layout in landscape -->
- <bool name="recents_transpose_search_layout_with_orientation">false</bool>
-
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">5</integer>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index dd158c2..7cee381 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -29,42 +29,9 @@
<!-- Bottom margin (from display edge) for status bar panels -->
<dimen name="panel_float">56dp</dimen>
- <!-- Recent Applications parameters -->
- <!-- How far the thumbnail for a recent app appears from left edge -->
- <dimen name="status_bar_recents_thumbnail_left_margin">28dp</dimen>
- <!-- Upper width limit for application icon -->
- <dimen name="status_bar_recents_app_icon_max_width">64dp</dimen>
- <!-- Upper height limit for application icon -->
- <dimen name="status_bar_recents_app_icon_max_height">64dp</dimen>
-
- <!-- Size of application icon -->
- <dimen name="status_bar_recents_thumbnail_width">208dp</dimen>
- <dimen name="status_bar_recents_thumbnail_height">130dp</dimen>
-
- <!-- Width of recents panel -->
- <dimen name="status_bar_recents_width">600dp</dimen>
- <!-- Padding for text descriptions -->
- <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
- <!-- Size of application label text -->
- <dimen name="status_bar_recents_app_label_text_size">18dip</dimen>
- <!-- Size of application description text -->
- <dimen name="status_bar_recents_app_description_text_size">18dip</dimen>
- <!-- Width of application label text -->
- <dimen name="status_bar_recents_app_label_width">97dip</dimen>
- <!-- Left margin for application label -->
- <dimen name="status_bar_recents_app_label_left_margin">16dip</dimen>
- <!-- Size of fading edge for text -->
- <dimen name="status_bar_recents_text_fading_edge_length">20dip</dimen>
- <!-- Size of fading edge for scrolling -->
- <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
-
<!-- The radius of the rounded corners on a task view. -->
<dimen name="recents_task_view_rounded_corners_radius">3dp</dimen>
- <!-- Where to place the app icon over the thumbnail -->
- <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
- <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
-
<!-- The fraction of the screen height where the clock on the Keyguard has its center. The
max value is used when no notifications are displaying, and the min value is when the
highest possible number of notifications are showing. -->
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index da21084..f40f0d9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -24,11 +24,8 @@
<color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
<color name="system_bar_background_transparent">#00000000</color>
<color name="notification_panel_solid_background">#ff000000</color>
- <drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
- <color name="status_bar_recents_app_label_color">#ffffffff</color>
<drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
<color name="notification_list_shadow_top">#80000000</color>
- <drawable name="recents_callout_line">#99ffffff</drawable>
<drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
<color name="batterymeter_frame_color">#4DFFFFFF</color><!-- 30% white -->
<color name="batterymeter_charge_color">#FFFFFFFF</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8da1148..f28c9d3 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -20,15 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
-
- <!-- Whether we're using the tablet-optimized recents interface (we use this
- value at runtime for some things) -->
- <bool name="config_recents_interface_for_tablets">false</bool>
-
- <!-- Whether recents thumbnails should stretch in both x and y to fill their
- ImageView -->
- <bool name="config_recents_thumbnail_image_fits_to_xy">false</bool>
-
<!-- Whether recents should use hardware layers for its taskviews. This flag can be enabled
for devices where the java drawing of round rects may be slow -->
<bool name="config_recents_use_hardware_layers">false</bool>
@@ -46,9 +37,6 @@
certain GPU's and thus can be turned off with only minimal visual impact. -->
<bool name="config_notifications_round_rect_clipping">true</bool>
- <!-- The theme to use for RecentsActivity. -->
- <item type="style" name="config_recents_activity_theme">@style/RecentsTheme.Wallpaper</item>
-
<!-- Control whether status bar should distinguish HSPA data icon form UMTS
data icon on devices -->
<bool name="config_hspa_data_distinguishable">false</bool>
@@ -92,10 +80,6 @@
<!-- The length of the vibration when the notification pops open. -->
<integer name="one_finger_pop_duration_ms">10</integer>
- <!-- Whether we're using the tablet-optimized recents interface (we use this
- value at runtime for some things) -->
- <integer name="status_bar_recents_bg_gradient_degrees">90</integer>
-
<!-- decay duration (from size_max -> size), in ms -->
<integer name="navigation_bar_deadzone_hold">333</integer>
<integer name="navigation_bar_deadzone_decay">333</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 96a77256..abfd863 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -16,45 +16,6 @@
*/
-->
<resources>
- <!-- Recent Applications parameters -->
- <!-- Upper width limit for application icon -->
- <dimen name="status_bar_recents_app_icon_max_width">48dp</dimen>
- <!-- Upper height limit for application icon -->
- <dimen name="status_bar_recents_app_icon_max_height">48dp</dimen>
-
- <!-- Size of application thumbnail -->
- <dimen name="status_bar_recents_thumbnail_width">164dp</dimen>
- <dimen name="status_bar_recents_thumbnail_height">145dp</dimen>
- <dimen name="status_bar_recents_thumbnail_bg_padding">4dp</dimen>
-
- <!-- Size of application label text -->
- <dimen name="status_bar_recents_app_label_text_size">14dip</dimen>
- <!-- Size of application description text -->
- <dimen name="status_bar_recents_app_description_text_size">14dip</dimen>
- <!-- Size of fading edge for text -->
- <dimen name="status_bar_recents_text_fading_edge_length">20dip</dimen>
- <!-- Size of fading edge for scrolling -->
- <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
- <!-- Margin between recents container and glow on the right -->
- <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
- <!-- How far the thumbnail for a recent app appears from left edge -->
- <dimen name="status_bar_recents_thumbnail_left_margin">20dp</dimen>
- <!-- Padding for text descriptions -->
- <dimen name="status_bar_recents_text_description_padding">8dp</dimen>
- <!-- Width of application label text -->
- <dimen name="status_bar_recents_app_label_width">88dip</dimen>
- <!-- Left margin of application label text -->
- <dimen name="status_bar_recents_app_label_left_margin">0dip</dimen>
- <!-- Padding between recents items -->
- <dimen name="status_bar_recents_item_padding">0dip</dimen>
- <!-- When recents first appears, how far the icon and label of the primary activity
- travel -->
- <dimen name="status_bar_recents_app_icon_translate_distance">35dip</dimen>
-
- <!-- Where to place the app icon over the thumbnail -->
- <dimen name="status_bar_recents_app_icon_left_margin">0dp</dimen>
- <dimen name="status_bar_recents_app_icon_top_margin">8dp</dimen>
-
<!-- Amount to offset bottom of notification peek window from top of status bar. -->
<dimen name="peek_window_y_offset">-12dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 33f6564..6207324 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -34,6 +34,8 @@
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
+import com.android.systemui.classifier.FalsingManager;
+
public class SwipeHelper implements Gefingerpoken {
static final String TAG = "com.android.systemui.SwipeHelper";
private static final boolean DEBUG = false;
@@ -67,6 +69,7 @@
private Handler mHandler;
private int mSwipeDirection;
private VelocityTracker mVelocityTracker;
+ private FalsingManager mFalsingManager;
private float mInitialTouchPos;
private boolean mDragging;
@@ -97,6 +100,7 @@
android.R.interpolator.fast_out_linear_in);
mFalsingThreshold = context.getResources().getDimensionPixelSize(
R.dimen.swipe_helper_falsing_threshold);
+ mFalsingManager = FalsingManager.getInstance(context);
}
public void setLongPressListener(LongPressListener listener) {
@@ -449,8 +453,13 @@
boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
(Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
(velocity > 0) == (getTranslation(mCurrAnimView) > 0);
- boolean falsingDetected = mCallback.isAntiFalsingNeeded()
- && !mTouchAboveFalsingThreshold;
+ boolean falsingDetected = mCallback.isAntiFalsingNeeded();
+
+ if (mFalsingManager.isClassiferEnabled()) {
+ falsingDetected = falsingDetected && mFalsingManager.isFalseTouch();
+ } else {
+ falsingDetected = falsingDetected && !mTouchAboveFalsingThreshold;
+ }
boolean dismissChild = mCallback.canChildBeDismissed(mCurrView)
&& !falsingDetected && (childSwipedFastEnough || childSwipedFarEnough)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
new file mode 100644
index 0000000..86bea87
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AccelerationClassifier.java
@@ -0,0 +1,94 @@
+/*
+ * 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.classifier;
+
+import android.view.MotionEvent;
+
+import java.util.HashMap;
+
+/**
+ * A classifier which looks at the speed and distance between successive points of a Stroke.
+ * It looks at two consecutive speeds between two points and calculates the ratio between them.
+ * The final result is the maximum of these values. It does the same for distances. If some speed
+ * or distance is equal to zero then the ratio between this and the next part is not calculated. To
+ * the duration of each part there is added one nanosecond so that it is always possible to
+ * calculate the speed of a part.
+ */
+public class AccelerationClassifier extends StrokeClassifier {
+ private final HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
+
+ public AccelerationClassifier(ClassifierData classifierData) {
+ mClassifierData = classifierData;
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mStrokeMap.clear();
+ }
+
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
+ Point point = stroke.getPoints().get(stroke.getPoints().size() - 1);
+ if (mStrokeMap.get(stroke) == null) {
+ mStrokeMap.put(stroke, new Data(point));
+ } else {
+ mStrokeMap.get(stroke).addPoint(point);
+ }
+ }
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ Data data = mStrokeMap.get(stroke);
+ return SpeedRatioEvaluator.evaluate(data.maxSpeedRatio)
+ + DistanceRatioEvaluator.evaluate(data.maxDistanceRatio);
+ }
+
+ private static class Data {
+ public Point previousPoint;
+ public float previousSpeed;
+ public float previousDistance;
+ public float maxSpeedRatio;
+ public float maxDistanceRatio;
+
+ public Data(Point point) {
+ previousPoint = point;
+ previousSpeed = previousDistance = 0.0f;
+ maxDistanceRatio = maxSpeedRatio = 0.0f;
+ }
+
+ public void addPoint(Point point) {
+ float distance = previousPoint.dist(point);
+ float duration = (float) (point.timeOffsetNano - previousPoint.timeOffsetNano + 1);
+ float speed = distance / duration;
+ if (previousDistance != 0.0f) {
+ maxDistanceRatio = Math.max(maxDistanceRatio, distance / previousDistance);
+ }
+
+ if (previousSpeed != 0.0f) {
+ maxSpeedRatio = Math.max(maxSpeedRatio, speed / previousSpeed);
+ }
+
+ previousDistance = distance;
+ previousSpeed = speed;
+ previousPoint = point;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
index 8c681fc..c74339b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
@@ -29,10 +29,15 @@
* For each stroke it keeps its last three points. If some successive points are the same, it
* ignores the repetitions. If a new point is added, the classifier calculates the angle between
* the last three points. After that, it calculates the difference between this angle and the
- * previously calculated angle. The return value of the classifier is the variance of the
- * differences from a stroke. To the differences there is artificially added value 0.0 and the
- * difference between the first angle and PI (angles are in radians). It helps with strokes which
- * have few points and punishes more strokes which are not smooth.
+ * previously calculated angle. Then it calculates the variance of the differences from a stroke.
+ * To the differences there is artificially added value 0.0 and the difference between the first
+ * angle and PI (angles are in radians). It helps with strokes which have few points and punishes
+ * more strokes which are not smooth. This classifier also tries to split the stroke into two parts
+ * int the place in which the biggest angle is. It calculates the angle variance of the two parts
+ * and sums them up. The reason the classifier is doing this, is because some human swipes at the
+ * beginning go for a moment in one direction and then they rapidly change direction for the rest
+ * of the stroke (like a tick). The final result is the minimum of angle variance of the whole
+ * stroke and the sum of angle variances of the two parts split up.
*/
public class AnglesVarianceClassifier extends StrokeClassifier {
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
@@ -61,21 +66,28 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return mStrokeMap.get(stroke).getAnglesVariance();
+ return AnglesVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
}
- private class Data {
+ private static class Data {
private List<Point> mLastThreePoints = new ArrayList<>();
+ private float mFirstAngleVariance;
private float mPreviousAngle;
+ private float mBiggestAngle;
private float mSumSquares;
+ private float mSecondSumSquares;
private float mSum;
+ private float mSecondSum;
private float mCount;
+ private float mSecondCount;
public Data() {
+ mFirstAngleVariance = 0.0f;
mPreviousAngle = (float) Math.PI;
- mSumSquares = 0.0f;
- mSum = 0.0f;
- mCount = 1.0f;
+ mBiggestAngle = 0.0f;
+ mSumSquares = mSecondSumSquares = 0.0f;
+ mSum = mSecondSum = 0.0f;
+ mCount = mSecondCount = 1.0f;
}
public void addPoint(Point point) {
@@ -87,10 +99,26 @@
if (mLastThreePoints.size() == 4) {
mLastThreePoints.remove(0);
- float angle = getAngle(mLastThreePoints.get(0), mLastThreePoints.get(1),
+ float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
mLastThreePoints.get(2));
float difference = angle - mPreviousAngle;
+
+ // If this is the biggest angle of the stroke so then we save the value of
+ // the angle variance so far and start to count the values for the angle
+ // variance of the second part.
+ if (mBiggestAngle < angle) {
+ mBiggestAngle = angle;
+ mFirstAngleVariance = getAnglesVariance(mSumSquares, mSum, mCount);
+ mSecondSumSquares = 0.0f;
+ mSecondSum = 0.0f;
+ mSecondCount = 1.0f;
+ } else {
+ mSecondSum += difference;
+ mSecondSumSquares += difference * difference;
+ mSecondCount += 1.0;
+ }
+
mSum += difference;
mSumSquares += difference * difference;
mCount += 1.0;
@@ -99,21 +127,14 @@
}
}
- private float getAngle(Point a, Point b, Point c) {
- float dist1 = a.dist(b);
- float dist2 = b.dist(c);
- float crossProduct = b.crossProduct(a, c);
- float dotProduct = b.dotProduct(a, c);
- float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
- float angle = (float) Math.acos(cos);
- if (crossProduct < 0.0) {
- angle = 2.0f * (float) Math.PI - angle;
- }
- return angle;
+ public float getAnglesVariance(float sumSquares, float sum, float count) {
+ return sumSquares / count - (sum / count) * (sum / count);
}
public float getAnglesVariance() {
- return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
+ return Math.min(getAnglesVariance(mSumSquares, mSum, mCount),
+ mFirstAngleVariance + getAnglesVariance(mSecondSumSquares, mSecondSum,
+ mSecondCount));
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
new file mode 100644
index 0000000..99cc1a6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.classifier;
+
+public class AnglesVarianceEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value > 0.05) evaluation++;
+ if (value > 0.10) evaluation++;
+ if (value > 0.20) evaluation++;
+ if (value > 0.40) evaluation++;
+ if (value > 0.80) evaluation++;
+ if (value > 1.50) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
index bccad4e..649279d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ClassifierData.java
@@ -28,8 +28,12 @@
public class ClassifierData {
private SparseArray<Stroke> mCurrentStrokes = new SparseArray<>();
private ArrayList<Stroke> mEndingStrokes = new ArrayList<>();
+ private float mXdpi;
+ private float mYdpi;
- public ClassifierData() {
+ public ClassifierData(float xdpi, float ydpi) {
+ mXdpi = xdpi;
+ mYdpi = ydpi;
}
public void update(MotionEvent event) {
@@ -42,7 +46,7 @@
for (int i = 0; i < event.getPointerCount(); i++) {
int id = event.getPointerId(i);
if (mCurrentStrokes.get(id) == null) {
- mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano()));
+ mCurrentStrokes.put(id, new Stroke(event.getEventTimeNano(), mXdpi, mYdpi));
}
mCurrentStrokes.get(id).addPoint(event.getX(i), event.getY(i),
event.getEventTimeNano());
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java
new file mode 100644
index 0000000..8acb009
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceRatioEvaluator.java
@@ -0,0 +1,29 @@
+/*
+ * 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.classifier;
+
+public class DistanceRatioEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value <= 1.0) evaluation++;
+ if (value <= 0.5) evaluation++;
+ if (value > 4.0) evaluation++;
+ if (value > 7.0) evaluation++;
+ if (value > 14.0) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
new file mode 100644
index 0000000..8924694
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountClassifier.java
@@ -0,0 +1,31 @@
+/*
+ * 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.classifier;
+
+/**
+ * A classifier which looks at the ratio between the duration of the stroke and its number of
+ * points.
+ */
+public class DurationCountClassifier extends StrokeClassifier {
+ public DurationCountClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return DurationCountEvaluator.evaluate(stroke.getDurationSeconds() / stroke.getCount());
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java
new file mode 100644
index 0000000..5395983
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/DurationCountEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.classifier;
+
+
+public class DurationCountEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.0105) evaluation++;
+ if (value < 0.00909) evaluation++;
+ if (value < 0.00667) evaluation++;
+ if (value > 0.0333) evaluation++;
+ if (value > 0.0500) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
new file mode 100644
index 0000000..78bc0dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthClassifier.java
@@ -0,0 +1,30 @@
+/*
+ * 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.classifier;
+
+/**
+ * A classifier which looks at the distance between the first and the last point from the stroke.
+ */
+public class EndPointLengthClassifier extends StrokeClassifier {
+ public EndPointLengthClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return EndPointLengthEvaluator.evaluate(stroke.getEndPointLength());
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java
new file mode 100644
index 0000000..bb2f1c4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointLengthEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.classifier;
+
+public class EndPointLengthEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.05) evaluation += 2.0;
+ if (value < 0.1) evaluation += 2.0;
+ if (value < 0.2) evaluation += 2.0;
+ if (value < 0.3) evaluation += 2.0;
+ if (value < 0.4) evaluation += 2.0;
+ if (value < 0.5) evaluation += 2.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
new file mode 100644
index 0000000..c125e00
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioClassifier.java
@@ -0,0 +1,36 @@
+/*
+ * 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.classifier;
+
+/**
+ * A classifier which looks at the ratio between the total length covered by the stroke and the
+ * distance between the first and last point from this stroke.
+ */
+public class EndPointRatioClassifier extends StrokeClassifier {
+ public EndPointRatioClassifier(ClassifierData classifierData) {
+ mClassifierData = classifierData;
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ if (stroke.getTotalLength() == 0.0f) {
+ return 1.0f;
+ }
+ return EndPointRatioEvaluator.evaluate(
+ stroke.getEndPointLength() / stroke.getTotalLength());
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java
new file mode 100644
index 0000000..529fcec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/EndPointRatioEvaluator.java
@@ -0,0 +1,30 @@
+/*
+ * 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.classifier;
+
+public class EndPointRatioEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.85) evaluation++;
+ if (value < 0.75) evaluation++;
+ if (value < 0.65) evaluation++;
+ if (value < 0.55) evaluation++;
+ if (value < 0.45) evaluation++;
+ if (value < 0.35) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index c68fff8..735a7c4 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -39,7 +39,11 @@
public class FalsingManager implements SensorEventListener {
private static final String ENFORCE_BOUNCER = "falsing_manager_enforce_bouncer";
- private static final int[] SENSORS = new int[] {
+ private static final int[] CLASSIFIER_SENSORS = new int[] {
+ Sensor.TYPE_PROXIMITY,
+ };
+
+ private static final int[] COLLECTOR_SENSORS = new int[] {
Sensor.TYPE_ACCELEROMETER,
Sensor.TYPE_GYROSCOPE,
Sensor.TYPE_PROXIMITY,
@@ -113,7 +117,17 @@
private void onSessionStart() {
mBouncerOn = false;
mSessionActive = true;
- for (int sensorType : SENSORS) {
+
+ if (mHumanInteractionClassifier.isEnabled()) {
+ registerSensors(CLASSIFIER_SENSORS);
+ }
+ if (mDataCollector.isEnabled()) {
+ registerSensors(COLLECTOR_SENSORS);
+ }
+ }
+
+ private void registerSensors(int [] sensors) {
+ for (int sensorType : sensors) {
Sensor s = mSensorManager.getDefaultSensor(sensorType);
if (s != null) {
mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
@@ -121,6 +135,10 @@
}
}
+ public boolean isClassiferEnabled() {
+ return mHumanInteractionClassifier.isEnabled();
+ }
+
private boolean isEnabled() {
return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
index e7f4c35..11388fc 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/GestureClassifier.java
@@ -25,7 +25,7 @@
/**
* @param type the type of action for which this method is called
* @return a non-negative value which is used to determine whether the most recent gesture is a
- * false interaction. The bigger the value the greater the chance that this a false
+ * false interaction; the bigger the value the greater the chance that this a false
* interaction.
*/
public abstract float getFalseTouchEvaluation(int type);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
index b057bda..85a9bee 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryEvaluator.java
@@ -100,7 +100,7 @@
* For each stroke it holds its initial value and the current weight. Initially the
* weight is set to 1.0
*/
- private class Data {
+ private static class Data {
public float evaluation;
public float weight;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 86ea640..595a476 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -55,10 +55,21 @@
private HumanInteractionClassifier(Context context) {
mContext = context;
- mClassifierData = new ClassifierData();
+ mClassifierData = new ClassifierData(mContext.getResources().getDisplayMetrics().xdpi,
+ mContext.getResources().getDisplayMetrics().ydpi);
mHistoryEvaluator = new HistoryEvaluator();
mStrokeClassifiers.add(new AnglesVarianceClassifier(mClassifierData));
+ mStrokeClassifiers.add(new SpeedClassifier(mClassifierData));
+ mStrokeClassifiers.add(new DurationCountClassifier(mClassifierData));
+ mStrokeClassifiers.add(new EndPointRatioClassifier(mClassifierData));
+ mStrokeClassifiers.add(new EndPointLengthClassifier(mClassifierData));
+ mStrokeClassifiers.add(new AccelerationClassifier(mClassifierData));
+ mStrokeClassifiers.add(new SpeedVarianceClassifier(mClassifierData));
+ mStrokeClassifiers.add(new LengthCountClassifier(mClassifierData));
+
+ mGestureClassifiers.add(new PointerCountClassifier(mClassifierData));
+ mGestureClassifiers.add(new ProximityClassifier(mClassifierData));
mStrokeClassifiersSize = mStrokeClassifiers.size();
mGestureClassifiersSize = mGestureClassifiers.size();
@@ -128,10 +139,20 @@
@Override
public void onSensorChanged(SensorEvent event) {
+ for (int i = 0; i < mStrokeClassifiers.size(); i++) {
+ mStrokeClassifiers.get(i).onSensorChanged(event);
+ }
+
+ for (int i = 0; i < mGestureClassifiers.size(); i++) {
+ mGestureClassifiers.get(i).onSensorChanged(event);
+ }
}
public boolean isFalseTouch() {
- return mHistoryEvaluator.getEvaluation() >= 5.0f;
+ if (mEnableClassifier) {
+ return mHistoryEvaluator.getEvaluation() >= 5.0f;
+ }
+ return false;
}
public boolean isEnabled() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
new file mode 100644
index 0000000..1ea467b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
@@ -0,0 +1,31 @@
+/*
+ * 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.classifier;
+
+/**
+ * A classifier which looks at the ratio between the duration of the stroke and its number of
+ * points.
+ */
+public class LengthCountClassifier extends StrokeClassifier {
+ public LengthCountClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return LengthCountEvaluator.evaluate(stroke.getTotalLength() / stroke.getCount());
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
new file mode 100644
index 0000000..68f163d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
@@ -0,0 +1,33 @@
+/*
+ * 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.classifier;
+
+/**
+ * A classifier which looks at the ratio between the length of the stroke and its number of
+ * points.
+ */
+public class LengthCountEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 0.07) evaluation++;
+ if (value < 0.05) evaluation++;
+ if (value < 0.02) evaluation++;
+ if (value > 0.6) evaluation++;
+ if (value > 1.2) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Point.java b/packages/SystemUI/src/com/android/systemui/classifier/Point.java
index e7dbae1..f3dc2be 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Point.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Point.java
@@ -56,4 +56,28 @@
public float dotProduct(Point a, Point b) {
return (a.x - x) * (b.x - x) + (a.y - y) * (b.y - y);
}
+
+ /**
+ * Calculates the angle in radians created by points (a, this, b). If any two of these points
+ * are the same, the method will return 0.0f
+ *
+ * @return the angle in radians
+ */
+ public float getAngle(Point a, Point b) {
+ float dist1 = dist(a);
+ float dist2 = dist(b);
+
+ if (dist1 == 0.0f || dist2 == 0.0f) {
+ return 0.0f;
+ }
+
+ float crossProduct = crossProduct(a, b);
+ float dotProduct = dotProduct(a, b);
+ float cos = Math.min(1.0f, Math.max(-1.0f, dotProduct / dist1 / dist2));
+ float angle = (float) Math.acos(cos);
+ if (crossProduct < 0.0) {
+ angle = 2.0f * (float) Math.PI - angle;
+ }
+ return angle;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java
new file mode 100644
index 0000000..5097b63
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.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 com.android.systemui.classifier;
+
+import android.view.MotionEvent;
+
+/**
+ * A classifier which looks at the total number of traces in the whole gesture.
+ */
+public class PointerCountClassifier extends GestureClassifier {
+ private int mCount;
+
+ public PointerCountClassifier(ClassifierData classifierData) {
+ mCount = 0;
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mCount = 1;
+ }
+
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ ++mCount;
+ }
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type) {
+ return PointerCountEvaluator.evaluate(mCount);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java
similarity index 73%
copy from services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
copy to packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java
index c47d194..d7a3af0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountEvaluator.java
@@ -11,11 +11,13 @@
* 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.
+ * limitations under the License
*/
-package com.android.server.devicepolicy;
-import android.app.admin.DeviceAdminReceiver;
+package com.android.systemui.classifier;
-public class DummyDeviceAdmin extends DeviceAdminReceiver {
+public class PointerCountEvaluator {
+ public static float evaluate(int value) {
+ return (value - 1) * (value - 1);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
new file mode 100644
index 0000000..6995064
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -0,0 +1,93 @@
+/*
+ * 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.classifier;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.view.MotionEvent;
+
+/**
+ * A classifier which looks at the proximity sensor during the gesture. It calculates the percentage
+ * the proximity sensor showing the near state during the whole gesture
+ */
+public class ProximityClassifier extends GestureClassifier {
+ private long mGestureStartTimeNano;
+ private long mNearStartTimeNano;
+ private long mNearDuration;
+ private boolean mNear;
+ private float mAverageNear;
+
+ public ProximityClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
+ update(event.values[0] < event.sensor.getMaximumRange(), event.timestamp);
+ }
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mGestureStartTimeNano = event.getEventTimeNano();
+ mNearStartTimeNano = event.getEventTimeNano();
+ mNearDuration = 0;
+ }
+
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ update(mNear, event.getEventTimeNano());
+ long duration = event.getEventTimeNano() - mGestureStartTimeNano;
+
+ if (duration == 0) {
+ mAverageNear = mNear ? 1.0f : 0.0f;
+ } else {
+ mAverageNear = (float) mNearDuration / (float) duration;
+ }
+ }
+ }
+
+
+ /**
+ * @param near is the sensor showing the near state right now
+ * @param timestampNano time of this event in nanoseconds
+ */
+ private void update(boolean near, long timestampNano) {
+ // This if is necessary because MotionEvents and SensorEvents do not come in
+ // chronological order
+ if (timestampNano > mNearStartTimeNano) {
+ // if the state before was near then add the difference of the current time and
+ // mNearStartTimeNano to mNearDuration.
+ if (mNear) {
+ mNearDuration += timestampNano - mNearStartTimeNano;
+ }
+
+ // if the new state is near, set mNearStartTimeNano equal to this moment.
+ if (near) {
+ mNearStartTimeNano = timestampNano;
+ }
+ }
+ mNear = near;
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type) {
+ return ProximityEvaluator.evaluate(mAverageNear, type);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java
new file mode 100644
index 0000000..91002bf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityEvaluator.java
@@ -0,0 +1,29 @@
+/*
+ * 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.classifier;
+
+public class ProximityEvaluator {
+ public static float evaluate(float value, int type) {
+ float evaluation = 0.0f;
+ float threshold = 0.1f;
+ if (type == Classifier.QUICK_SETTINGS) {
+ threshold = 1.0f;
+ }
+ if (value >= threshold) evaluation += 2.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.java
new file mode 100644
index 0000000..81b78c7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedClassifier.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.systemui.classifier;
+
+/**
+ * A classifier that looks at the speed of the stroke. It calculates the speed of a stroke in
+ * inches per second.
+ */
+public class SpeedClassifier extends StrokeClassifier {
+ private final float NANOS_TO_SECONDS = 1e9f;
+
+ public SpeedClassifier(ClassifierData classifierData) {
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ float duration = (float) stroke.getDurationNanos() / NANOS_TO_SECONDS;
+ if (duration == 0.0f) {
+ return SpeedEvaluator.evaluate(0.0f);
+ }
+ return SpeedEvaluator.evaluate(stroke.getTotalLength() / duration);
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
similarity index 61%
copy from services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
copy to packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
index c47d194..c0e4a2d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedEvaluator.java
@@ -11,11 +11,17 @@
* 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.
+ * limitations under the License
*/
-package com.android.server.devicepolicy;
-import android.app.admin.DeviceAdminReceiver;
+package com.android.systemui.classifier;
-public class DummyDeviceAdmin extends DeviceAdminReceiver {
+public class SpeedEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 4.0 || value > 35.0) evaluation += 1.0;
+ if (value < 2.2) evaluation += 1.0;
+ if (value > 50.0) evaluation += 1.0;
+ return evaluation;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
similarity index 65%
copy from services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
copy to packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
index c47d194..349aa9e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedRatioEvaluator.java
@@ -11,11 +11,16 @@
* 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.
+ * limitations under the License
*/
-package com.android.server.devicepolicy;
-import android.app.admin.DeviceAdminReceiver;
+package com.android.systemui.classifier;
-public class DummyDeviceAdmin extends DeviceAdminReceiver {
+public class SpeedRatioEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value > 9.0) ++evaluation;
+ if (value > 18.0) ++evaluation;
+ return evaluation;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java
new file mode 100644
index 0000000..9a30fe1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java
@@ -0,0 +1,124 @@
+/*
+ * 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.classifier;
+
+import android.view.MotionEvent;
+
+import java.lang.Math;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * A classifier which for each point from a stroke, it creates a point on plane with coordinates
+ * (timeOffsetNano, distanceCoveredUpToThisPoint) (scaled by DURATION_SCALE and LENGTH_SCALE)
+ * and then it calculates the angle variance of these points like the class
+ * {@link AnglesVarianceClassifier} (without splitting it into two parts). The classifier ignores
+ * the last point of a stroke because the UP event comes in with some delay and this ruins the
+ * smoothness of this curve
+ */
+public class SpeedVarianceClassifier extends StrokeClassifier {
+ private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
+
+ public SpeedVarianceClassifier(ClassifierData classifierData) {
+ mClassifierData = classifierData;
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent event) {
+ int action = event.getActionMasked();
+
+ if (action == MotionEvent.ACTION_DOWN) {
+ mStrokeMap.clear();
+ }
+
+ for (int i = 0; i < event.getPointerCount(); i++) {
+ Stroke stroke = mClassifierData.getStroke(event.getPointerId(i));
+
+ if (mStrokeMap.get(stroke) == null) {
+ mStrokeMap.put(stroke, new Data());
+ }
+
+ if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL
+ && !(action == MotionEvent.ACTION_POINTER_UP && i == event.getActionIndex())) {
+ mStrokeMap.get(stroke).addPoint(
+ stroke.getPoints().get(stroke.getPoints().size() - 1));
+ }
+ }
+ }
+
+ @Override
+ public float getFalseTouchEvaluation(int type, Stroke stroke) {
+ return SpeedVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
+ }
+
+ private static class Data {
+ private final float DURATION_SCALE = 1e8f;
+ private final float LENGTH_SCALE = 1.0f;
+
+ private List<Point> mLastThreePoints = new ArrayList<>();
+ private Point mPreviousPoint;
+ private float mPreviousAngle;
+ private float mSumSquares;
+ private float mSum;
+ private float mCount;
+ private float mDist;
+
+ public Data() {
+ mPreviousPoint = null;
+ mPreviousAngle = (float) Math.PI;
+ mSumSquares = 0.0f;
+ mSum = 0.0f;
+ mCount = 1.0f;
+ mDist = 0.0f;
+ }
+
+ public void addPoint(Point point) {
+ if (mPreviousPoint != null) {
+ mDist += mPreviousPoint.dist(point);
+ }
+
+ mPreviousPoint = point;
+ Point speedPoint = new Point((float) point.timeOffsetNano / DURATION_SCALE,
+ mDist / LENGTH_SCALE);
+
+ // Checking if the added point is different than the previously added point
+ // Repetitions are being ignored so that proper angles are calculated.
+ if (mLastThreePoints.isEmpty()
+ || !mLastThreePoints.get(mLastThreePoints.size() - 1).equals(speedPoint)) {
+ mLastThreePoints.add(speedPoint);
+ if (mLastThreePoints.size() == 4) {
+ mLastThreePoints.remove(0);
+
+ float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
+ mLastThreePoints.get(2));
+
+ float difference = angle - mPreviousAngle;
+ mSum += difference;
+ mSumSquares += difference * difference;
+ mCount += 1.0;
+ mPreviousAngle = angle;
+ }
+ }
+ }
+
+ public float getAnglesVariance() {
+ return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.java
new file mode 100644
index 0000000..8f9a7e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceEvaluator.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.classifier;
+
+public class SpeedVarianceEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value > 0.06) evaluation += 1.0;
+ if (value > 0.15) evaluation += 1.0;
+ if (value > 0.3) evaluation += 1.0;
+ if (value > 0.6) evaluation += 1.0;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
index 8c3fdd4..49e6fb8 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/Stroke.java
@@ -23,17 +23,48 @@
* DOWN/POINTER_DOWN event till the UP/POINTER_UP/CANCEL event.)
*/
public class Stroke {
+ private final float NANOS_TO_SECONDS = 1e9f;
+
private ArrayList<Point> mPoints = new ArrayList<>();
private long mStartTimeNano;
private long mEndTimeNano;
+ private float mLength;
+ private float mXdpi;
+ private float mYdpi;
- public Stroke(long eventTimeNano) {
+ public Stroke(long eventTimeNano, float xdpi, float ydpi) {
+ mXdpi = xdpi;
+ mYdpi = ydpi;
mStartTimeNano = mEndTimeNano = eventTimeNano;
}
public void addPoint(float x, float y, long eventTimeNano) {
mEndTimeNano = eventTimeNano;
- mPoints.add(new Point(x, y, eventTimeNano - mStartTimeNano));
+ Point point = new Point(x / mXdpi, y / mYdpi, eventTimeNano - mStartTimeNano);
+ if (!mPoints.isEmpty()) {
+ mLength += mPoints.get(mPoints.size() - 1).dist(point);
+ }
+ mPoints.add(point);
+ }
+
+ public int getCount() {
+ return mPoints.size();
+ }
+
+ public float getTotalLength() {
+ return mLength;
+ }
+
+ public float getEndPointLength() {
+ return mPoints.get(0).dist(mPoints.get(mPoints.size() - 1));
+ }
+
+ public long getDurationNanos() {
+ return mEndTimeNano - mStartTimeNano;
+ }
+
+ public float getDurationSeconds() {
+ return (float) getDurationNanos() / NANOS_TO_SECONDS;
}
public ArrayList<Point> getPoints() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
index d561f46..5da392f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/StrokeClassifier.java
@@ -24,8 +24,8 @@
/**
* @param type the type of action for which this method is called
* @param stroke the stroke for which the evaluation will be calculated
- * @return a non-negative value which is used to determine whether this a false touch. The
- * bigger the value the greater the chance that this a false touch.
+ * @return a non-negative value which is used to determine whether this a false touch; the
+ * bigger the value the greater the chance that this a false touch
*/
public abstract float getFalseTouchEvaluation(int type, Stroke stroke);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index e1a8815..9781664 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -29,8 +29,6 @@
}
public static class DebugFlags {
- // Enable this with any other debug flag to see more info
- public static final boolean Verbose = false;
public static class App {
// Enables debug drawing for the transition thumbnail
@@ -39,10 +37,6 @@
public static final boolean EnableTaskFiltering = false;
// Enables dismiss-all
public static final boolean EnableDismissAll = false;
- // Enables debug mode
- public static final boolean EnableDebugMode = false;
- // Enables the search bar layout
- public static final boolean EnableSearchLayout = true;
// Enables the thumbnail alpha on the front-most task
public static final boolean EnableThumbnailAlphaOnFrontmost = false;
// This disables the bitmap and icon caches
@@ -63,7 +57,6 @@
public static class Values {
public static class App {
public static int AppWidgetHostId = 1024;
- public static String DebugModeVersion = "A";
}
public static class TaskStackView {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 4bb3e4a..c53e573 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -38,14 +38,12 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.misc.Console;
-import com.android.systemui.recents.misc.DebugTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.DebugOverlayView;
import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.recents.views.ViewAnimation;
@@ -57,8 +55,7 @@
* The main Recents activity that is started from AlternateRecentsComponent.
*/
public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
- RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
- DebugOverlayView.DebugOverlayViewCallbacks {
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
RecentsConfiguration mConfig;
long mLastTabKeyEventTime;
@@ -67,9 +64,7 @@
RecentsView mRecentsView;
SystemBarScrimViews mScrimViews;
ViewStub mEmptyViewStub;
- ViewStub mDebugOverlayStub;
View mEmptyView;
- DebugOverlayView mDebugOverlay;
// Resize task debug
RecentsResizeTaskDialog mResizeTaskDebugDialog;
@@ -176,16 +171,6 @@
}
};
- /**
- * A custom debug trigger to listen for a debug key chord.
- */
- final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() {
- @Override
- public void run() {
- onDebugModeTriggered();
- }
- });
-
/** Updates the set of recent tasks */
void updateRecentsTasks() {
// If AlternateRecentsComponent has preloaded a load plan, then use that to prevent
@@ -352,9 +337,7 @@
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
- mDebugOverlayStub = (ViewStub) findViewById(R.id.debug_overlay_stub);
mScrimViews = new SystemBarScrimViews(this, mConfig);
- inflateDebugOverlay();
// Bind the search app widget when we first start up
mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
@@ -366,27 +349,10 @@
registerReceiver(mSystemBroadcastReceiver, filter);
}
- /** Inflates the debug overlay if debug mode is enabled. */
- void inflateDebugOverlay() {
- if (!Constants.DebugFlags.App.EnableDebugMode) return;
-
- if (mConfig.debugModeEnabled && mDebugOverlay == null) {
- // Inflate the overlay and seek bars
- mDebugOverlay = (DebugOverlayView) mDebugOverlayStub.inflate();
- mDebugOverlay.setCallbacks(this);
- mRecentsView.setDebugOverlay(mDebugOverlay);
- }
- }
-
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
-
- // Clear any debug rects
- if (mDebugOverlay != null) {
- mDebugOverlay.clear();
- }
}
@Override
@@ -538,8 +504,6 @@
default:
break;
}
- // Pass through the debug trigger
- mDebugTrigger.onKeyEvent(keyCode);
return super.onKeyDown(keyCode, event);
}
@@ -557,33 +521,6 @@
dismissRecentsToFocusedTaskOrHome(true);
}
- /** Called when debug mode is triggered */
- public void onDebugModeTriggered() {
- if (mConfig.developerOptionsEnabled) {
- if (Prefs.getBoolean(this, Prefs.Key.DEBUG_MODE_ENABLED, false /* boolean */)) {
- // Disable the debug mode
- Prefs.remove(this, Prefs.Key.DEBUG_MODE_ENABLED);
- mConfig.debugModeEnabled = false;
- inflateDebugOverlay();
- if (mDebugOverlay != null) {
- mDebugOverlay.disable();
- }
- } else {
- // Enable the debug mode
- Prefs.putBoolean(this, Prefs.Key.DEBUG_MODE_ENABLED, true);
- mConfig.debugModeEnabled = true;
- inflateDebugOverlay();
- if (mDebugOverlay != null) {
- mDebugOverlay.enable();
- }
- }
- Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion + ") " +
- (mConfig.debugModeEnabled ? "Enabled" : "Disabled") + ", please restart Recents now",
- Toast.LENGTH_SHORT).show();
- }
- }
-
-
/**** RecentsResizeTaskDialog ****/
private RecentsResizeTaskDialog getResizeTaskDebugDialog() {
@@ -655,16 +592,4 @@
mRecentsView.setSearchBar(null);
}
}
-
- /**** DebugOverlayView.DebugOverlayViewCallbacks ****/
-
- @Override
- public void onPrimarySeekBarChanged(float progress) {
- // Do nothing
- }
-
- @Override
- public void onSecondarySeekBarChanged(float progress) {
- // Do nothing
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DebugTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DebugTrigger.java
deleted file mode 100644
index fbf8a86..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DebugTrigger.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-import android.os.Handler;
-import android.os.SystemClock;
-import android.view.KeyEvent;
-import com.android.systemui.recents.Constants;
-
-/**
- * A trigger for catching a debug chord.
- * We currently use volume up then volume down to trigger this mode.
- */
-public class DebugTrigger {
-
- Handler mHandler;
- Runnable mTriggeredRunnable;
-
- int mLastKeyCode;
- long mLastKeyCodeTime;
-
- public DebugTrigger(Runnable triggeredRunnable) {
- mHandler = new Handler();
- mTriggeredRunnable = triggeredRunnable;
- }
-
- /** Resets the debug trigger */
- void reset() {
- mLastKeyCode = 0;
- mLastKeyCodeTime = 0;
- }
-
- /**
- * Processes a key event and tests if it is a part of the trigger. If the chord is complete,
- * then we just call the callback.
- */
- public void onKeyEvent(int keyCode) {
- if (!Constants.DebugFlags.App.EnableDebugMode) return;
-
- if (mLastKeyCode == 0) {
- if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
- mLastKeyCode = keyCode;
- mLastKeyCodeTime = SystemClock.uptimeMillis();
- return;
- }
- } else {
- if (mLastKeyCode == KeyEvent.KEYCODE_VOLUME_UP &&
- keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
- if ((SystemClock.uptimeMillis() - mLastKeyCodeTime) < 750) {
- mTriggeredRunnable.run();
- }
- }
- }
- reset();
- }
-}
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 a760a41..515e578 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents.model;
import android.graphics.Color;
-import android.graphics.Rect;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.NamedCounter;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java
deleted file mode 100644
index 452830d..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Pair;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.SeekBar;
-import com.android.systemui.R;
-import com.android.systemui.recents.RecentsConfiguration;
-
-import java.util.ArrayList;
-
-/**
- * A full screen overlay layer that allows us to draw views from throughout the system on the top
- * most layer.
- */
-public class DebugOverlayView extends FrameLayout implements SeekBar.OnSeekBarChangeListener {
-
- public interface DebugOverlayViewCallbacks {
- public void onPrimarySeekBarChanged(float progress);
- public void onSecondarySeekBarChanged(float progress);
- }
-
- final static int sCornerRectSize = 50;
-
- RecentsConfiguration mConfig;
- DebugOverlayViewCallbacks mCb;
-
- ArrayList<Pair<Rect, Integer>> mRects = new ArrayList<Pair<Rect, Integer>>();
- String mText;
- Paint mDebugOutline = new Paint();
- Paint mTmpPaint = new Paint();
- Rect mTmpRect = new Rect();
- boolean mEnabled = true;
-
- SeekBar mPrimarySeekBar;
- SeekBar mSecondarySeekBar;
-
- public DebugOverlayView(Context context) {
- this(context, null);
- }
-
- public DebugOverlayView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public DebugOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public DebugOverlayView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mConfig = RecentsConfiguration.getInstance();
- mDebugOutline.setColor(0xFFff0000);
- mDebugOutline.setStyle(Paint.Style.STROKE);
- mDebugOutline.setStrokeWidth(8f);
- setWillNotDraw(false);
- }
-
- public void setCallbacks(DebugOverlayViewCallbacks cb) {
- mCb = cb;
- }
-
- @Override
- protected void onFinishInflate() {
- mPrimarySeekBar = (SeekBar) findViewById(R.id.debug_seek_bar_1);
- mPrimarySeekBar.setOnSeekBarChangeListener(this);
- mSecondarySeekBar = (SeekBar) findViewById(R.id.debug_seek_bar_2);
- mSecondarySeekBar.setOnSeekBarChangeListener(this);
- }
-
- /** Enables the debug overlay drawing. */
- public void enable() {
- mEnabled = true;
- setVisibility(View.VISIBLE);
- }
-
- /** Disables the debug overlay drawing. */
- public void disable() {
- mEnabled = false;
- setVisibility(View.GONE);
- }
-
- /** Clears all debug rects. */
- public void clear() {
- mRects.clear();
- }
-
- /** Adds a rect to be drawn. */
- void addRect(Rect r, int color) {
- mRects.add(new Pair<Rect, Integer>(r, color));
- invalidate();
- }
-
- /** Adds a view's global rect to be drawn. */
- void addViewRect(View v, int color) {
- Rect vr = new Rect();
- v.getGlobalVisibleRect(vr);
- mRects.add(new Pair<Rect, Integer>(vr, color));
- invalidate();
- }
-
- /** Adds a rect, relative to a given view to be drawn. */
- void addRectRelativeToView(View v, Rect r, int color) {
- Rect vr = new Rect();
- v.getGlobalVisibleRect(vr);
- r.offsetTo(vr.left, vr.top);
- mRects.add(new Pair<Rect, Integer>(r, color));
- invalidate();
- }
-
- /** Sets the debug text at the bottom of the screen. */
- void setText(String message) {
- mText = message;
- invalidate();
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- addRect(new Rect(0, 0, sCornerRectSize, sCornerRectSize), 0xFFff0000);
- addRect(new Rect(getMeasuredWidth() - sCornerRectSize, getMeasuredHeight() - sCornerRectSize,
- getMeasuredWidth(), getMeasuredHeight()), 0xFFff0000);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (mEnabled) {
- // Draw the outline
- canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugOutline);
-
- // Draw the rects
- int numRects = mRects.size();
- for (int i = 0; i < numRects; i++) {
- Pair<Rect, Integer> r = mRects.get(i);
- mTmpPaint.setColor(r.second);
- canvas.drawRect(r.first, mTmpPaint);
- }
-
- // Draw the text
- if (mText != null && mText.length() > 0) {
- mTmpPaint.setColor(0xFFff0000);
- mTmpPaint.setTextSize(60);
- mTmpPaint.getTextBounds(mText, 0, 1, mTmpRect);
- canvas.drawText(mText, 10f, getMeasuredHeight() - mTmpRect.height() - mConfig.systemInsets.bottom, mTmpPaint);
- }
- }
- }
-
- /**** SeekBar.OnSeekBarChangeListener Implementation ****/
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // Do nothing
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- // Do nothing
- }
-
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (seekBar == mPrimarySeekBar) {
- mCb.onPrimarySeekBarChanged((float) progress / mPrimarySeekBar.getMax());
- } else if (seekBar == mSecondarySeekBar) {
- mCb.onSecondarySeekBarChanged((float) progress / mSecondarySeekBar.getMax());
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
index 509ad1b..41adbed 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
@@ -28,7 +28,6 @@
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.util.Log;
-
import com.android.systemui.R;
import com.android.systemui.recents.RecentsConfiguration;
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 c7d1dd1..fab8b3a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -78,7 +78,6 @@
RecentsConfiguration mConfig;
LayoutInflater mInflater;
- DebugOverlayView mDebugOverlay;
ArrayList<TaskStack> mStacks;
TaskStackView mTaskStackView;
@@ -108,11 +107,6 @@
mCb = cb;
}
- /** Sets the debug overlay */
- public void setDebugOverlay(DebugOverlayView overlay) {
- mDebugOverlay = overlay;
- }
-
/** Set/get the bsp root node */
public void setTaskStack(TaskStack stack) {
if (mConfig.launchedReuseTaskStackViews) {
@@ -134,11 +128,6 @@
addView(mTaskStackView);
}
- // Enable debug mode drawing on all the stacks if necessary
- if (mConfig.debugModeEnabled) {
- mTaskStackView.setDebugOverlay(mDebugOverlay);
- }
-
// Trigger a new layout
requestLayout();
}
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 8058c5e..4db8b37 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -79,7 +79,6 @@
ViewPool<TaskView, Task> mViewPool;
ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<TaskViewTransform>();
DozeTrigger mUIDozeTrigger;
- DebugOverlayView mDebugOverlay;
DismissView mDismissAllButton;
boolean mDismissAllButtonAnimating;
int mFocusedTaskIndex = -1;
@@ -161,11 +160,6 @@
return mStack;
}
- /** Sets the debug overlay */
- public void setDebugOverlay(DebugOverlayView overlay) {
- mDebugOverlay = overlay;
- }
-
/** Updates the list of task views */
void updateTaskViewsList() {
mTaskViews.clear();
@@ -334,9 +328,6 @@
int[] visibleRange = mTmpVisibleRange;
boolean isValidVisibleRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
stackScroll, visibleRange, false);
- if (mDebugOverlay != null) {
- mDebugOverlay.setText("vis[" + visibleRange[1] + "-" + visibleRange[0] + "]");
- }
// Inflate and add the dismiss button if necessary
if (Constants.DebugFlags.App.EnableDismissAll && mDismissAllButton == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index b01a2a8..10d4a96 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -112,7 +112,7 @@
public void appTransitionStarting(long startTime, long duration);
public void showAssistDisclosure();
public void startAssist(Bundle args);
- public void onCameraLaunchGestureDetected();
+ public void onCameraLaunchGestureDetected(int source);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -306,10 +306,10 @@
}
@Override
- public void onCameraLaunchGestureDetected() {
+ public void onCameraLaunchGestureDetected(int source) {
synchronized (mList) {
mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
- mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE).sendToTarget();
+ mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE, source, 0).sendToTarget();
}
}
@@ -415,7 +415,7 @@
mCallbacks.startAssist((Bundle) msg.obj);
break;
case MSG_CAMERA_LAUNCH_GESTURE:
- mCallbacks.onCameraLaunchGestureDetected();
+ mCallbacks.onCameraLaunchGestureDetected(msg.arg1);
break;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index d912795..687f6c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -130,7 +130,7 @@
}
return true;
case MotionEvent.ACTION_UP:
- if (mDraggedFarEnough && mDragDownCallback.onDraggedDown(mStartingChild,
+ if (!isFalseTouch() && mDragDownCallback.onDraggedDown(mStartingChild,
(int) (y - mInitialTouchY))) {
if (mStartingChild == null) {
mDragDownCallback.setEmptyDragAmount(0f);
@@ -148,6 +148,13 @@
return false;
}
+ private boolean isFalseTouch() {
+ if (mFalsingManager.isClassiferEnabled()) {
+ return mFalsingManager.isFalseTouch();
+ }
+ return !mDraggedFarEnough;
+ }
+
private void captureStartingChild(float x, float y) {
if (mStartingChild == null) {
mStartingChild = findView(x, y);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 60ebfdf..41adeb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -28,6 +28,7 @@
import android.view.animation.Interpolator;
import com.android.systemui.R;
+import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
@@ -62,6 +63,7 @@
private Interpolator mAppearInterpolator;
private Interpolator mDisappearInterpolator;
private Animator mSwipeAnimator;
+ private FalsingManager mFalsingManager;
private int mMinBackgroundRadius;
private boolean mMotionCancelled;
private int mTouchTargetSize;
@@ -109,6 +111,7 @@
android.R.interpolator.linear_out_slow_in);
mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.fast_out_linear_in);
+ mFalsingManager = FalsingManager.getInstance(mContext);
}
private void initIcons() {
@@ -322,7 +325,12 @@
float vel = getCurrentVelocity(lastX, lastY);
// We snap back if the current translation is not far enough
- boolean snapBack = isBelowFalsingThreshold();
+ boolean snapBack;
+ if (mFalsingManager.isFalseTouch()) {
+ snapBack = mFalsingManager.isFalseTouch();
+ } else {
+ snapBack = isBelowFalsingThreshold();
+ }
// or if the velocity is in the opposite direction.
boolean velIsInWrongDirection = vel * mTranslation < 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 012dc9c..14176a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -77,6 +77,13 @@
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
+ public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
+ public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
+ public static final String CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = "power_double_tap";
+
+ public static final String EXTRA_CAMERA_LAUNCH_SOURCE
+ = "com.android.systemui.camera_launch_source";
+
private static final Intent SECURE_CAMERA_INTENT =
new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
@@ -170,7 +177,7 @@
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
return true;
} else if (host == mCameraImageView) {
- launchCamera();
+ launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
return true;
} else if (host == mLeftAffordanceView) {
launchLeftAffordance();
@@ -349,7 +356,7 @@
@Override
public void onClick(View v) {
if (v == mCameraImageView) {
- launchCamera();
+ launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
} else if (v == mLeftAffordanceView) {
launchLeftAffordance();
} if (v == mLockIcon) {
@@ -417,8 +424,9 @@
}
}
- public void launchCamera() {
+ public void launchCamera(String source) {
final Intent intent = getCameraIntent();
+ intent.putExtra(EXTRA_CAMERA_LAUNCH_SOURCE, source);
boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 980527b..08353cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -22,6 +22,7 @@
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
+import android.app.StatusBarManager;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
@@ -204,6 +205,7 @@
private boolean mHeadsUpAnimatingAway;
private boolean mLaunchingAffordance;
private FalsingManager mFalsingManager;
+ private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
@Override
@@ -480,6 +482,7 @@
mUnlockIconActive = false;
if (!mLaunchingAffordance) {
mAfforanceHelper.reset(false);
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
}
closeQs();
mStatusBar.dismissPopups();
@@ -692,7 +695,7 @@
}
private boolean flingExpandsQs(float vel) {
- if (isBelowFalsingThreshold()) {
+ if (isFalseTouch()) {
return false;
}
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -702,8 +705,14 @@
}
}
- private boolean isBelowFalsingThreshold() {
- return !mQsTouchAboveFalsingThreshold && mStatusBarState == StatusBarState.KEYGUARD;
+ private boolean isFalseTouch() {
+ if (mStatusBarState != StatusBarState.KEYGUARD) {
+ return false;
+ }
+ if (mFalsingManager.isClassiferEnabled()) {
+ return mFalsingManager.isFalseTouch();
+ }
+ return !mQsTouchAboveFalsingThreshold;
}
private float getQsExpansionFraction() {
@@ -1428,7 +1437,7 @@
}
return;
}
- boolean belowFalsingThreshold = isBelowFalsingThreshold();
+ boolean belowFalsingThreshold = isFalseTouch();
if (belowFalsingThreshold) {
vel = 0;
}
@@ -1965,20 +1974,23 @@
mKeyguardBottomArea.launchLeftAffordance();
}
} else {
- EventLogTags.writeSysuiLockscreenGesture(
- EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
-
+ if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals(
+ mLastCameraLaunchSource)) {
+ EventLogTags.writeSysuiLockscreenGesture(
+ EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA,
+ lengthDp, velocityDp);
+ }
mFalsingManager.onCameraOn();
if (mFalsingManager.shouldEnforceBouncer()) {
mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
@Override
public void run() {
- mKeyguardBottomArea.launchCamera();
+ mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
}
}, null, true /* dismissShade */, false /* afterKeyguardGone */);
}
else {
- mKeyguardBottomArea.launchCamera();
+ mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
}
}
mStatusBar.startLaunchTransitionTimeout();
@@ -2419,7 +2431,17 @@
return !mDozing;
}
- public void launchCamera(boolean animate) {
+ public void launchCamera(boolean animate, int source) {
+ if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
+ } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
+ } else {
+
+ // Default.
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ }
+
// If we are launching it when we are occluded already we don't want it to animate,
// nor setting these flags, since the occluded state doesn't change anymore, hence it's
// never reset.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 3feead8..bd16257 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -610,8 +610,8 @@
if (!mStatusBar.isFalsingThresholdNeeded()) {
return false;
}
- if (mFalsingManager.isFalseTouch()) {
- return true;
+ if (mFalsingManager.isClassiferEnabled()) {
+ return mFalsingManager.isFalseTouch();
}
if (!mTouchAboveFalsingThreshold) {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 151fa3c..98f5444 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -492,6 +492,7 @@
private ExpandableNotificationRow mDraggedDownRow;
private boolean mLaunchCameraOnScreenTurningOn;
private boolean mLaunchCameraOnFinishedGoingToSleep;
+ private int mLastCameraLaunchSource;
private PowerManager.WakeLock mGestureWakeLock;
private Vibrator mVibrator;
@@ -3992,7 +3993,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- onCameraLaunchGestureDetected();
+ onCameraLaunchGestureDetected(mLastCameraLaunchSource);
}
});
}
@@ -4010,7 +4011,7 @@
mFalsingManager.onScreenTurningOn();
mNotificationPanel.onScreenTurningOn();
if (mLaunchCameraOnScreenTurningOn) {
- mNotificationPanel.launchCamera(false);
+ mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
mLaunchCameraOnScreenTurningOn = false;
}
}
@@ -4175,7 +4176,8 @@
}
@Override
- public void onCameraLaunchGestureDetected() {
+ public void onCameraLaunchGestureDetected(int source) {
+ mLastCameraLaunchSource = source;
if (mStartedGoingToSleep) {
mLaunchCameraOnFinishedGoingToSleep = true;
return;
@@ -4201,7 +4203,7 @@
mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
}
if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
- mNotificationPanel.launchCamera(mDeviceInteractive /* animate */);
+ mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
} else {
// We need to defer the camera launch until the screen comes on, since otherwise
// we will dismiss us too early since we are waiting on an activity to be drawn and
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 2587b9f..bbe5dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -171,7 +171,7 @@
}
@Override
- public void onCameraLaunchGestureDetected() {
+ public void onCameraLaunchGestureDetected(int source) {
}
@Override
diff --git a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
index 2727338..990d770 100644
--- a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
+++ b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
@@ -130,7 +130,7 @@
return jret;
}
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "createV8ParserNativeLocked", "()Z",
(void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
{ "destroyV8ParserNativeLocked", "()Z",
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 0419d33..8c830e8 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -2494,7 +2494,7 @@
static const char *classPathName = "android/renderscript/RenderScript";
-static JNINativeMethod methods[] = {
+static const JNINativeMethod methods[] = {
{"_nInit", "()V", (void*)_nInit },
{"nDeviceCreate", "()J", (void*)nDeviceCreate },
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 85730cd..c3f5c43 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -29,6 +29,7 @@
import android.os.Handler;
import android.os.SystemClock;
import android.util.Slog;
+import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -114,9 +115,6 @@
// Timeout within which we try to detect a tap.
private final int mTapTimeout;
- // Timeout within which we try to detect a double tap.
- private final int mDoubleTapTimeout;
-
// Slop between the down and up tap to be a tap.
private final int mTouchSlop;
@@ -230,7 +228,6 @@
mInjectedPointerTracker = new InjectedPointerTracker();
mTapTimeout = ViewConfiguration.getTapTimeout();
mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
- mDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
mHandler = new Handler(context.getMainLooper());
@@ -248,7 +245,7 @@
mSendTouchInteractionEndDelayed = new SendAccessibilityEventDelayed(
AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
mDetermineUserIntentTimeout);
- mDoubleTapDetector = new DoubleTapDetector();
+ mDoubleTapDetector = new DoubleTapDetector(mContext);
final float density = context.getResources().getDisplayMetrics().density;
mScaledMinPointerDistanceToUseMiddleLocation =
(int) (MIN_POINTER_DISTANCE_TO_USE_MIDDLE_LOCATION_DIP * density);
@@ -1109,66 +1106,63 @@
}
}
- private class DoubleTapDetector {
- private MotionEvent mDownEvent;
- private MotionEvent mFirstTapEvent;
+ private class DoubleTapDetector extends GestureDetector.SimpleOnGestureListener {
+ private final GestureDetector mGestureDetector;
+ private boolean mFirstTapDetected;
+ private boolean mDoubleTapDetected;
- public void onMotionEvent(MotionEvent event, int policyFlags) {
- final int actionIndex = event.getActionIndex();
- final int action = event.getActionMasked();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN: {
- if (mFirstTapEvent != null
- && !GestureUtils.isSamePointerContext(mFirstTapEvent, event)) {
- clear();
- }
- mDownEvent = MotionEvent.obtain(event);
- } break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP: {
- if (mDownEvent == null) {
- return;
- }
- if (!GestureUtils.isSamePointerContext(mDownEvent, event)) {
- clear();
- return;
- }
- if (GestureUtils.isTap(mDownEvent, event, mTapTimeout, mTouchSlop,
- actionIndex)) {
- if (mFirstTapEvent == null || GestureUtils.isTimedOut(mFirstTapEvent,
- event, mDoubleTapTimeout)) {
- mFirstTapEvent = MotionEvent.obtain(event);
- mDownEvent.recycle();
- mDownEvent = null;
- return;
- }
- if (GestureUtils.isMultiTap(mFirstTapEvent, event, mDoubleTapTimeout,
- mDoubleTapSlop, actionIndex)) {
- onDoubleTap(event, policyFlags);
- mFirstTapEvent.recycle();
- mFirstTapEvent = null;
- mDownEvent.recycle();
- mDownEvent = null;
- return;
- }
- mFirstTapEvent.recycle();
- mFirstTapEvent = null;
- } else {
- if (mFirstTapEvent != null) {
- mFirstTapEvent.recycle();
- mFirstTapEvent = null;
- }
- }
- mDownEvent.recycle();
- mDownEvent = null;
- } break;
- }
+ DoubleTapDetector(Context context) {
+ mGestureDetector = new GestureDetector(context, this);
+ mGestureDetector.setOnDoubleTapListener(this);
}
- public void onDoubleTap(MotionEvent secondTapUp, int policyFlags) {
+ public void onMotionEvent(MotionEvent event, int policyFlags) {
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mDoubleTapDetected = false;
+ break;
+
+ case MotionEvent.ACTION_UP:
+ maybeFinishDoubleTap(event, policyFlags);
+ break;
+ }
+ mGestureDetector.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onDown(MotionEvent event) {
+ return true;
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent event) {
+ mFirstTapDetected = true;
+ return false;
+ }
+
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent event) {
+ clear();
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTap(MotionEvent event) {
+ // The processing of the double tap is deferred until the finger is
+ // lifted, so that we can detect a long press on the second tap.
+ mDoubleTapDetected = true;
+ return true;
+ }
+
+ private void maybeFinishDoubleTap(MotionEvent event, int policyFlags) {
+ if (!mDoubleTapDetected) {
+ return;
+ }
+
+ clear();
+
// This should never be called when more than two pointers are down.
- if (secondTapUp.getPointerCount() > 2) {
+ if (event.getPointerCount() > 2) {
return;
}
@@ -1184,8 +1178,8 @@
mSendTouchInteractionEndDelayed.forceSendAndRemove();
}
- final int pointerId = secondTapUp.getPointerId(secondTapUp.getActionIndex());
- final int pointerIndex = secondTapUp.findPointerIndex(pointerId);
+ final int pointerId = event.getPointerId(event.getActionIndex());
+ final int pointerIndex = event.findPointerIndex(pointerId);
Point clickLocation = mTempPoint;
final int result = computeClickLocation(clickLocation);
@@ -1196,34 +1190,28 @@
// Do the click.
PointerProperties[] properties = new PointerProperties[1];
properties[0] = new PointerProperties();
- secondTapUp.getPointerProperties(pointerIndex, properties[0]);
+ event.getPointerProperties(pointerIndex, properties[0]);
PointerCoords[] coords = new PointerCoords[1];
coords[0] = new PointerCoords();
coords[0].x = clickLocation.x;
coords[0].y = clickLocation.y;
- MotionEvent event = MotionEvent.obtain(secondTapUp.getDownTime(),
- secondTapUp.getEventTime(), MotionEvent.ACTION_DOWN, 1, properties,
- coords, 0, 0, 1.0f, 1.0f, secondTapUp.getDeviceId(), 0,
- secondTapUp.getSource(), secondTapUp.getFlags());
+ MotionEvent click_event = MotionEvent.obtain(event.getDownTime(),
+ event.getEventTime(), MotionEvent.ACTION_DOWN, 1, properties,
+ coords, 0, 0, 1.0f, 1.0f, event.getDeviceId(), 0,
+ event.getSource(), event.getFlags());
final boolean targetAccessibilityFocus = (result == CLICK_LOCATION_ACCESSIBILITY_FOCUS);
- sendActionDownAndUp(event, policyFlags, targetAccessibilityFocus);
- event.recycle();
+ sendActionDownAndUp(click_event, policyFlags, targetAccessibilityFocus);
+ click_event.recycle();
+ return;
}
public void clear() {
- if (mDownEvent != null) {
- mDownEvent.recycle();
- mDownEvent = null;
- }
- if (mFirstTapEvent != null) {
- mFirstTapEvent.recycle();
- mFirstTapEvent = null;
- }
+ mFirstTapDetected = false;
+ mDoubleTapDetected = false;
}
public boolean firstTapDetected() {
- return mFirstTapEvent != null
- && SystemClock.uptimeMillis() - mFirstTapEvent.getEventTime() < mDoubleTapTimeout;
+ return mFirstTapDetected;
}
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 7c85001..f245985 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.ActivityManager;
+import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -263,7 +264,8 @@
}
if (launched) {
Slog.i(TAG, "Power button double tap gesture detected, launching camera.");
- launched = handleCameraLaunchGesture(false /* useWakelock */);
+ launched = handleCameraLaunchGesture(false /* useWakelock */,
+ StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
if (launched) {
MetricsLogger.action(mContext, MetricsLogger.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
(int) doubleTapInterval);
@@ -276,7 +278,7 @@
/**
* @return true if camera was launched, false otherwise.
*/
- private boolean handleCameraLaunchGesture(boolean useWakelock) {
+ private boolean handleCameraLaunchGesture(boolean useWakelock, int source) {
boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
if (!userSetupComplete) {
@@ -295,7 +297,7 @@
}
StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
- service.onCameraLaunchGestureDetected();
+ service.onCameraLaunchGestureDetected(source);
return true;
}
@@ -334,7 +336,8 @@
Slog.d(TAG, String.format("Received a camera launch event: " +
"values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
}
- if (handleCameraLaunchGesture(true /* useWakelock */)) {
+ if (handleCameraLaunchGesture(true /* useWakelock */,
+ StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE)) {
MetricsLogger.action(mContext, MetricsLogger.ACTION_WIGGLE_CAMERA_GESTURE);
trackCameraLaunchEvent(event);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 07a7af4..bd10c63 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -994,6 +994,8 @@
*/
int mConfigurationSeq = 0;
+ boolean mSuppressResizeConfigChanges = false;
+
/**
* Hardware-reported OpenGLES version.
*/
@@ -17515,6 +17517,15 @@
}
@Override
+ public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "suppressResizeConfigChanges()");
+ synchronized (this) {
+ mSuppressResizeConfigChanges = suppress;
+ }
+ }
+
+ @Override
public void updatePersistentConfiguration(Configuration values) {
enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 9809c2e..5d106dc 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4181,8 +4181,12 @@
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) == 0;
}
- private boolean relaunchActivityLocked(ActivityRecord r, int changes, boolean andResume,
- boolean preserveWindow) {
+ private void relaunchActivityLocked(
+ ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) {
+ if (mService.mSuppressResizeConfigChanges && preserveWindow) {
+ return;
+ }
+
List<ResultInfo> results = null;
List<ReferrerIntent> newIntents = null;
if (andResume) {
@@ -4222,8 +4226,6 @@
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
r.state = ActivityState.PAUSED;
}
-
- return true;
}
boolean willActivityBeVisibleLocked(IBinder token) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 17a4472..842b8cd 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -24,6 +24,7 @@
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
@@ -87,6 +88,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.Trace;
import android.os.TransactionTooLargeException;
import android.os.UserHandle;
import android.os.WorkSource;
@@ -2968,6 +2970,8 @@
return;
}
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
+
ActivityRecord r = stack.topRunningActivityLocked(null);
mTmpBounds.clear();
@@ -3051,6 +3055,8 @@
resumeTopActivitiesLocked(stack, null, null);
}
}
+
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
void resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode) {
@@ -3079,6 +3085,8 @@
return;
}
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + task.taskId);
+
// The stack of a task is determined by its size (fullscreen vs non-fullscreen).
// Place the task in the right stack if it isn't there already based on the requested
// bounds.
@@ -3124,6 +3132,8 @@
}
}
mWindowManager.resizeTask(task.taskId, bounds, task.mOverrideConfig, kept, forced);
+
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 99ca050..e49a7e4 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2524,11 +2524,14 @@
}
/** @see AudioManager#setBluetoothScoOn(boolean) */
- public void setBluetoothScoOn(boolean on){
+ public void setBluetoothScoOn(boolean on) {
if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
return;
}
+ setBluetoothScoOnInt(on);
+ }
+ public void setBluetoothScoOnInt(boolean on) {
if (on) {
mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
} else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
@@ -2889,6 +2892,8 @@
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
}
+ AudioSystem.setParameters("A2dpSuspended=false");
+ setBluetoothScoOnInt(false);
}
private void broadcastScoConnectionState(int state) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 533f425..452378f 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -837,7 +837,6 @@
if (mPendingScreenOff && target != Display.STATE_OFF) {
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
- mPowerState.dismissColorFade();
}
if (target == Display.STATE_ON) {
@@ -911,7 +910,6 @@
// A black surface is already hiding the contents of the screen.
setScreenState(Display.STATE_OFF);
mPendingScreenOff = false;
- mPowerState.dismissColorFade();
} else if (performScreenOffTransition
&& mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ?
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index be37f52..088d96e 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -544,7 +544,7 @@
physIndex = findDisplayInfoIndexLocked(colorTransformId, modeId);
}
}
- if (physIndex > 0 && mActivePhysIndex == physIndex) {
+ if (mActivePhysIndex == physIndex) {
return;
}
SurfaceControl.setActiveConfig(getDisplayTokenLocked(), physIndex);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index af0a73e..17a3f56 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6156,41 +6156,6 @@
it.remove();
}
}
- // Give priority to system apps.
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
- // Give priority to updated system apps.
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (pkg.isUpdatedSystemApp()) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
- // Give priority to apps that listen for boot complete.
- intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
- pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
- for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) {
- PackageParser.Package pkg = it.next();
- if (pkgNames.contains(pkg.packageName)) {
- if (DEBUG_DEXOPT) {
- Log.i(TAG, "Adding boot app " + sortedPkgs.size() + ": " + pkg.packageName);
- }
- sortedPkgs.add(pkg);
- it.remove();
- }
- }
// Filter out packages that aren't recently used.
filterRecentlyUsedApps(pkgs);
// Add all remaining apps.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3974205..dbc3970 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4432,6 +4432,7 @@
if (attrs.type == TYPE_STATUS_BAR) {
if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mForceStatusBarFromKeyguard = true;
+ mShowingLockscreen = true;
}
if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
mForceStatusBarTransparent = true;
@@ -4452,9 +4453,6 @@
mForceStatusBar = true;
}
}
- if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mShowingLockscreen = true;
- }
if (attrs.type == TYPE_DREAM) {
// If the lockscreen was showing when the dream started then wait
// for the dream to draw before hiding the lockscreen.
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 5d01931..25d646d 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -28,5 +28,5 @@
void showScreenPinningRequest();
void showAssistDisclosure();
void startAssist(Bundle args);
- void onCameraLaunchGestureDetected();
+ void onCameraLaunchGestureDetected(int source);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 11a1639..19b03d5 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -178,10 +178,10 @@
}
@Override
- public void onCameraLaunchGestureDetected() {
+ public void onCameraLaunchGestureDetected(int source) {
if (mBar != null) {
try {
- mBar.onCameraLaunchGestureDetected();
+ mBar.onCameraLaunchGestureDetected(source);
} catch (RemoteException e) {
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4392ab4..ede377d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
+import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
import android.graphics.Rect;
import android.graphics.Region;
@@ -255,10 +256,10 @@
}
/**
- * Find the id of the task whose outside touch area (for resizing) (x, y)
- * falls within. Returns -1 if the touch doesn't fall into a resizing area.
+ * Find the window whose outside touch area (for resizing) (x, y) falls within.
+ * Returns null if the touch doesn't fall into a resizing area.
*/
- int taskIdForControlPoint(int x, int y) {
+ WindowState findWindowForControlPoint(int x, int y) {
final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
TaskStack stack = mStacks.get(stackNdx);
@@ -269,22 +270,31 @@
for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
final Task task = tasks.get(taskNdx);
if (task.isFullscreen()) {
- return -1;
+ return null;
}
- task.getBounds(mTmpRect);
- mTmpRect.inset(-delta, -delta);
- if (mTmpRect.contains(x, y)) {
- mTmpRect.inset(delta, delta);
- if (!mTmpRect.contains(x, y)) {
- return task.mTaskId;
+
+ // We need to use the visible frame on the window for any touch-related
+ // tests. Can't use the task's bounds because the original task bounds
+ // might be adjusted to fit the content frame. (One example is when the
+ // task is put to top-left quadrant, the actual visible frame would not
+ // start at (0,0) after it's adjusted for the status bar.)
+ WindowState win = task.getTopAppMainWindow();
+ if (win != null) {
+ win.getVisibleBounds(mTmpRect, !BOUNDS_FOR_TOUCH);
+ mTmpRect.inset(-delta, -delta);
+ if (mTmpRect.contains(x, y)) {
+ mTmpRect.inset(delta, delta);
+ if (!mTmpRect.contains(x, y)) {
+ return win;
+ }
+ // User touched inside the task. No need to look further,
+ // focus transfer will be handled in ACTION_UP.
+ return null;
}
- // User touched inside the task. No need to look further,
- // focus transfer will be handled in ACTION_UP.
- return -1;
}
}
}
- return -1;
+ return null;
}
void setTouchExcludeRegion(Task focusedTask) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6ebff42..d1111f7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -437,6 +437,11 @@
return mStack != null && mStack.mStackId == DOCKED_STACK_ID;
}
+ WindowState getTopAppMainWindow() {
+ final int tokensCount = mAppTokens.size();
+ return tokensCount > 0 ? mAppTokens.get(tokensCount - 1).findMainWindow() : null;
+ }
+
@Override
public boolean isFullscreen() {
return mFullscreen;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 9557d121..df2e5e8 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -22,6 +22,7 @@
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static com.android.server.wm.WindowManagerService.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
@@ -33,14 +34,16 @@
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
+import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Slog;
+import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
-import android.view.InputEventReceiver;
+import android.view.BatchedInputEventReceiver;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -103,9 +106,10 @@
InputApplicationHandle mDragApplicationHandle;
InputWindowHandle mDragWindowHandle;
- private final class WindowPositionerEventReceiver extends InputEventReceiver {
- public WindowPositionerEventReceiver(InputChannel inputChannel, Looper looper) {
- super(inputChannel, looper);
+ private final class WindowPositionerEventReceiver extends BatchedInputEventReceiver {
+ public WindowPositionerEventReceiver(
+ InputChannel inputChannel, Looper looper, Choreographer choreographer) {
+ super(inputChannel, looper, choreographer);
}
@Override
@@ -143,10 +147,12 @@
synchronized (mService.mWindowMap) {
mDragEnded = notifyMoveLocked(newX, newY);
}
+ 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: {
@@ -222,8 +228,8 @@
mClientChannel = channels[1];
mService.mInputManager.registerInputChannel(mServerChannel, null);
- mInputEventReceiver = new WindowPositionerEventReceiver(mClientChannel,
- mService.mH.getLooper());
+ mInputEventReceiver = new WindowPositionerEventReceiver(
+ mClientChannel, mService.mH.getLooper(), mService.mChoreographer);
mDragApplicationHandle = new InputApplicationHandle(null);
mDragApplicationHandle.name = TAG;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d510c4a..22f9f50 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6885,37 +6885,29 @@
}
boolean startMovingTask(IWindow window, float startX, float startY) {
- WindowState callingWin = null;
+ WindowState win = null;
synchronized (mWindowMap) {
- callingWin = windowForClientLocked(null, window, false);
- if (!startPositioningLocked(callingWin, false /*resize*/, startX, startY)) {
+ win = windowForClientLocked(null, window, false);
+ if (!startPositioningLocked(win, false /*resize*/, startX, startY)) {
return false;
}
}
try {
- mActivityManager.setFocusedTask(callingWin.getTask().mTaskId);
+ mActivityManager.setFocusedTask(win.getTask().mTaskId);
} catch(RemoteException e) {}
return true;
}
private void startResizingTask(DisplayContent displayContent, int startX, int startY) {
- int taskId = -1;
- AppWindowToken atoken = null;
+ WindowState win = null;
synchronized (mWindowMap) {
- taskId = displayContent.taskIdForControlPoint(startX, startY);
- Task task = mTaskIdToTask.get(taskId);
- if (task == null || task.mAppTokens == null) {
- return;
- }
- AppTokenList tokens = task.mAppTokens;
- atoken = tokens.get(tokens.size() - 1);
- WindowState win = atoken.findMainWindow();
+ win = displayContent.findWindowForControlPoint(startX, startY);
if (!startPositioningLocked(win, true /*resize*/, startX, startY)) {
return;
}
}
try {
- mActivityManager.setFocusedTask(taskId);
+ mActivityManager.setFocusedTask(win.getTask().mTaskId);
} catch(RemoteException e) {}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 64440d3..37deffe 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
@@ -38,6 +39,7 @@
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.SystemClock;
+import android.os.Trace;
import android.os.WorkSource;
import android.util.DisplayMetrics;
import android.util.TimeUtils;
@@ -943,7 +945,6 @@
*/
void getVisibleBounds(Rect bounds, boolean forTouch) {
boolean intersectWithStackBounds = mAppToken != null && mAppToken.mCropWindowsToStack;
- boolean isFreeform = false;
bounds.setEmpty();
mTmpRect.setEmpty();
if (intersectWithStackBounds) {
@@ -955,13 +956,9 @@
}
}
- final Task task = getTask();
- if (task != null) {
- task.getBounds(bounds);
- isFreeform = task.inFreeformWorkspace();
- if (intersectWithStackBounds) {
- bounds.intersect(mTmpRect);
- }
+ bounds.set(mVisibleFrame);
+ if (intersectWithStackBounds) {
+ bounds.intersect(mTmpRect);
}
if (bounds.isEmpty()) {
@@ -971,7 +968,7 @@
}
return;
}
- if (forTouch && isFreeform) {
+ if (forTouch && inFreeformWorkspace()) {
final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
bounds.inset(-delta, -delta);
@@ -1470,10 +1467,7 @@
// We want the tag name to be somewhat stable so that it is easier to correlate
// in wake lock statistics. So in particular, we don't want to include the
// window's hash code as in toString().
- CharSequence tag = mAttrs.getTitle();
- if (tag == null) {
- tag = mAttrs.packageName;
- }
+ final CharSequence tag = getWindowTag();
mDrawLock = mService.mPowerManager.newWakeLock(
PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
mDrawLock.setReferenceCounted(false);
@@ -1610,6 +1604,7 @@
}
void reportResized() {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
@@ -1675,6 +1670,7 @@
mService.mPendingRemove.add(this);
mService.mWindowPlacerLocked.requestTraversal();
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
public void registerFocusObserver(IWindowFocusObserver observer) {
@@ -1906,15 +1902,20 @@
String makeInputChannelName() {
return Integer.toHexString(System.identityHashCode(this))
- + " " + mAttrs.getTitle();
+ + " " + getWindowTag();
+ }
+
+ private CharSequence getWindowTag() {
+ CharSequence tag = mAttrs.getTitle();
+ if (tag == null || tag.length() <= 0) {
+ tag = mAttrs.packageName;
+ }
+ return tag;
}
@Override
public String toString() {
- CharSequence title = mAttrs.getTitle();
- if (title == null || title.length() <= 0) {
- title = mAttrs.packageName;
- }
+ final CharSequence title = getWindowTag();
if (mStringNameCache == null || mLastTitle != title || mWasExiting != mExiting) {
mLastTitle = title;
mWasExiting = mExiting;
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 3fd0f84..5cbb277 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -460,7 +460,7 @@
return result;
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"init", "()J", (void*)android_server_AlarmManagerService_init},
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 8f4fb51..ed79ceb 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -204,7 +204,7 @@
const char* const kClassPathName = "com/android/server/AssetAtlasService";
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{ "nUploadAtlas", "(Landroid/view/GraphicBuffer;Landroid/graphics/Bitmap;)Z",
(void*) com_android_server_AssetAtlasService_upload },
};
diff --git a/services/core/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp
index f5121cd..7104870 100644
--- a/services/core/jni/com_android_server_ConsumerIrService.cpp
+++ b/services/core/jni/com_android_server_ConsumerIrService.cpp
@@ -100,7 +100,7 @@
return freqsOut.getJavaArray();
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "halOpen", "()J", (void *)halOpen },
{ "halTransmit", "(JI[I)I", (void *)halTransmit },
{ "halGetCarrierFrequencies", "(J)[I", (void *)halGetCarrierFrequencies},
diff --git a/services/core/jni/com_android_server_PersistentDataBlockService.cpp b/services/core/jni/com_android_server_PersistentDataBlockService.cpp
index 4ccfa56..06de592 100644
--- a/services/core/jni/com_android_server_PersistentDataBlockService.cpp
+++ b/services/core/jni/com_android_server_PersistentDataBlockService.cpp
@@ -97,7 +97,7 @@
return wipe_block_device(fd);
}
- static JNINativeMethod sMethods[] = {
+ static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"nativeGetBlockDeviceSize", "(Ljava/lang/String;)J", (void*)com_android_server_PersistentDataBlockService_getBlockDeviceSize},
{"nativeWipe", "(Ljava/lang/String;)I", (void*)com_android_server_PersistentDataBlockService_wipe},
diff --git a/services/core/jni/com_android_server_SerialService.cpp b/services/core/jni/com_android_server_SerialService.cpp
index d48d159..1bd7a59 100644
--- a/services/core/jni/com_android_server_SerialService.cpp
+++ b/services/core/jni/com_android_server_SerialService.cpp
@@ -55,7 +55,7 @@
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "native_open", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
(void*)android_server_SerialService_open },
};
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 64514a9..c7d6b95 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -37,7 +37,7 @@
/*
* JNI registration.
*/
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "startSensorService", "()V", (void*) android_server_SystemServer_startSensorService },
};
diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp
index a1bff9d..3733a55 100644
--- a/services/core/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp
@@ -118,7 +118,7 @@
return result;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "nativeGetAccessoryStrings", "()[Ljava/lang/String;",
(void*)android_server_UsbDeviceManager_getAccessoryStrings },
{ "nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;",
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index d8c172f..795f6aa 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -186,7 +186,7 @@
gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "monitorUsbHostBus", "()V", (void*)android_server_UsbHostManager_monitorUsbHostBus },
{ "nativeOpenDevice", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
(void*)android_server_UsbHostManager_openDevice },
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index fb1166b..64278ed 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -46,7 +46,7 @@
vibrator_off();
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff }
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index dfc5ef6..5c43659 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -170,7 +170,7 @@
return mergedreasonpos - mergedreason;
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
};
diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp
index 7faeb49..2d0dfd2 100644
--- a/services/core/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp
@@ -350,7 +350,7 @@
//------------------------------------------------------------------------------
-static JNINativeMethod gMethods[] = {
+static const JNINativeMethod gMethods[] = {
{"jniCreate", "(I)I", (void *)create},
{"jniGetName", "(I)Ljava/lang/String;", (void *)getName},
{"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index f2d0f06..b72cf4d 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -384,7 +384,7 @@
return controller->isConnected(port) ? JNI_TRUE : JNI_FALSE ;
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Lcom/android/server/hdmi/HdmiCecController;Landroid/os/MessageQueue;)J",
diff --git a/services/core/jni/com_android_server_input_InputApplicationHandle.cpp b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
index 11388d8..bdc109d 100644
--- a/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
+++ b/services/core/jni/com_android_server_input_InputApplicationHandle.cpp
@@ -120,7 +120,7 @@
}
-static JNINativeMethod gInputApplicationHandleMethods[] = {
+static const JNINativeMethod gInputApplicationHandleMethods[] = {
/* name, signature, funcPtr */
{ "nativeDispose", "()V",
(void*) android_server_InputApplicationHandle_nativeDispose },
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index e29d0a9..1d4f047 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -1369,7 +1369,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gInputManagerMethods[] = {
+static const JNINativeMethod gInputManagerMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit",
"(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
diff --git a/services/core/jni/com_android_server_input_InputWindowHandle.cpp b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
index 01c51cf..92ef7f1 100644
--- a/services/core/jni/com_android_server_input_InputWindowHandle.cpp
+++ b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
@@ -210,7 +210,7 @@
}
-static JNINativeMethod gInputWindowHandleMethods[] = {
+static const JNINativeMethod gInputWindowHandleMethods[] = {
/* name, signature, funcPtr */
{ "nativeDispose", "()V",
(void*) android_server_InputWindowHandle_nativeDispose },
diff --git a/services/core/jni/com_android_server_lights_LightsService.cpp b/services/core/jni/com_android_server_lights_LightsService.cpp
index b2b2783..3f074f5 100644
--- a/services/core/jni/com_android_server_lights_LightsService.cpp
+++ b/services/core/jni/com_android_server_lights_LightsService.cpp
@@ -126,7 +126,7 @@
}
}
-static JNINativeMethod method_table[] = {
+static const JNINativeMethod method_table[] = {
{ "init_native", "()J", (void*)init_native },
{ "finalize_native", "(J)V", (void*)finalize_native },
{ "setLight_native", "(JIIIIII)V", (void*)setLight_native },
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index c0a0c9c..774577d 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -1023,7 +1023,7 @@
env->ReleaseIntArrayElements(geofenceIdsArray, geofenceIds, 0 /*mode*/);
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
//{"name", "signature", functionPointer }
{"nativeClassInit", "()V", reinterpret_cast<void*>(ClassInit)},
{"nativeInit", "()V", reinterpret_cast<void*>(Init)},
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 5c27b1f..b8d4196 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -1434,7 +1434,7 @@
env->ReleaseStringUTFChars(config_content, data);
}
-static JNINativeMethod sMethods[] = {
+static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
{"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 1662755..2fdb8e2 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -166,7 +166,7 @@
// ----------------------------------------------------------------------------
-static JNINativeMethod gPowerManagerServiceMethods[] = {
+static const JNINativeMethod gPowerManagerServiceMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "()V",
(void*) nativeInit },
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 507bc9c..89b2a47 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -662,7 +662,7 @@
delete tvInputHal;
}
-static JNINativeMethod gTvInputHalMethods[] = {
+static const JNINativeMethod gTvInputHalMethods[] = {
/* name, signature, funcPtr */
{ "nativeOpen", "(Landroid/os/MessageQueue;)J",
(void*) nativeOpen },
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b0a04c7..3f70e0c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -271,7 +271,6 @@
final Context mContext;
final PackageManager mPackageManager;
final UserManager mUserManager;
- final PowerManager.WakeLock mWakeLock;
final LocalService mLocalService;
@@ -995,7 +994,7 @@
boolean removed = false;
if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
synchronized (this) {
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
ActiveAdmin aa = policy.mAdminList.get(i);
@@ -1071,7 +1070,7 @@
/** Unit test will override it to inject a mock. */
@VisibleForTesting
- IWindowManager newIWindowManager() {
+ IWindowManager getIWindowManager() {
return IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
}
@@ -1083,6 +1082,12 @@
/** Unit test will override it to inject a mock. */
@VisibleForTesting
+ IPackageManager getIPackageManager() {
+ return AppGlobals.getPackageManager();
+ }
+
+ /** Unit test will override it to inject a mock. */
+ @VisibleForTesting
LockPatternUtils newLockPatternUtils(Context context) {
return new LockPatternUtils(context);
}
@@ -1129,13 +1134,33 @@
}
@VisibleForTesting
- WakeLock powerManagerNewWakeLock(int levelAndFlags, String tag) {
- return mContext.getSystemService(PowerManager.class).newWakeLock(levelAndFlags, tag);
+ void powerManagerGoToSleep(long time, int reason, int flags) {
+ mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
}
@VisibleForTesting
- void powerManagerGoToSleep(long time, int reason, int flags) {
- mContext.getSystemService(PowerManager.class).goToSleep(time, reason, flags);
+ boolean systemPropertiesGetBoolean(String key, boolean def) {
+ return SystemProperties.getBoolean(key, def);
+ }
+
+ @VisibleForTesting
+ long systemPropertiesGetLong(String key, long def) {
+ return SystemProperties.getLong(key, def);
+ }
+
+ @VisibleForTesting
+ String systemPropertiesGet(String key, String def) {
+ return SystemProperties.get(key, def);
+ }
+
+ @VisibleForTesting
+ String systemPropertiesGet(String key) {
+ return SystemProperties.get(key);
+ }
+
+ @VisibleForTesting
+ void systemPropertiesSet(String key, String value) {
+ SystemProperties.set(key, value);
}
/**
@@ -1145,14 +1170,16 @@
mContext = context;
mHandler = new Handler(getMyLooper());
mOwners = newOwners();
- mUserManager = getUserManager();
- mPackageManager = getPackageManager();
- mHasFeature = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
- mPowerManagerInternal = getPowerManagerInternal();
- mWakeLock = powerManagerNewWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
- mIWindowManager = newIWindowManager();
- mNotificationManager = getNotificationManager();
+
+ mUserManager = Preconditions.checkNotNull(getUserManager());
+ mPackageManager = Preconditions.checkNotNull(getPackageManager());
+ mPowerManagerInternal = Preconditions.checkNotNull(getPowerManagerInternal());
+ mIWindowManager = Preconditions.checkNotNull(getIWindowManager());
+ mNotificationManager = Preconditions.checkNotNull(getNotificationManager());
+
mLocalService = new LocalService();
+
+ mHasFeature = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
if (!mHasFeature) {
// Skip the rest of the initialization
return;
@@ -1862,7 +1889,7 @@
// Ensure the status of the camera is synced down to the system. Interested native services
// should monitor this value and act accordingly.
String cameraPropertyForUser = SYSTEM_PROP_DISABLE_CAMERA_PREFIX + policy.mUserHandle;
- boolean systemState = SystemProperties.getBoolean(cameraPropertyForUser, false);
+ boolean systemState = systemPropertiesGetBoolean(cameraPropertyForUser, false);
boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
if (cameraDisabled != systemState) {
long token = binderClearCallingIdentity();
@@ -1870,7 +1897,7 @@
String value = cameraDisabled ? "1" : "0";
if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
+ cameraPropertyForUser + "] = " + value);
- SystemProperties.set(cameraPropertyForUser, value);
+ systemPropertiesSet(cameraPropertyForUser, value);
} finally {
binderRestoreCallingIdentity(token);
}
@@ -3231,7 +3258,7 @@
}
private boolean isExtStorageEncrypted() {
- String state = SystemProperties.get("vold.decrypt");
+ String state = systemPropertiesGet("vold.decrypt");
return !"".equals(state);
}
@@ -3969,7 +3996,7 @@
* {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
*/
private int getEncryptionStatus() {
- String status = SystemProperties.get("ro.crypto.state", "unsupported");
+ String status = systemPropertiesGet("ro.crypto.state", "unsupported");
if ("encrypted".equalsIgnoreCase(status)) {
final long token = binderClearCallingIdentity();
try {
@@ -4377,7 +4404,7 @@
}
boolean isInitializerSystemApp;
try {
- isInitializerSystemApp = isSystemApp(AppGlobals.getPackageManager(),
+ isInitializerSystemApp = isSystemApp(getIPackageManager(),
initializer.getPackageName(), binderGetCallingUserHandle().getIdentifier());
} catch (RemoteException | IllegalArgumentException e) {
isInitializerSystemApp = false;
@@ -4528,7 +4555,7 @@
final long ident = binderClearCallingIdentity();
try {
clearUserRestrictions(userHandle);
- AppGlobals.getPackageManager().updatePermissionFlagsForAllApps(
+ getIPackageManager().updatePermissionFlagsForAllApps(
PackageManager.FLAG_PERMISSION_POLICY_FIXED,
0 /* flagValues */, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -4596,7 +4623,7 @@
long id = binderClearCallingIdentity();
try {
if (!isDeviceOwner(activeAdmin.info.getPackageName())) {
- IPackageManager ipm = AppGlobals.getPackageManager();
+ IPackageManager ipm = getIPackageManager();
ipm.setComponentEnabledSetting(who,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP, userId);
@@ -4857,7 +4884,7 @@
private void enableIfNecessary(String packageName, int userId) {
try {
- IPackageManager ipm = AppGlobals.getPackageManager();
+ IPackageManager ipm = getIPackageManager();
ApplicationInfo ai = ipm.getApplicationInfo(packageName,
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
userId);
@@ -4919,7 +4946,7 @@
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
long id = binderClearCallingIdentity();
try {
pm.addPersistentPreferredActivity(filter, activity, userHandle);
@@ -4938,7 +4965,7 @@
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
long id = binderClearCallingIdentity();
try {
pm.clearPackagePersistentPreferredActivities(packageName, userHandle);
@@ -5074,7 +5101,7 @@
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
long id = binderClearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -5105,7 +5132,7 @@
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
long id = binderClearCallingIdentity();
try {
UserInfo parent = mUserManager.getProfileParent(callingUserId);
@@ -5144,7 +5171,7 @@
userIdToCheck = user.profileGroupId;
}
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
for (String enabledPackage : enabledPackages) {
boolean systemService = false;
try {
@@ -5276,7 +5303,7 @@
List<AccessibilityServiceInfo> installedServices =
accessibilityManager.getInstalledAccessibilityServiceList();
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
if (installedServices != null) {
for (AccessibilityServiceInfo service : installedServices) {
ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
@@ -5425,7 +5452,7 @@
List<InputMethodInfo> imes = inputMethodManager.getInputMethodList();
long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
if (imes != null) {
for (InputMethodInfo ime : imes) {
ServiceInfo serviceInfo = ime.getServiceInfo();
@@ -5472,7 +5499,7 @@
long id = binderClearCallingIdentity();
try {
String profileOwnerPkg = profileOwnerComponent.getPackageName();
- final IPackageManager ipm = AppGlobals.getPackageManager();
+ final IPackageManager ipm = getIPackageManager();
IActivityManager activityManager = getIActivityManager();
final int userHandle = user.getIdentifier();
@@ -5624,8 +5651,8 @@
// Send out notifications however as some clients may want to reread the
// value which actually changed due to a restriction having been applied.
final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
- long version = SystemProperties.getLong(property, 0) + 1;
- SystemProperties.set(property, Long.toString(version));
+ long version = systemPropertiesGetLong(property, 0) + 1;
+ systemPropertiesSet(property, Long.toString(version));
final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
@@ -5660,7 +5687,7 @@
long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
return pm.setApplicationHiddenSettingAsUser(packageName, hidden, callingUserId);
} catch (RemoteException re) {
// shouldn't happen
@@ -5681,7 +5708,7 @@
long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
return pm.getApplicationHiddenSettingAsUser(packageName, callingUserId);
} catch (RemoteException re) {
// shouldn't happen
@@ -5718,7 +5745,7 @@
primaryUser = um.getUserInfo(userId);
}
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
if (!isSystemApp(pm, packageName, primaryUser.id)) {
throw new IllegalArgumentException("Only system apps can be enabled this way.");
}
@@ -5755,7 +5782,7 @@
primaryUser = um.getUserInfo(userId);
}
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
0, // no flags
@@ -5851,7 +5878,7 @@
long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
pm.setBlockUninstallForUser(packageName, uninstallBlocked, userId);
} catch (RemoteException re) {
// Shouldn't happen.
@@ -5876,7 +5903,7 @@
long id = binderClearCallingIdentity();
try {
- IPackageManager pm = AppGlobals.getPackageManager();
+ IPackageManager pm = getIPackageManager();
return pm.getBlockUninstallForUser(packageName, userId);
} catch (RemoteException re) {
// Shouldn't happen.
@@ -6560,7 +6587,7 @@
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long ident = binderClearCallingIdentity();
try {
- final ApplicationInfo ai = AppGlobals.getPackageManager()
+ final ApplicationInfo ai = getIPackageManager()
.getApplicationInfo(packageName, 0, user.getIdentifier());
final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion;
if (targetSdkVersion < android.os.Build.VERSION_CODES.M) {
@@ -6607,7 +6634,7 @@
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long ident = binderClearCallingIdentity();
try {
- int granted = AppGlobals.getPackageManager().checkPermission(permission,
+ int granted = getIPackageManager().checkPermission(permission,
packageName, user.getIdentifier());
int permFlags = packageManager.getPermissionFlags(permission, packageName, user);
if ((permFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED)
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 9ee9cf4..e0d2ac1 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -244,8 +244,9 @@
private PendingIntent createStateMachineCommandIntent(final String cmdName, final int cmd) {
String action = DhcpClient.class.getName() + "." + mIfaceName + "." + cmdName;
- Intent intent = new Intent(action, null)
- .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ Intent intent = new Intent(action, null).addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
// TODO: The intent's package covers the whole of the system server, so it's pretty generic.
// Consider adding some sort of token as well.
intent.setPackage(mContext.getPackageName());
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index cb2c9b7..c147bcc 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -67,8 +67,26 @@
</intent-filter>
</receiver>
- <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmin"
- android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_sample" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin2"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
+ <meta-data android:name="android.app.device_admin"
+ android:resource="@xml/device_admin_sample" />
+ <intent-filter>
+ <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmins$Admin3"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
android:resource="@xml/device_admin_sample" />
<intent-filter>
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index cb439eb..7e730f6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -20,6 +20,7 @@
import android.app.IActivityManager;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Looper;
import android.os.PowerManager.WakeLock;
@@ -45,9 +46,9 @@
public static final String DEVICE_OWNER_FILE = "device_owner2.xml";
public static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
- final private File mLegacyFile;
- final private File mDeviceOwnerFile;
- final private File mProfileOwnerBase;
+ private final File mLegacyFile;
+ private final File mDeviceOwnerFile;
+ private final File mProfileOwnerBase;
public OwnersTestable(Context context, File dataDir) {
super(context);
@@ -96,47 +97,52 @@
}
@Override
- protected Owners newOwners() {
+ Owners newOwners() {
return new OwnersTestable(getContext(), dataDir);
}
@Override
- protected UserManager getUserManager() {
+ UserManager getUserManager() {
return getContext().userManager;
}
@Override
- protected PackageManager getPackageManager() {
+ PackageManager getPackageManager() {
return getContext().packageManager;
}
@Override
- protected PowerManagerInternal getPowerManagerInternal() {
+ PowerManagerInternal getPowerManagerInternal() {
return getContext().powerManagerInternal;
}
@Override
- protected NotificationManager getNotificationManager() {
+ NotificationManager getNotificationManager() {
return getContext().notificationManager;
}
@Override
- protected IWindowManager newIWindowManager() {
+ IWindowManager getIWindowManager() {
return getContext().iwindowManager;
}
@Override
- protected IActivityManager getIActivityManager() {
+ IActivityManager getIActivityManager() {
return getContext().iactivityManager;
}
@Override
- protected LockPatternUtils newLockPatternUtils(Context context) {
+ IPackageManager getIPackageManager() {
+ return getContext().ipackageManager;
+ }
+
+ @Override
+ LockPatternUtils newLockPatternUtils(Context context) {
return getContext().lockPatternUtils;
}
@Override
- protected Looper getMyLooper() {
+ Looper getMyLooper() {
return Looper.getMainLooper();
}
@@ -181,12 +187,32 @@
}
@Override
- WakeLock powerManagerNewWakeLock(int levelAndFlags, String tag) {
- return getContext().powerManager.newWakeLock(levelAndFlags, tag);
+ void powerManagerGoToSleep(long time, int reason, int flags) {
+ getContext().powerManager.goToSleep(time, reason, flags);
}
@Override
- void powerManagerGoToSleep(long time, int reason, int flags) {
- getContext().powerManager.goToSleep(time, reason, flags);
+ boolean systemPropertiesGetBoolean(String key, boolean def) {
+ return getContext().systemProperties.getBoolean(key, def);
+ }
+
+ @Override
+ long systemPropertiesGetLong(String key, long def) {
+ return getContext().systemProperties.getLong(key, def);
+ }
+
+ @Override
+ String systemPropertiesGet(String key, String def) {
+ return getContext().systemProperties.get(key, def);
+ }
+
+ @Override
+ String systemPropertiesGet(String key) {
+ return getContext().systemProperties.get(key);
+ }
+
+ @Override
+ void systemPropertiesSet(String key, String value) {
+ getContext().systemProperties.set(key, value);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 7cce56c..0da459d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -13,33 +13,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.android.server.devicepolicy;
import com.android.server.LocalServices;
+import android.Manifest.permission;
+import android.app.Activity;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.UserHandle;
+import android.os.Bundle;
import org.mockito.ArgumentCaptor;
import java.util.List;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
- * Tests for {@link DevicePolicyManager} and {@link DevicePolicyManagerService}.
+ * Tests for DevicePolicyManager( and DevicePolicyManagerService).
*
m FrameworksServicesTests &&
adb install \
@@ -51,9 +57,13 @@
*/
public class DevicePolicyManagerTest extends DpmTestBase {
+
private DpmMockContext mContext;
public DevicePolicyManager dpm;
public DevicePolicyManagerServiceTestable dpms;
+ public ComponentName admin1;
+ public ComponentName admin2;
+ public ComponentName admin3;
@Override
protected void setUp() throws Exception {
@@ -67,6 +77,59 @@
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
dpm = new DevicePolicyManagerTestable(mContext, dpms);
+
+ admin1 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin1.class);
+ admin2 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin2.class);
+ admin3 = new ComponentName(mRealTestContext, DummyDeviceAdmins.Admin3.class);
+
+ setUpPackageManagerForAdmin(admin1);
+ setUpPackageManagerForAdmin(admin2);
+ setUpPackageManagerForAdmin(admin3);
+
+ setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED);
+ }
+
+ /**
+ * Set up a mock result for {@link PackageManager#queryBroadcastReceivers}. We'll return
+ * the actual ResolveInfo for the admin component, but we need to mock PM so it'll return
+ * it for user {@link DpmMockContext#CALLER_USER_HANDLE}.
+ */
+ private void setUpPackageManagerForAdmin(ComponentName admin) {
+ final Intent resolveIntent = new Intent();
+ resolveIntent.setComponent(admin);
+ final List<ResolveInfo> realResolveInfo =
+ mRealTestContext.getPackageManager().queryBroadcastReceivers(
+ resolveIntent,
+ PackageManager.GET_META_DATA);
+ assertNotNull(realResolveInfo);
+ assertEquals(1, realResolveInfo.size());
+
+ // We need to rewrite the UID in the activity info.
+ realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
+
+ doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
+ MockUtils.checkIntentComponent(admin),
+ eq(PackageManager.GET_META_DATA
+ | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+ eq(DpmMockContext.CALLER_USER_HANDLE)
+ );
+ }
+
+ /**
+ * Set up a mock result for {@link IPackageManager#getApplicationInfo} for user
+ * {@link DpmMockContext#CALLER_USER_HANDLE}.
+ */
+ private void setUpApplicationInfo(int enabledSetting) throws Exception {
+ final ApplicationInfo ai = mRealTestContext.getPackageManager().getApplicationInfo(
+ admin1.getPackageName(),
+ PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
+
+ ai.enabledSetting = enabledSetting;
+
+ doReturn(ai).when(mContext.ipackageManager).getApplicationInfo(
+ eq(admin1.getPackageName()),
+ eq(PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
+ eq(DpmMockContext.CALLER_USER_HANDLE));
}
public void testHasNoFeature() {
@@ -84,13 +147,11 @@
* Caller doesn't have proper permissions.
*/
public void testSetActiveAdmin_SecurityException() {
- final ComponentName admin = new ComponentName(mRealTestContext, DummyDeviceAdmin.class);
-
// 1. Failure cases.
// Caller doesn't have MANAGE_DEVICE_ADMINS.
try {
- dpm.setActiveAdmin(admin, false);
+ dpm.setActiveAdmin(admin1, false);
fail("Didn't throw SecurityException");
} catch (SecurityException expected) {
}
@@ -98,62 +159,246 @@
// Caller has MANAGE_DEVICE_ADMINS, but for different user.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
try {
- dpm.setActiveAdmin(admin, false, DpmMockContext.CALLER_USER_HANDLE + 1);
+ dpm.setActiveAdmin(admin1, false, DpmMockContext.CALLER_USER_HANDLE + 1);
fail("Didn't throw SecurityException");
} catch (SecurityException expected) {
}
}
- public void testSetActiveAdmin() {
- final ComponentName admin = new ComponentName(mRealTestContext, DummyDeviceAdmin.class);
-
- // 1. Prepare mock package manager (and other mocks)
-
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#setActiveAdmin}
+ * with replace=false and replace=true
+ * {@link DevicePolicyManager#isAdminActive}
+ * {@link DevicePolicyManager#isAdminActiveAsUser}
+ * {@link DevicePolicyManager#getActiveAdmins}
+ * {@link DevicePolicyManager#getActiveAdminsAsUser}
+ */
+ public void testSetActiveAdmin() throws Exception {
+ // 1. Make sure the caller has proper permissions.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
- // Create ResolveInfo for the admin.
- final Intent resolveIntent = new Intent();
- resolveIntent.setComponent(admin);
- final List<ResolveInfo> realResolveInfo =
- mRealTestContext.getPackageManager().queryBroadcastReceivers(
- resolveIntent,
- PackageManager.GET_META_DATA
- | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
- assertNotNull(realResolveInfo);
- assertEquals(1, realResolveInfo.size());
-
- // We need to rewrite the UID in the activity info.
- realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
-
- doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
- any(Intent.class), // TODO check the intent too.
- eq(PackageManager.GET_META_DATA
- | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
- eq(DpmMockContext.CALLER_USER_HANDLE)
- );
-
- // 2. Everything is ready; call the method.
- dpm.setActiveAdmin(admin, false);
+ // 2. Call the API.
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
// 3. Verify internal calls.
// Check if the boradcast is sent.
- final ArgumentCaptor<Intent> intentCap = ArgumentCaptor.forClass(Intent.class);
- final ArgumentCaptor<UserHandle> uhCap = ArgumentCaptor.forClass(UserHandle.class);
-
- verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
- intentCap.capture(),
+ verify(mContext.spiedContext).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+ verify(mContext.spiedContext).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
- // First call from saveSettingsLocked().
- assertEquals(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED,
- intentCap.getAllValues().get(0).getAction());
-
- // Second call from setActiveAdmin/sendAdminCommandLocked()
- assertEquals(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
- intentCap.getAllValues().get(1).getAction());
+ verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
+ eq(admin1.getPackageName()),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
+ eq(PackageManager.DONT_KILL_APP),
+ eq(DpmMockContext.CALLER_USER_HANDLE),
+ anyString());
// TODO Verify other calls too.
+
+ // Make sure it's active admin1.
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isAdminActive(admin2));
+ assertFalse(dpm.isAdminActive(admin3));
+
+ // But not admin1 for a different user.
+
+ // For this to work, caller needs android.permission.INTERACT_ACROSS_USERS_FULL.
+ // (Because we're checking a different user's status from CALLER_USER_HANDLE.)
+ mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+ assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE + 1));
+ assertFalse(dpm.isAdminActiveAsUser(admin2, DpmMockContext.CALLER_USER_HANDLE + 1));
+
+ mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+ // Next, add one more admin.
+ // Before doing so, update the application info, now it's enabled.
+ setUpApplicationInfo(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+
+ dpm.setActiveAdmin(admin2, /* replace =*/ false);
+
+ // Now we have two admins.
+ assertTrue(dpm.isAdminActive(admin1));
+ assertTrue(dpm.isAdminActive(admin2));
+ assertFalse(dpm.isAdminActive(admin3));
+
+ // Admin2 was already enabled, so setApplicationEnabledSetting() shouldn't have called
+ // again. (times(1) because it was previously called for admin1)
+ verify(mContext.ipackageManager, times(1)).setApplicationEnabledSetting(
+ eq(admin1.getPackageName()),
+ eq(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT),
+ eq(PackageManager.DONT_KILL_APP),
+ eq(DpmMockContext.CALLER_USER_HANDLE),
+ anyString());
+
+ // 4. Add the same admin1 again without replace, which should throw.
+ try {
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ fail("Didn't throw");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // 5. Add the same admin1 again with replace, which should succeed.
+ dpm.setActiveAdmin(admin1, /* replace =*/ true);
+
+ // TODO make sure it's replaced.
+
+ // 6. Test getActiveAdmins()
+ List<ComponentName> admins = dpm.getActiveAdmins();
+ assertEquals(2, admins.size());
+ assertEquals(admin1, admins.get(0));
+ assertEquals(admin2, admins.get(1));
+
+ // Another user has no admins.
+ mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
+
+ assertEquals(0, DpmTestUtils.getListSizeAllowingNull(
+ dpm.getActiveAdminsAsUser(DpmMockContext.CALLER_USER_HANDLE + 1)));
+
+ mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#setActiveAdmin}
+ * with replace=false
+ */
+ public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
+ // 1. Make sure the caller has proper permissions.
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ assertTrue(dpm.isAdminActive(admin1));
+
+ // Add the same admin1 again without replace, which should throw.
+ try {
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ fail("Didn't throw");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#removeActiveAdmin}
+ */
+ public void testRemoveActiveAdmin_SecurityException() {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin.
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ assertTrue(dpm.isAdminActive(admin1));
+
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Directly call the DPMS method with a different userid, which should fail.
+ try {
+ dpms.removeActiveAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE + 1);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+
+ // Try to remove active admin with a different caller userid should fail too, without
+ // having MANAGE_DEVICE_ADMINS.
+ mContext.callerPermissions.clear();
+
+ mContext.binder.callingUid = 1234567;
+ try {
+ dpm.removeActiveAdmin(admin1);
+ fail("Didn't throw SecurityException");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#removeActiveAdmin}
+ */
+ public void testRemoveActiveAdmin_fromDifferentUserWithMINTERACT_ACROSS_USERS_FULL() {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin1.
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Different user, but should work, because caller has proper permissions.
+ mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
+ mContext.binder.callingUid = 1234567;
+ dpm.removeActiveAdmin(admin1);
+
+ assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // TODO DO Still can't be removed in this case.
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#removeActiveAdmin}
+ */
+ public void testRemoveActiveAdmin_sameUserNoMANAGE_DEVICE_ADMINS() {
+ // Need MANAGE_DEVICE_ADMINS for setActiveAdmin. We'll remove it later.
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin1.
+
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+
+ assertTrue(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Broadcast from saveSettingsLocked().
+ verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+ // Remove. No permissions, but same user, so it'll work.
+ mContext.callerPermissions.clear();
+ dpm.removeActiveAdmin(admin1);
+
+ final ArgumentCaptor<BroadcastReceiver> brCap =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+
+ // Is removing now, but not removed yet.
+ assertTrue(dpm.isAdminActive(admin1));
+ assertTrue(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ verify(mContext.spiedContext).sendOrderedBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+ isNull(String.class),
+ brCap.capture(),
+ eq(dpms.mHandler),
+ eq(Activity.RESULT_OK),
+ isNull(String.class),
+ isNull(Bundle.class));
+
+ brCap.getValue().onReceive(mContext, null);
+
+ assertFalse(dpm.isAdminActive(admin1));
+ assertFalse(dpm.isRemovingAdmin(admin1, DpmMockContext.CALLER_USER_HANDLE));
+
+ // Again broadcast from saveSettingsLocked().
+ verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+
+ // TODO Check other internal calls.
}
}
+
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index 8644311..6bb9833 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -16,6 +16,7 @@
package com.android.server.devicepolicy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockPatternUtils;
import android.app.IActivityManager;
@@ -24,11 +25,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager.WakeLock;
import android.os.PowerManagerInternal;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.mock.MockContext;
@@ -71,27 +74,27 @@
public static final int SYSTEM_PID = 11111;
public static class MockBinder {
- int mCallingUid = CALLER_UID;
- int mCallingPid = CALLER_PID;
+ public int callingUid = CALLER_UID;
+ public int callingPid = CALLER_PID;
public long clearCallingIdentity() {
- final long token = (((long) mCallingUid) << 32) | (mCallingPid);
- mCallingUid = SYSTEM_UID;
- mCallingPid = SYSTEM_PID;
+ final long token = (((long) callingUid) << 32) | (callingPid);
+ callingUid = SYSTEM_UID;
+ callingPid = SYSTEM_PID;
return token;
}
public void restoreCallingIdentity(long token) {
- mCallingUid = (int) (token >> 32);
- mCallingPid = (int) token;
+ callingUid = (int) (token >> 32);
+ callingPid = (int) token;
}
public int getCallingUid() {
- return mCallingUid;
+ return callingUid;
}
public int getCallingPid() {
- return mCallingPid;
+ return callingPid;
}
public UserHandle getCallingUserHandle() {
@@ -99,7 +102,7 @@
}
public boolean isCallerUidMyUid() {
- return mCallingUid == SYSTEM_UID;
+ return callingUid == SYSTEM_UID;
}
}
@@ -118,6 +121,27 @@
}
}
+ public static class SystemPropertiesForMock {
+ public boolean getBoolean(String key, boolean def) {
+ return false;
+ }
+
+ public long getLong(String key, long def) {
+ return 0;
+ }
+
+ public String get(String key, String def) {
+ return null;
+ }
+
+ public String get(String key) {
+ return null;
+ }
+
+ public void set(String key, String value) {
+ }
+ }
+
public final Context realTestContext;
/**
@@ -129,12 +153,14 @@
public final MockBinder binder;
public final EnvironmentForMock environment;
+ public final SystemPropertiesForMock systemProperties;
public final UserManager userManager;
public final PowerManagerForMock powerManager;
public final PowerManagerInternal powerManagerInternal;
public final NotificationManager notificationManager;
public final IWindowManager iwindowManager;
public final IActivityManager iactivityManager;
+ public final IPackageManager ipackageManager;
public final LockPatternUtils lockPatternUtils;
/** Note this is a partial mock, not a real mock. */
@@ -146,12 +172,14 @@
realTestContext = context;
binder = new MockBinder();
environment = mock(EnvironmentForMock.class);
+ systemProperties= mock(SystemPropertiesForMock.class);
userManager = mock(UserManager.class);
powerManager = mock(PowerManagerForMock.class);
powerManagerInternal = mock(PowerManagerInternal.class);
notificationManager = mock(NotificationManager.class);
iwindowManager = mock(IWindowManager.class);
iactivityManager = mock(IActivityManager.class);
+ ipackageManager = mock(IPackageManager.class);
lockPatternUtils = mock(LockPatternUtils.class);
// Package manager is huge, so we use a partial mock instead.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
index a8e2c3c..44a851a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestUtils.java
@@ -23,6 +23,7 @@
import org.junit.Assert;
import java.io.File;
+import java.util.List;
public class DpmTestUtils {
private DpmTestUtils() {
@@ -33,6 +34,11 @@
Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
}
dir.mkdirs();
+ Log.i(DpmTestBase.TAG, "Created " + dir);
+ }
+
+ public static int getListSizeAllowingNull(List<?> list) {
+ return list == null ? 0 : list.size();
}
public static Printer LOG_PRINTER = new Printer() {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
similarity index 75%
rename from services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
rename to services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
index c47d194..5cd1555 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmin.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DummyDeviceAdmins.java
@@ -17,5 +17,11 @@
import android.app.admin.DeviceAdminReceiver;
-public class DummyDeviceAdmin extends DeviceAdminReceiver {
-}
+public class DummyDeviceAdmins {
+ public static class Admin1 extends DeviceAdminReceiver {
+ }
+ public static class Admin2 extends DeviceAdminReceiver {
+ }
+ public static class Admin3 extends DeviceAdminReceiver {
+ }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index f2a2bf7..5008fbf 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -17,6 +17,8 @@
import com.google.common.base.Objects;
+import android.content.ComponentName;
+import android.content.Intent;
import android.os.UserHandle;
import org.hamcrest.BaseMatcher;
@@ -44,4 +46,35 @@
return Mockito.argThat(m);
}
+ public static Intent checkIntentComponent(final ComponentName component) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return Objects.equal(((Intent) item).getComponent(), component);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Intent: component=\"" + component + "\"");
+ }
+ };
+ return Mockito.argThat(m);
+ }
+
+ public static Intent checkIntentAction(final String action) {
+ final Matcher<Intent> m = new BaseMatcher<Intent>() {
+ @Override
+ public boolean matches(Object item) {
+ if (item == null) return false;
+ return Objects.equal(((Intent) item).getAction(), action);
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("Intent: action=\"" + action + "\"");
+ }
+ };
+ return Mockito.argThat(m);
+ }
}
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
index 0b43666..8085db7 100644
--- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
@@ -31,5 +31,7 @@
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_activity);
Log.i(TAG, "Activity created");
+ Log.i(TAG, "Source: "
+ + getIntent().getStringExtra("com.android.systemui.camera_launch_source"));
}
}
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java
index 530fe00..242d3b2 100644
--- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/SecureCameraActivity.java
@@ -17,6 +17,7 @@
package com.google.android.test.cameraprewarm;
import android.app.Activity;
+import android.graphics.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
@@ -31,5 +32,7 @@
setContentView(R.layout.camera_activity);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
Log.i(CameraActivity.TAG, "Activity created");
+ Log.i(CameraActivity.TAG, "Source: "
+ + getIntent().getStringExtra("com.android.systemui.camera_launch_source"));
}
}