Merge "camera3: Add camera neutral tag."
diff --git a/api/current.txt b/api/current.txt
index 200c811..c9d1b5f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11287,6 +11287,7 @@
field public static final android.hardware.camera2.CameraMetadata.Key SCALER_AVAILABLE_PROCESSED_SIZES;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_AVAILABLE_TEST_PATTERN_MODES;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BASE_GAIN_FACTOR;
+ field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BLACK_LEVEL_PATTERN;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_ACTIVE_ARRAY_SIZE;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_EXPOSURE_TIME_RANGE;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_MAX_FRAME_DURATION;
@@ -28633,6 +28634,7 @@
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
method public void createContextMenu(android.view.ContextMenu);
method public void destroyDrawingCache();
+ method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
method public void dispatchConfigurationChanged(android.content.res.Configuration);
method public void dispatchDisplayHint(int);
method public boolean dispatchDragEvent(android.view.DragEvent);
@@ -28664,7 +28666,7 @@
method public final android.view.View findViewById(int);
method public final android.view.View findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
- method protected boolean fitSystemWindows(android.graphics.Rect);
+ method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
method public void forceLayout();
method public static int generateViewId();
@@ -28850,6 +28852,7 @@
method public void offsetTopAndBottom(int);
method protected void onAnimationEnd();
method protected void onAnimationStart();
+ method public android.view.WindowInsets onApplyWindowInsets(android.view.WindowInsets);
method protected void onAttachedToWindow();
method public void onCancelPendingInputEvents();
method public boolean onCheckIsTextEditor();
@@ -28916,7 +28919,8 @@
method public boolean removeCallbacks(java.lang.Runnable);
method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
- method public void requestFitSystemWindows();
+ method public void requestApplyInsets();
+ method public deprecated void requestFitSystemWindows();
method public final boolean requestFocus();
method public final boolean requestFocus(int);
method public boolean requestFocus(int, android.graphics.Rect);
@@ -28980,6 +28984,7 @@
method public void setNextFocusLeftId(int);
method public void setNextFocusRightId(int);
method public void setNextFocusUpId(int);
+ method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
method public void setOnClickListener(android.view.View.OnClickListener);
method public void setOnCreateContextMenuListener(android.view.View.OnCreateContextMenuListener);
method public void setOnDragListener(android.view.View.OnDragListener);
@@ -29201,6 +29206,10 @@
field public static final int UNSPECIFIED = 0; // 0x0
}
+ public static abstract interface View.OnApplyWindowInsetsListener {
+ method public abstract android.view.WindowInsets onApplyWindowInsets(android.view.View, android.view.WindowInsets);
+ }
+
public static abstract interface View.OnAttachStateChangeListener {
method public abstract void onViewAttachedToWindow(android.view.View);
method public abstract void onViewDetachedFromWindow(android.view.View);
@@ -29820,6 +29829,27 @@
method public abstract void onFocusLost(android.view.WindowId);
}
+ public class WindowInsets {
+ ctor public WindowInsets(android.view.WindowInsets);
+ method public android.view.WindowInsets cloneWithSystemWindowInsets(int, int, int, int);
+ method public android.view.WindowInsets cloneWithSystemWindowInsetsConsumed();
+ method public android.view.WindowInsets cloneWithSystemWindowInsetsConsumed(boolean, boolean, boolean, boolean);
+ method public android.view.WindowInsets cloneWithWindowDecorInsets(int, int, int, int);
+ method public android.view.WindowInsets cloneWithWindowDecorInsetsConsumed();
+ method public android.view.WindowInsets cloneWithWindowDecorInsetsConsumed(boolean, boolean, boolean, boolean);
+ method public int getSystemWindowInsetBottom();
+ method public int getSystemWindowInsetLeft();
+ method public int getSystemWindowInsetRight();
+ method public int getSystemWindowInsetTop();
+ method public int getWindowDecorInsetBottom();
+ method public int getWindowDecorInsetLeft();
+ method public int getWindowDecorInsetRight();
+ method public int getWindowDecorInsetTop();
+ method public boolean hasInsets();
+ method public boolean hasSystemWindowInsets();
+ method public boolean hasWindowDecorInsets();
+ }
+
public abstract interface WindowManager implements android.view.ViewManager {
method public abstract android.view.Display getDefaultDisplay();
method public abstract void removeViewImmediate(android.view.View);
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 913b273..83314ea 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -614,6 +614,17 @@
new Key<Rational>("android.sensor.baseGainFactor", Rational.class);
/**
+ * <p>A fixed black level offset for each of the color filter arrangement
+ * (CFA) mosaic channels.</p>
+ * <p>This tag specifies the zero light value for each of the CFA mosaic
+ * channels in the camera sensor.</p>
+ * <p>The values are given in row-column scan order, with the first value
+ * corresponding to the element of the CFA in row=0, column=0.</p>
+ */
+ public static final Key<int[]> SENSOR_BLACK_LEVEL_PATTERN =
+ new Key<int[]>("android.sensor.blackLevelPattern", int[].class);
+
+ /**
* <p>Maximum sensitivity that is implemented
* purely through analog gain.</p>
* <p>For {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} values less than or
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4879be6..345ff82 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -551,9 +551,9 @@
public static final int STATE_WIFI_FULL_LOCK_FLAG = 1<<28;
public static final int STATE_WIFI_SCAN_FLAG = 1<<29;
public static final int STATE_WIFI_MULTICAST_ON_FLAG = 1<<26;
+ public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
// These are on the lower bits used for the command; if they change
// we need to write another int of data.
- public static final int STATE_WIFI_RUNNING_FLAG = 1<<24;
public static final int STATE_PHONE_SCANNING_FLAG = 1<<23;
public static final int STATE_AUDIO_ON_FLAG = 1<<22;
public static final int STATE_VIDEO_ON_FLAG = 1<<21;
@@ -572,9 +572,26 @@
// The wake lock that was acquired at this point.
public HistoryTag wakelockTag;
- public static final int EVENT_NONE = 0;
- public static final int EVENT_PROC_STARTED = 1;
- public static final int EVENT_PROC_FINISHED = 2;
+ public static final int EVENT_FLAG_START = 0x8000;
+ public static final int EVENT_FLAG_FINISH = 0x4000;
+
+ // No event in this item.
+ public static final int EVENT_NONE = 0x0000;
+ // Event is about a process that is running.
+ public static final int EVENT_PROC = 0x0001;
+ // Event is about an application package that is in the foreground.
+ public static final int EVENT_FOREGROUND = 0x0002;
+ // Event is about an application package that is at the top of the screen.
+ public static final int EVENT_TOP = 0x0003;
+ // Number of event types.
+ public static final int EVENT_COUNT = 0x0004;
+
+ public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
+ public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
+ public static final int EVENT_FOREGROUND_START = EVENT_FOREGROUND | EVENT_FLAG_START;
+ public static final int EVENT_FOREGROUND_FINISH = EVENT_FOREGROUND | EVENT_FLAG_FINISH;
+ public static final int EVENT_TOP_START = EVENT_TOP | EVENT_FLAG_START;
+ public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH;
// For CMD_EVENT.
public int eventCode;
@@ -942,6 +959,14 @@
SCREEN_BRIGHTNESS_NAMES, SCREEN_BRIGHTNESS_SHORT_NAMES),
};
+ public static final String[] HISTORY_EVENT_NAMES = new String[] {
+ "null", "proc", "fg", "top"
+ };
+
+ public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
+ "Nl", "Pr", "Fg", "Tp"
+ };
+
/**
* Returns the time in microseconds that wifi has been on while the device was
* running on battery.
@@ -2497,6 +2522,9 @@
case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
pw.print(checkin ? "f" : "failure");
break;
+ case BatteryManager.BATTERY_HEALTH_COLD:
+ pw.print(checkin ? "c" : "cold");
+ break;
default:
pw.print(oldHealth);
break;
@@ -2536,25 +2564,23 @@
printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
HISTORY_STATE_DESCRIPTIONS, !checkin);
if (rec.eventCode != HistoryItem.EVENT_NONE) {
- switch (rec.eventCode) {
- case HistoryItem.EVENT_PROC_STARTED:
- pw.print(checkin ? ",PrSt=" : " procstart=");
- break;
- case HistoryItem.EVENT_PROC_FINISHED:
- pw.print(checkin ? ",PrFn=" : " procfin=");
- break;
- default:
- if (checkin) {
- pw.print(",?cmd_");
- pw.print(rec.eventCode);
- pw.print("=");
- } else {
- pw.print(" cmd_");
- pw.print(rec.eventCode);
- pw.print("=");
- }
- break;
+ pw.print(checkin ? "," : " ");
+ if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
+ pw.print("+");
+ } else if ((rec.eventCode&HistoryItem.EVENT_FLAG_FINISH) != 0) {
+ pw.print("-");
}
+ String[] eventNames = checkin ? HISTORY_EVENT_CHECKIN_NAMES
+ : HISTORY_EVENT_NAMES;
+ int idx = rec.eventCode & ~(HistoryItem.EVENT_FLAG_START
+ | HistoryItem.EVENT_FLAG_FINISH);
+ if (idx >= 0 && idx < eventNames.length) {
+ pw.print(eventNames[idx]);
+ } else {
+ pw.print(checkin ? "Ev" : "event");
+ pw.print(idx);
+ }
+ pw.print("=");
if (checkin) {
pw.print(rec.eventTag.poolIdx);
} else {
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 905dcb0..f59ef0f6d 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -115,6 +115,13 @@
}
}
+ /** @hide */
+ public void removeAt(int index) {
+ System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1));
+ System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1));
+ mSize--;
+ }
+
/**
* Adds a mapping from the specified key to the specified value,
* replacing the previous mapping from the specified key if there
@@ -191,6 +198,11 @@
return mValues[index];
}
+ /** @hide */
+ public void setValueAt(int index, boolean value) {
+ mValues[index] = value;
+ }
+
/**
* Returns the index for which {@link #keyAt} would return the
* specified key, or a negative number if the specified
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 8b63359..a96d46c 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -431,7 +431,19 @@
}
/**
- * Sets the outline, defining the shape that casts a shadow.
+ * Sets whether the display list is a projection receiver - that its parent
+ * DisplayList should draw any descendent DisplayLists with
+ * ProjectBackwards=true directly on top of it. Default value is false.
+ */
+ public void setProjectionReceiver(boolean shouldRecieve) {
+ if (hasNativeDisplayList()) {
+ nSetProjectionReceiver(mFinalizer.mNativeDisplayList, shouldRecieve);
+ }
+ }
+
+ /**
+ * Sets the outline, defining the shape that casts a shadow, and the path to
+ * be clipped if setClipToOutline is set.
*
* Deep copies the native path to simplify reference ownership.
*
@@ -445,6 +457,17 @@
}
/**
+ * Enables or disables clipping to the outline.
+ *
+ * @param clipToOutline true if clipping to the outline.
+ */
+ public void setClipToOutline(boolean clipToOutline) {
+ if (hasNativeDisplayList()) {
+ nSetClipToOutline(mFinalizer.mNativeDisplayList, clipToOutline);
+ }
+ }
+
+ /**
* Set the static matrix on the display list. The specified matrix is combined with other
* transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
*
@@ -1065,8 +1088,10 @@
private static native void nSetCaching(long displayList, boolean caching);
private static native void nSetClipToBounds(long displayList, boolean clipToBounds);
private static native void nSetProjectBackwards(long displayList, boolean shouldProject);
+ private static native void nSetProjectionReceiver(long displayList, boolean shouldRecieve);
private static native void nSetIsolatedZVolume(long displayList, boolean isolateZVolume);
private static native void nSetOutline(long displayList, long nativePath);
+ private static native void nSetClipToOutline(long displayList, boolean clipToOutline);
private static native void nSetAlpha(long displayList, float alpha);
private static native void nSetHasOverlappingRendering(long displayList,
boolean hasOverlappingRendering);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2710fdf..d017d56 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2335,7 +2335,6 @@
* 1 PFLAG3_IS_LAID_OUT
* 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
* 1 PFLAG3_CALLED_SUPER
- * 1 PFLAG3_PROJECT_BACKGROUND
* |-------|-------|-------|-------|
*/
@@ -2372,10 +2371,19 @@
static final int PFLAG3_CALLED_SUPER = 0x10;
/**
- * Flag indicating that the background of this view will be drawn into a
- * display list and projected onto the closest parent projection surface.
+ * Flag indicating that an view will be clipped to its outline.
*/
- static final int PFLAG3_PROJECT_BACKGROUND = 0x20;
+ static final int PFLAG3_CLIP_TO_OUTLINE = 0x20;
+
+ /**
+ * Flag indicating that we're in the process of applying window insets.
+ */
+ static final int PFLAG3_APPLYING_INSETS = 0x40;
+
+ /**
+ * Flag indicating that we're in the process of fitting system windows using the old method.
+ */
+ static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x80;
/* End of masks for mPrivateFlags3 */
@@ -3304,6 +3312,8 @@
private OnDragListener mOnDragListener;
private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
+
+ OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
}
ListenerInfo mListenerInfo;
@@ -3322,7 +3332,8 @@
private int[] mDrawableState = null;
/**
- * Stores the outline of the view, passed down to the DisplayList level for shadow shape.
+ * Stores the outline of the view, passed down to the DisplayList level for
+ * defining shadow shape and clipping.
*/
private Path mOutline;
@@ -6123,10 +6134,33 @@
* @return {@code true} if this view applied the insets and it should not
* continue propagating further down the hierarchy, {@code false} otherwise.
* @see #getFitsSystemWindows()
- * @see #setFitsSystemWindows(boolean)
+ * @see #setFitsSystemWindows(boolean)
* @see #setSystemUiVisibility(int)
+ *
+ * @deprecated As of API XX use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
+ * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
+ * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
+ * to implement handling their own insets.
*/
protected boolean fitSystemWindows(Rect insets) {
+ if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
+ // If we're not in the process of dispatching the newer apply insets call,
+ // that means we're not in the compatibility path. Dispatch into the newer
+ // apply insets path and take things from there.
+ try {
+ mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
+ return !dispatchApplyWindowInsets(new WindowInsets(insets)).hasInsets();
+ } finally {
+ mPrivateFlags3 &= PFLAG3_FITTING_SYSTEM_WINDOWS;
+ }
+ } else {
+ // We're being called from the newer apply insets path.
+ // Perform the standard fallback behavior.
+ return fitSystemWindowsInt(insets);
+ }
+ }
+
+ private boolean fitSystemWindowsInt(Rect insets) {
if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
mUserPaddingStart = UNDEFINED_PADDING;
mUserPaddingEnd = UNDEFINED_PADDING;
@@ -6146,6 +6180,97 @@
}
/**
+ * Called when the view should apply {@link WindowInsets} according to its internal policy.
+ *
+ * <p>This method should be overridden by views that wish to apply a policy different from or
+ * in addition to the default behavior. Clients that wish to force a view subtree
+ * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
+ *
+ * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
+ * it will be called during dispatch instead of this method. The listener may optionally
+ * call this method from its own implementation if it wishes to apply the view's default
+ * insets policy in addition to its own.</p>
+ *
+ * <p>Implementations of this method should either return the insets parameter unchanged
+ * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
+ * that this view applied itself. This allows new inset types added in future platform
+ * versions to pass through existing implementations unchanged without being erroneously
+ * consumed.</p>
+ *
+ * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
+ * property is set then the view will consume the system window insets and apply them
+ * as padding for the view.</p>
+ *
+ * @param insets Insets to apply
+ * @return The supplied insets with any applied insets consumed
+ */
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
+ // We weren't called from within a direct call to fitSystemWindows,
+ // call into it as a fallback in case we're in a class that overrides it
+ // and has logic to perform.
+ if (fitSystemWindows(insets.getSystemWindowInsets())) {
+ return insets.cloneWithSystemWindowInsetsConsumed();
+ }
+ } else {
+ // We were called from within a direct call to fitSystemWindows.
+ if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
+ return insets.cloneWithSystemWindowInsetsConsumed();
+ }
+ }
+ return insets;
+ }
+
+ /**
+ * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
+ * window insets to this view. The listener's
+ * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
+ * method will be called instead of the view's
+ * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
+ *
+ * @param listener Listener to set
+ *
+ * @see #onApplyWindowInsets(WindowInsets)
+ */
+ public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
+ getListenerInfo().mOnApplyWindowInsetsListener = listener;
+ }
+
+ /**
+ * Request to apply the given window insets to this view or another view in its subtree.
+ *
+ * <p>This method should be called by clients wishing to apply insets corresponding to areas
+ * obscured by window decorations or overlays. This can include the status and navigation bars,
+ * action bars, input methods and more. New inset categories may be added in the future.
+ * The method returns the insets provided minus any that were applied by this view or its
+ * children.</p>
+ *
+ * <p>Clients wishing to provide custom behavior should override the
+ * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
+ * {@link OnApplyWindowInsetsListener} via the
+ * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
+ * method.</p>
+ *
+ * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
+ * </p>
+ *
+ * @param insets Insets to apply
+ * @return The provided insets minus the insets that were consumed
+ */
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ try {
+ mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
+ if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
+ return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
+ } else {
+ return onApplyWindowInsets(insets);
+ }
+ } finally {
+ mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
+ }
+ }
+
+ /**
* @hide Compute the insets that should be consumed by this view and the ones
* that should propagate to those under it.
*/
@@ -6217,6 +6342,7 @@
/**
* Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
+ * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
*/
public void requestFitSystemWindows() {
if (mParent != null) {
@@ -6225,6 +6351,13 @@
}
/**
+ * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
+ */
+ public void requestApplyInsets() {
+ requestFitSystemWindows();
+ }
+
+ /**
* For use by PhoneWindow to make its own system window fitting optional.
* @hide
*/
@@ -10693,6 +10826,30 @@
}
/**
+ * @hide
+ */
+ public void setClipToOutline(boolean clipToOutline) {
+ // TODO : Add a fast invalidation here.
+ if (getClipToOutline() != clipToOutline) {
+ if (clipToOutline) {
+ mPrivateFlags3 |= PFLAG3_CLIP_TO_OUTLINE;
+ } else {
+ mPrivateFlags3 &= ~PFLAG3_CLIP_TO_OUTLINE;
+ }
+ if (mDisplayList != null) {
+ mDisplayList.setClipToOutline(clipToOutline);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public final boolean getClipToOutline() {
+ return ((mPrivateFlags3 & PFLAG3_CLIP_TO_OUTLINE) != 0);
+ }
+
+ /**
* Hit rectangle in parent's coordinates
*
* @param outRect The hit rectangle of the view.
@@ -14344,6 +14501,7 @@
(((ViewGroup) this).mGroupFlags & ViewGroup.FLAG_ISOLATED_Z_VOLUME) != 0);
}
displayList.setOutline(mOutline);
+ displayList.setClipToOutline(getClipToOutline());
float alpha = 1;
if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
@@ -15014,6 +15172,7 @@
// Set up drawable properties that are view-independent.
displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
displayList.setProjectBackwards(drawable.isProjected());
+ displayList.setProjectionReceiver(true);
displayList.setClipToBounds(false);
return displayList;
}
@@ -19104,6 +19263,31 @@
public void onViewDetachedFromWindow(View v);
}
+ /**
+ * Listener for applying window insets on a view in a custom way.
+ *
+ * <p>Apps may choose to implement this interface if they want to apply custom policy
+ * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
+ * is set, its
+ * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
+ * method will be called instead of the View's own
+ * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
+ * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
+ * the View's normal behavior as part of its own.</p>
+ */
+ public interface OnApplyWindowInsetsListener {
+ /**
+ * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
+ * on a View, this listener method will be called instead of the view's own
+ * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
+ *
+ * @param v The view applying window insets
+ * @param insets The insets to apply
+ * @return The insets supplied, minus any insets that were consumed
+ */
+ public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
+ }
+
private final class UnsetPressedState implements Runnable {
public void run() {
setPressed(false);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 73b108f..7aa568b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5514,21 +5514,19 @@
}
}
-
@Override
- protected boolean fitSystemWindows(Rect insets) {
- boolean done = super.fitSystemWindows(insets);
- if (!done) {
- final int count = mChildrenCount;
- final View[] children = mChildren;
+ public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
+ insets = super.dispatchApplyWindowInsets(insets);
+ if (insets.hasInsets()) {
+ final int count = getChildCount();
for (int i = 0; i < count; i++) {
- done = children[i].fitSystemWindows(insets);
- if (done) {
+ insets = getChildAt(i).dispatchApplyWindowInsets(insets);
+ if (!insets.hasInsets()) {
break;
}
}
}
- return done;
+ return insets;
}
/**
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
new file mode 100644
index 0000000..cdfcb43
--- /dev/null
+++ b/core/java/android/view/WindowInsets.java
@@ -0,0 +1,278 @@
+/*
+ * 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 android.view;
+
+import android.graphics.Rect;
+
+/**
+ * Describes a set of insets for window content.
+ *
+ * <p>WindowInsets are immutable and may be expanded to include more inset types in the future.
+ * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance
+ * with the adjusted properties.</p>
+ *
+ * @see View.OnApplyWindowInsetsListener
+ * @see View#onApplyWindowInsets(WindowInsets)
+ */
+public class WindowInsets {
+ private Rect mSystemWindowInsets;
+ private Rect mWindowDecorInsets;
+ private Rect mTempRect;
+
+ private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
+
+ /**
+ * Since new insets may be added in the future that existing apps couldn't
+ * know about, this fully empty constant shouldn't be made available to apps
+ * since it would allow them to inadvertently consume unknown insets by returning it.
+ * @hide
+ */
+ public static final WindowInsets EMPTY = new WindowInsets(EMPTY_RECT, EMPTY_RECT);
+
+ /** @hide */
+ public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets) {
+ mSystemWindowInsets = systemWindowInsets;
+ mWindowDecorInsets = windowDecorInsets;
+ }
+
+ /**
+ * Construct a new WindowInsets, copying all values from a source WindowInsets.
+ *
+ * @param src Source to copy insets from
+ */
+ public WindowInsets(WindowInsets src) {
+ mSystemWindowInsets = src.mSystemWindowInsets;
+ mWindowDecorInsets = src.mWindowDecorInsets;
+ }
+
+ /** @hide */
+ public WindowInsets(Rect systemWindowInsets) {
+ mSystemWindowInsets = systemWindowInsets;
+ mWindowDecorInsets = EMPTY_RECT;
+ }
+
+ /**
+ * Used to provide a safe copy of the system window insets to pass through
+ * to the existing fitSystemWindows method and other similar internals.
+ * @hide
+ */
+ public Rect getSystemWindowInsets() {
+ if (mTempRect == null) {
+ mTempRect = new Rect();
+ }
+ mTempRect.set(mSystemWindowInsets);
+ return mTempRect;
+ }
+
+ /**
+ * Returns the left system window inset in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return The left system window inset
+ */
+ public int getSystemWindowInsetLeft() {
+ return mSystemWindowInsets.left;
+ }
+
+ /**
+ * Returns the top system window inset in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return The top system window inset
+ */
+ public int getSystemWindowInsetTop() {
+ return mSystemWindowInsets.top;
+ }
+
+ /**
+ * Returns the right system window inset in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return The right system window inset
+ */
+ public int getSystemWindowInsetRight() {
+ return mSystemWindowInsets.right;
+ }
+
+ /**
+ * Returns the bottom system window inset in pixels.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return The bottom system window inset
+ */
+ public int getSystemWindowInsetBottom() {
+ return mSystemWindowInsets.bottom;
+ }
+
+ /**
+ * Returns the left window decor inset in pixels.
+ *
+ * <p>The window decor inset represents the area of the window content area that is
+ * partially or fully obscured by decorations within the window provided by the framework.
+ * This can include action bars, title bars, toolbars, etc.</p>
+ *
+ * @return The left window decor inset
+ */
+ public int getWindowDecorInsetLeft() {
+ return mWindowDecorInsets.left;
+ }
+
+ /**
+ * Returns the top window decor inset in pixels.
+ *
+ * <p>The window decor inset represents the area of the window content area that is
+ * partially or fully obscured by decorations within the window provided by the framework.
+ * This can include action bars, title bars, toolbars, etc.</p>
+ *
+ * @return The top window decor inset
+ */
+ public int getWindowDecorInsetTop() {
+ return mWindowDecorInsets.top;
+ }
+
+ /**
+ * Returns the right window decor inset in pixels.
+ *
+ * <p>The window decor inset represents the area of the window content area that is
+ * partially or fully obscured by decorations within the window provided by the framework.
+ * This can include action bars, title bars, toolbars, etc.</p>
+ *
+ * @return The right window decor inset
+ */
+ public int getWindowDecorInsetRight() {
+ return mWindowDecorInsets.right;
+ }
+
+ /**
+ * Returns the bottom window decor inset in pixels.
+ *
+ * <p>The window decor inset represents the area of the window content area that is
+ * partially or fully obscured by decorations within the window provided by the framework.
+ * This can include action bars, title bars, toolbars, etc.</p>
+ *
+ * @return The bottom window decor inset
+ */
+ public int getWindowDecorInsetBottom() {
+ return mWindowDecorInsets.bottom;
+ }
+
+ /**
+ * Returns true if this WindowInsets has nonzero system window insets.
+ *
+ * <p>The system window inset represents the area of a full-screen window that is
+ * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+ * </p>
+ *
+ * @return true if any of the system window inset values are nonzero
+ */
+ public boolean hasSystemWindowInsets() {
+ return mSystemWindowInsets.left != 0 || mSystemWindowInsets.top != 0 ||
+ mSystemWindowInsets.right != 0 || mSystemWindowInsets.bottom != 0;
+ }
+
+ /**
+ * Returns true if this WindowInsets has nonzero window decor insets.
+ *
+ * <p>The window decor inset represents the area of the window content area that is
+ * partially or fully obscured by decorations within the window provided by the framework.
+ * This can include action bars, title bars, toolbars, etc.</p>
+ *
+ * @return true if any of the window decor inset values are nonzero
+ */
+ public boolean hasWindowDecorInsets() {
+ return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 ||
+ mWindowDecorInsets.right != 0 || mWindowDecorInsets.bottom != 0;
+ }
+
+ /**
+ * Returns true if this WindowInsets has any nonzero insets.
+ *
+ * @return true if any inset values are nonzero
+ */
+ public boolean hasInsets() {
+ return hasSystemWindowInsets() || hasWindowDecorInsets();
+ }
+
+ public WindowInsets cloneWithSystemWindowInsetsConsumed() {
+ final WindowInsets result = new WindowInsets(this);
+ result.mSystemWindowInsets = new Rect(0, 0, 0, 0);
+ return result;
+ }
+
+ public WindowInsets cloneWithSystemWindowInsetsConsumed(boolean left, boolean top,
+ boolean right, boolean bottom) {
+ if (left || top || right || bottom) {
+ final WindowInsets result = new WindowInsets(this);
+ result.mSystemWindowInsets = new Rect(left ? 0 : mSystemWindowInsets.left,
+ top ? 0 : mSystemWindowInsets.top,
+ right ? 0 : mSystemWindowInsets.right,
+ bottom ? 0 : mSystemWindowInsets.bottom);
+ return result;
+ }
+ return this;
+ }
+
+ public WindowInsets cloneWithSystemWindowInsets(int left, int top, int right, int bottom) {
+ final WindowInsets result = new WindowInsets(this);
+ result.mSystemWindowInsets = new Rect(left, top, right, bottom);
+ return result;
+ }
+
+ public WindowInsets cloneWithWindowDecorInsetsConsumed() {
+ final WindowInsets result = new WindowInsets(this);
+ result.mWindowDecorInsets.set(0, 0, 0, 0);
+ return result;
+ }
+
+ public WindowInsets cloneWithWindowDecorInsetsConsumed(boolean left, boolean top,
+ boolean right, boolean bottom) {
+ if (left || top || right || bottom) {
+ final WindowInsets result = new WindowInsets(this);
+ result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left,
+ top ? 0 : mWindowDecorInsets.top,
+ right ? 0 : mWindowDecorInsets.right,
+ bottom ? 0 : mWindowDecorInsets.bottom);
+ return result;
+ }
+ return this;
+ }
+
+ public WindowInsets cloneWithWindowDecorInsets(int left, int top, int right, int bottom) {
+ final WindowInsets result = new WindowInsets(this);
+ result.mWindowDecorInsets = new Rect(left, top, right, bottom);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets + " windowDecorInsets=" +
+ mWindowDecorInsets + "}";
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index e7e8006f..c22a5e9 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -54,7 +54,7 @@
*/
public class BatteryStatsHelper {
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final String TAG = BatteryStatsHelper.class.getSimpleName();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 21d2e52..82dcbdb 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -45,6 +45,7 @@
import android.util.Printer;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
@@ -77,7 +78,7 @@
*/
public final class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final boolean DEBUG_HISTORY = false;
private static final boolean USE_OLD_HISTORY = false; // for debugging.
@@ -87,7 +88,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 77 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 79 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -178,6 +179,9 @@
boolean mShuttingDown;
+ HashMap<String, SparseBooleanArray>[] mActiveEvents
+ = (HashMap<String, SparseBooleanArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
+
long mHistoryBaseTime;
boolean mHaveBatteryLevel = false;
boolean mRecordingHistory = true;
@@ -1521,15 +1525,25 @@
static final int DELTA_TIME_INT = 0xffffe; // The delta is a following int
static final int DELTA_TIME_ABS = 0xffffd; // Following is an entire abs update.
// Flag in delta int: a new battery level int follows.
- static final int DELTA_BATTERY_LEVEL_FLAG = 0x00400000;
+ static final int DELTA_BATTERY_LEVEL_FLAG = 0x00100000;
// Flag in delta int: a new full state and battery status int follows.
- static final int DELTA_STATE_FLAG = 0x00800000;
+ static final int DELTA_STATE_FLAG = 0x00200000;
// Flag in delta int: contains a wakelock tag.
- static final int DELTA_WAKELOCK_FLAG = 0x01000000;
+ static final int DELTA_WAKELOCK_FLAG = 0x00400000;
// Flag in delta int: contains an event description.
- static final int DELTA_EVENT_FLAG = 0x02000000;
+ static final int DELTA_EVENT_FLAG = 0x00800000;
// These upper bits are the frequently changing state bits.
- static final int DELTA_STATE_MASK = 0xfc000000;
+ static final int DELTA_STATE_MASK = 0xff000000;
+
+ // These are the pieces of battery state that are packed in to the upper bits of
+ // the state int that have been packed in to the first delta int. They must fit
+ // in DELTA_STATE_MASK.
+ static final int STATE_BATTERY_STATUS_MASK = 0x00000007;
+ static final int STATE_BATTERY_STATUS_SHIFT = 29;
+ static final int STATE_BATTERY_HEALTH_MASK = 0x00000007;
+ static final int STATE_BATTERY_HEALTH_SHIFT = 26;
+ static final int STATE_BATTERY_PLUG_MASK = 0x00000003;
+ static final int STATE_BATTERY_PLUG_SHIFT = 24;
public void writeHistoryDelta(Parcel dest, HistoryItem cur, HistoryItem last) {
if (last == null || cur.cmd != HistoryItem.CMD_UPDATE) {
@@ -1620,9 +1634,17 @@
}
private int buildStateInt(HistoryItem h) {
- return ((((int)h.batteryStatus)<<28)&0xf0000000)
- | ((((int)h.batteryHealth)<<24)&0x0f000000)
- | ((((int)h.batteryPlugType)<<22)&0x00c00000)
+ int plugType = 0;
+ if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_AC) != 0) {
+ plugType = 1;
+ } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_USB) != 0) {
+ plugType = 2;
+ } else if ((h.batteryPlugType&BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0) {
+ plugType = 3;
+ }
+ return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
+ | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
+ | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
| (h.states&(~DELTA_STATE_MASK));
}
@@ -1670,9 +1692,23 @@
if ((firstToken&DELTA_STATE_FLAG) != 0) {
int stateInt = src.readInt();
cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
- cur.batteryStatus = (byte)((stateInt>>28)&0xf);
- cur.batteryHealth = (byte)((stateInt>>24)&0xf);
- cur.batteryPlugType = (byte)((stateInt>>22)&0x3);
+ cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
+ & STATE_BATTERY_STATUS_MASK);
+ cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
+ & STATE_BATTERY_HEALTH_MASK);
+ cur.batteryPlugType = (byte)((stateInt>>STATE_BATTERY_PLUG_SHIFT)
+ & STATE_BATTERY_PLUG_MASK);
+ switch (cur.batteryPlugType) {
+ case 1:
+ cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_AC;
+ break;
+ case 2:
+ cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+ break;
+ case 3:
+ cur.batteryPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ break;
+ }
cur.numReadInts += 1;
if (DEBUG) Slog.i(TAG, "READ DELTA: stateToken=0x"
+ Integer.toHexString(stateInt)
@@ -1968,6 +2004,45 @@
public void noteEventLocked(int code, String name, int uid) {
uid = mapUid(uid);
+ if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
+ int idx = code&~HistoryItem.EVENT_FLAG_START;
+ HashMap<String, SparseBooleanArray> active = mActiveEvents[idx];
+ if (active == null) {
+ active = new HashMap<String, SparseBooleanArray>();
+ mActiveEvents[idx] = active;
+ }
+ SparseBooleanArray uids = active.get(name);
+ if (uids == null) {
+ uids = new SparseBooleanArray();
+ active.put(name, uids);
+ }
+ if (uids.get(uid)) {
+ // Already set, nothing to do!
+ return;
+ }
+ uids.put(uid, true);
+ } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
+ int idx = code&~HistoryItem.EVENT_FLAG_FINISH;
+ HashMap<String, SparseBooleanArray> active = mActiveEvents[idx];
+ if (active == null) {
+ // not currently active, nothing to do.
+ return;
+ }
+ SparseBooleanArray uids = active.get(name);
+ if (uids == null) {
+ // not currently active, nothing to do.
+ return;
+ }
+ idx = uids.indexOfKey(uid);
+ if (idx < 0 || !uids.valueAt(idx)) {
+ // not currently active, nothing to do.
+ return;
+ }
+ uids.removeAt(idx);
+ if (uids.size() <= 0) {
+ active.remove(name);
+ }
+ }
addHistoryEventLocked(SystemClock.elapsedRealtime(), code, name, uid);
}
@@ -5125,6 +5200,7 @@
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
}
+ initActiveHistoryEventsLocked(mSecRealtime);
}
private void resetAllStatsLocked() {
@@ -5172,6 +5248,23 @@
clearHistoryLocked();
}
+ private void initActiveHistoryEventsLocked(long nowRealtime) {
+ for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
+ HashMap<String, SparseBooleanArray> active = mActiveEvents[i];
+ if (active == null) {
+ continue;
+ }
+ for (HashMap.Entry<String, SparseBooleanArray> ent : active.entrySet()) {
+ SparseBooleanArray uids = ent.getValue();
+ for (int j=0; j<uids.size(); j++) {
+ if (uids.valueAt(j)) {
+ addHistoryEventLocked(nowRealtime, i, ent.getKey(), uids.keyAt(j));
+ }
+ }
+ }
+ }
+ }
+
void updateDischargeScreenLevelsLocked(boolean oldScreenOn, boolean newScreenOn) {
if (oldScreenOn) {
int diff = mDischargeScreenOnUnplugLevel - mDischargeCurrentLevel;
@@ -5221,12 +5314,14 @@
// battery was last full, or the level is at 100, or
// we have gone through a significant charge (from a very low
// level to a now very high level).
+ boolean reset = false;
if (oldStatus == BatteryManager.BATTERY_STATUS_FULL
|| level >= 90
|| (mDischargeCurrentLevel < 20 && level >= 80)) {
doWrite = true;
resetAllStatsLocked();
mDischargeStartLevel = level;
+ reset = true;
}
pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
@@ -5249,6 +5344,9 @@
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
+ if (reset) {
+ initActiveHistoryEventsLocked(mSecRealtime);
+ }
} else {
pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 5469b63..c957b67 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -20,6 +20,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import com.android.internal.app.ActionBarImpl;
import android.content.Context;
@@ -96,7 +97,7 @@
if (mLastSystemUiVisibility != 0) {
int newVis = mLastSystemUiVisibility;
onWindowSystemUiVisibilityChanged(newVis);
- requestFitSystemWindows();
+ requestApplyInsets();
}
}
}
@@ -152,7 +153,7 @@
}
if ((diff&SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
if (mActionBar != null) {
- requestFitSystemWindows();
+ requestApplyInsets();
}
}
}
@@ -190,19 +191,20 @@
}
@Override
- protected boolean fitSystemWindows(Rect insets) {
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
pullChildren();
final int vis = getWindowSystemUiVisibility();
final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
+ final Rect systemInsets = insets.getSystemWindowInsets();
// The top and bottom action bars are always within the content area.
- boolean changed = applyInsets(mActionBarTop, insets, true, true, false, true);
+ boolean changed = applyInsets(mActionBarTop, systemInsets, true, true, false, true);
if (mActionBarBottom != null) {
- changed |= applyInsets(mActionBarBottom, insets, true, false, true, true);
+ changed |= applyInsets(mActionBarBottom, systemInsets, true, false, true, true);
}
- mBaseInnerInsets.set(insets);
+ mBaseInnerInsets.set(systemInsets);
computeFitSystemWindows(mBaseInnerInsets, mBaseContentInsets);
if (!mLastBaseContentInsets.equals(mBaseContentInsets)) {
changed = true;
@@ -215,9 +217,9 @@
// We don't do any more at this point. To correctly compute the content/inner
// insets in all cases, we need to know the measured size of the various action
- // bar elements. fitSystemWindows() happens before the measure pass, so we can't
+ // bar elements. onApplyWindowInsets() happens before the measure pass, so we can't
// do that here. Instead we will take this up in onMeasure().
- return true;
+ return WindowInsets.EMPTY;
}
@Override
@@ -321,7 +323,7 @@
// the app's fitSystemWindows(). We do this before measuring the content
// view to keep the same semantics as the normal fitSystemWindows() call.
mLastInnerInsets.set(mInnerInsets);
- super.fitSystemWindows(mInnerInsets);
+ mContent.dispatchApplyWindowInsets(new WindowInsets(mInnerInsets));
}
measureChildWithMargins(mContent, widthMeasureSpec, 0, heightMeasureSpec, 0);
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 2cb2812..e98d45b 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -327,9 +327,10 @@
}
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
- SkPath* path, jint op) {
+ jlong pathHandle, jint op) {
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- bool result = canvas->clipPath(*path, static_cast<SkRegion::Op>(op));
+ bool result = canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
+ static_cast<SkRegion::Op>(op));
return result ? JNI_TRUE : JNI_FALSE;
}
@@ -342,9 +343,9 @@
}
static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
- SkDrawFilter* filter) {
+ jlong filterHandle) {
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- canvas->setDrawFilter(filter);
+ canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
}
static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
@@ -356,9 +357,9 @@
}
static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
- SkPath* path) {
+ jlong pathHandle) {
SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- bool result = canvas->quickReject(*path);
+ bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
return result ? JNI_TRUE : JNI_FALSE;
}
diff --git a/core/jni/android_view_DisplayList.cpp b/core/jni/android_view_DisplayList.cpp
index 9379375..5f7912b 100644
--- a/core/jni/android_view_DisplayList.cpp
+++ b/core/jni/android_view_DisplayList.cpp
@@ -117,6 +117,12 @@
displayList->setProjectBackwards(shouldProject);
}
+static void android_view_DisplayList_setProjectionReceiver(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jboolean shouldRecieve) {
+ DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+ displayList->setProjectionReceiver(shouldRecieve);
+}
+
static void android_view_DisplayList_setOutline(JNIEnv* env,
jobject clazz, jlong displayListPtr, jlong outlinePathPtr) {
DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -124,6 +130,12 @@
displayList->setOutline(outline);
}
+static void android_view_DisplayList_setClipToOutline(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jboolean clipToOutline) {
+ DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+ displayList->setClipToOutline(clipToOutline);
+}
+
static void android_view_DisplayList_setAlpha(JNIEnv* env,
jobject clazz, jlong displayListPtr, float alpha) {
DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -391,8 +403,10 @@
{ "nSetAnimationMatrix", "(JJ)V", (void*) android_view_DisplayList_setAnimationMatrix },
{ "nSetClipToBounds", "(JZ)V", (void*) android_view_DisplayList_setClipToBounds },
{ "nSetIsolatedZVolume", "(JZ)V", (void*) android_view_DisplayList_setIsolatedZVolume },
- { "nSetProjectBackwards", "(JZ)V", (void*) android_view_DisplayList_setProjectBackwards },
+ { "nSetProjectBackwards", "(JZ)V", (void*) android_view_DisplayList_setProjectBackwards },
+ { "nSetProjectionReceiver","(JZ)V", (void*) android_view_DisplayList_setProjectionReceiver },
{ "nSetOutline", "(JJ)V", (void*) android_view_DisplayList_setOutline },
+ { "nSetClipToOutline", "(JZ)V", (void*) android_view_DisplayList_setClipToOutline },
{ "nSetAlpha", "(JF)V", (void*) android_view_DisplayList_setAlpha },
{ "nSetHasOverlappingRendering", "(JZ)V",
(void*) android_view_DisplayList_setHasOverlappingRendering },
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 1dc3630..04e51be 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -210,7 +210,7 @@
}
static void android_view_GLES20Canvas_detachFunctor(JNIEnv* env,
- jobject clazz, jlong rendererPtr, jint functorPtr) {
+ jobject clazz, jlong rendererPtr, jlong functorPtr) {
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
Functor* functor = reinterpret_cast<Functor*>(functorPtr);
renderer->detachFunctor(functor);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 8ad973d..6f8292d 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -94,6 +94,11 @@
private static final String ACTION_CHOOSER = "com.android.keychain.CHOOSER";
/**
+ * Package name for the Certificate Installer.
+ */
+ private static final String CERT_INSTALLER_PACKAGE = "com.android.certinstaller";
+
+ /**
* Extra for use with {@link #ACTION_CHOOSER}
* @hide Also used by KeyChainActivity implementation
*/
@@ -201,7 +206,7 @@
*/
public static Intent createInstallIntent() {
Intent intent = new Intent(ACTION_INSTALL);
- intent.setClassName("com.android.certinstaller",
+ intent.setClassName(CERT_INSTALLER_PACKAGE,
"com.android.certinstaller.CertInstallerMain");
return intent;
}
@@ -267,6 +272,7 @@
throw new NullPointerException("response == null");
}
Intent intent = new Intent(ACTION_CHOOSER);
+ intent.setPackage(CERT_INSTALLER_PACKAGE);
intent.putExtra(EXTRA_RESPONSE, new AliasResponse(response));
intent.putExtra(EXTRA_HOST, host);
intent.putExtra(EXTRA_PORT, port);
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index fd3dae7..2a39bd9 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -240,7 +240,9 @@
mClipToBounds = true;
mIsolatedZVolume = true;
mProjectBackwards = false;
+ mProjectionReceiver = false;
mOutline.rewind();
+ mClipToOutline = false;
mAlpha = 1;
mHasOverlappingRendering = true;
mTranslationX = 0;
@@ -299,12 +301,13 @@
void DisplayList::updateMatrix() {
if (mMatrixDirty) {
- if (!mTransformMatrix) {
- mTransformMatrix = new SkMatrix();
- }
- if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
- mTransformMatrix->reset();
- } else {
+ // NOTE: mTransformMatrix won't be up to date if a DisplayList goes from a complex transform
+ // to a pure translate. This is safe because the matrix isn't read in pure translate cases.
+ if (mMatrixFlags && mMatrixFlags != TRANSLATION) {
+ if (!mTransformMatrix) {
+ // only allocate a matrix if we have a complex transform
+ mTransformMatrix = new Matrix4();
+ }
if (!mPivotExplicitlySet) {
if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
mPrevWidth = mWidth;
@@ -313,28 +316,36 @@
mPivotY = mPrevHeight / 2.0f;
}
}
- if (!Caches::getInstance().propertyEnable3d && (mMatrixFlags & ROTATION_3D) == 0) {
- mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
- mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
- mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ const bool perspectiveEnabled = Caches::getInstance().propertyEnable3d;
+ if (!perspectiveEnabled && (mMatrixFlags & ROTATION_3D) == 0) {
+ mTransformMatrix->loadTranslate(
+ mPivotX + mTranslationX,
+ mPivotY + mTranslationY,
+ 0);
+ mTransformMatrix->rotate(mRotation, 0, 0, 1);
+ mTransformMatrix->scale(mScaleX, mScaleY, 1);
+ mTransformMatrix->translate(-mPivotX, -mPivotY);
} else {
- if (Caches::getInstance().propertyEnable3d) {
- mTransform.loadTranslate(mPivotX + mTranslationX, mPivotY + mTranslationY,
+ if (perspectiveEnabled) {
+ mTransformMatrix->loadTranslate(
+ mPivotX + mTranslationX,
+ mPivotY + mTranslationY,
mTranslationZ);
- mTransform.rotate(mRotationX, 1, 0, 0);
- mTransform.rotate(mRotationY, 0, 1, 0);
- mTransform.rotate(mRotation, 0, 0, 1);
- mTransform.scale(mScaleX, mScaleY, 1);
- mTransform.translate(-mPivotX, -mPivotY);
+ mTransformMatrix->rotate(mRotationX, 1, 0, 0);
+ mTransformMatrix->rotate(mRotationY, 0, 1, 0);
+ mTransformMatrix->rotate(mRotation, 0, 0, 1);
+ mTransformMatrix->scale(mScaleX, mScaleY, 1);
+ mTransformMatrix->translate(-mPivotX, -mPivotY);
} else {
/* TODO: support this old transform approach, based on API level */
if (!mTransformCamera) {
mTransformCamera = new Sk3DView();
mTransformMatrix3D = new SkMatrix();
}
- mTransformMatrix->reset();
+ SkMatrix transformMatrix;
+ transformMatrix.reset();
mTransformCamera->save();
- mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
+ transformMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY);
mTransformCamera->rotateX(mRotationX);
mTransformCamera->rotateY(mRotationY);
mTransformCamera->rotateZ(-mRotation);
@@ -342,8 +353,10 @@
mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
mPivotY + mTranslationY);
- mTransformMatrix->postConcat(*mTransformMatrix3D);
+ transformMatrix.postConcat(*mTransformMatrix3D);
mTransformCamera->restore();
+
+ mTransformMatrix->load(transformMatrix);
}
}
}
@@ -357,19 +370,20 @@
ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
}
if (mStaticMatrix) {
- ALOGD("%*sConcatMatrix (static) %p: " MATRIX_STRING,
- level * 2, "", mStaticMatrix, MATRIX_ARGS(mStaticMatrix));
+ ALOGD("%*sConcatMatrix (static) %p: " SK_MATRIX_STRING,
+ level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix));
}
if (mAnimationMatrix) {
- ALOGD("%*sConcatMatrix (animation) %p: " MATRIX_STRING,
- level * 2, "", mAnimationMatrix, MATRIX_ARGS(mAnimationMatrix));
+ ALOGD("%*sConcatMatrix (animation) %p: " SK_MATRIX_STRING,
+ level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix));
}
if (mMatrixFlags != 0) {
if (mMatrixFlags == TRANSLATION) {
- ALOGD("%*sTranslate %f, %f", level * 2, "", mTranslationX, mTranslationY);
+ ALOGD("%*sTranslate %.2f, %.2f, %.2f",
+ level * 2, "", mTranslationX, mTranslationY, mTranslationZ);
} else {
- ALOGD("%*sConcatMatrix %p: " MATRIX_STRING,
- level * 2, "", mTransformMatrix, MATRIX_ARGS(mTransformMatrix));
+ ALOGD("%*sConcatMatrix %p: " MATRIX_4_STRING,
+ level * 2, "", mTransformMatrix, MATRIX_4_ARGS(mTransformMatrix));
}
}
@@ -419,19 +433,11 @@
renderer.concatMatrix(mAnimationMatrix);
}
if (mMatrixFlags != 0) {
- if (Caches::getInstance().propertyEnable3d) {
- if (mMatrixFlags == TRANSLATION) {
- renderer.translate(mTranslationX, mTranslationY, mTranslationZ);
- } else {
- renderer.concatMatrix(mTransform);
- }
+ if (mMatrixFlags == TRANSLATION) {
+ renderer.translate(mTranslationX, mTranslationY,
+ Caches::getInstance().propertyEnable3d ? mTranslationZ : 0.0f); // TODO: necessary?
} else {
- // avoid setting translationZ, use SkMatrix
- if (mMatrixFlags == TRANSLATION) {
- renderer.translate(mTranslationX, mTranslationY, 0);
- } else {
- renderer.concatMatrix(mTransformMatrix);
- }
+ renderer.concatMatrix(*mTransformMatrix);
}
}
bool clipToBoundsNeeded = mCaching ? false : mClipToBounds;
@@ -451,8 +457,7 @@
}
SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
- 0, 0, mRight - mLeft, mBottom - mTop,
- mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags);
+ 0, 0, mRight - mLeft, mBottom - mTop, mAlpha * 255, saveFlags);
handler(op, PROPERTY_SAVECOUNT, mClipToBounds);
}
}
@@ -461,6 +466,10 @@
mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, mClipToBounds);
}
+ if (CC_UNLIKELY(mClipToOutline && !mOutline.isEmpty())) {
+ ClipPathOp* op = new (handler.allocator()) ClipPathOp(&mOutline, SkRegion::kIntersect_Op);
+ handler(op, PROPERTY_SAVECOUNT, mClipToBounds);
+ }
}
/**
@@ -482,12 +491,7 @@
if (mMatrixFlags == TRANSLATION) {
matrix.translate(mTranslationX, mTranslationY, mTranslationZ);
} else {
- if (Caches::getInstance().propertyEnable3d) {
- matrix.multiply(mTransform);
- } else {
- mat4 temp(*mTransformMatrix);
- matrix.multiply(temp);
- }
+ matrix.multiply(*mTransformMatrix);
}
}
}
@@ -524,6 +528,7 @@
const mat4* transformFromProjectionSurface) {
m3dNodes.clear();
mProjectedNodes.clear();
+ if (mDisplayListData == NULL || mSize == 0) return;
// TODO: should avoid this calculation in most cases
// TODO: just calculate single matrix, down to all leaf composited elements
@@ -553,32 +558,46 @@
opState->mSkipInOrderDraw = false;
}
- if (mIsolatedZVolume) {
- // create a new 3d space for descendents by collecting them
- compositedChildrenOf3dRoot = &m3dNodes;
- transformFrom3dRoot = &mat4::identity();
- } else {
- applyViewPropertyTransforms(localTransformFrom3dRoot);
- transformFrom3dRoot = &localTransformFrom3dRoot;
- }
+ if (mDisplayListData->children.size() > 0) {
+ if (mIsolatedZVolume) {
+ // create a new 3d space for descendents by collecting them
+ compositedChildrenOf3dRoot = &m3dNodes;
+ transformFrom3dRoot = &mat4::identity();
+ } else {
+ applyViewPropertyTransforms(localTransformFrom3dRoot);
+ transformFrom3dRoot = &localTransformFrom3dRoot;
+ }
- if (mDisplayListData != NULL && mDisplayListData->projectionIndex >= 0) {
- // create a new projection surface for descendents by collecting them
- compositedChildrenOfProjectionSurface = &mProjectedNodes;
- transformFromProjectionSurface = &mat4::identity();
- } else {
- applyViewPropertyTransforms(localTransformFromProjectionSurface);
- transformFromProjectionSurface = &localTransformFromProjectionSurface;
- }
-
- if (mDisplayListData != NULL && mDisplayListData->children.size() > 0) {
+ const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0;
+ bool haveAppliedPropertiesToProjection = false;
for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
DrawDisplayListOp* childOp = mDisplayListData->children[i];
- childOp->mDisplayList->computeOrderingImpl(childOp,
+ DisplayList* child = childOp->mDisplayList;
+
+ Vector<DrawDisplayListOp*>* projectionChildren = NULL;
+ const mat4* projectionTransform = NULL;
+ if (isProjectionReceiver && !child->mProjectBackwards) {
+ // if receiving projections, collect projecting descendent
+
+ // Note that if a direct descendent is projecting backwards, we pass it's
+ // grandparent projection collection, since it shouldn't project onto it's
+ // parent, where it will already be drawing.
+ projectionChildren = &mProjectedNodes;
+ projectionTransform = &mat4::identity();
+ } else {
+ if (!haveAppliedPropertiesToProjection) {
+ applyViewPropertyTransforms(localTransformFromProjectionSurface);
+ haveAppliedPropertiesToProjection = true;
+ }
+ projectionChildren = compositedChildrenOfProjectionSurface;
+ projectionTransform = &localTransformFromProjectionSurface;
+ }
+ child->computeOrderingImpl(childOp,
compositedChildrenOf3dRoot, transformFrom3dRoot,
- compositedChildrenOfProjectionSurface, transformFromProjectionSurface);
+ projectionChildren, projectionTransform);
}
}
+
}
class DeferOperationHandler {
@@ -638,11 +657,11 @@
return;
}
+ int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
LinearAllocator& alloc = handler.allocator();
ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight,
SkRegion::kIntersect_Op); // clip to 3d root bounds for now
handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds);
- int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
for (size_t i = 0; i < m3dNodes.size(); i++) {
const float zValue = m3dNodes[i].key;
@@ -677,18 +696,22 @@
template <class T>
void DisplayList::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level) {
+ int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
LinearAllocator& alloc = handler.allocator();
ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight,
SkRegion::kReplace_Op); // clip to projection surface root bounds
handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds);
- int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
for (size_t i = 0; i < mProjectedNodes.size(); i++) {
DrawDisplayListOp* childOp = mProjectedNodes[i];
+
+ // matrix save, concat, and restore can be done safely without allocating operations
+ int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
renderer.concatMatrix(childOp->mTransformFromCompositingAncestor);
childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone
handler(childOp, renderer.getSaveCount() - 1, mClipToBounds);
childOp->mSkipInOrderDraw = true;
+ renderer.restoreToCount(restoreTo);
}
handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, mClipToBounds);
}
@@ -740,7 +763,7 @@
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
const int saveCountOffset = renderer.getSaveCount() - 1;
- const int projectionIndex = mDisplayListData->projectionIndex;
+ const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
DisplayListOp *op = mDisplayListData->displayListOps[i];
@@ -751,7 +774,7 @@
logBuffer.writeCommand(level, op->name());
handler(op, saveCountOffset, mClipToBounds);
- if (CC_UNLIKELY(i == projectionIndex && mProjectedNodes.size() > 0)) {
+ if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
iterateProjectedChildren(renderer, handler, level);
}
}
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 8622d61..42a4e74 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -112,7 +112,7 @@
*/
class DisplayListData : public LightRefBase<DisplayListData> {
public:
- DisplayListData() : projectionIndex(-1) {}
+ DisplayListData() : projectionReceiveIndex(-1) {}
// allocator into which all ops were allocated
LinearAllocator allocator;
@@ -123,8 +123,7 @@
Vector<DrawDisplayListOp*> children;
// index of DisplayListOp restore, after which projected descendents should be drawn
- int projectionIndex;
- Matrix4 projectionTransform;
+ int projectionReceiveIndex;
};
/**
@@ -198,6 +197,14 @@
mProjectBackwards = shouldProject;
}
+ void setProjectionReceiver(bool shouldRecieve) {
+ mProjectionReceiver = shouldRecieve;
+ }
+
+ bool isProjectionReceiver() {
+ return mProjectionReceiver;
+ }
+
void setOutline(const SkPath* outline) {
if (!outline) {
mOutline.reset();
@@ -206,6 +213,10 @@
}
}
+ void setClipToOutline(bool clipToOutline) {
+ mClipToOutline = clipToOutline;
+ }
+
void setStaticMatrix(SkMatrix* matrix) {
delete mStaticMatrix;
mStaticMatrix = new SkMatrix(*matrix);
@@ -600,7 +611,9 @@
bool mClipToBounds;
bool mIsolatedZVolume;
bool mProjectBackwards;
+ bool mProjectionReceiver;
SkPath mOutline;
+ bool mClipToOutline;
float mAlpha;
bool mHasOverlappingRendering;
float mTranslationX, mTranslationY, mTranslationZ;
@@ -614,13 +627,20 @@
bool mPivotExplicitlySet;
bool mMatrixDirty;
bool mMatrixIsIdentity;
+
+ /**
+ * Stores the total transformation of the DisplayList based upon its scalar
+ * translate/rotate/scale properties.
+ *
+ * In the common translation-only case, the matrix isn't allocated and the mTranslation
+ * properties are used directly.
+ */
+ Matrix4* mTransformMatrix;
uint32_t mMatrixFlags;
- SkMatrix* mTransformMatrix;
Sk3DView* mTransformCamera;
SkMatrix* mTransformMatrix3D;
SkMatrix* mStaticMatrix;
SkMatrix* mAnimationMatrix;
- Matrix4 mTransform;
bool mCaching;
/**
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 20bc93d..d4f82ea 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -327,9 +327,13 @@
class SaveLayerOp : public StateOp {
public:
- SaveLayerOp(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags)
- : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
+ SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
+ : mArea(left, top, right, bottom), mPaint(&mCachedPaint), mFlags(flags) {
+ mCachedPaint.setAlpha(alpha);
+ }
+
+ SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
+ : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) {
@@ -340,11 +344,11 @@
// NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
// setup the snapshot for deferral, and re-issue the op at flush time
deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
- mAlpha, mMode, mFlags);
+ mPaint, mFlags);
}
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
+ renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mPaint, mFlags);
}
virtual void output(int level, uint32_t logFlags) const {
@@ -357,21 +361,15 @@
int getFlags() { return mFlags; }
private:
- // Special case, reserved for direct DisplayList usage
- SaveLayerOp() {}
- DisplayListOp* reinit(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags) {
- mArea.set(left, top, right, bottom);
- mAlpha = alpha;
- mMode = mode;
- mFlags = flags;
- return this;
+ bool isSaveLayerAlpha() const {
+ SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
+ int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
+ return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
}
- bool isSaveLayerAlpha() const { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
Rect mArea;
- int mAlpha;
- SkXfermode::Mode mMode;
+ const SkPaint* mPaint;
+ SkPaint mCachedPaint;
int mFlags;
};
@@ -465,7 +463,7 @@
virtual void output(int level, uint32_t logFlags) const {
if (mMatrix) {
- OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
+ OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix));
} else {
OP_LOGS("SetMatrix (reset)");
}
@@ -487,7 +485,7 @@
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
+ OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix));
}
virtual const char* name() { return "ConcatMatrix"; }
@@ -848,7 +846,7 @@
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
+ OP_LOG("Draw bitmap %p matrix " SK_MATRIX_STRING, mBitmap, SK_MATRIX_ARGS(mMatrix));
}
virtual const char* name() { return "DrawBitmapMatrix"; }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index c8a6c2d..7c85297 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -173,17 +173,10 @@
StatefulBaseRenderer::restoreToCount(saveCount);
}
-void DisplayListRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
- bool restoreProjection = removed.flags & Snapshot::kFlagProjectionTarget;
- if (restoreProjection) {
- mDisplayListData->projectionIndex = mDisplayListData->displayListOps.size() - 1;
- mDisplayListData->projectionTransform.load(*currentTransform());
- }
-}
-
int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags) {
- addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, alpha, mode, flags));
+ const SkPaint* paint, int flags) {
+ paint = refPaint(paint);
+ addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
return StatefulBaseRenderer::save(flags);
}
@@ -254,6 +247,9 @@
flags, *currentTransform());
addDrawOp(op);
mDisplayListData->children.push(op);
+ if (displayList->isProjectionReceiver()) {
+ mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1;
+ }
return DrawGlInfo::kStatusDone;
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 1360808..3c14212 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -82,7 +82,7 @@
virtual void restore();
virtual void restoreToCount(int saveCount);
virtual int saveLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags);
+ const SkPaint* paint, int flags);
// Matrix
virtual void translate(float dx, float dy, float dz);
@@ -221,8 +221,6 @@
uint32_t getFunctorCount() const {
return mFunctorCount;
}
-protected:
- virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored);
private:
void insertRestoreToCount();
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 00ca050..5cd79b1 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -26,12 +26,20 @@
namespace android {
namespace uirenderer {
-#define MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
-#define MATRIX_ARGS(m) \
+#define SK_MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
+#define SK_MATRIX_ARGS(m) \
(m)->get(0), (m)->get(1), (m)->get(2), \
(m)->get(3), (m)->get(4), (m)->get(5), \
(m)->get(6), (m)->get(7), (m)->get(8)
+#define MATRIX_4_STRING "[%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]" \
+ " [%.2f %.2f %.2f %.2f] [%.2f %.2f %.2f %.2f]"
+#define MATRIX_4_ARGS(m) \
+ (m)->data[0], (m)->data[4], (m)->data[8], (m)->data[12], \
+ (m)->data[1], (m)->data[5], (m)->data[9], (m)->data[13], \
+ (m)->data[2], (m)->data[6], (m)->data[10], (m)->data[14], \
+ (m)->data[3], (m)->data[7], (m)->data[11], (m)->data[15] \
+
///////////////////////////////////////////////////////////////////////////////
// Classes
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b710825..4b947a6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -731,11 +731,11 @@
///////////////////////////////////////////////////////////////////////////////
int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags) {
+ const SkPaint* paint, int flags) {
const int count = saveSnapshot(flags);
if (!currentSnapshot()->isIgnored()) {
- createLayer(left, top, right, bottom, alpha, mode, flags);
+ createLayer(left, top, right, bottom, paint, flags);
}
return count;
@@ -786,7 +786,7 @@
}
int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags) {
+ const SkPaint* paint, int flags) {
const int count = saveSnapshot(flags);
if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
@@ -797,7 +797,7 @@
Rect bounds(left, top, right, bottom);
Rect clip;
calculateLayerBoundsAndClip(bounds, clip, true);
- updateSnapshotIgnoreForLayer(bounds, clip, true, alpha);
+ updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint));
if (!currentSnapshot()->isIgnored()) {
mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
@@ -862,12 +862,15 @@
* something actually gets drawn are the layers regions cleared.
*/
bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags) {
+ const SkPaint* paint, int flags) {
LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
+ SkXfermode::Mode mode = getXfermodeDirect(paint);
+ int alpha = getAlphaDirect(paint);
+
// Window coordinates of the layer
Rect clip;
Rect bounds(left, top, right, bottom);
@@ -889,6 +892,7 @@
layer->layer.set(bounds);
layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
bounds.getWidth() / float(layer->getWidth()), 0.0f);
+
layer->setColorFilter(mDrawModifiers.mColorFilter);
layer->setBlend(true);
layer->setDirty(false);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index c8ecdda..131681e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -154,21 +154,11 @@
ANDROID_API void clearLayerUpdates();
ANDROID_API void flushLayerUpdates();
- ANDROID_API int saveLayer(float left, float top, float right, float bottom,
- SkPaint* paint, int flags) {
- SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
- if (paint) mode = getXfermode(paint->getXfermode());
- return saveLayer(left, top, right, bottom, paint ? paint->getAlpha() : 255, mode, flags);
- }
- ANDROID_API int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, int flags) {
- return saveLayer(left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
- }
- virtual int saveLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags);
+ ANDROID_API virtual int saveLayer(float left, float top, float right, float bottom,
+ const SkPaint* paint, int flags);
int saveLayerDeferred(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags);
+ const SkPaint* paint, int flags);
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t replayFlags = 1);
virtual status_t drawLayer(Layer* layer, float x, float y);
@@ -538,7 +528,7 @@
* @return True if the layer was successfully created, false otherwise
*/
bool createLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags);
+ const SkPaint* paint, int flags);
/**
* Creates a new layer stored in the specified snapshot as an FBO.
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 4799b32..058548a 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -146,22 +146,15 @@
virtual void restore() = 0;
virtual void restoreToCount(int saveCount) = 0;
- int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, int flags) {
- SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
- int alpha = 255;
- if (paint) {
- mode = getXfermode(paint->getXfermode());
- alpha = paint->getAlpha();
- }
- return saveLayer(left, top, right, bottom, alpha, mode, flags);
- }
+ virtual int saveLayer(float left, float top, float right, float bottom,
+ const SkPaint* paint, int flags) = 0;
+
int saveLayerAlpha(float left, float top, float right, float bottom,
int alpha, int flags) {
- return saveLayer(left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
+ SkPaint paint;
+ paint.setAlpha(alpha);
+ return saveLayer(left, top, right, bottom, &paint, flags);
}
- virtual int saveLayer(float left, float top, float right, float bottom,
- int alpha, SkXfermode::Mode mode, int flags) = 0;
// Matrix
virtual void getMatrix(SkMatrix* outMatrix) const = 0;
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index a6ec183..d26ee38 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -70,10 +70,6 @@
} else {
region = NULL;
}
-
- if (saveFlags & Snapshot::kFlagProjectionTarget) {
- flags |= Snapshot::kFlagProjectionTarget;
- }
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index d61d972..cc6d0cd 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -75,13 +75,7 @@
* Indicates that this snapshot or an ancestor snapshot is
* an FBO layer.
*/
- kFlagFboTarget = 0x10,
- /**
- * Indicates that the save/restore pair encapsulates a
- * projection target, and that after the restore any projected
- * descendents should be drawn.
- */
- kFlagProjectionTarget = 0x20
+ kFlagFboTarget = 0x10
};
/**
diff --git a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
new file mode 100644
index 0000000..cba7667
--- /dev/null
+++ b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<!-- This is the host view that generally contains two sub views: the widget view
+ and the security view. -->
+<com.android.keyguard.KeyguardSimpleHostView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+ android:id="@+id/keyguard_host_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.keyguard.KeyguardSecurityContainer
+ android:id="@+id/keyguard_security_container"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/keyguard_security_height"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:padding="0dp"
+ android:layout_gravity="center">
+ <com.android.keyguard.KeyguardSecurityViewFlipper
+ android:id="@+id/view_flipper"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:paddingTop="@dimen/keyguard_security_view_margin"
+ android:gravity="center">
+ </com.android.keyguard.KeyguardSecurityViewFlipper>
+ </com.android.keyguard.KeyguardSecurityContainer>
+
+</com.android.keyguard.KeyguardSimpleHostView>
+
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 1548dee..7ac94bd 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -17,15 +17,14 @@
package com.android.keyguard;
import android.nfc.NfcUnlock;
+
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
-import android.app.AlertDialog;
import android.app.SearchManager;
import android.app.admin.DevicePolicyManager;
import android.appwidget.AppWidgetHost;
@@ -39,9 +38,9 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
-import android.graphics.Canvas;
import android.graphics.Rect;
import android.media.RemoteControlClient;
+import android.os.Bundle;
import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
@@ -51,12 +50,9 @@
import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Slog;
-
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManager;
import android.widget.RemoteViews.OnClickHandler;
import java.io.File;
@@ -65,6 +61,8 @@
public class KeyguardHostView extends KeyguardViewBase {
private static final String TAG = "KeyguardHostView";
+ public static boolean DEBUG = KeyguardViewMediator.DEBUG;
+ public static boolean DEBUGXPORT = true; // debug music transport control
// Transport control states.
static final int TRANSPORT_GONE = 0;
@@ -73,13 +71,8 @@
private int mTransportState = TRANSPORT_GONE;
- // Use this to debug all of keyguard
- public static boolean DEBUG = KeyguardViewMediator.DEBUG;
- public static boolean DEBUGXPORT = true; // debug music transport control
-
// Found in KeyguardAppWidgetPickActivity.java
static final int APPWIDGET_HOST_ID = 0x4B455947;
-
private final int MAX_WIDGETS = 5;
private AppWidgetHost mAppWidgetHost;
@@ -89,18 +82,13 @@
private int mAppWidgetToShow;
protected int mFailedAttempts;
- private LockPatternUtils mLockPatternUtils;
private KeyguardViewStateManager mViewStateManager;
private Rect mTempRect = new Rect();
-
private int mDisabledFeatures;
-
private boolean mCameraDisabled;
-
private boolean mSafeModeEnabled;
-
private boolean mUserSetupCompleted;
// User for whom this host view was created. Final because we should never change the
@@ -119,8 +107,6 @@
private Runnable mPostBootCompletedRunnable;
- private OnDismissAction mDismissAction;
-
/*package*/ interface UserSwitcherCallback {
void hideSecurityView(int duration);
void showSecurityView();
@@ -309,27 +295,18 @@
private SlidingChallengeLayout mSlidingChallengeLayout;
private MultiPaneChallengeLayout mMultiPaneChallengeLayout;
- private KeyguardSecurityContainer mSecurityContainer;
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
mTempRect.set(0, 0, 0, 0);
- offsetRectIntoDescendantCoords(mSecurityContainer, mTempRect);
+ offsetRectIntoDescendantCoords(getSecurityContainer(), mTempRect);
ev.offsetLocation(mTempRect.left, mTempRect.top);
- result = mSecurityContainer.dispatchTouchEvent(ev) || result;
+ result = getSecurityContainer().dispatchTouchEvent(ev) || result;
ev.offsetLocation(-mTempRect.left, -mTempRect.top);
return result;
}
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.keyguardDoneDrawing();
- }
- }
-
private int getWidgetPosition(int id) {
final KeyguardWidgetPager appWidgetContainer = mAppWidgetContainer;
final int children = appWidgetContainer.getChildCount();
@@ -347,6 +324,8 @@
@Override
protected void onFinishInflate() {
+ super.onFinishInflate();
+
// Grab instances of and make any necessary changes to the main layouts. Create
// view state manager and wire up necessary listeners / callbacks.
View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
@@ -372,49 +351,7 @@
mViewStateManager.setPagedView(mAppWidgetContainer);
mViewStateManager.setChallengeLayout(challenge);
- mSecurityContainer =
- (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
- mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
- mSecurityContainer.setSecurityCallback(new SecurityCallback() {
- @Override
- public void userActivity(long timeout) {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.userActivity(timeout);
- }
- }
-
- @Override
- public void dismiss(boolean authenticated) {
- KeyguardHostView.this.dismiss(authenticated);
- }
-
- @Override
- public void finish() {
-
- // If the alternate unlock was suppressed, it can now be safely
- // enabled because the user has left keyguard.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
-
- // If there's a pending runnable because the user interacted with a widget
- // and we're leaving keyguard, then run it.
- boolean deferKeyguardDone = false;
- if (mDismissAction != null) {
- deferKeyguardDone = mDismissAction.onDismiss();
- mDismissAction = null;
- }
- if (mViewMediatorCallback != null) {
- if (deferKeyguardDone) {
- mViewMediatorCallback.keyguardDonePending();
- } else {
- mViewMediatorCallback.keyguardDone(true);
- }
- }
- }
- });
-
- mViewStateManager.setSecurityViewContainer(mSecurityContainer);
-
- setBackButtonEnabled(false);
+ mViewStateManager.setSecurityViewContainer(getSecurityContainer());
if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
updateAndAddWidgets();
@@ -429,8 +366,7 @@
};
}
- mSecurityContainer.showPrimarySecurityScreen(false);
- mSecurityContainer.updateSecurityViews(mViewStateManager.isBouncing());
+ getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
enableUserSelectorIfNecessary();
}
@@ -459,17 +395,37 @@
}
}
- private void setBackButtonEnabled(boolean enabled) {
- if (mContext instanceof Activity) return; // always enabled in activity mode
- setSystemUiVisibility(enabled ?
- getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
- getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
- }
-
private boolean shouldEnableAddWidget() {
return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
}
+ @Override
+ public boolean dismiss(boolean authenticated) {
+ boolean finished = super.dismiss(authenticated);
+ if (!finished) {
+ mViewStateManager.showBouncer(true);
+
+ // Enter full screen mode if we're in SIM or Account screen
+ SecurityMode securityMode = getSecurityContainer().getSecurityMode();
+ boolean isFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
+ boolean isSimOrAccount = securityMode == SecurityMode.SimPin
+ || securityMode == SecurityMode.SimPuk
+ || securityMode == SecurityMode.Account;
+ mAppWidgetContainer.setVisibility(
+ isSimOrAccount && isFullScreen ? View.GONE : View.VISIBLE);
+
+ // Don't show camera or search in navbar when SIM or Account screen is showing
+ setSystemUiVisibility(isSimOrAccount ?
+ (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
+ : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
+
+ if (mSlidingChallengeLayout != null) {
+ mSlidingChallengeLayout.setChallengeInteractive(!isFullScreen);
+ }
+ }
+ return finished;
+ }
+
private int getDisabledFeatures(DevicePolicyManager dpm) {
int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
if (dpm != null) {
@@ -492,10 +448,10 @@
|| (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0;
}
- void setLockPatternUtils(LockPatternUtils utils) {
- mLockPatternUtils = utils;
- mSecurityContainer.setLockPatternUtils(utils);
- mSecurityContainer.updateSecurityViews(mViewStateManager.isBouncing());
+ @Override
+ protected void setLockPatternUtils(LockPatternUtils utils) {
+ super.setLockPatternUtils(utils);
+ getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
}
@Override
@@ -554,7 +510,8 @@
}
};
- public void initializeSwitchingUserState(boolean switching) {
+ @Override
+ public void onUserSwitching(boolean switching) {
if (!switching && mKeyguardMultiUserSelectorView != null) {
mKeyguardMultiUserSelectorView.finalizeActiveUserView(false);
}
@@ -582,8 +539,6 @@
return -1;
}
-
-
private static class MyOnClickHandler extends OnClickHandler {
// weak reference to the hostView to avoid keeping a live reference
@@ -641,75 +596,31 @@
@Override
public void onScreenTurnedOn() {
- if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
- mSecurityContainer.showPrimarySecurityScreen(false);
- mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
-
- // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
- // layout is blank but forcing a layout causes it to reappear (e.g. with with
- // hierarchyviewer).
- requestLayout();
-
+ super.onScreenTurnedOn();
if (mViewStateManager != null) {
mViewStateManager.showUsabilityHints();
}
-
- requestFocus();
}
@Override
public void onScreenTurnedOff() {
- if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
- Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
- // Once the screen turns off, we no longer consider this to be first boot and we want the
- // biometric unlock to start next time keyguard is shown.
- KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+ super.onScreenTurnedOff();
// We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
// turns off we reset that behavior
clearAppWidgetToShow();
if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
checkAppWidgetConsistency();
}
- mSecurityContainer.showPrimarySecurityScreen(true);
- mSecurityContainer.onPause();
CameraWidgetFrame cameraPage = findCameraPage();
if (cameraPage != null) {
cameraPage.onScreenTurnedOff();
}
-
- clearFocus();
}
public void clearAppWidgetToShow() {
mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
}
- @Override
- public void show() {
- if (DEBUG) Log.d(TAG, "show()");
- mSecurityContainer.showPrimarySecurityScreen(false);
- }
-
- @Override
- public void verifyUnlock() {
- SecurityMode securityMode = mSecurityContainer.getSecurityMode();
- if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.keyguardDone(true);
- }
- } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
- && securityMode != KeyguardSecurityModel.SecurityMode.PIN
- && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
- // can only verify unlock when in pattern/password mode
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.keyguardDone(false);
- }
- } else {
- // otherwise, go to the unlock screen, see if they can verify it
- mSecurityContainer.verifyUnlock();
- }
- }
-
private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
if (appWidgetInfo != null) {
@@ -757,28 +668,6 @@
}
};
- private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
- @Override
- Context getContext() {
- return mContext;
- }
-
- @Override
- void setOnDismissAction(OnDismissAction action) {
- mDismissAction = action;
- }
-
- @Override
- LockPatternUtils getLockPatternUtils() {
- return mLockPatternUtils;
- }
-
- @Override
- void requestDismissKeyguard() {
- KeyguardHostView.this.dismiss(false);
- }
- };
-
private int numWidgets() {
final int childCount = mAppWidgetContainer.getChildCount();
int widgetCount = 0;
@@ -800,7 +689,7 @@
@Override
public void onClick(View v) {
// Pass in an invalid widget id... the picker will allocate an ID for us
- mActivityLauncher.launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
+ getActivityLauncher().launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
}
});
}
@@ -810,8 +699,8 @@
// inflate system-provided camera?
if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
&& mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
- View cameraWidget =
- CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
+ View cameraWidget = CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks,
+ getActivityLauncher());
if (cameraWidget != null) {
mAppWidgetContainer.addWidget(cameraWidget);
}
@@ -1198,18 +1087,18 @@
UserSwitcherCallback callback = new UserSwitcherCallback() {
@Override
public void hideSecurityView(int duration) {
- mSecurityContainer.animate().alpha(0).setDuration(duration);
+ getSecurityContainer().animate().alpha(0).setDuration(duration);
}
@Override
public void showSecurityView() {
- mSecurityContainer.setAlpha(1.0f);
+ getSecurityContainer().setAlpha(1.0f);
}
@Override
public void showUnlockHint() {
- if (mSecurityContainer != null) {
- mSecurityContainer.showUsabilityHint();
+ if (getSecurityContainer() != null) {
+ getSecurityContainer().showUsabilityHint();
}
}
@@ -1244,124 +1133,31 @@
}
}
- /**
- * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
- * some cases where we wish to disable it, notably when the menu button placement or technology
- * is prone to false positives.
- *
- * @return true if the menu key should be enabled
- */
- private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
- private boolean shouldEnableMenuKey() {
- final Resources res = getResources();
- final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
- final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
- final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
- return !configDisabled || isTestHarness || fileOverride;
- }
-
public void goToWidget(int appWidgetId) {
mAppWidgetToShow = appWidgetId;
mSwitchPageRunnable.run();
}
- public boolean handleMenuKey() {
- // The following enables the MENU key to work for testing automation
- if (shouldEnableMenuKey()) {
- dismiss();
- return true;
- }
- return false;
+ @Override
+ protected void showBouncer(boolean show) {
+ super.showBouncer(show);
+ mViewStateManager.showBouncer(show);
}
- public boolean handleBackKey() {
- if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
- // go back to primary screen and re-disable back
- setBackButtonEnabled(false);
- mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
- return true;
- }
- if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
- mSecurityContainer.dismiss(false);
- return true;
- }
- return false;
- }
-
- /**
- * Dismisses the keyguard by going to the next screen or making it gone.
- */
- public void dismiss() {
- dismiss(false);
- }
-
- private void dismiss(boolean authenticated) {
- boolean finished = mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
- if (!finished) {
- updateAfterSecuritySelection();
- mViewStateManager.showBouncer(true);
- }
- }
-
- void setOnDismissAction(OnDismissAction action) {
- mDismissAction = action;
- }
-
- public void announceCurrentSecurityMethod() {
- mSecurityContainer.announceCurrentSecurityMethod();
- }
-
- private void updateAfterSecuritySelection() {
- // Enable or disable the back button based on security mode
- if (mSecurityContainer.getSecurityMode() == SecurityMode.Account
- && !mLockPatternUtils.isPermanentlyLocked()) {
- // we're showing account as a backup, provide a way to get back to primary
- setBackButtonEnabled(true);
- }
-
- // Enter full screen mode if we're in SIM or Account screen
- SecurityMode securityMode = mSecurityContainer.getSecurityMode();
- boolean isFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
- boolean isSimOrAccount = securityMode == SecurityMode.SimPin
- || securityMode == SecurityMode.SimPuk
- || securityMode == SecurityMode.Account;
- mAppWidgetContainer.setVisibility(
- isSimOrAccount && isFullScreen ? View.GONE : View.VISIBLE);
-
- // Don't show camera or search in navbar when SIM or Account screen is showing
- setSystemUiVisibility(isSimOrAccount ?
- (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
- : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
-
- if (mSlidingChallengeLayout != null) {
- mSlidingChallengeLayout.setChallengeInteractive(!isFullScreen);
- }
-
- if (mViewMediatorCallback != null) {
- mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
- }
- }
-
- public void showAssistant() {
- final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
-
- if (intent == null) return;
-
- final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
- getHandler(), null);
-
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mActivityLauncher.launchActivityWithAnimation(intent, false, opts.toBundle(), null, null);
- }
-
- public void dispatch(MotionEvent event) {
+ @Override
+ public void onExternalMotionEvent(MotionEvent event) {
mAppWidgetContainer.handleExternalCameraEvent(event);
}
- public void launchCamera() {
- mActivityLauncher.launchCamera(getHandler(), null);
+ @Override
+ protected void onCreateOptions(Bundle options) {
+ if (options != null) {
+ int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
+ AppWidgetManager.INVALID_APPWIDGET_ID);
+ if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
+ goToWidget(widgetToShow);
+ }
+ }
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index ea92b64..0f62100 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -44,8 +44,9 @@
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
- public void dismiss(boolean authenticated);
+ public boolean dismiss(boolean authenticated);
public void userActivity(long timeout);
+ public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
public void finish();
}
@@ -293,18 +294,12 @@
showSecurityScreen(backup);
}
- private boolean showNextSecurityScreenIfPresent() {
- SecurityMode securityMode = mSecurityModel.getSecurityMode();
- // Allow an alternate, such as biometric unlock
- securityMode = mSecurityModel.getAlternateFor(securityMode);
- if (SecurityMode.None == securityMode) {
- return false;
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- return true;
- }
- }
-
+ /**
+ * Shows the next security screen if there is one.
+ * @param authenticated true if the user entered the correct authentication
+ * @param authenticated
+ * @return true if keyguard is done
+ */
boolean showNextSecurityScreenOrFinish(boolean authenticated) {
if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
boolean finish = false;
@@ -386,6 +381,7 @@
}
mCurrentSecuritySelection = securityMode;
+ mSecurityCallback.onSecurityModeChanged(securityMode, newView.needsInput());
}
private KeyguardSecurityViewFlipper getFlipper() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 4129e33..9f5768a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -105,7 +105,7 @@
break;
default:
- throw new IllegalStateException("Unknown unlock mode:" + mode);
+ throw new IllegalStateException("Unknown security quality:" + security);
}
}
return mode;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
new file mode 100644
index 0000000..cf983cb
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
@@ -0,0 +1,70 @@
+/*
+ * 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.keyguard;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+public class KeyguardSimpleHostView extends KeyguardViewBase {
+
+ public KeyguardSimpleHostView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void showBouncer(boolean show) {
+ super.showBouncer(show);
+ if (show) {
+ getSecurityContainer().showBouncer(250);
+ } else {
+ getSecurityContainer().hideBouncer(250);
+ }
+ }
+
+ @Override
+ public void verifyUnlock() {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public void cleanUp() {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public long getUserActivityTimeout() {
+ return -1; // not used
+ }
+
+ @Override
+ protected void onUserSwitching(boolean switching) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ protected void onCreateOptions(Bundle options) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ protected void onExternalMotionEvent(MotionEvent event) {
+ // TODO Auto-generated method stub
+ }
+
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index bff1f93..78f4506 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -17,18 +17,36 @@
package com.android.keyguard;
import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.SearchManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Canvas;
import android.media.AudioManager;
import android.media.IAudioService;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
import android.widget.FrameLayout;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
+import java.io.File;
+
/**
* Base class for keyguard view. {@link #reset} is where you should
* reset the state of your view. Use the {@link KeyguardViewCallback} via
@@ -38,16 +56,22 @@
* Handles intercepting of media keys that still work when the keyguard is
* showing.
*/
-public abstract class KeyguardViewBase extends FrameLayout {
+public abstract class KeyguardViewBase extends FrameLayout implements SecurityCallback {
private AudioManager mAudioManager;
private TelephonyManager mTelephonyManager = null;
protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+ protected LockPatternUtils mLockPatternUtils;
+ private OnDismissAction mDismissAction;
// Whether the volume keys should be handled by keyguard. If true, then
// they will be handled here for specific media types such as music, otherwise
// the audio service will bring up the volume dialog.
private static final boolean KEYGUARD_MANAGES_VOLUME = true;
+ private static final boolean DEBUG = false;
+ private static final String TAG = "KeyguardViewBase";
+
+ private KeyguardSecurityContainer mSecurityContainer;
public KeyguardViewBase(Context context) {
this(context, null);
@@ -57,20 +81,181 @@
super(context, attrs);
}
- /**
- * Called when the screen turned off.
- */
- abstract public void onScreenTurnedOff();
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDoneDrawing();
+ }
+ }
/**
- * Called when the screen turned on.
+ * Sets an action to run when keyguard finishes.
+ *
+ * @param action
*/
- abstract public void onScreenTurnedOn();
+ public void setOnDismissAction(OnDismissAction action) {
+ mDismissAction = action;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mSecurityContainer =
+ (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
+ mLockPatternUtils = new LockPatternUtils(mContext);
+ mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
+ mSecurityContainer.setSecurityCallback(this);
+ mSecurityContainer.showPrimarySecurityScreen(false);
+ // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
+ setBackButtonEnabled(false);
+ }
/**
* Called when the view needs to be shown.
*/
- abstract public void show();
+ public void show() {
+ if (DEBUG) Log.d(TAG, "show()");
+ mSecurityContainer.showPrimarySecurityScreen(false);
+ }
+
+ /**
+ * Dismisses the keyguard by going to the next screen or making it gone.
+ */
+ public void dismiss() {
+ dismiss(false);
+ }
+
+ private void setBackButtonEnabled(boolean enabled) {
+ setSystemUiVisibility(enabled ?
+ getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
+ getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
+ }
+
+ protected void showBouncer(boolean show) {
+ CharSequence what = getContext().getResources().getText(
+ show ? R.string.keyguard_accessibility_show_bouncer
+ : R.string.keyguard_accessibility_hide_bouncer);
+ announceForAccessibility(what);
+ announceCurrentSecurityMethod();
+ }
+
+ public boolean handleBackKey() {
+ if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
+ // go back to primary screen and re-disable back
+ setBackButtonEnabled(false);
+ mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
+ return true;
+ }
+ if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
+ mSecurityContainer.dismiss(false);
+ return true;
+ }
+ return false;
+ }
+
+ protected void announceCurrentSecurityMethod() {
+ mSecurityContainer.announceCurrentSecurityMethod();
+ }
+
+ protected KeyguardSecurityContainer getSecurityContainer() {
+ return mSecurityContainer;
+ }
+
+ /**
+ * Extend display timeout
+ * @param timeout duration to delay timeout, in ms.
+ */
+ @Override
+ public void userActivity(long timeout) {
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.userActivity(timeout);
+ }
+ }
+
+ @Override
+ public boolean dismiss(boolean authenticated) {
+ return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
+ }
+
+ /**
+ * Authentication has happened and it's time to dismiss keyguard. This function
+ * should clean up and inform KeyguardViewMediator.
+ */
+ @Override
+ public void finish() {
+ // If the alternate unlock was suppressed, it can now be safely
+ // enabled because the user has left keyguard.
+ KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+
+ // If there's a pending runnable because the user interacted with a widget
+ // and we're leaving keyguard, then run it.
+ boolean deferKeyguardDone = false;
+ if (mDismissAction != null) {
+ deferKeyguardDone = mDismissAction.onDismiss();
+ mDismissAction = null;
+ }
+ if (mViewMediatorCallback != null) {
+ if (deferKeyguardDone) {
+ mViewMediatorCallback.keyguardDonePending();
+ } else {
+ mViewMediatorCallback.keyguardDone(true);
+ }
+ }
+ }
+
+ @Override
+ public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
+ // Enable or disable the back button based on security mode
+ if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
+ // we're showing account as a backup, provide a way to get back to primary
+ setBackButtonEnabled(true);
+ }
+
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.setNeedsInput(needsInput);
+ }
+ }
+
+ public void userActivity() {
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.userActivity();
+ }
+ }
+
+ protected void onUserActivityTimeoutChanged() {
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.onUserActivityTimeoutChanged();
+ }
+ }
+
+ /**
+ * Called when the screen turned off.
+ */
+ protected void onScreenTurnedOff() {
+ if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
+ Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+ // Once the screen turns off, we no longer consider this to be first boot and we want the
+ // biometric unlock to start next time keyguard is shown.
+ KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+ mSecurityContainer.showPrimarySecurityScreen(true);
+ mSecurityContainer.onPause();
+ clearFocus();
+ }
+
+ /**
+ * Called when the screen turned on.
+ */
+ protected void onScreenTurnedOn() {
+ if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
+ mSecurityContainer.showPrimarySecurityScreen(false);
+ mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
+
+ // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
+ // layout is blank but forcing a layout causes it to reappear (e.g. with with
+ // hierarchyviewer).
+ requestLayout();
+ requestFocus();
+ }
/**
* Verify that the user can get past the keyguard securely. This is called,
@@ -79,7 +264,24 @@
*
* The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
*/
- abstract public void verifyUnlock();
+ public void verifyUnlock() {
+ SecurityMode securityMode = mSecurityContainer.getSecurityMode();
+ if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDone(true);
+ }
+ } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
+ && securityMode != KeyguardSecurityModel.SecurityMode.PIN
+ && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
+ // can only verify unlock when in pattern/password mode
+ if (mViewMediatorCallback != null) {
+ mViewMediatorCallback.keyguardDone(false);
+ }
+ } else {
+ // otherwise, go to the unlock screen, see if they can verify it
+ mSecurityContainer.verifyUnlock();
+ }
+ }
/**
* Called before this view is being removed.
@@ -183,7 +385,7 @@
return false;
}
- void handleMediaKeyEvent(KeyEvent keyEvent) {
+ private void handleMediaKeyEvent(KeyEvent keyEvent) {
IAudioService audioService = IAudioService.Stub.asInterface(
ServiceManager.checkService(Context.AUDIO_SERVICE));
if (audioService != null) {
@@ -206,8 +408,91 @@
}
}
+ /**
+ * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
+ * some cases where we wish to disable it, notably when the menu button placement or technology
+ * is prone to false positives.
+ *
+ * @return true if the menu key should be enabled
+ */
+ private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+ private boolean shouldEnableMenuKey() {
+ final Resources res = getResources();
+ final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
+ final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+ final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+ return !configDisabled || isTestHarness || fileOverride;
+ }
+
+ public boolean handleMenuKey() {
+ // The following enables the MENU key to work for testing automation
+ if (shouldEnableMenuKey()) {
+ dismiss();
+ return true;
+ }
+ return false;
+ }
+
public void setViewMediatorCallback(
KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
mViewMediatorCallback = viewMediatorCallback;
+ // Update ViewMediator with the current input method requirements
+ mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
}
+
+ protected KeyguardActivityLauncher getActivityLauncher() {
+ return mActivityLauncher;
+ }
+
+ private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
+ @Override
+ Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ void setOnDismissAction(OnDismissAction action) {
+ KeyguardViewBase.this.setOnDismissAction(action);
+ }
+
+ @Override
+ LockPatternUtils getLockPatternUtils() {
+ return mLockPatternUtils;
+ }
+
+ @Override
+ void requestDismissKeyguard() {
+ KeyguardViewBase.this.dismiss(false);
+ }
+ };
+
+ public void showAssistant() {
+ final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+
+ if (intent == null) return;
+
+ final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
+ getHandler(), null);
+
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mActivityLauncher.launchActivityWithAnimation(intent, false, opts.toBundle(), null, null);
+ }
+
+ public void launchCamera() {
+ mActivityLauncher.launchCamera(getHandler(), null);
+ }
+
+ protected void setLockPatternUtils(LockPatternUtils utils) {
+ mLockPatternUtils = utils;
+ mSecurityContainer.setLockPatternUtils(utils);
+ }
+
+ protected abstract void onUserSwitching(boolean switching);
+
+ protected abstract void onCreateOptions(Bundle options);
+
+ protected abstract void onExternalMotionEvent(MotionEvent event);
+
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
index f2853c8..baf520e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
@@ -18,11 +18,15 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
+
import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.widget.LockPatternUtils;
+import org.xmlpull.v1.XmlPullParser;
+
import android.app.ActivityManager;
import android.appwidget.AppWidgetManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -38,6 +42,7 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.provider.Settings;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -75,7 +80,7 @@
private boolean mNeedsInput = false;
private ViewManagerHost mKeyguardHost;
- private KeyguardHostView mKeyguardView;
+ private KeyguardViewBase mKeyguardView;
private boolean mScreenOn = false;
private LockPatternUtils mLockPatternUtils;
@@ -259,6 +264,7 @@
}
SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
+ private int mCurrentLayout;
private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
Bundle options) {
@@ -306,7 +312,14 @@
if (force || mKeyguardView == null) {
mKeyguardHost.setCustomBackground(null);
mKeyguardHost.removeAllViews();
- inflateKeyguardView(options);
+ int layout = allowNotificationsOnSecureKeyguard()
+ ? R.layout.keyguard_simple_host_view
+ : R.layout.keyguard_host_view;
+ if (mCurrentLayout != layout) {
+ mStateContainer.clear(); // don't restore to the wrong view hierarchy
+ mCurrentLayout = layout;
+ }
+ mKeyguardView = inflateKeyguardView(options, layout);
mKeyguardView.requestFocus();
}
updateUserActivityTimeoutInWindowLayoutParams();
@@ -315,38 +328,24 @@
mKeyguardHost.restoreHierarchyState(mStateContainer);
}
- private void inflateKeyguardView(Bundle options) {
+ private boolean allowNotificationsOnSecureKeyguard() {
+ ContentResolver cr = mContext.getContentResolver();
+ return Settings.Secure.getInt(cr, Settings.Secure.LOCK_SCREEN_ALLOW_NOTIFICATIONS, 0) == 1;
+ }
+
+ private KeyguardViewBase inflateKeyguardView(Bundle options, int layoutId) {
View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
if (v != null) {
mKeyguardHost.removeView(v);
}
final LayoutInflater inflater = LayoutInflater.from(mContext);
- View view = inflater.inflate(R.layout.keyguard_host_view, mKeyguardHost, true);
- mKeyguardView = (KeyguardHostView) view.findViewById(R.id.keyguard_host_view);
- mKeyguardView.setLockPatternUtils(mLockPatternUtils);
- mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
- mKeyguardView.initializeSwitchingUserState(options != null &&
- options.getBoolean(IS_SWITCHING_USER));
-
- // HACK
- // The keyguard view will have set up window flags in onFinishInflate before we set
- // the view mediator callback. Make sure it knows the correct IME state.
- if (mViewMediatorCallback != null) {
- KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById(
- R.id.keyguard_password_view);
-
- if (kpv != null) {
- mViewMediatorCallback.setNeedsInput(kpv.needsInput());
- }
- }
-
- if (options != null) {
- int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
- AppWidgetManager.INVALID_APPWIDGET_ID);
- if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
- mKeyguardView.goToWidget(widgetToShow);
- }
- }
+ View view = inflater.inflate(layoutId, mKeyguardHost, true);
+ KeyguardViewBase keyguard = (KeyguardViewBase) view.findViewById(R.id.keyguard_host_view);
+ keyguard.setLockPatternUtils(mLockPatternUtils);
+ keyguard.setViewMediatorCallback(mViewMediatorCallback);
+ keyguard.onUserSwitching(options != null && options.getBoolean(IS_SWITCHING_USER));
+ keyguard.onCreateOptions(options);
+ return keyguard;
}
public void updateUserActivityTimeout() {
@@ -541,7 +540,7 @@
public void dispatch(MotionEvent event) {
if (mKeyguardView != null) {
- mKeyguardView.dispatch(event);
+ mKeyguardView.onExternalMotionEvent(event);
}
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
index a7b72e2..e47edf3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
@@ -105,11 +105,6 @@
}
public void showBouncer(boolean show) {
- CharSequence what = mKeyguardHostView.getContext().getResources().getText(
- show ? R.string.keyguard_accessibility_show_bouncer
- : R.string.keyguard_accessibility_hide_bouncer);
- mKeyguardHostView.announceForAccessibility(what);
- mKeyguardHostView.announceCurrentSecurityMethod();
mChallengeLayout.showBouncer();
}
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
index f3b894c..1f39aef 100644
--- a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
+++ b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
@@ -15,6 +15,7 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
@@ -27,6 +28,7 @@
android:layout_height="32dp"
android:padding="3dp"
android:layout_gravity="top|center_horizontal"
+ systemui:frameColor="@color/qs_batterymeter_frame_color"
/>
<TextView
style="@style/TextAppearance.QuickSettings.TileView"
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 047570f..734abdc 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -42,7 +42,9 @@
<attr name="decayTime" format="integer" />
<attr name="orientation" />
</declare-styleable>
-
+ <declare-styleable name="BatteryMeterView">
+ <attr name="frameColor" format="color" />
+ </declare-styleable>
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9301618..e525fbb 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -35,6 +35,7 @@
<color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
<color name="batterymeter_charge_color">#FFFFFFFF</color>
<color name="batterymeter_bolt_color">#FFFFFFFF</color>
+ <color name="qs_batterymeter_frame_color">#FF404040</color>
<color name="status_bar_clock_color">#FFFFFFFF</color>
<drawable name="notification_item_background_color">#ff111111</drawable>
<drawable name="notification_item_background_color_pressed">#ff454545</drawable>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index eb2c44a..19d06be 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -178,6 +178,10 @@
super(context, attrs, defStyle);
final Resources res = context.getResources();
+ TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView,
+ defStyle, 0);
+ final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
+ res.getColor(R.color.batterymeter_frame_color));
TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
@@ -189,12 +193,13 @@
}
levels.recycle();
colors.recycle();
+ atts.recycle();
mShowPercent = ENABLE_PERCENT && 0 != Settings.System.getInt(
context.getContentResolver(), "status_bar_show_battery_percent", 0);
mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mFramePaint.setColor(res.getColor(R.color.batterymeter_frame_color));
+ mFramePaint.setColor(frameColor);
mFramePaint.setDither(true);
mFramePaint.setStrokeWidth(0);
mFramePaint.setStyle(Paint.Style.FILL_AND_STROKE);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 17bb3e0..be2df04 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -28,6 +28,7 @@
import android.os.Looper;
import android.os.SystemProperties;
import android.util.ArrayMap;
+import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.TransferPipe;
@@ -595,12 +596,7 @@
break;
}
}
- if (anyForeground != proc.foregroundServices) {
- proc.foregroundServices = anyForeground;
- if (oomAdj) {
- mAm.updateOomAdjLocked();
- }
- }
+ mAm.updateProcessForegroundLocked(proc, anyForeground, oomAdj);
}
private boolean updateServiceClientActivitiesLocked(ProcessRecord proc,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a0de8d8..8975d12 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -921,11 +921,25 @@
long mLowRamTimeSinceLastIdle = 0;
/**
- * If RAM is currently low, when that horrible situatin started.
+ * If RAM is currently low, when that horrible situation started.
*/
long mLowRamStartTime = 0;
/**
+ * For reporting to battery stats the current top application.
+ */
+ private String mCurResumedPackage = null;
+ private int mCurResumedUid = -1;
+
+ /**
+ * For reporting to battery stats the apps currently running foreground
+ * service. The ProcessMap is package/uid tuples; each of these contain
+ * an array of the currently foreground processes.
+ */
+ final ProcessMap<ArrayList<ProcessRecord>> mForegroundPackages
+ = new ProcessMap<ArrayList<ProcessRecord>>();
+
+ /**
* This is set if we had to do a delayed dexopt of an app before launching
* it, to increasing the ANR timeouts in that case.
*/
@@ -2767,7 +2781,7 @@
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
- mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_STARTED,
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_START,
app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);
@@ -4727,7 +4741,7 @@
mPidsSelfLocked.remove(pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
- mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISHED,
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISH,
app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
@@ -4772,7 +4786,7 @@
mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
- mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISHED,
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISH,
app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
@@ -4861,7 +4875,7 @@
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
- app.foregroundServices = false;
+ updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
@@ -5564,7 +5578,7 @@
return;
}
pr.forcingToForeground = null;
- pr.foregroundServices = false;
+ updateProcessForegroundLocked(pr, false, false);
}
updateOomAdjLocked();
}
@@ -12115,7 +12129,25 @@
if (!brief) {
if (!isCompact) {
pw.print("Total RAM: "); pw.print(memInfo.getTotalSizeKb());
- pw.println(" kB");
+ pw.print(" kB (status ");
+ switch (mLastMemoryLevel) {
+ case ProcessStats.ADJ_MEM_FACTOR_NORMAL:
+ pw.println("normal)");
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_MODERATE:
+ pw.println("moderate)");
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_LOW:
+ pw.println("low)");
+ break;
+ case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+ pw.println("critical)");
+ break;
+ default:
+ pw.print(mLastMemoryLevel);
+ pw.println(")");
+ break;
+ }
pw.print(" Free RAM: "); pw.print(cachedPss + memInfo.getCachedSizeKb()
+ memInfo.getFreeSizeKb()); pw.print(" kB (");
pw.print(cachedPss); pw.print(" cached pss + ");
@@ -12330,7 +12362,7 @@
app.unlinkDeathRecipient();
app.makeInactive(mProcessStats);
app.forcingToForeground = null;
- app.foregroundServices = false;
+ updateProcessForegroundLocked(app, false, false);
app.foregroundActivities = false;
app.hasShownUi = false;
app.hasAboveClient = false;
@@ -12464,7 +12496,7 @@
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
- mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISHED,
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_PROC_FINISH,
app.processName, app.info.uid);
if (app.isolated) {
mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
@@ -15285,8 +15317,66 @@
reportingProcessState, now);
}
+ final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
+ boolean oomAdj) {
+ if (isForeground != proc.foregroundServices) {
+ proc.foregroundServices = isForeground;
+ ArrayList<ProcessRecord> curProcs = mForegroundPackages.get(proc.info.packageName,
+ proc.info.uid);
+ if (isForeground) {
+ if (curProcs == null) {
+ curProcs = new ArrayList<ProcessRecord>();
+ mForegroundPackages.put(proc.info.packageName, proc.info.uid, curProcs);
+ }
+ if (!curProcs.contains(proc)) {
+ curProcs.add(proc);
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_FOREGROUND_START,
+ proc.info.packageName, proc.info.uid);
+ }
+ } else {
+ if (curProcs != null) {
+ if (curProcs.remove(proc)) {
+ mBatteryStatsService.noteEvent(
+ BatteryStats.HistoryItem.EVENT_FOREGROUND_FINISH,
+ proc.info.packageName, proc.info.uid);
+ if (curProcs.size() <= 0) {
+ mForegroundPackages.remove(proc.info.packageName, proc.info.uid);
+ }
+ }
+ }
+ }
+ if (oomAdj) {
+ updateOomAdjLocked();
+ }
+ }
+ }
+
private final ActivityRecord resumedAppLocked() {
- return mStackSupervisor.resumedAppLocked();
+ ActivityRecord act = mStackSupervisor.resumedAppLocked();
+ String pkg;
+ int uid;
+ if (act != null) {
+ pkg = act.packageName;
+ uid = act.info.applicationInfo.uid;
+ } else {
+ pkg = null;
+ uid = -1;
+ }
+ // Has the UID or resumed package name changed?
+ if (uid != mCurResumedUid || (pkg != mCurResumedPackage
+ && (pkg == null || !pkg.equals(mCurResumedPackage)))) {
+ if (mCurResumedPackage != null) {
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_FINISH,
+ mCurResumedPackage, mCurResumedUid);
+ }
+ mCurResumedPackage = pkg;
+ mCurResumedUid = uid;
+ if (mCurResumedPackage != null) {
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_START,
+ mCurResumedPackage, mCurResumedUid);
+ }
+ }
+ return act;
}
final boolean updateOomAdjLocked(ProcessRecord app) {
diff --git a/tests/HwAccelerationTest/res/layout/projection.xml b/tests/HwAccelerationTest/res/layout/projection.xml
index 564201a..b6e4c5e 100644
--- a/tests/HwAccelerationTest/res/layout/projection.xml
+++ b/tests/HwAccelerationTest/res/layout/projection.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<view class="com.android.test.hwui.ProjectionActivity$ProjecteeLayout"
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
+ android:background="#66ff0000"
tools:context="com.example.projection.ProjectionActivity"
tools:ignore="MergeRootFrame">
<TextView
@@ -33,4 +34,4 @@
android:layout_height="100dp"
android:textSize="50sp"
android:text="TextView"/>
-</view>
\ No newline at end of file
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
index f27652d..208c387 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionActivity.java
@@ -72,33 +72,6 @@
}
}
- public static class ProjecteeLayout extends LinearLayout {
- private final Paint mPaint = new Paint();
- private final RectF mRectF = new RectF();
-
- public ProjecteeLayout(Context context) {
- this(context, null);
- }
-
- public ProjecteeLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ProjecteeLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- canvas.save(0x20); // secret save flag
- mRectF.set(0, 0, getWidth(), getHeight());
- mPaint.setColor(0x5f000000);
- canvas.drawOval(mRectF, mPaint);
- canvas.restore();
- super.dispatchDraw(canvas);
- }
- }
-
static View container;
@Override