diff options
72 files changed, 975 insertions, 363 deletions
diff --git a/api/current.txt b/api/current.txt index 24501f352609..3e11cda0903c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28625,7 +28625,6 @@ package android.telephony { method public int getIconTint(); method public int getMcc(); method public int getMnc(); - method public int getNameSource(); method public java.lang.String getNumber(); method public int getSimSlotIndex(); method public int getSubscriptionId(); @@ -28634,6 +28633,7 @@ package android.telephony { } public class SubscriptionManager { + method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); method public static android.telephony.SubscriptionManager from(android.content.Context); method public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int); method public int getActiveSubscriptionInfoCount(); @@ -28641,8 +28641,9 @@ package android.telephony { method public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int); method public java.util.List<android.telephony.SubscriptionInfo> getActiveSubscriptionInfoList(); method public boolean isNetworkRoaming(int); - method public void registerOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); - method public void unregisterOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener); + field public static final int DATA_ROAMING_DISABLE = 0; // 0x0 + field public static final int DATA_ROAMING_ENABLE = 1; // 0x1 } public static class SubscriptionManager.OnSubscriptionsChangedListener { @@ -28688,9 +28689,9 @@ package android.telephony { method public boolean isVoiceCapable(); method public void listen(android.telephony.PhoneStateListener, int); method public java.lang.String sendEnvelopeWithStatus(java.lang.String); - method public boolean setGlobalPreferredNetworkType(); method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String); method public boolean setOperatorBrandOverride(java.lang.String); + method public boolean setPreferredNetworkTypeToGlobal(); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE"; field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE"; @@ -33332,6 +33333,7 @@ package android.view { method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent); method public boolean dispatchNestedFling(float, float, boolean); method public boolean dispatchNestedPreFling(float, float); + method public boolean dispatchNestedPrePerformAccessibilityAction(int, android.os.Bundle); method public boolean dispatchNestedPreScroll(int, int, int[], int[]); method public boolean dispatchNestedScroll(int, int, int, int, int[]); method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent); @@ -34144,6 +34146,7 @@ package android.view { method protected abstract void onLayout(boolean, int, int, int, int); method public boolean onNestedFling(android.view.View, float, float, boolean); method public boolean onNestedPreFling(android.view.View, float, float); + method public boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle); method public void onNestedPreScroll(android.view.View, int, int, int[]); method public void onNestedScroll(android.view.View, int, int, int, int); method public void onNestedScrollAccepted(android.view.View, android.view.View, int); @@ -34292,6 +34295,7 @@ package android.view { method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int); method public abstract boolean onNestedFling(android.view.View, float, float, boolean); method public abstract boolean onNestedPreFling(android.view.View, float, float); + method public abstract boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle); method public abstract void onNestedPreScroll(android.view.View, int, int, int[]); method public abstract void onNestedScroll(android.view.View, int, int, int, int); method public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 121126013bb8..7e15ec2607aa 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -465,20 +465,20 @@ public class DevicePolicyManager { = "android.app.action.SET_NEW_PASSWORD"; /** - * Flag used by {@link #addCrossProfileIntentFilter} to allow access - * <em>from</em> a managed profile <em>to</em> its parent. That is, any - * matching activities in the parent profile are included in the - * disambiguation list shown when an app in the managed profile calls - * {@link Activity#startActivity(Intent)}. + * Flag used by {@link #addCrossProfileIntentFilter} to allow activities in + * the parent profile to access intents sent from the managed profile. + * That is, when an app in the managed profile calls + * {@link Activity#startActivity(Intent)}, the intent can be resolved by a + * matching activity in the parent profile. */ public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001; /** - * Flag used by {@link #addCrossProfileIntentFilter} to allow access - * <em>from</em> a parent <em>to</em> its managed profile. That is, any - * matching activities in the managed profile are included in the - * disambiguation list shown when an app in the parent profile calls - * {@link Activity#startActivity(Intent)}. + * Flag used by {@link #addCrossProfileIntentFilter} to allow activities in + * the managed profile to access intents sent from the parent profile. + * That is, when an app in the parent profile calls + * {@link Activity#startActivity(Intent)}, the intent can be resolved by a + * matching activity in the managed profile. */ public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002; diff --git a/core/java/android/app/backup/BackupHelperDispatcher.java b/core/java/android/app/backup/BackupHelperDispatcher.java index 5466db561576..681153236967 100644 --- a/core/java/android/app/backup/BackupHelperDispatcher.java +++ b/core/java/android/app/backup/BackupHelperDispatcher.java @@ -50,7 +50,6 @@ public class BackupHelperDispatcher { Header header = new Header(); TreeMap<String,BackupHelper> helpers = (TreeMap<String,BackupHelper>)mHelpers.clone(); FileDescriptor oldStateFD = null; - FileDescriptor newStateFD = newState.getFileDescriptor(); if (oldState != null) { oldStateFD = oldState.getFileDescriptor(); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 5ebbf169ef58..af7ec5eecbd0 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3949,10 +3949,12 @@ public class Intent implements Parcelable, Cloneable { * is: * * <pre class="prettyprint"> - * android-app://{package_id}/{scheme}/{host}/{path}{#Intent;...}</pre> + * android-app://{package_id}[/{scheme}[/{host}[/{path}]]][#Intent;{...}]</pre> * - * <p>In this scheme, only the <code>pacakge_id</code> is required, and all - * other components can be included as desired. Note that this can not be + * <p>In this scheme, only the <code>package_id</code> is required. If you include a host, + * you must also include a scheme; including a path also requires both a host and a scheme. + * The final #Intent; fragment can be used without a scheme, host, or path. + * Note that this can not be * used with intents that have a {@link #setSelector}, since the base intent * will always have an explicit package name.</p> * diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index c0dca0e65d6c..cd45cfb326ac 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -4083,7 +4083,7 @@ public abstract class BatteryStats implements Parcelable { prepareForDumpLocked(); dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA, - "11", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion()); + "12", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion()); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index ffbed940d440..d124a499f66d 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -56,6 +56,7 @@ public class UserManager { /** * Specifies if a user is disallowed from changing Wi-Fi * access points. The default value is <code>false</code>. + * <p/>This restriction has no effect in a managed profile. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -87,8 +88,10 @@ public class UserManager { public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps"; /** - * Specifies if a user is disallowed from toggling location sharing. + * Specifies if a user is disallowed from turning on location sharing. * The default value is <code>false</code>. + * <p/>In a managed profile, location sharing always reflects the primary user's setting, but + * can be overridden and forced off by setting this restriction to true in the managed profile. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -112,6 +115,7 @@ public class UserManager { /** * Specifies if a user is disallowed from configuring bluetooth. * The default value is <code>false</code>. + * <p/>This restriction has no effect in a managed profile. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -144,8 +148,10 @@ public class UserManager { public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; /** - * Specifies if a user is disallowed from removing itself and other - * users. The default value is <code>false</code>. + * When set on the primary user this specifies if the user can remove other users. + * When set on a secondary user, this specifies if the user can remove itself. + * This restriction has no effect on managed profiles. + * The default value is <code>false</code>. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -168,6 +174,7 @@ public class UserManager { /** * Specifies if a user is disallowed from configuring VPN. * The default value is <code>false</code>. + * This restriction has no effect in a managed profile. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -192,6 +199,8 @@ public class UserManager { * Specifies if a user is disallowed from factory resetting * from Settings. This can only be set by device owners and profile owners on the primary user. * The default value is <code>false</code>. + * <p/>This restriction has no effect on secondary users and managed profiles since only the + * primary user can factory reset the device. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -204,6 +213,8 @@ public class UserManager { * Specifies if a user is disallowed from adding new users and * profiles. This can only be set by device owners and profile owners on the primary user. * The default value is <code>false</code>. + * <p/>This restriction has no effect on secondary users and managed profiles since only the + * primary user can add other users. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -227,6 +238,8 @@ public class UserManager { * Specifies if a user is disallowed from configuring cell * broadcasts. This can only be set by device owners and profile owners on the primary user. * The default value is <code>false</code>. + * <p/>This restriction has no effect on secondary users and managed profiles since only the + * primary user can configure cell broadcasts. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -239,6 +252,8 @@ public class UserManager { * Specifies if a user is disallowed from configuring mobile * networks. This can only be set by device owners and profile owners on the primary user. * The default value is <code>false</code>. + * <p/>This restriction has no effect on secondary users and managed profiles since only the + * primary user can configure mobile networks. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -307,6 +322,8 @@ public class UserManager { * Specifies that the user is not allowed to make outgoing * phone calls. Emergency calls are still permitted. * The default value is <code>false</code>. + * <p/>This restriction has no effect on managed profiles since call intents are normally + * forwarded to the primary user. * * <p/>Key for user restrictions. * <p/>Type: Boolean @@ -383,8 +400,10 @@ public class UserManager { * * <p/>Key for application restrictions. * <p/>Type: Boolean - * @see android.app.admin.DevicePolicyManager#setApplicationRestrictions() - * @see android.app.admin.DevicePolicyManager#getApplicationRestrictions() + * @see android.app.admin.DevicePolicyManager#setApplicationRestrictions( + * android.content.ComponentName, String, Bundle) + * @see android.app.admin.DevicePolicyManager#getApplicationRestrictions( + * android.content.ComponentName, String) */ public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending"; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 23792be63652..6a36c269df9a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8159,6 +8159,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Report an accessibility action to this view's parents for delegated processing. + * + * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally + * call this method to delegate an accessibility action to a supporting parent. If the parent + * returns true from its + * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)} + * method this method will return true to signify that the action was consumed.</p> + * + * <p>This method is useful for implementing nested scrolling child views. If + * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action + * a custom view implementation may invoke this method to allow a parent to consume the + * scroll first. If this method returns true the custom view should skip its own scrolling + * behavior.</p> + * + * @param action Accessibility action to delegate + * @param arguments Optional action arguments + * @return true if the action was consumed by a parent + */ + public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) { + for (ViewParent p = getParent(); p != null; p = p.getParent()) { + if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) { + return true; + } + } + return false; + } + + /** * Performs the specified accessibility action on the view. For * possible accessibility actions look at {@link AccessibilityNodeInfo}. * <p> @@ -8168,6 +8196,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * is responsible for handling this call. * </p> * + * <p>The default implementation will delegate + * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and + * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if + * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p> + * * @param action The action to perform. * @param arguments Optional action arguments. * @return Whether the action was performed. @@ -8188,6 +8221,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide Until we've refactored all accessibility delegation methods. */ public boolean performAccessibilityActionInternal(int action, Bundle arguments) { + if (isNestedScrollingEnabled() + && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD + || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) { + if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) { + return true; + } + } + switch (action) { case AccessibilityNodeInfo.ACTION_CLICK: { if (isClickable()) { diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 22c51859ea31..6678ff223b14 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -32,6 +32,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.os.Build; +import android.os.Bundle; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; @@ -2923,6 +2924,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * {@inheritDoc} + * + * <p>Subclasses should always call <code>super.onNestedPrePerformAccessibilityAction</code></p> + * + * @param target The target view dispatching this action + * @param action Action being performed; see + * {@link android.view.accessibility.AccessibilityNodeInfo} + * @param args Optional action arguments + * @return false by default. Subclasses should return true if they handle the event. + */ + @Override + public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) { + return false; + } + + /** + * {@inheritDoc} */ @Override void dispatchDetachedFromWindow() { diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java index 87a37f4739be..035871d87671 100644 --- a/core/java/android/view/ViewParent.java +++ b/core/java/android/view/ViewParent.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Rect; +import android.os.Bundle; import android.view.accessibility.AccessibilityEvent; /** @@ -551,4 +552,23 @@ public interface ViewParent { * @return true if this parent consumed the fling ahead of the target view */ public boolean onNestedPreFling(View target, float velocityX, float velocityY); + + /** + * React to an accessibility action delegated by a target descendant view before the target + * processes it. + * + * <p>This method may be called by a target descendant view if the target wishes to give + * a view in its parent chain a chance to react to the event before normal processing occurs. + * Most commonly this will be a scroll event such as + * {@link android.view.accessibility.AccessibilityNodeInfo#ACTION_SCROLL_FORWARD}. + * A ViewParent that supports acting as a nested scrolling parent should override this + * method and act accordingly to implement scrolling via accesibility systems.</p> + * + * @param target The target view dispatching this action + * @param action Action being performed; see + * {@link android.view.accessibility.AccessibilityNodeInfo} + * @param arguments Optional action arguments + * @return true if the action was consumed by this ViewParent + */ + public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a8bc5c948517..87d9a581feb8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -6417,6 +6417,11 @@ public final class ViewRootImpl implements ViewParent, return false; } + @Override + public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) { + return false; + } + void changeCanvasOpacity(boolean opaque) { Log.d(TAG, "changeCanvasOpacity: opaque=" + opaque); if (mAttachInfo.mHardwareRenderer != null) { diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 55c6cb89c936..3f2f3a53ca21 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -156,7 +156,10 @@ public abstract class Window { public static final String NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME = "android:navigation:background"; - /** The default features enabled */ + /** + * The default features enabled. + * @deprecated use {@link #getDefaultFeatures(android.content.Context)} instead. + */ @Deprecated @SuppressWarnings({"PointlessBitwiseExpression"}) protected static final int DEFAULT_FEATURES = (1 << FEATURE_OPTIONS_PANEL) | @@ -1087,6 +1090,10 @@ public abstract class Window { /** * Sets the window elevation. + * <p> + * Changes to this property take effect immediately and will cause the + * window surface to be recreated. This is an expensive operation and as a + * result, this property should not be animated. * * @param elevation The window elevation. * @see View#setElevation(float) diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 765d196509c5..cc5d45775c26 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5017,9 +5017,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return (int) Math.max(0, mShadowDy + mShadowRadius); } + private int getFudgedPaddingRight() { + // Add sufficient space for cursor and tone marks + int cursorWidth = 2 + (int)mTextPaint.density; // adequate for Material cursors + return Math.max(0, getCompoundPaddingRight() - (cursorWidth - 1)); + } + @Override protected int getRightPaddingOffset() { - return -(getCompoundPaddingRight() - mPaddingRight) + + return -(getFudgedPaddingRight() - mPaddingRight) + (int) Math.max(0, mShadowDx + mShadowRadius); } @@ -5373,13 +5379,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int vspace = mBottom - mTop - compoundPaddingBottom - compoundPaddingTop; final int maxScrollY = mLayout.getHeight() - vspace; - // Add sufficient space for cursor and tone marks - int cursorWidth = 2 + (int)mTextPaint.density; // adequate for Material cursors - int fudgedPaddingRight = Math.max(0, compoundPaddingRight - (cursorWidth - 1)); - float clipLeft = compoundPaddingLeft + scrollX; float clipTop = (scrollY == 0) ? 0 : extendedPaddingTop + scrollY; - float clipRight = right - left - fudgedPaddingRight + scrollX; + float clipRight = right - left - getFudgedPaddingRight() + scrollX; float clipBottom = bottom - top + scrollY - ((scrollY == maxScrollY) ? 0 : extendedPaddingBottom); diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java index 7ad347020923..916f19d53f67 100644 --- a/core/java/com/android/internal/util/StateMachine.java +++ b/core/java/com/android/internal/util/StateMachine.java @@ -25,6 +25,7 @@ import android.util.Log; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -1940,19 +1941,25 @@ public class StateMachine { * @param args */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - pw.println(this.toString()); + // Cannot just invoke pw.println(this.toString()) because if the + // resulting string is to long it won't be displayed. + pw.println(getName() + ":"); + pw.println(" total records=" + getLogRecCount()); + for (int i = 0; i < getLogRecSize(); i++) { + pw.println(" rec[" + i + "]: " + getLogRec(i).toString()); + pw.flush(); + } + pw.println("curState=" + getCurrentState().getName()); } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(getName() + ":\n"); - sb.append(" total records=" + getLogRecCount() + "\n"); - for (int i = 0; i < getLogRecSize(); i++) { - sb.append(" rec[" + i + "]: " + getLogRec(i).toString() + "\n"); - } - sb.append("curState=" + getCurrentState().getName()); - return sb.toString(); + StringWriter sr = new StringWriter(); + PrintWriter pr = new PrintWriter(sr); + dump(null, pr, null); + pr.flush(); + pr.close(); + return sr.toString(); } /** diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index ed7af2f3525a..4e48454250e0 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -20,6 +20,7 @@ package com.android.internal.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; @@ -31,6 +32,8 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AnimationUtils; import android.widget.AbsListView; import android.widget.OverScroller; @@ -367,8 +370,14 @@ public class ResolverDrawerLayout extends ViewGroup { child.offsetTopAndBottom((int) dy); } } + final boolean isCollapsedOld = mCollapseOffset != 0; mCollapseOffset = newPos; mTopOffset += dy; + final boolean isCollapsedNew = newPos != 0; + if (isCollapsedOld != isCollapsedNew) { + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } postInvalidateOnAnimation(); return dy; } @@ -571,6 +580,50 @@ public class ResolverDrawerLayout extends ViewGroup { } @Override + public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) { + if (super.onNestedPrePerformAccessibilityAction(target, action, args)) { + return true; + } + + if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD && mCollapseOffset != 0) { + smoothScrollTo(0, 0); + return true; + } + return false; + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(ResolverDrawerLayout.class.getName()); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(ResolverDrawerLayout.class.getName()); + if (isEnabled()) { + if (mCollapseOffset != 0) { + info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); + info.setScrollable(true); + } + } + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (super.performAccessibilityAction(action, arguments)) { + return true; + } + + if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD && mCollapseOffset != 0) { + smoothScrollTo(0, 0); + return true; + } + return false; + } + + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec); int widthSize = sourceWidth; @@ -615,7 +668,13 @@ public class ResolverDrawerLayout extends ViewGroup { mUncollapsibleHeight = heightUsed - mCollapsibleHeight; if (isLaidOut()) { + final boolean isCollapsedOld = mCollapseOffset != 0; mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight); + final boolean isCollapsedNew = mCollapseOffset != 0; + if (isCollapsedOld != isCollapsedNew) { + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } } else { // Start out collapsed at first unless we restored state for otherwise mCollapseOffset = mOpenOnLayout ? 0 : mCollapsibleHeight; diff --git a/core/res/res/layout-land/date_picker_holo.xml b/core/res/res/layout-land/date_picker_holo.xml index 9a9b8b0ec380..991888c2daf5 100644 --- a/core/res/res/layout-land/date_picker_holo.xml +++ b/core/res/res/layout-land/date_picker_holo.xml @@ -18,12 +18,14 @@ android:layout_width="match_parent" android:layout_height="@dimen/datepicker_view_animator_height" android:gravity="center" - android:orientation="horizontal" > + android:orientation="horizontal" + android:minWidth="@dimen/datepicker_dialog_width" > <include layout="@layout/date_picker_selected_date" android:layout_width="wrap_content" - android:layout_height="match_parent" /> + android:layout_height="match_parent" + android:layout_weight="1" /> <include layout="@layout/date_picker_view_animator" /> diff --git a/core/res/res/layout/date_picker_selected_date.xml b/core/res/res/layout/date_picker_selected_date.xml index d212cb0f23b3..9becb817c12a 100644 --- a/core/res/res/layout/date_picker_selected_date.xml +++ b/core/res/res/layout/date_picker_selected_date.xml @@ -20,22 +20,22 @@ android:layout_width="@dimen/datepicker_component_width" android:layout_height="wrap_content" android:gravity="center" - android:paddingBottom="8dp" android:orientation="vertical"> <TextView android:id="@+id/date_picker_header" - android:layout_width="@dimen/datepicker_component_width" + android:layout_width="match_parent" android:layout_height="@dimen/datepicker_header_height" android:gravity="center" - android:importantForAccessibility="no" - android:layout_marginBottom="8dp" /> + android:importantForAccessibility="no" /> <LinearLayout android:id="@+id/date_picker_month_day_year_layout" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" + android:paddingTop="4dp" + android:paddingBottom="4dp" android:orientation="vertical" android:gravity="center"> @@ -57,8 +57,8 @@ android:id="@+id/date_picker_day" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="-10dip" - android:layout_marginBottom="-10dip" + android:layout_marginTop="-23dp" + android:layout_marginBottom="-20dp" android:duplicateParentState="true" android:gravity="center" /> </LinearLayout> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index ae7698450e5d..02fa128c550e 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -385,12 +385,13 @@ <dimen name="datepicker_month_day_label_text_size">12sp</dimen> <dimen name="datepicker_month_list_item_header_height">48dp</dimen> <dimen name="datepicker_day_number_select_circle_radius">16dp</dimen> - <dimen name="datepicker_view_animator_height">244dp</dimen> + <dimen name="datepicker_view_animator_height">226dp</dimen> <dimen name="datepicker_year_picker_padding_top">8dp</dimen> <dimen name="datepicker_year_label_height">64dp</dimen> <dimen name="datepicker_year_label_text_size">22dp</dimen> - <dimen name="datepicker_component_width">270dp</dimen> + <dimen name="datepicker_component_width">260dp</dimen> + <dimen name="datepicker_dialog_width">520dp</dimen> <dimen name="datepicker_selected_date_day_size">88dp</dimen> <dimen name="datepicker_selected_date_month_size">24dp</dimen> <dimen name="datepicker_selected_date_year_size">24dp</dimen> diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd index adba1cdf4418..05e3133f0223 100644 --- a/docs/html/guide/components/intents-common.jd +++ b/docs/html/guide/components/intents-common.jd @@ -1754,7 +1754,7 @@ public void showStepCount() { </div> <p>To call a taxi, use the -<a href="{@docRoot}com/google/android/gms/actions/ReserveIntents.html#ACTION_RESERVE_TAXI_RESERVATION"><code>ACTION_RESERVE_TAXI_RESERVATION</code></a> +<a href="{@docRoot}reference/com/google/android/gms/actions/ReserveIntents.html#ACTION_RESERVE_TAXI_RESERVATION"><code>ACTION_RESERVE_TAXI_RESERVATION</code></a> action.</p> <p class="note"><strong>Note:</strong> Apps must ask for confirmation from the user @@ -1762,7 +1762,7 @@ before completing the action.</p> <dl> <dt><b>Action</b></dt> - <dd><a href="{@docRoot}com/google/android/gms/actions/ReserveIntents.html#ACTION_RESERVE_TAXI_RESERVATION"><code>ACTION_RESERVE_TAXI_RESERVATION</code></a></dd> + <dd><a href="{@docRoot}reference/com/google/android/gms/actions/ReserveIntents.html#ACTION_RESERVE_TAXI_RESERVATION"><code>ACTION_RESERVE_TAXI_RESERVATION</code></a></dd> <dt><b>Data URI</b></dt> <dd>None</dd> diff --git a/docs/html/training/wearables/notifications/creating.jd b/docs/html/training/wearables/notifications/creating.jd index 542664ba84f6..6f8497a21ec4 100644 --- a/docs/html/training/wearables/notifications/creating.jd +++ b/docs/html/training/wearables/notifications/creating.jd @@ -270,10 +270,10 @@ methods are just two examples of new notification features available with {@link android.support.v4.app.NotificationCompat.WearableExtender#setBackground setBackground()} should have a resolution of 400x400 for non-scrolling backgrounds and 640x400 for backgrounds that support parallax scrolling. Place these bitmap images in the <code>res/drawable-nodpi</code> -directory of your handheld app. Place other non-bitmap resources for wearable notifications, such +directory. Place other non-bitmap resources for wearable notifications, such as those used with the {@link android.support.v4.app.NotificationCompat.WearableExtender#setContentIcon setContentIcon()} -method, in the <code>res/drawable-hdpi</code> directory of your handheld app.</p> +method, in the <code>res/drawable-hdpi</code> directory.</p> <p>If you ever need to read wearable-specific options at a later time, use the corresponding get method for the option. This example calls the diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java index ba1e86c6f5a3..bb1d3cb4e6ee 100644 --- a/graphics/java/android/graphics/drawable/Ripple.java +++ b/graphics/java/android/graphics/drawable/Ripple.java @@ -214,7 +214,7 @@ class Ripple { final boolean canUseHardware = c.isHardwareAccelerated(); if (mCanUseHardware != canUseHardware && mCanUseHardware) { // We've switched from hardware to non-hardware mode. Panic. - cancelHardwareAnimations(false); + cancelHardwareAnimations(true); } mCanUseHardware = canUseHardware; diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java index cc42aacf4266..fae4902d1d3d 100644 --- a/graphics/java/android/graphics/drawable/RippleBackground.java +++ b/graphics/java/android/graphics/drawable/RippleBackground.java @@ -148,7 +148,7 @@ class RippleBackground { final boolean canUseHardware = c.isHardwareAccelerated(); if (mCanUseHardware != canUseHardware && mCanUseHardware) { // We've switched from hardware to non-hardware mode. Panic. - cancelHardwareAnimations(false); + cancelHardwareAnimations(true); } mCanUseHardware = canUseHardware; diff --git a/include/androidfw/BackupHelpers.h b/include/androidfw/BackupHelpers.h index 1bb04a7123a3..0841af60faaa 100644 --- a/include/androidfw/BackupHelpers.h +++ b/include/androidfw/BackupHelpers.h @@ -152,7 +152,7 @@ private: KeyedVector<String8,FileRec> m_files; }; -#define TEST_BACKUP_HELPERS 1 +//#define TEST_BACKUP_HELPERS 1 #if TEST_BACKUP_HELPERS int backup_helper_test_empty(); diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp index 52dce9f7f5c5..33cf8ef6f65c 100644 --- a/libs/androidfw/BackupHelpers.cpp +++ b/libs/androidfw/BackupHelpers.cpp @@ -225,8 +225,6 @@ write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& file_metadata_v1 metadata; char* buf = (char*)malloc(bufsize); - int crc = crc32(0L, Z_NULL, 0); - fileSize = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); @@ -310,8 +308,12 @@ write_update_file(BackupDataWriter* dataStream, const String8& key, char const* } static int -compute_crc32(int fd) -{ +compute_crc32(const char* file, FileRec* out) { + int fd = open(file, O_RDONLY); + if (fd < 0) { + return -1; + } + const int bufsize = 4*1024; int amt; @@ -324,8 +326,11 @@ compute_crc32(int fd) crc = crc32(crc, (Bytef*)buf, amt); } + close(fd); free(buf); - return crc; + + out->s.crc32 = crc; + return NO_ERROR; } int @@ -353,7 +358,8 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD err = stat(file, &st); if (err != 0) { - r.deleted = true; + // not found => treat as deleted + continue; } else { r.deleted = false; r.s.modTime_sec = st.st_mtime; @@ -361,12 +367,17 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD //r.s.modTime_nsec = st.st_mtime_nsec; r.s.mode = st.st_mode; r.s.size = st.st_size; - // we compute the crc32 later down below, when we already have the file open. if (newSnapshot.indexOfKey(key) >= 0) { LOGP("back_up_files key already in use '%s'", key.string()); return -1; } + + // compute the CRC + if (compute_crc32(file, &r) != NO_ERROR) { + ALOGW("Unable to open file %s", file); + continue; + } } newSnapshot.add(key, r); } @@ -374,49 +385,41 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD int n = 0; int N = oldSnapshot.size(); int m = 0; + int M = newSnapshot.size(); - while (n<N && m<fileCount) { + while (n<N && m<M) { const String8& p = oldSnapshot.keyAt(n); const String8& q = newSnapshot.keyAt(m); FileRec& g = newSnapshot.editValueAt(m); int cmp = p.compare(q); - if (g.deleted || cmp < 0) { - // file removed + if (cmp < 0) { + // file present in oldSnapshot, but not present in newSnapshot LOGP("file removed: %s", p.string()); - g.deleted = true; // They didn't mention the file, but we noticed that it's gone. - dataStream->WriteEntityHeader(p, -1); + write_delete_file(dataStream, p); n++; - } - else if (cmp > 0) { + } else if (cmp > 0) { // file added - LOGP("file added: %s", g.file.string()); + LOGP("file added: %s crc=0x%08x", g.file.string(), g.s.crc32); write_update_file(dataStream, q, g.file.string()); m++; - } - else { - // both files exist, check them + } else { + // same file exists in both old and new; check whether to update const FileState& f = oldSnapshot.valueAt(n); - int fd = open(g.file.string(), O_RDONLY); - if (fd < 0) { - // We can't open the file. Don't report it as a delete either. Let the - // server keep the old version. Maybe they'll be able to deal with it - // on restore. - LOGP("Unable to open file %s - skipping", g.file.string()); - } else { - g.s.crc32 = compute_crc32(fd); - - LOGP("%s", q.string()); - LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x", - f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32); - LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x", - g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32); - if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec - || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) { + LOGP("%s", q.string()); + LOGP(" old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x", + f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32); + LOGP(" new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x", + g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32); + if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec + || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) { + int fd = open(g.file.string(), O_RDONLY); + if (fd < 0) { + ALOGE("Unable to read file for backup: %s", g.file.string()); + } else { write_update_file(dataStream, fd, g.s.mode, p, g.file.string()); + close(fd); } - - close(fd); } n++; m++; @@ -425,12 +428,12 @@ back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD // these were deleted while (n<N) { - dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1); + write_delete_file(dataStream, oldSnapshot.keyAt(n)); n++; } // these were added - while (m<fileCount) { + while (m<M) { const String8& q = newSnapshot.keyAt(m); FileRec& g = newSnapshot.editValueAt(m); write_update_file(dataStream, q, g.file.string()); diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 3e4e9653518c..84826b7a3bff 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -284,6 +284,14 @@ bool RenderThread::threadLoop() { mPendingRegistrationFrameCallbacks.clear(); requestVsync(); } + + if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) { + // TODO: Clean this up. This is working around an issue where a combination + // of bad timing and slow drawing can result in dropping a stale vsync + // on the floor (correct!) but fails to schedule to listen for the + // next vsync (oops), so none of the callbacks are run. + requestVsync(); + } } return false; diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 5b6ca2987355..f4c8986b7440 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -1511,9 +1511,11 @@ public class AudioService extends IAudioService.Stub { if (mUseFixedVolume) { return; } - + int streamAlias = mStreamVolumeAlias[streamType]; for (int stream = 0; stream < mStreamStates.length; stream++) { - if (!isStreamAffectedByMute(stream) || stream == streamType) continue; + if (!isStreamAffectedByMute(streamAlias) || streamAlias == mStreamVolumeAlias[stream]) { + continue; + } mStreamStates[stream].mute(cb, state); } } @@ -1526,17 +1528,21 @@ public class AudioService extends IAudioService.Stub { if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { streamType = getActiveStreamType(streamType); } - - if (isStreamAffectedByMute(streamType)) { - if (streamType == AudioSystem.STREAM_MUSIC) { + int streamAlias = mStreamVolumeAlias[streamType]; + if (isStreamAffectedByMute(streamAlias)) { + if (streamAlias == AudioSystem.STREAM_MUSIC) { setSystemAudioMute(state); } - mStreamStates[streamType].mute(cb, state); + for (int stream = 0; stream < mStreamStates.length; stream++) { + if (streamAlias == mStreamVolumeAlias[stream]) { + mStreamStates[stream].mute(cb, state); - Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); - intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state); - sendBroadcastToAll(intent); + Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, stream); + intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state); + sendBroadcastToAll(intent); + } + } } } diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java index 06e8574c9b39..d898555182ee 100644 --- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java +++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java @@ -55,7 +55,7 @@ import java.lang.reflect.Method; public class CaptivePortalLoginActivity extends Activity { private static final String TAG = "CaptivePortalLogin"; - private static final String DEFAULT_SERVER = "clients3.google.com"; + private static final String DEFAULT_SERVER = "connectivitycheck.android.com"; private static final int SOCKET_TIMEOUT_MS = 10000; // Keep this in sync with NetworkMonitor. diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 84bacc33404b..64fb24bb2f3b 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -274,12 +274,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { // Hack level over 9000: Because the subscription id is not yet valid when we see the // first update in handleSimStateChange, we need to force refresh all all SIM states // so the subscription id for them is consistent. + ArrayList<SubscriptionInfo> changedSubscriptions = new ArrayList<>(); for (int i = 0; i < subscriptionInfos.size(); i++) { SubscriptionInfo info = subscriptionInfos.get(i); - refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex()); + boolean changed = refreshSimState(info.getSubscriptionId(), info.getSimSlotIndex()); + if (changed) { + changedSubscriptions.add(info); + } } - for (int i = 0; i < subscriptionInfos.size(); i++) { - SimData data = mSimDatas.get(mSubscriptionInfo.get(i).getSubscriptionId()); + for (int i = 0; i < changedSubscriptions.size(); i++) { + SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId()); for (int j = 0; j < mCallbacks.size(); j++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get(); if (cb != null) { @@ -705,7 +709,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter, null, null); - mSubscriptionManager.registerOnSubscriptionsChangedListener(mSubscriptionListener); + mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); try { ActivityManagerNative.getDefault().registerUserSwitchObserver( new IUserSwitchObserver.Stub() { @@ -1242,7 +1246,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } } - private void refreshSimState(int subId, int slotId) { + /** + * @return true if and only if the state has changed for the specified {@code slotId} + */ + private boolean refreshSimState(int subId, int slotId) { // This is awful. It exists because there are two APIs for getting the SIM status // that don't return the complete set of values and have different types. In Keyguard we @@ -1256,8 +1263,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { } catch(IllegalArgumentException ex) { Log.w(TAG, "Unknown sim state: " + simState); state = State.UNKNOWN; - } - mSimDatas.put(subId, new SimData(state, slotId, subId)); + } + SimData data = mSimDatas.get(subId); + final boolean changed; + if (data == null) { + data = new SimData(state, slotId, subId); + mSimDatas.put(subId, data); + changed = true; // no data yet; force update + } else { + changed = data.simState != state; + data.simState = state; + } + return changed; } public static boolean isSimPinSecure(IccCardConstants.State state) { diff --git a/packages/SystemUI/src/com/android/systemui/EventLogConstants.java b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java new file mode 100644 index 000000000000..c8af2d44ec58 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/EventLogConstants.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui; + +/** + * Constants to be passed as sysui_* eventlog parameters. + */ +public class EventLogConstants { + /** The user swiped up on the lockscreen, unlocking the device. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK = 1; + /** The user swiped down on the lockscreen, going to the full shade. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE = 2; + /** The user tapped in an empty area, causing the unlock hint to be shown. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT = 3; + /** The user swiped inward on the camera icon, launching the camera. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA = 4; + /** The user swiped inward on the dialer icon, launching the dialer. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER = 5; + /** The user tapped the lock, locking the device. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK = 6; + /** The user tapped a notification, needs to tap again to launch. */ + public static final int SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE = 7; +} diff --git a/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags b/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags index 191cba53d489..d2ce94b42e2a 100644 --- a/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags +++ b/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags @@ -9,7 +9,14 @@ option java_package com.android.systemui; 36001 sysui_heads_up_status (key|3),(visible|1) 36002 sysui_fullscreen_notification (key|3) 36003 sysui_heads_up_escalation (key|3) -36004 sysui_status_bar_state (state|1) +# sysui_status_bar_state: Logged whenever the status bar / keyguard state changes +## state: 0: SHADE, 1: KEYGUARD, 2: SHADE_LOCKED +## keyguardShowing: 1: Keyguard shown to the user (or keyguardOccluded) +## keyguardOccluded: 1: Keyguard active, but another activity is occluding it +## bouncerShowing: 1: Bouncer currently shown to the user +## secure: 1: The user has set up a secure unlock method (PIN, password, etc.) +## currentlyInsecure: 1: No secure unlock method set up (!secure), or trusted environment (TrustManager) +36004 sysui_status_bar_state (state|1),(keyguardShowing|1),(keyguardOccluded|1),(bouncerShowing|1),(secure|1),(currentlyInsecure|1) # --------------------------- # PhoneStatusBarView.java @@ -20,6 +27,15 @@ option java_package com.android.systemui; # NotificationPanelView.java # --------------------------- 36020 sysui_notificationpanel_touch (type|1),(x|1),(y|1) +## type: 1: SWIPE_UP_UNLOCK Swiped up to dismiss the lockscreen. +## 2: SWIPE_DOWN_FULL_SHADE Swiped down to enter full shade. +## 3: TAP_UNLOCK_HINT Tapped in empty area, causes unlock hint. +## 4: SWIPE_CAMERA Swiped the camera icon, launches. +## 5: SWIPE_DIALER Swiped the dialer icon, launches. +## 6: TAP_LOCK Tapped the (unlocked) lock icon, locks the device. +## 7: TAP_NOTIFICATION_ACTIVATE Tapped a lockscreen notification, causes "tap again" hint. +## Note: Second tap logged as notification_clicked. +36021 sysui_lockscreen_gesture (type|1),(lengthDp|1),(velocityDp|1) # --------------------------- # SettingsPanelView.java diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 0516768d2d9f..7c725b32c5ce 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -105,10 +105,6 @@ public class ImageWallpaper extends WallpaperService { static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; static final int EGL_OPENGL_ES2_BIT = 4; - // TODO: Not currently used, keeping around until we know we don't need it - @SuppressWarnings({"UnusedDeclaration"}) - private WallpaperObserver mReceiver; - Bitmap mBackground; int mBackgroundWidth = -1, mBackgroundHeight = -1; int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; @@ -151,22 +147,6 @@ public class ImageWallpaper extends WallpaperService { private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; - class WallpaperObserver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (DEBUG) { - Log.d(TAG, "onReceive"); - } - - mLastSurfaceWidth = mLastSurfaceHeight = -1; - mBackground = null; - mBackgroundWidth = -1; - mBackgroundHeight = -1; - mRedrawNeeded = true; - drawFrame(); - } - } - public DrawableEngine() { super(); setFixedSizeAllowed(true); @@ -194,12 +174,6 @@ public class ImageWallpaper extends WallpaperService { super.onCreate(surfaceHolder); - // TODO: Don't need this currently because the wallpaper service - // will restart the image wallpaper whenever the image changes. - //IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); - //mReceiver = new WallpaperObserver(); - //registerReceiver(mReceiver, filter, null, mHandler); - updateSurfaceSize(surfaceHolder); setOffsetNotificationsEnabled(false); @@ -208,9 +182,6 @@ public class ImageWallpaper extends WallpaperService { @Override public void onDestroy() { super.onDestroy(); - if (mReceiver != null) { - unregisterReceiver(mReceiver); - } mBackground = null; mWallpaperManager.forgetLoadedWallpaper(); } @@ -562,7 +533,7 @@ public class ImageWallpaper extends WallpaperService { boolean status = mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); checkEglError(); - finishGL(); + finishGL(texture, program); return status; } @@ -615,21 +586,18 @@ public class ImageWallpaper extends WallpaperService { int program = glCreateProgram(); glAttachShader(program, vertexShader); - checkGlError(); - glAttachShader(program, fragmentShader); - checkGlError(); - glLinkProgram(program); checkGlError(); + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + int[] status = new int[1]; glGetProgramiv(program, GL_LINK_STATUS, status, 0); if (status[0] != GL_TRUE) { String error = glGetProgramInfoLog(program); Log.d(GL_LOG_TAG, "Error while linking program:\n" + error); - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); glDeleteProgram(program); return 0; } @@ -672,7 +640,11 @@ public class ImageWallpaper extends WallpaperService { } } - private void finishGL() { + private void finishGL(int texture, int program) { + int[] textures = new int[1]; + textures[0] = texture; + glDeleteTextures(1, textures, 0); + glDeleteProgram(program); mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); mEgl.eglDestroySurface(mEglDisplay, mEglSurface); mEgl.eglDestroyContext(mEglDisplay, mEglContext); diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java index 10618e00e3c4..4ce2c2bc0de2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java @@ -642,12 +642,13 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta /** Starts the recents activity */ void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, boolean isTopTaskHome) { + RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); + RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy); + if (sInstanceLoadPlan == null) { // Create a new load plan if onPreloadRecents() was never triggered - RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); sInstanceLoadPlan = loader.createLoadPlan(mContext); } - RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome); TaskStack stack = sInstanceLoadPlan.getTaskStack(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index ee631f54f865..0f535db0fd3c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -361,12 +361,11 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // For the non-primary user, ensure that the SystemSericesProxy is initialized + // For the non-primary user, ensure that the SystemServicesProxy and configuration is + // initialized RecentsTaskLoader.initialize(this); - - // Initialize the loader and the configuration - mConfig = RecentsConfiguration.reinitialize(this, - RecentsTaskLoader.getInstance().getSystemServicesProxy()); + SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy(); + mConfig = RecentsConfiguration.reinitialize(this, ssp); // Initialize the widget host (the host id is static and does not change) mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId); @@ -421,9 +420,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView super.onNewIntent(intent); setIntent(intent); - // Reinitialize the configuration - RecentsConfiguration.reinitialize(this, RecentsTaskLoader.getInstance().getSystemServicesProxy()); - // Clear any debug rects if (mDebugOverlay != null) { mDebugOverlay.clear(); @@ -450,6 +446,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView // Update the recent tasks updateRecentsTasks(getIntent()); + + // If this is a new instance from a configuration change, then we have to manually trigger + // the enter animation state + if (mConfig.launchedHasConfigurationChanged) { + onEnterAnimationTriggered(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index 255d64299ef4..81f0cefd8209 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -252,6 +252,8 @@ public class TaskStack { if (group.getTaskCount() == 0) { removeGroup(group); } + // Update the lock-to-app state + t.lockToThisTask = false; if (mCb != null) { // Notify that a task has been removed mCb.onStackTaskRemoved(this, t, null); @@ -480,4 +482,4 @@ public class TaskStack { } return str; } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index ee79242aaa45..427ffe56c705 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -542,7 +542,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV loader.deleteTaskData(t, false); // Remove the old task from activity manager - RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id); + loader.getSystemServicesProxy().removeTask(t.key.id); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java index df475d5ccd03..c9f0260619b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java @@ -126,7 +126,8 @@ public class DragDownHelper implements Gefingerpoken { } return true; case MotionEvent.ACTION_UP: - if (mDraggedFarEnough && mDragDownCallback.onDraggedDown(mStartingChild)) { + if (mDraggedFarEnough && mDragDownCallback.onDraggedDown(mStartingChild, + (int) (y - mInitialTouchY))) { if (mStartingChild == null) { mDragDownCallback.setEmptyDragAmount(0f); } @@ -221,7 +222,7 @@ public class DragDownHelper implements Gefingerpoken { /** * @return true if the interaction is accepted, false if it should be cancelled */ - boolean onDraggedDown(View startingChild); + boolean onDraggedDown(View startingChild, int dragLengthY); void onDragDownReset(); void onThresholdReached(); void onTouchSlopExceeded(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java index 58a2d41372e9..3b8fcccb2dbb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -317,7 +317,7 @@ public class KeyguardAffordanceHelper { animator.addListener(mFlingEndListener); if (!snapBack) { startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable); - mCallback.onAnimationToSideStarted(mTranslation < 0); + mCallback.onAnimationToSideStarted(mTranslation < 0, mTranslation, vel); } else { reset(true); } @@ -461,7 +461,7 @@ public class KeyguardAffordanceHelper { * * @param rightPage Is the page animated to the right page? */ - void onAnimationToSideStarted(boolean rightPage); + void onAnimationToSideStarted(boolean rightPage, float translation, float vel); /** * Notifies the callback the animation to a side page has ended. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 503f588b0987..acf7af91f897 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -47,6 +47,8 @@ import android.widget.TextView; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.EventLogConstants; +import com.android.systemui.EventLogTags; import com.android.systemui.R; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardAffordanceView; @@ -320,6 +322,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private void handleTrustCircleClick() { + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_LOCK, 0 /* lengthDp - N/A */, + 0 /* velocityDp - N/A */); mIndicationController.showTransientIndication( R.string.keyguard_indication_trust_disabled); mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser()); @@ -388,7 +393,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL // TODO: Real icon for facelock. int iconRes = mUnlockMethodCache.isFaceUnlockRunning() ? com.android.internal.R.drawable.ic_account_circle - : mUnlockMethodCache.isMethodInsecure() ? R.drawable.ic_lock_open_24dp + : mUnlockMethodCache.isCurrentlyInsecure() ? R.drawable.ic_lock_open_24dp : R.drawable.ic_lock_24dp; if (mLastUnlockIconRes != iconRes) { Drawable icon = mContext.getDrawable(iconRes); @@ -438,7 +443,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } @Override - public void onMethodSecureChanged(boolean methodSecure) { + public void onUnlockMethodStateChanged() { updateLockIcon(); updateCameraVisibility(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 3292f9be4f19..5bc13211b69b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -212,6 +212,9 @@ public class KeyguardBouncer { return false; } + /** + * WARNING: This method might cause Binder calls. + */ public boolean isSecure() { return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 1b00e5993e96..e30a5c2b50f7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -39,6 +39,8 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.keyguard.KeyguardStatusView; +import com.android.systemui.EventLogTags; +import com.android.systemui.EventLogConstants; import com.android.systemui.R; import com.android.systemui.qs.QSContainer; import com.android.systemui.qs.QSPanel; @@ -1670,13 +1672,20 @@ public class NotificationPanelView extends PanelView implements } @Override - public void onAnimationToSideStarted(boolean rightPage) { + public void onAnimationToSideStarted(boolean rightPage, float translation, float vel) { boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? rightPage : !rightPage; mIsLaunchTransitionRunning = true; mLaunchAnimationEndRunnable = null; + float displayDensity = mStatusBar.getDisplayDensity(); + int lengthDp = Math.abs((int) (translation / displayDensity)); + int velocityDp = Math.abs((int) (vel / displayDensity)); if (start) { + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp); mKeyguardBottomArea.launchPhone(); } else { + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp); mSecureCameraLaunchManager.startSecureCameraLaunch(); } mStatusBar.startLaunchTransitionTimeout(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index a04474364c58..d86cceee1cd7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -32,6 +32,8 @@ import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.FrameLayout; +import com.android.systemui.EventLogConstants; +import com.android.systemui.EventLogTags; import com.android.systemui.R; import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.FlingAnimationUtils; @@ -338,6 +340,15 @@ public abstract class PanelView extends FrameLayout { DozeLog.traceFling(expand, mTouchAboveFalsingThreshold, mStatusBar.isFalsingThresholdNeeded(), mStatusBar.isScreenOnComingFromTouch()); + // Log collapse gesture if on lock screen. + if (!expand && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { + float displayDensity = mStatusBar.getDisplayDensity(); + int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity); + int velocityDp = (int) Math.abs(vel / displayDensity); + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_UP_UNLOCK, + heightDp, velocityDp); + } fling(vel, expand); mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown; if (mUpdateFlingOnLayout) { @@ -941,6 +952,9 @@ public abstract class PanelView extends FrameLayout { switch (mStatusBar.getBarState()) { case StatusBarState.KEYGUARD: if (!mDozingOnDown) { + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_UNLOCK_HINT, + 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); startUnlockHintAnimation(); } return true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index d6647af8d221..140c3ba53925 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -121,6 +121,7 @@ import com.android.keyguard.KeyguardHostView.OnDismissAction; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.BatteryMeterView; import com.android.systemui.DemoMode; +import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; @@ -147,6 +148,7 @@ import com.android.systemui.statusbar.SignalClusterView; import com.android.systemui.statusbar.SpeedBumpView; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; @@ -183,7 +185,7 @@ import java.util.List; import java.util.Map; public class PhoneStatusBar extends BaseStatusBar implements DemoMode, - DragDownHelper.DragDownCallback, ActivityStarter { + DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener { static final String TAG = "PhoneStatusBar"; public static final boolean DEBUG = BaseStatusBar.DEBUG; public static final boolean SPEW = false; @@ -493,6 +495,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private boolean mLaunchTransitionFadingAway; private ExpandableNotificationRow mDraggedDownRow; + // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. + private int mLastLoggedStateFingerprint; + private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD | ViewState.LOCATION_TOP_STACK_PEEKING | ViewState.LOCATION_MAIN_AREA @@ -603,6 +608,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mHeadsUpObserver); } mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); + mUnlockMethodCache.addListener(this); startKeyguard(); mDozeServiceHost = new DozeServiceHost(); @@ -2159,8 +2165,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public boolean isFalsingThresholdNeeded() { boolean onKeyguard = getBarState() == StatusBarState.KEYGUARD; - boolean isMethodInsecure = mUnlockMethodCache.isMethodInsecure(); - return onKeyguard && (isMethodInsecure || mDozing || mScreenOnComingFromTouch); + boolean isCurrentlyInsecure = mUnlockMethodCache.isCurrentlyInsecure(); + return onKeyguard && (isCurrentlyInsecure || mDozing || mScreenOnComingFromTouch); } public boolean isDozing() { @@ -2177,6 +2183,18 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } /** + * To be called when there's a state change in StatusBarKeyguardViewManager. + */ + public void onKeyguardViewManagerStatesUpdated() { + logStateToEventlog(); + } + + @Override // UnlockMethodCache.OnUnlockMethodChangedListener + public void onUnlockMethodStateChanged() { + logStateToEventlog(); + } + + /** * All changes to the status bar and notifications funnel through here and are batched. */ private class H extends BaseStatusBar.H { @@ -3061,6 +3079,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } + float getDisplayDensity() { + return mDisplayMetrics.density; + } + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade) { if (onlyProvisioned && !isDeviceProvisioned()) return; @@ -3348,6 +3370,47 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } + // State logging + + private void logStateToEventlog() { + boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); + boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); + boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); + boolean isSecure = mUnlockMethodCache.isMethodSecure(); + boolean isCurrentlyInsecure = mUnlockMethodCache.isCurrentlyInsecure(); + int stateFingerprint = getLoggingFingerprint(mState, + isShowing, + isOccluded, + isBouncerShowing, + isSecure, + isCurrentlyInsecure); + if (stateFingerprint != mLastLoggedStateFingerprint) { + EventLogTags.writeSysuiStatusBarState(mState, + isShowing ? 1 : 0, + isOccluded ? 1 : 0, + isBouncerShowing ? 1 : 0, + isSecure ? 1 : 0, + isCurrentlyInsecure ? 1 : 0); + mLastLoggedStateFingerprint = stateFingerprint; + } + } + + /** + * Returns a fingerprint of fields logged to eventlog + */ + private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, + boolean keyguardOccluded, boolean bouncerShowing, boolean secure, + boolean currentlyInsecure) { + // Reserve 8 bits for statusBarState. We'll never go higher than + // that, right? Riiiight. + return (statusBarState & 0xFF) + | ((keyguardShowing ? 1 : 0) << 8) + | ((keyguardOccluded ? 1 : 0) << 9) + | ((bouncerShowing ? 1 : 0) << 10) + | ((secure ? 1 : 0) << 11) + | ((currentlyInsecure ? 1 : 0) << 12); + } + // // tracing // @@ -3824,6 +3887,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void onActivated(ActivatableNotificationView view) { + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE, + 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again); ActivatableNotificationView previousView = mStackScroller.getActivatedChild(); if (previousView != null) { @@ -3836,19 +3902,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, * @param state The {@link StatusBarState} to set. */ public void setBarState(int state) { - if (state != mState) { - EventLogTags.writeSysuiStatusBarState(state); - - // If we're visible and switched to SHADE_LOCKED (the user dragged - // down on the lockscreen), clear notification LED, vibration, - // ringing. - // Other transitions are covered in handleVisibleToUserChanged(). - if (mVisible && state == StatusBarState.SHADE_LOCKED) { - try { - mBarService.clearNotificationEffects(); - } catch (RemoteException e) { - // Ignore. - } + // If we're visible and switched to SHADE_LOCKED (the user dragged + // down on the lockscreen), clear notification LED, vibration, + // ringing. + // Other transitions are covered in handleVisibleToUserChanged(). + if (state != mState && mVisible && state == StatusBarState.SHADE_LOCKED) { + try { + mBarService.clearNotificationEffects(); + } catch (RemoteException e) { + // Ignore. } } mState = state; @@ -3890,7 +3952,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void onTrackingStopped(boolean expand) { if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { - if (!expand && !mUnlockMethodCache.isMethodInsecure()) { + if (!expand && !mUnlockMethodCache.isCurrentlyInsecure()) { showBouncer(); } } @@ -3908,8 +3970,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------ @Override - public boolean onDraggedDown(View startingChild) { + public boolean onDraggedDown(View startingChild, int dragLengthY) { if (hasActiveNotifications()) { + EventLogTags.writeSysuiLockscreenGesture( + EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE, + (int) (dragLengthY / mDisplayMetrics.density), + 0 /* velocityDp - N/A */); // We have notifications, go to locked shade. goToLockedShade(startingChild); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index d6bd94b3d978..0e8a7942d1b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -88,7 +88,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { public void onTrackingStarted() { mExpanding = true; - mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure(); + mDarkenWhileDragging = !mUnlockMethodCache.isCurrentlyInsecure(); } public void onExpandingFinished() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index f4edab57fb7b..1724e7087c95 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -303,6 +303,9 @@ public class StatusBarKeyguardViewManager { } } + /** + * WARNING: This method might cause Binder calls. + */ public boolean isSecure() { return mBouncer.isSecure(); } @@ -396,6 +399,8 @@ public class StatusBarKeyguardViewManager { mLastOccluded = occluded; mLastBouncerShowing = bouncerShowing; mLastBouncerDismissible = bouncerDismissible; + + mPhoneStatusBar.onKeyguardViewManagerStatesUpdated(); } public boolean onMenuPressed() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java index e5eef9db7a89..5ef345bd7cbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java @@ -36,7 +36,10 @@ public class UnlockMethodCache { private final LockPatternUtils mLockPatternUtils; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>(); - private boolean mMethodInsecure; + /** Whether the user configured a secure unlock method (PIN, password, etc.) */ + private boolean mSecure; + /** Whether the unlock method is currently insecure (insecure method or trusted environment) */ + private boolean mCurrentlyInsecure; private boolean mTrustManaged; private boolean mFaceUnlockRunning; @@ -44,7 +47,7 @@ public class UnlockMethodCache { mLockPatternUtils = new LockPatternUtils(ctx); mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx); KeyguardUpdateMonitor.getInstance(ctx).registerCallback(mCallback); - updateMethodSecure(true /* updateAlways */); + update(true /* updateAlways */); } public static UnlockMethodCache getInstance(Context context) { @@ -55,10 +58,17 @@ public class UnlockMethodCache { } /** - * @return whether the current security method is secure, i. e. the bouncer will be shown + * @return whether the user configured a secure unlock method like PIN, password, etc. */ - public boolean isMethodInsecure() { - return mMethodInsecure; + public boolean isMethodSecure() { + return mSecure; + } + + /** + * @return whether the lockscreen is currently insecure, i. e. the bouncer won't be shown + */ + public boolean isCurrentlyInsecure() { + return mCurrentlyInsecure; } public void addListener(OnUnlockMethodChangedListener listener) { @@ -69,58 +79,59 @@ public class UnlockMethodCache { mListeners.remove(listener); } - private void updateMethodSecure(boolean updateAlways) { + private void update(boolean updateAlways) { int user = mLockPatternUtils.getCurrentUser(); - boolean methodInsecure = !mLockPatternUtils.isSecure() || - mKeyguardUpdateMonitor.getUserHasTrust(user); + boolean secure = mLockPatternUtils.isSecure(); + boolean currentlyInsecure = !secure || mKeyguardUpdateMonitor.getUserHasTrust(user); boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user); boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user) && trustManaged; - boolean changed = methodInsecure != mMethodInsecure || trustManaged != mTrustManaged - || faceUnlockRunning != mFaceUnlockRunning; + boolean changed = secure != mSecure || currentlyInsecure != mCurrentlyInsecure || + trustManaged != mTrustManaged || faceUnlockRunning != mFaceUnlockRunning; if (changed || updateAlways) { - mMethodInsecure = methodInsecure; + mSecure = secure; + mCurrentlyInsecure = currentlyInsecure; mTrustManaged = trustManaged; mFaceUnlockRunning = faceUnlockRunning; - notifyListeners(mMethodInsecure); + notifyListeners(); } } - private void notifyListeners(boolean secure) { + private void notifyListeners() { for (OnUnlockMethodChangedListener listener : mListeners) { - listener.onMethodSecureChanged(secure); + listener.onUnlockMethodStateChanged(); } } private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() { @Override public void onUserSwitchComplete(int userId) { - updateMethodSecure(false /* updateAlways */); + update(false /* updateAlways */); } @Override public void onTrustChanged(int userId) { - updateMethodSecure(false /* updateAlways */); + update(false /* updateAlways */); } @Override public void onTrustManagedChanged(int userId) { - updateMethodSecure(false /* updateAlways */); + update(false /* updateAlways */); } @Override public void onScreenTurnedOn() { - updateMethodSecure(false /* updateAlways */); + update(false /* updateAlways */); } @Override public void onFingerprintRecognized(int userId) { - updateMethodSecure(false /* updateAlways */); + update(false /* updateAlways */); } @Override public void onFaceUnlockStateChanged(boolean running, int userId) { - updateMethodSecure(false /* updateAlways */); + update(false /* updateAlways */); } }; @@ -133,6 +144,6 @@ public class UnlockMethodCache { } public static interface OnUnlockMethodChangedListener { - void onMethodSecureChanged(boolean methodSecure); + void onUnlockMethodStateChanged(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 3cd0e64ce2c3..6d38d38816a0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -195,7 +195,7 @@ public class NetworkControllerImpl extends BroadcastReceiver for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { mobileSignalController.registerListener(); } - mSubscriptionManager.registerOnSubscriptionsChangedListener(mSubscriptionListener); + mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); // broadcasts IntentFilter filter = new IntentFilter(); @@ -221,7 +221,7 @@ public class NetworkControllerImpl extends BroadcastReceiver for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { mobileSignalController.unregisterListener(); } - mSubscriptionManager.unregisterOnSubscriptionsChangedListener(mSubscriptionListener); + mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionListener); mContext.unregisterReceiver(this); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 30a271e0aa96..1f9867008ba3 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -1338,6 +1338,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { if (mDecor != null) { mDecor.setElevation(elevation); } + dispatchWindowAttributesChanged(getAttributes()); } @Override diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0f8fd05a033f..61a70730c00e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2271,6 +2271,46 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + // Is nai unneeded by all NetworkRequests (and should be disconnected)? + // For validated Networks this is simply whether it is satsifying any NetworkRequests. + // For unvalidated Networks this is whether it is satsifying any NetworkRequests or + // were it to become validated, would it have a chance of satisfying any NetworkRequests. + private boolean unneeded(NetworkAgentInfo nai) { + if (!nai.created || nai.isVPN()) return false; + boolean unneeded = true; + if (nai.everValidated) { + for (int i = 0; i < nai.networkRequests.size() && unneeded; i++) { + final NetworkRequest nr = nai.networkRequests.valueAt(i); + try { + if (isRequest(nr)) unneeded = false; + } catch (Exception e) { + loge("Request " + nr + " not found in mNetworkRequests."); + loge(" it came from request list of " + nai.name()); + } + } + } else { + for (NetworkRequestInfo nri : mNetworkRequests.values()) { + // If this Network is already the highest scoring Network for a request, or if + // there is hope for it to become one if it validated, then it is needed. + if (nri.isRequest && nai.satisfies(nri.request) && + (nai.networkRequests.get(nri.request.requestId) != null || + // Note that this catches two important cases: + // 1. Unvalidated cellular will not be reaped when unvalidated WiFi + // is currently satisfying the request. This is desirable when + // cellular ends up validating but WiFi does not. + // 2. Unvalidated WiFi will not be reaped when validated cellular + // is currently satsifying the request. This is desirable when + // WiFi ends up validating and out scoring cellular. + mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() < + nai.getCurrentScoreAsValidated())) { + unneeded = false; + break; + } + } + } + return unneeded; + } + private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) { NetworkRequestInfo nri = mNetworkRequests.get(request); if (nri != null) { @@ -2292,16 +2332,9 @@ public class ConnectivityService extends IConnectivityManager.Stub ", leaving " + nai.networkRequests.size() + " requests."); } - // check if has any requests remaining and if not, - // disconnect (unless it's a VPN). - boolean keep = nai.isVPN(); - for (int i = 0; i < nai.networkRequests.size() && !keep; i++) { - NetworkRequest r = nai.networkRequests.valueAt(i); - if (isRequest(r)) keep = true; - } - if (!keep) { + if (unneeded(nai)) { if (DBG) log("no live requests for " + nai.name() + "; disconnecting"); - nai.asyncChannel.disconnect(); + teardownUnneededNetwork(nai); } } } @@ -4056,19 +4089,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Linger any networks that are no longer needed. for (NetworkAgentInfo nai : affectedNetworks) { - boolean teardown = !nai.isVPN() && nai.everValidated; - for (int i = 0; i < nai.networkRequests.size() && teardown; i++) { - NetworkRequest nr = nai.networkRequests.valueAt(i); - try { - if (isRequest(nr)) { - teardown = false; - } - } catch (Exception e) { - loge("Request " + nr + " not found in mNetworkRequests."); - loge(" it came from request list of " + nai.name()); - } - } - if (teardown) { + if (nai.everValidated && unneeded(nai)) { nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_LINGER); notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOSING); } else { @@ -4168,27 +4189,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) { for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { - if (!nai.created || nai.everValidated || nai.isVPN()) continue; - boolean reap = true; - for (NetworkRequestInfo nri : mNetworkRequests.values()) { - // If this Network is already the highest scoring Network for a request, or if - // there is hope for it to become one if it validated, then don't reap it. - if (nri.isRequest && nai.satisfies(nri.request) && - (nai.networkRequests.get(nri.request.requestId) != null || - // Note that this catches two important cases: - // 1. Unvalidated cellular will not be reaped when unvalidated WiFi - // is currently satisfying the request. This is desirable when - // cellular ends up validating but WiFi does not. - // 2. Unvalidated WiFi will not be reaped when validated cellular - // is currently satsifying the request. This is desirable when - // WiFi ends up validating and out scoring cellular. - mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() < - nai.getCurrentScoreAsValidated())) { - reap = false; - break; - } - } - if (reap) { + if (!nai.everValidated && unneeded(nai)) { if (DBG) log("Reaping " + nai.name()); teardownUnneededNetwork(nai); } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 72c2eaf15de3..8d7a182d5669 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -338,7 +338,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void registerOnSubscriptionsChangedListener(String pkgForDebug, + public void addOnSubscriptionsChangedListener(String pkgForDebug, IOnSubscriptionsChangedListener callback) { int callerUid = UserHandle.getCallingUserId(); int myUid = UserHandle.myUserId(); @@ -393,7 +393,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void unregisterOnSubscriptionsChangedListener(String pkgForDebug, + public void removeOnSubscriptionsChangedListener(String pkgForDebug, IOnSubscriptionsChangedListener callback) { if (DBG) log("listen oscl: Unregister"); remove(callback.asBinder()); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4b7fb2b28171..b107d9a4d681 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2106,7 +2106,7 @@ public final class ActivityManagerService extends ActivityManagerNative mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations")); mConfiguration.setToDefaults(); - mConfiguration.setLocale(Locale.getDefault()); + mConfiguration.locale = Locale.getDefault(); mConfigurationSeq = mConfiguration.seq = 1; mProcessCpuTracker.init(); @@ -16605,6 +16605,7 @@ public final class ActivityManagerService extends ActivityManagerNative Configuration ci; synchronized(this) { ci = new Configuration(mConfiguration); + ci.userSetLocale = false; } return ci; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 19252ee3956a..b81df9e7338e 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -414,6 +414,12 @@ public final class ActivityStackSupervisor implements DisplayListener { if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: topStack old=" + topStack + " new=" + mFocusedStack); } + if (mService.mBooting || !mService.mBooted) { + final ActivityRecord r = topRunningActivityLocked(); + if (r != null && r.idle) { + checkFinishBootingLocked(); + } + } } void moveHomeStackTaskToTop(int homeStackTaskType) { @@ -2235,6 +2241,24 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + /** + * Called when the frontmost task is idle. + * @return the state of mService.mBooting before this was called. + */ + private boolean checkFinishBootingLocked() { + final boolean booting = mService.mBooting; + boolean enableScreen = false; + mService.mBooting = false; + if (!mService.mBooted) { + mService.mBooted = true; + enableScreen = true; + } + if (booting || enableScreen) { + mService.postFinishBooting(booting, enableScreen); + } + return booting; + } + // Checked. final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) { @@ -2246,7 +2270,6 @@ public final class ActivityStackSupervisor implements DisplayListener { int NS = 0; int NF = 0; boolean booting = false; - boolean enableScreen = false; boolean activityRemoved = false; ActivityRecord r = ActivityRecord.forToken(token); @@ -2274,12 +2297,7 @@ public final class ActivityStackSupervisor implements DisplayListener { //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); if (isFrontStack(r.task.stack) || fromTimeout) { - booting = mService.mBooting; - mService.mBooting = false; - if (!mService.mBooted) { - mService.mBooted = true; - enableScreen = true; - } + booting = checkFinishBootingLocked(); } } @@ -2352,10 +2370,6 @@ public final class ActivityStackSupervisor implements DisplayListener { //dump(); //mWindowManager.dump(); - if (booting || enableScreen) { - mService.postFinishBooting(booting, enableScreen); - } - if (activityRemoved) { resumeTopActivitiesLocked(); } @@ -2624,6 +2638,8 @@ public final class ActivityStackSupervisor implements DisplayListener { // before an application stack is created...Go ahead and create one on the default // display. stack = getStack(createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY)); + // Restore home stack to top. + moveHomeStack(true); if (DEBUG_RECENTS) Slog.v(TAG, "Created stack=" + stack + " for recents restoration."); } diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 9fa362c8776d..af5ed8387721 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -68,7 +68,7 @@ import java.util.Random; public class NetworkMonitor extends StateMachine { private static final boolean DBG = true; private static final String TAG = "NetworkMonitor"; - private static final String DEFAULT_SERVER = "clients3.google.com"; + private static final String DEFAULT_SERVER = "connectivitycheck.android.com"; private static final int SOCKET_TIMEOUT_MS = 10000; public static final String ACTION_NETWORK_CONDITIONS_MEASURED = "android.net.conn.NETWORK_CONDITIONS_MEASURED"; diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index f549f3d3fd2b..6e61e41ade09 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -464,13 +464,13 @@ final class ColorFade { try { SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay( SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), s); + st.updateTexImage(); + st.getTransformMatrix(mTexMatrix); } finally { s.release(); + st.release(); } - st.updateTexImage(); - st.getTransformMatrix(mTexMatrix); - // Set up texture coordinates for a quad. // We might need to change this if the texture ends up being // a different size from the display for some reason. diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 2593e2b522ce..cc8c53c653f2 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -1427,6 +1427,11 @@ public final class HdmiControlService extends SystemService { runOnServiceThread(new Runnable() { @Override public void run() { + HdmiMhlLocalDeviceStub mhlDevice = mMhlController.getLocalDeviceById(deviceId); + if (mhlDevice != null) { + mhlDevice.sendStandby(); + return; + } HdmiCecLocalDevice device = mCecController.getLocalDevice(deviceType); if (device == null) { Slog.w(TAG, "Local device not available"); @@ -1546,6 +1551,12 @@ public final class HdmiControlService extends SystemService { mCecController.dump(pw); pw.decreaseIndent(); } + + pw.println("mMhlController: "); + pw.increaseIndent(); + mMhlController.dump(pw); + pw.decreaseIndent(); + pw.println("mPortInfo: "); pw.increaseIndent(); for (HdmiPortInfo hdmiPortInfo : mPortInfo) { diff --git a/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java b/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java index 708aee6b4c84..3883200308bf 100644 --- a/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java +++ b/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java @@ -19,6 +19,7 @@ package com.android.server.hdmi; import android.hardware.hdmi.HdmiPortInfo; import android.util.SparseArray; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** @@ -135,4 +136,7 @@ final class HdmiMhlControllerStub { int getEcbusDeviceRoles(int portId) { return INVALID_DEVICE_ROLES; } + + void dump(IndentingPrintWriter pw) { + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiMhlLocalDeviceStub.java b/services/core/java/com/android/server/hdmi/HdmiMhlLocalDeviceStub.java index 53a7c5c2e5dc..06ecb5a2c8a0 100644 --- a/services/core/java/com/android/server/hdmi/HdmiMhlLocalDeviceStub.java +++ b/services/core/java/com/android/server/hdmi/HdmiMhlLocalDeviceStub.java @@ -43,4 +43,7 @@ final class HdmiMhlLocalDeviceStub { void sendKeyEvent(int keycode, boolean isPressed) { } + + void sendStandby() { + } } diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 9c0f9874b5bc..bec0e22d446b 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -648,7 +648,7 @@ public class GpsLocationProvider implements LocationProviderInterface { // Register for SubscriptionInfo list changes which is guaranteed // to invoke onSubscriptionsChanged the first time. SubscriptionManager.from(mContext) - .registerOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); + .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); // construct handler, listen for events mHandler = new ProviderHandler(looper); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index b0feca8fadab..f57adaffc2cd 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -379,14 +379,18 @@ class DisplayContent { pw.println(" Application tokens in top down Z order:"); int ndx = 0; for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + final TaskStack stack = mStacks.get(stackNdx); + pw.print(" mStackId="); pw.println(stack.mStackId); + ArrayList<Task> tasks = stack.getTasks(); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { - AppTokenList tokens = tasks.get(taskNdx).mAppTokens; - for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) { + final Task task = tasks.get(taskNdx); + pw.print(" mTaskId="); pw.println(task.taskId); + AppTokenList tokens = task.mAppTokens; + for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx, ++ndx) { final AppWindowToken wtoken = tokens.get(tokenNdx); - pw.print(" App #"); pw.print(ndx++); + pw.print(" Activity #"); pw.print(tokenNdx); pw.print(' '); pw.print(wtoken); pw.println(":"); - wtoken.dump(pw, " "); + wtoken.dump(pw, " "); } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 4d0169d55916..b9a2cbe02c8b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -262,6 +262,8 @@ public class WindowManagerService extends IWindowManager.Stub /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */ static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000; + /** Amount of time to allow a last ANR message to exist before freeing the memory. */ + static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours /** * If true, the window manager will do its own custom freezing and general * management of the screen during rotation. @@ -940,7 +942,7 @@ public class WindowManagerService extends IWindowManager.Stub private void placeWindowAfter(WindowState pos, WindowState window) { final WindowList windows = pos.getWindowList(); final int i = windows.indexOf(pos); - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( + if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( TAG, "Adding window " + window + " at " + (i+1) + " of " + windows.size() + " (after " + pos + ")"); windows.add(i+1, window); @@ -950,7 +952,7 @@ public class WindowManagerService extends IWindowManager.Stub private void placeWindowBefore(WindowState pos, WindowState window) { final WindowList windows = pos.getWindowList(); int i = windows.indexOf(pos); - if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( + if (true || DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v( TAG, "Adding window " + window + " at " + i + " of " + windows.size() + " (before " + pos + ")"); if (i < 0) { @@ -1048,7 +1050,7 @@ public class WindowManagerService extends IWindowManager.Stub //apptoken note that the window could be a floating window //that was created later or a window at the top of the list of //windows associated with this token. - if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, + if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of " + N); windows.add(newIdx + 1, win); @@ -1164,15 +1166,15 @@ public class WindowManagerService extends IWindowManager.Stub // Just search for the start of this layer. final int myLayer = win.mBaseLayer; int i; - for (i = 0; i < N; i++) { + for (i = N - 1; i >= 0; --i) { WindowState w = windows.get(i); - if (w.mBaseLayer > myLayer) { + if (w.mBaseLayer <= myLayer) { break; } } - if (DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, - "Based on layer: Adding window " + win + " at " + i + " of " + N); - windows.add(i, win); + if (true || DEBUG_FOCUS_LIGHT || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, + "Based on layer: Adding window " + win + " at " + (i + 1) + " of " + N); + windows.add(i + 1, win); mWindowsChanged = true; return tokenWindowsPos; } @@ -3657,7 +3659,7 @@ public class WindowManagerService extends IWindowManager.Stub atoken.layoutConfigChanges = (configChanges & (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; atoken.mLaunchTaskBehind = launchTaskBehind; - if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken + if (true || DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken + " to stack=" + stackId + " task=" + taskId + " at " + addPos); Task task = mTaskIdToTask.get(taskId); @@ -5379,7 +5381,12 @@ public class WindowManagerService extends IWindowManager.Stub @Override public boolean isKeyguardSecure() { - return mPolicy.isKeyguardSecure(); + long origId = Binder.clearCallingIdentity(); + try { + return mPolicy.isKeyguardSecure(); + } finally { + Binder.restoreCallingIdentity(origId); + } } @Override @@ -7608,6 +7615,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; + public static final int RESET_ANR_MESSAGE = 38; @Override public void handleMessage(Message msg) { @@ -8118,6 +8126,12 @@ public class WindowManagerService extends IWindowManager.Stub } } break; + case RESET_ANR_MESSAGE: { + synchronized (mWindowMap) { + mLastANRState = null; + } + } + break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG, "handleMessage: exit"); @@ -11299,8 +11313,14 @@ public class WindowManagerService extends IWindowManager.Stub } pw.println(); dumpWindowsNoHeaderLocked(pw, true, null); + pw.println(); + pw.println("Last ANR continued"); + dumpDisplayContentsLocked(pw, true); pw.close(); mLastANRState = sw.toString(); + + mH.removeMessages(H.RESET_ANR_MESSAGE); + mH.sendEmptyMessageDelayed(H.RESET_ANR_MESSAGE, LAST_ANR_LIFETIME_DURATION_MSECS); } @Override diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java index e764cd57f5b8..33bbb295ab24 100644 --- a/telecomm/java/android/telecom/Conference.java +++ b/telecomm/java/android/telecom/Conference.java @@ -32,6 +32,12 @@ import java.util.concurrent.CopyOnWriteArraySet; @SystemApi public abstract class Conference implements IConferenceable { + /** + * Used to indicate that the conference connection time is not specified. If not specified, + * Telecom will set the connect time. + */ + public static long CONNECT_TIME_NOT_SPECIFIED = 0; + /** @hide */ public abstract static class Listener { public void onStateChanged(Conference conference, int oldState, int newState) {} @@ -59,6 +65,7 @@ public abstract class Conference implements IConferenceable { private DisconnectCause mDisconnectCause; private int mConnectionCapabilities; private String mDisconnectMessage; + private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED; private final Connection.Listener mConnectionDeathListener = new Connection.Listener() { @Override @@ -422,6 +429,26 @@ public abstract class Conference implements IConferenceable { } /** + * Sets the connect time of the {@code Conference}. + * + * @param connectTimeMillis The connection time, in milliseconds. + */ + public void setConnectTimeMillis(long connectTimeMillis) { + mConnectTimeMillis = connectTimeMillis; + } + + /** + * Retrieves the connect time of the {@code Conference}, if specified. A value of + * {@link #CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the start time + * of the conference. + * + * @return The time the {@code Conference} has been connected. + */ + public long getConnectTimeMillis() { + return mConnectTimeMillis; + } + + /** * Inform this Conference that the state of its audio output has been changed externally. * * @param state The new audio state. diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index df1637594e12..dfdc3e12f7b0 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -883,7 +883,8 @@ public abstract class ConnectionService extends Service { conference.getPhoneAccountHandle(), conference.getState(), conference.getConnectionCapabilities(), - connectionIds); + connectionIds, + conference.getConnectTimeMillis()); mAdapter.addConferenceCall(id, parcelableConference); // Go through any child calls and set the parent. diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java index c4e11d6b6f59..dcc2713ec96b 100644 --- a/telecomm/java/android/telecom/ParcelableConference.java +++ b/telecomm/java/android/telecom/ParcelableConference.java @@ -32,6 +32,7 @@ public final class ParcelableConference implements Parcelable { private int mState; private int mConnectionCapabilities; private List<String> mConnectionIds; + private long mConnectTimeMillis; public ParcelableConference( PhoneAccountHandle phoneAccount, @@ -42,6 +43,17 @@ public final class ParcelableConference implements Parcelable { mState = state; mConnectionCapabilities = connectionCapabilities; mConnectionIds = connectionIds; + mConnectTimeMillis = Conference.CONNECT_TIME_NOT_SPECIFIED; + } + + public ParcelableConference( + PhoneAccountHandle phoneAccount, + int state, + int connectionCapabilities, + List<String> connectionIds, + long connectTimeMillis) { + this(phoneAccount, state, connectionCapabilities, connectionIds); + mConnectTimeMillis = connectTimeMillis; } @Override @@ -53,6 +65,8 @@ public final class ParcelableConference implements Parcelable { .append(Connection.stateToString(mState)) .append(", capabilities: ") .append(Connection.capabilitiesToString(mConnectionCapabilities)) + .append(", connectTime: ") + .append(mConnectTimeMillis) .append(", children: ") .append(mConnectionIds) .toString(); @@ -74,6 +88,10 @@ public final class ParcelableConference implements Parcelable { return mConnectionIds; } + public long getConnectTimeMillis() { + return mConnectTimeMillis; + } + public static final Parcelable.Creator<ParcelableConference> CREATOR = new Parcelable.Creator<ParcelableConference> () { @Override @@ -84,8 +102,10 @@ public final class ParcelableConference implements Parcelable { int capabilities = source.readInt(); List<String> connectionIds = new ArrayList<>(2); source.readList(connectionIds, classLoader); + long connectTimeMillis = source.readLong(); - return new ParcelableConference(phoneAccount, state, capabilities, connectionIds); + return new ParcelableConference(phoneAccount, state, capabilities, connectionIds, + connectTimeMillis); } @Override @@ -107,5 +127,6 @@ public final class ParcelableConference implements Parcelable { destination.writeInt(mState); destination.writeInt(mConnectionCapabilities); destination.writeList(mConnectionIds); + destination.writeLong(mConnectTimeMillis); } } diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java index e57f9e31a82f..adbe1d8453ca 100644 --- a/telephony/java/android/telephony/SubscriptionInfo.java +++ b/telephony/java/android/telephony/SubscriptionInfo.java @@ -129,28 +129,28 @@ public class SubscriptionInfo implements Parcelable { } /** - * Returns the subscription ID. + * @return the subscription ID. */ public int getSubscriptionId() { return this.mId; } /** - * Returns the ICC ID. + * @return the ICC ID. */ public String getIccId() { return this.mIccId; } /** - * Returns the slot index of this Subscription's SIM card. + * @return the slot index of this Subscription's SIM card. */ public int getSimSlotIndex() { return this.mSimSlotIndex; } /** - * Returns the name displayed to the user that identifies this subscription + * @return the name displayed to the user that identifies this subscription */ public CharSequence getDisplayName() { return this.mDisplayName; @@ -165,7 +165,7 @@ public class SubscriptionInfo implements Parcelable { } /** - * Returns the name displayed to the user that identifies Subscription provider name + * @return the name displayed to the user that identifies Subscription provider name */ public CharSequence getCarrierName() { return this.mCarrierName; @@ -180,8 +180,9 @@ public class SubscriptionInfo implements Parcelable { } /** - * Return the source of the name, eg NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE, + * @return the source of the name, eg NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE, * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT. + * @hide */ public int getNameSource() { return this.mNameSource; @@ -246,35 +247,36 @@ public class SubscriptionInfo implements Parcelable { } /** - * Returns the number of this subscription. + * @return the number of this subscription. */ public String getNumber() { return mNumber; } /** - * Return the data roaming value. + * @return the data roaming state for this subscription, either + * {@link SubscriptionManager#DATA_ROAMING_ENABLE} or {@link SubscriptionManager#DATA_ROAMING_DISABLE}. */ public int getDataRoaming() { return this.mDataRoaming; } /** - * Returns the MCC. + * @return the MCC. */ public int getMcc() { return this.mMcc; } /** - * Returns the MNC. + * @return the MNC. */ public int getMnc() { return this.mMnc; } /** - * Returns the ISO country code + * @return the ISO country code */ public String getCountryIso() { return this.mCountryIso; diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index d174f47447c3..c67629d19316 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -226,10 +226,10 @@ public class SubscriptionManager { /** @hide */ public static final String DATA_ROAMING = "data_roaming"; - /** @hide */ + /** Indicates that data roaming is enabled for a subscription */ public static final int DATA_ROAMING_ENABLE = 1; - /** @hide */ + /** Indicates that data roaming is disabled for a subscription */ public static final int DATA_ROAMING_DISABLE = 0; /** @hide */ @@ -266,9 +266,9 @@ public class SubscriptionManager { * A listener class for monitoring changes to {@link SubscriptionInfo} records. * <p> * Override the onSubscriptionsChanged method in the object that extends this - * class and pass it to {@link #registerOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} + * class and pass it to {@link #addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} * to register your listener and to unregister invoke - * {@link #unregisterOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} + * {@link #removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} * <p> * Permissions android.Manifest.permission.READ_PHONE_STATE is required * for #onSubscriptionsChanged to be invoked. @@ -340,7 +340,7 @@ public class SubscriptionManager { * @param listener an instance of {@link OnSubscriptionsChangedListener} with * onSubscriptionsChanged overridden. */ - public void registerOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { + public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>"; if (DBG) { logd("register OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug @@ -352,7 +352,7 @@ public class SubscriptionManager { ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); if (tr != null) { - tr.registerOnSubscriptionsChangedListener(pkgForDebug, listener.callback); + tr.addOnSubscriptionsChangedListener(pkgForDebug, listener.callback); } } catch (RemoteException ex) { // Should not happen @@ -366,7 +366,7 @@ public class SubscriptionManager { * * @param listener that is to be unregistered. */ - public void unregisterOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { + public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>"; if (DBG) { logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug @@ -378,7 +378,7 @@ public class SubscriptionManager { ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); if (tr != null) { - tr.unregisterOnSubscriptionsChangedListener(pkgForDebug, listener.callback); + tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback); } } catch (RemoteException ex) { // Should not happen diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 99d0af179d36..dca1f82772a2 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3099,7 +3099,7 @@ public class TelephonyManager { * * @return true on success; false on any failure. */ - public boolean setGlobalPreferredNetworkType() { + public boolean setPreferredNetworkTypeToGlobal() { return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); } @@ -3142,8 +3142,6 @@ public class TelephonyManager { * call will return true. This access is granted by the owner of the UICC * card and does not depend on the registered carrier. * - * TODO: Add a link to documentation. - * * @return true if the app has carrier privileges. */ public boolean hasCarrierPrivileges() { diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index ba62f5f1594d..7d8a8d66582e 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -30,9 +30,9 @@ import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener; interface ITelephonyRegistry { - void registerOnSubscriptionsChangedListener(String pkg, + void addOnSubscriptionsChangedListener(String pkg, IOnSubscriptionsChangedListener callback); - void unregisterOnSubscriptionsChangedListener(String pkg, + void removeOnSubscriptionsChangedListener(String pkg, IOnSubscriptionsChangedListener callback); void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow); void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events, diff --git a/tests/Split/res/layout/main.xml b/tests/Split/res/layout/main.xml index 607cdb0b130b..5a33c86355d2 100644 --- a/tests/Split/res/layout/main.xml +++ b/tests/Split/res/layout/main.xml @@ -21,5 +21,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" + android:colorAccent="#ffffffff" + android:paddingStart="13dp" android:src="@drawable/image"/> </RelativeLayout> diff --git a/tests/Split/res/values-v10/values.xml b/tests/Split/res/values-v10/values.xml new file mode 100644 index 000000000000..3d41a84bdbb8 --- /dev/null +++ b/tests/Split/res/values-v10/values.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <style name="toop"> + <item name="android:paddingStart">12dp</item> + <item name="android:layout_width">23dp</item> + </style> + + <style name="temp"> + <item name="android:versionName">hey</item> + <item name="android:allowBackup">true</item> + <item name="android:colorAccent">#ffffffff</item> + </style> +</resources> diff --git a/tests/Split/res/values-v17/values.xml b/tests/Split/res/values-v17/values.xml new file mode 100644 index 000000000000..c24eeaeced37 --- /dev/null +++ b/tests/Split/res/values-v17/values.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <style name="toop"> + <item name="android:paddingStart">12dp</item> + <item name="android:layout_width">23dp</item> + <item name="android:layout_height">45dp</item> + </style> + +</resources> diff --git a/tests/Split/res/values/values.xml b/tests/Split/res/values/values.xml index 68edc77d47f8..aabb2325ba45 100644 --- a/tests/Split/res/values/values.xml +++ b/tests/Split/res/values/values.xml @@ -44,4 +44,10 @@ <item>@string/boom</item> <item>25dp</item> </array> + + <style name="temp"> + <item name="android:versionName">hey</item> + <item name="android:allowBackup">true</item> + <item name="android:colorAccent">#ffffffff</item> + </style> </resources> diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index e87138c89818..e000a1dc1feb 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -4329,38 +4329,80 @@ bool ResourceTable::getItemValue( } /** - * Returns true if the given attribute ID comes from - * a platform version from or after L. + * Returns the SDK version at which the attribute was + * made public, or -1 if the resource ID is not an attribute + * or is not public. */ -bool ResourceTable::isAttributeFromL(uint32_t attrId) { - const uint32_t baseAttrId = 0x010103f7; - if ((attrId & 0xffff0000) != (baseAttrId & 0xffff0000)) { - return false; +int ResourceTable::getPublicAttributeSdkLevel(uint32_t attrId) const { + if (Res_GETPACKAGE(attrId) + 1 != 0x01 || Res_GETTYPE(attrId) + 1 != 0x01) { + return -1; } uint32_t specFlags; if (!mAssets->getIncludedResources().getResourceFlags(attrId, &specFlags)) { - return false; + return -1; + } + + if ((specFlags & ResTable_typeSpec::SPEC_PUBLIC) == 0) { + return -1; + } + + const size_t entryId = Res_GETENTRY(attrId); + if (entryId <= 0x021c) { + return 1; + } else if (entryId <= 0x021d) { + return 2; + } else if (entryId <= 0x0269) { + return SDK_CUPCAKE; + } else if (entryId <= 0x028d) { + return SDK_DONUT; + } else if (entryId <= 0x02ad) { + return SDK_ECLAIR; + } else if (entryId <= 0x02b3) { + return SDK_ECLAIR_0_1; + } else if (entryId <= 0x02b5) { + return SDK_ECLAIR_MR1; + } else if (entryId <= 0x02bd) { + return SDK_FROYO; + } else if (entryId <= 0x02cb) { + return SDK_GINGERBREAD; + } else if (entryId <= 0x0361) { + return SDK_HONEYCOMB; + } else if (entryId <= 0x0366) { + return SDK_HONEYCOMB_MR1; + } else if (entryId <= 0x03a6) { + return SDK_HONEYCOMB_MR2; + } else if (entryId <= 0x03ae) { + return SDK_JELLY_BEAN; + } else if (entryId <= 0x03cc) { + return SDK_JELLY_BEAN_MR1; + } else if (entryId <= 0x03da) { + return SDK_JELLY_BEAN_MR2; + } else if (entryId <= 0x03f1) { + return SDK_KITKAT; + } else if (entryId <= 0x03f6) { + return SDK_KITKAT_WATCH; + } else if (entryId <= 0x04ce) { + return SDK_LOLLIPOP; + } else { + // Anything else is marked as defined in + // SDK_LOLLIPOP_MR1 since after this + // version no attribute compat work + // needs to be done. + return SDK_LOLLIPOP_MR1; } - - return (specFlags & ResTable_typeSpec::SPEC_PUBLIC) != 0 && - (attrId & 0x0000ffff) >= (baseAttrId & 0x0000ffff); } -static bool isMinSdkVersionLOrAbove(const Bundle* bundle) { - if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) { - const char firstChar = bundle->getMinSdkVersion()[0]; - if (firstChar >= 'L' && firstChar <= 'Z') { - // L is the code-name for the v21 release. - return true; - } - - const int minSdk = atoi(bundle->getMinSdkVersion()); - if (minSdk >= SDK_LOLLIPOP) { - return true; - } +/** + * First check the Manifest, then check the command line flag. + */ +static int getMinSdkVersion(const Bundle* bundle) { + if (bundle->getManifestMinSdkVersion() != NULL && strlen(bundle->getManifestMinSdkVersion()) > 0) { + return atoi(bundle->getManifestMinSdkVersion()); + } else if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) { + return atoi(bundle->getMinSdkVersion()); } - return false; + return 0; } /** @@ -4406,9 +4448,10 @@ static bool isMinSdkVersionLOrAbove(const Bundle* bundle) { * attribute will be respected. */ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { - if (isMinSdkVersionLOrAbove(bundle)) { - // If this app will only ever run on L+ devices, - // we don't need to do any compatibility work. + const int minSdk = getMinSdkVersion(bundle); + if (minSdk >= SDK_LOLLIPOP_MR1) { + // Lollipop MR1 and up handles public attributes differently, no + // need to do any compat modifications. return NO_ERROR; } @@ -4447,20 +4490,19 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { } const ConfigDescription& config = entries.keyAt(ei); - if (config.sdkVersion >= SDK_LOLLIPOP) { - // We don't need to do anything if the resource is - // already qualified for version 21 or higher. + if (config.sdkVersion >= SDK_LOLLIPOP_MR1) { continue; } - Vector<String16> attributesToRemove; + KeyedVector<int, Vector<String16> > attributesToRemove; const KeyedVector<String16, Item>& bag = e->getBag(); const size_t bagCount = bag.size(); for (size_t bi = 0; bi < bagCount; bi++) { const Item& item = bag.valueAt(bi); const uint32_t attrId = getResId(bag.keyAt(bi), &attr16); - if (isAttributeFromL(attrId)) { - attributesToRemove.add(bag.keyAt(bi)); + const int sdkLevel = getPublicAttributeSdkLevel(attrId); + if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) { + AaptUtil::appendValue(attributesToRemove, sdkLevel, bag.keyAt(bi)); } } @@ -4468,16 +4510,41 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { continue; } - // Duplicate the entry under the same configuration - // but with sdkVersion == SDK_LOLLIPOP. - ConfigDescription newConfig(config); - newConfig.sdkVersion = SDK_LOLLIPOP; - entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >( - newConfig, new Entry(*e))); + const size_t sdkCount = attributesToRemove.size(); + for (size_t i = 0; i < sdkCount; i++) { + const int sdkLevel = attributesToRemove.keyAt(i); + + // Duplicate the entry under the same configuration + // but with sdkVersion == sdkLevel. + ConfigDescription newConfig(config); + newConfig.sdkVersion = sdkLevel; + + sp<Entry> newEntry = new Entry(*e); + + // Remove all items that have a higher SDK level than + // the one we are synthesizing. + for (size_t j = 0; j < sdkCount; j++) { + if (j == i) { + continue; + } + + if (attributesToRemove.keyAt(j) > sdkLevel) { + const size_t attrCount = attributesToRemove[j].size(); + for (size_t k = 0; k < attrCount; k++) { + newEntry->removeFromBag(attributesToRemove[j][k]); + } + } + } + + entriesToAdd.add(key_value_pair_t<ConfigDescription, sp<Entry> >( + newConfig, newEntry)); + } // Remove the attribute from the original. for (size_t i = 0; i < attributesToRemove.size(); i++) { - e->removeFromBag(attributesToRemove[i]); + for (size_t j = 0; j < attributesToRemove[i].size(); j++) { + e->removeFromBag(attributesToRemove[i][j]); + } } } @@ -4494,7 +4561,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { if (bundle->getVerbose()) { entriesToAdd[i].value->getPos() .printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.", - SDK_LOLLIPOP, + entriesToAdd[i].key.sdkVersion, String8(p->getName()).string(), String8(t->getName()).string(), String8(entriesToAdd[i].value->getName()).string(), @@ -4517,17 +4584,23 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, const sp<XMLNode>& root) { - if (isMinSdkVersionLOrAbove(bundle)) { + const int minSdk = getMinSdkVersion(bundle); + if (minSdk >= SDK_LOLLIPOP_MR1) { + // Lollipop MR1 and up handles public attributes differently, no + // need to do any compat modifications. return NO_ERROR; } - if (target->getResourceType() == "" || target->getGroupEntry().toParams().sdkVersion >= SDK_LOLLIPOP) { + const ConfigDescription config(target->getGroupEntry().toParams()); + if (target->getResourceType() == "" || config.sdkVersion >= SDK_LOLLIPOP_MR1) { // Skip resources that have no type (AndroidManifest.xml) or are already version qualified with v21 // or higher. return NO_ERROR; } sp<XMLNode> newRoot = NULL; + ConfigDescription newConfig(target->getGroupEntry().toParams()); + newConfig.sdkVersion = SDK_LOLLIPOP_MR1; Vector<sp<XMLNode> > nodesToVisit; nodesToVisit.push(root); @@ -4538,11 +4611,19 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, const Vector<XMLNode::attribute_entry>& attrs = node->getAttributes(); for (size_t i = 0; i < attrs.size(); i++) { const XMLNode::attribute_entry& attr = attrs[i]; - if (isAttributeFromL(attr.nameResId)) { + const int sdkLevel = getPublicAttributeSdkLevel(attr.nameResId); + if (sdkLevel > 1 && sdkLevel > config.sdkVersion && sdkLevel > minSdk) { if (newRoot == NULL) { newRoot = root->clone(); } + // Find the smallest sdk version that we need to synthesize for + // and do that one. Subsequent versions will be processed on + // the next pass. + if (sdkLevel < newConfig.sdkVersion) { + newConfig.sdkVersion = sdkLevel; + } + if (bundle->getVerbose()) { SourcePos(node->getFilename(), node->getStartLineNumber()).printf( "removing attribute %s%s%s from <%s>", @@ -4568,9 +4649,6 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, return NO_ERROR; } - ConfigDescription newConfig(target->getGroupEntry().toParams()); - newConfig.sdkVersion = SDK_LOLLIPOP; - // Look to see if we already have an overriding v21 configuration. sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()), String16(target->getResourceType()), resourceName); @@ -4587,7 +4665,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle, if (bundle->getVerbose()) { SourcePos(target->getSourceFile(), -1).printf( "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.", - SDK_LOLLIPOP, + newConfig.sdkVersion, mAssets->getPackage().string(), newFile->getResourceType().string(), String8(resourceName).string(), diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index 81590bc961db..eef0ae10e60d 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -575,7 +575,7 @@ private: const Item* getItem(uint32_t resID, uint32_t attrID) const; bool getItemValue(uint32_t resID, uint32_t attrID, Res_value* outValue); - bool isAttributeFromL(uint32_t attrId); + int getPublicAttributeSdkLevel(uint32_t attrId) const; String16 mAssetsPackage; diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h index 7fd10301b15c..4e0fe10022a8 100644 --- a/tools/aapt/SdkConstants.h +++ b/tools/aapt/SdkConstants.h @@ -37,6 +37,7 @@ enum { SDK_KITKAT = 19, SDK_KITKAT_WATCH = 20, SDK_LOLLIPOP = 21, + SDK_LOLLIPOP_MR1 = 22, }; #endif // H_AAPT_SDK_CONSTANTS |