summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt12
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java20
-rw-r--r--core/java/android/app/backup/BackupHelperDispatcher.java1
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/os/BatteryStats.java2
-rw-r--r--core/java/android/os/UserManager.java29
-rw-r--r--core/java/android/view/View.java41
-rw-r--r--core/java/android/view/ViewGroup.java17
-rw-r--r--core/java/android/view/ViewParent.java20
-rw-r--r--core/java/android/view/ViewRootImpl.java5
-rw-r--r--core/java/android/view/Window.java9
-rw-r--r--core/java/android/widget/TextView.java14
-rw-r--r--core/java/com/android/internal/util/StateMachine.java25
-rw-r--r--core/java/com/android/internal/widget/ResolverDrawerLayout.java59
-rw-r--r--core/res/res/layout-land/date_picker_holo.xml6
-rw-r--r--core/res/res/layout/date_picker_selected_date.xml12
-rw-r--r--core/res/res/values/dimens.xml5
-rw-r--r--docs/html/guide/components/intents-common.jd4
-rw-r--r--docs/html/training/wearables/notifications/creating.jd4
-rw-r--r--graphics/java/android/graphics/drawable/Ripple.java2
-rw-r--r--graphics/java/android/graphics/drawable/RippleBackground.java2
-rw-r--r--include/androidfw/BackupHelpers.h2
-rw-r--r--libs/androidfw/BackupHelpers.cpp79
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp8
-rw-r--r--media/java/android/media/AudioService.java26
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/EventLogConstants.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/EventLogTags.logtags18
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java4
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java1
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java87
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java4
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java38
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkMonitor.java2
-rw-r--r--services/core/java/com/android/server/display/ColorFade.java6
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java11
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java4
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiMhlLocalDeviceStub.java3
-rw-r--r--services/core/java/com/android/server/location/GpsLocationProvider.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java40
-rw-r--r--telecomm/java/android/telecom/Conference.java27
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java3
-rw-r--r--telecomm/java/android/telecom/ParcelableConference.java23
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java24
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java16
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java4
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl4
-rw-r--r--tests/Split/res/layout/main.xml2
-rw-r--r--tests/Split/res/values-v10/values.xml28
-rw-r--r--tests/Split/res/values-v17/values.xml24
-rw-r--r--tests/Split/res/values/values.xml6
-rw-r--r--tools/aapt/ResourceTable.cpp172
-rw-r--r--tools/aapt/ResourceTable.h2
-rw-r--r--tools/aapt/SdkConstants.h1
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