Merge "[Fix extra data in cache]" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 5d28d2c..6110d1c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -32174,7 +32174,6 @@
field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
- field public static final java.lang.String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
@@ -34094,6 +34093,7 @@
method public boolean isDigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public static final class KeyGenParameterSpec.Builder {
@@ -34116,6 +34116,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
@@ -34135,6 +34136,7 @@
method public boolean isInsideSecureHardware();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -34197,6 +34199,7 @@
method public boolean isDigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public static final class KeyProtection.Builder {
@@ -34212,6 +34215,7 @@
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
+ method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index a2943ff..c01f1c3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -34661,7 +34661,6 @@
field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
- field public static final java.lang.String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
@@ -36583,6 +36582,7 @@
method public boolean isDigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public static final class KeyGenParameterSpec.Builder {
@@ -36605,6 +36605,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
@@ -36624,6 +36625,7 @@
method public boolean isInsideSecureHardware();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -36686,6 +36688,7 @@
method public boolean isDigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public static final class KeyProtection.Builder {
@@ -36701,6 +36704,7 @@
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
+ method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
}
diff --git a/api/test-current.txt b/api/test-current.txt
index d42c18c..96d29d1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -32187,7 +32187,6 @@
field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
- field public static final java.lang.String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
@@ -34109,6 +34108,7 @@
method public boolean isDigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public static final class KeyGenParameterSpec.Builder {
@@ -34131,6 +34131,7 @@
method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
@@ -34150,6 +34151,7 @@
method public boolean isInsideSecureHardware();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationRequirementEnforcedBySecureHardware();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public class KeyNotYetValidException extends java.security.InvalidKeyException {
@@ -34212,6 +34214,7 @@
method public boolean isDigestsSpecified();
method public boolean isRandomizedEncryptionRequired();
method public boolean isUserAuthenticationRequired();
+ method public boolean isUserAuthenticationValidWhileOnBody();
}
public static final class KeyProtection.Builder {
@@ -34227,6 +34230,7 @@
method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
+ method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
}
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 3385a17..980329f 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -807,8 +807,6 @@
}
/**
- * AnimatorSet is only reversible when the set contains no sequential animation, and no child
- * animators have a start delay.
* @hide
*/
@Override
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 35b7c39..52631d1 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -263,8 +263,8 @@
* The view that will represent this notification in the notification list (which is pulled
* down from the status bar).
*
- * As of N, this field is not used. The notification view is determined by the inputs to
- * {@link Notification.Builder}; a custom RemoteViews can optionally be
+ * As of N, this field may be null. The notification view is determined by the inputs
+ * to {@link Notification.Builder}; a custom RemoteViews can optionally be
* supplied with {@link Notification.Builder#setCustomContentView(RemoteViews)}.
*/
@Deprecated
@@ -275,7 +275,7 @@
* opportunity to show more detail. The system UI may choose to show this
* instead of the normal content view at its discretion.
*
- * As of N, this field is not used. The expanded notification view is determined by the
+ * As of N, this field may be null. The expanded notification view is determined by the
* inputs to {@link Notification.Builder}; a custom RemoteViews can optionally be
* supplied with {@link Notification.Builder#setCustomBigContentView(RemoteViews)}.
*/
@@ -289,7 +289,7 @@
* choose to show this as a heads-up notification, which will pop up so the user can see
* it without leaving their current activity.
*
- * As of N, this field is not used. The heads-up notification view is determined by the
+ * As of N, this field may be null. The heads-up notification view is determined by the
* inputs to {@link Notification.Builder}; a custom RemoteViews can optionally be
* supplied with {@link Notification.Builder#setCustomHeadsUpContentView(RemoteViews)}.
*/
@@ -2129,8 +2129,23 @@
* </pre>
*/
public static class Builder {
+ /**
+ * @hide
+ */
+ public static final String EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT =
+ "android.rebuild.contentViewActionCount";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT
+ = "android.rebuild.bigViewActionCount";
+ /**
+ * @hide
+ */
+ public static final String EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT
+ = "android.rebuild.hudViewActionCount";
+
private static final int MAX_ACTION_BUTTONS = 3;
- private static final float LARGE_TEXT_SCALE = 1.3f;
private Context mContext;
private Notification mN;
@@ -3566,19 +3581,6 @@
return null;
}
- private void setBuilderContentView(Notification n, RemoteViews contentView) {
- n.contentView = contentView;
- }
-
- private void setBuilderBigContentView(Notification n, RemoteViews bigContentView) {
- n.bigContentView = bigContentView;
- }
-
- private void setBuilderHeadsUpContentView(Notification n,
- RemoteViews headsUpContentView) {
- n.headsUpContentView = headsUpContentView;
- }
-
/**
* @deprecated Use {@link #build()} instead.
*/
@@ -3606,6 +3608,28 @@
mStyle.buildStyled(mN);
}
+ if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+ if (mN.contentView == null) {
+ mN.contentView = makeContentView();
+ mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT,
+ mN.contentView.getSequenceNumber());
+ }
+ if (mN.bigContentView == null) {
+ mN.bigContentView = makeBigContentView();
+ if (mN.bigContentView != null) {
+ mN.extras.putInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT,
+ mN.bigContentView.getSequenceNumber());
+ }
+ }
+ if (mN.headsUpContentView == null) {
+ mN.headsUpContentView = makeHeadsUpContentView();
+ if (mN.headsUpContentView != null) {
+ mN.extras.putInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT,
+ mN.headsUpContentView.getSequenceNumber());
+ }
+ }
+ }
+
if ((mN.defaults & DEFAULT_LIGHTS) != 0) {
mN.flags |= FLAG_SHOW_LIGHTS;
}
@@ -3623,6 +3647,40 @@
return n;
}
+ /**
+ * @hide
+ */
+ public static void stripForDelivery(Notification n) {
+ String templateClass = n.extras.getString(EXTRA_TEMPLATE);
+ if (TextUtils.isEmpty(templateClass)) {
+ return;
+ }
+ // Only strip views for known Styles because we won't know how to
+ // re-create them otherwise.
+ if (getNotificationStyleClass(templateClass) == null) {
+ return;
+ }
+ // Get rid of unmodified BuilderRemoteViews.
+ if (n.contentView instanceof BuilderRemoteViews &&
+ n.extras.getInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, -1) ==
+ n.contentView.getSequenceNumber()) {
+ n.contentView = null;
+ n.extras.remove(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT);
+ }
+ if (n.bigContentView instanceof BuilderRemoteViews &&
+ n.extras.getInt(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT, -1) ==
+ n.bigContentView.getSequenceNumber()) {
+ n.bigContentView = null;
+ n.extras.remove(EXTRA_REBUILD_BIG_CONTENT_VIEW_ACTION_COUNT);
+ }
+ if (n.headsUpContentView instanceof BuilderRemoteViews &&
+ n.extras.getInt(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT, -1) ==
+ n.headsUpContentView.getSequenceNumber()) {
+ n.headsUpContentView = null;
+ n.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
+ }
+ }
+
private int getBaseLayoutResource() {
return R.layout.notification_template_material_base;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 1f17024..ff2cfd6 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -246,6 +246,7 @@
}
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
final Notification copy = notification.clone();
+ Builder.stripForDelivery(copy);
try {
service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
copy, idOut, user.getIdentifier());
diff --git a/core/java/android/net/BaseDhcpStateMachine.java b/core/java/android/net/BaseDhcpStateMachine.java
deleted file mode 100644
index a25847d..0000000
--- a/core/java/android/net/BaseDhcpStateMachine.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import com.android.internal.util.StateMachine;
-
-/**
- * Interface that must be implemented by DHCP state machines.
- *
- * This is an abstract class instead of a Java interface so that callers can just declare an object
- * of this type and be able to call all the methods defined by either StateMachine or this class.
- *
- * @hide
- */
-public abstract class BaseDhcpStateMachine extends StateMachine {
- protected BaseDhcpStateMachine(String tag) {
- super(tag);
- }
- public abstract void registerForPreDhcpNotification();
- public abstract void doQuit();
-}
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
deleted file mode 100644
index 73ef78e..0000000
--- a/core/java/android/net/DhcpStateMachine.java
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import com.android.internal.util.Protocol;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.DhcpResults;
-import android.net.NetworkUtils;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.util.Log;
-
-/**
- * StateMachine that interacts with the native DHCP client and can talk to
- * a controller that also needs to be a StateMachine
- *
- * The DhcpStateMachine provides the following features:
- * - Wakeup and renewal using the native DHCP client (which will not renew
- * on its own when the device is in suspend state and this can lead to device
- * holding IP address beyond expiry)
- * - A notification right before DHCP request or renewal is started. This
- * can be used for any additional setup before DHCP. For example, wifi sets
- * BT-Wifi coex settings right before DHCP is initiated
- *
- * @hide
- */
-public class DhcpStateMachine extends BaseDhcpStateMachine {
-
- private static final String TAG = "DhcpStateMachine";
- private static final boolean DBG = false;
-
-
- /* A StateMachine that controls the DhcpStateMachine */
- private StateMachine mController;
-
- private Context mContext;
- private BroadcastReceiver mBroadcastReceiver;
- private AlarmManager mAlarmManager;
- private PendingIntent mDhcpRenewalIntent;
- private PowerManager.WakeLock mDhcpRenewWakeLock;
- private static final String WAKELOCK_TAG = "DHCP";
-
- //Remember DHCP configuration from first request
- private DhcpResults mDhcpResults;
-
- private static final int DHCP_RENEW = 0;
- private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW";
-
- //Used for sanity check on setting up renewal
- private static final int MIN_RENEWAL_TIME_SECS = 5 * 60; // 5 minutes
-
- private final String mInterfaceName;
- private boolean mRegisteredForPreDhcpNotification = false;
-
- private static final int BASE = Protocol.BASE_DHCP;
-
- /* Commands from controller to start/stop DHCP */
- public static final int CMD_START_DHCP = BASE + 1;
- public static final int CMD_STOP_DHCP = BASE + 2;
- public static final int CMD_RENEW_DHCP = BASE + 3;
-
- /* Notification from DHCP state machine prior to DHCP discovery/renewal */
- public static final int CMD_PRE_DHCP_ACTION = BASE + 4;
- /* Notification from DHCP state machine post DHCP discovery/renewal. Indicates
- * success/failure */
- public static final int CMD_POST_DHCP_ACTION = BASE + 5;
- /* Notification from DHCP state machine before quitting */
- public static final int CMD_ON_QUIT = BASE + 6;
-
- /* Command from controller to indicate DHCP discovery/renewal can continue
- * after pre DHCP action is complete */
- public static final int CMD_PRE_DHCP_ACTION_COMPLETE = BASE + 7;
-
- /* Command from ourselves to see if DHCP results are available */
- private static final int CMD_GET_DHCP_RESULTS = BASE + 8;
-
- /* Message.arg1 arguments to CMD_POST_DHCP notification */
- public static final int DHCP_SUCCESS = 1;
- public static final int DHCP_FAILURE = 2;
-
- private State mDefaultState = new DefaultState();
- private State mStoppedState = new StoppedState();
- private State mWaitBeforeStartState = new WaitBeforeStartState();
- private State mRunningState = new RunningState();
- private State mWaitBeforeRenewalState = new WaitBeforeRenewalState();
- private State mPollingState = new PollingState();
-
- private DhcpStateMachine(Context context, StateMachine controller, String intf) {
- super(TAG);
-
- mContext = context;
- mController = controller;
- mInterfaceName = intf;
-
- mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
- Intent dhcpRenewalIntent = new Intent(ACTION_DHCP_RENEW, null);
- mDhcpRenewalIntent = PendingIntent.getBroadcast(mContext, DHCP_RENEW, dhcpRenewalIntent, 0);
-
- PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
- mDhcpRenewWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
- mDhcpRenewWakeLock.setReferenceCounted(false);
-
- mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- //DHCP renew
- if (DBG) Log.d(TAG, "Sending a DHCP renewal " + this);
- //Lock released after 40s in worst case scenario
- mDhcpRenewWakeLock.acquire(40000);
- sendMessage(CMD_RENEW_DHCP);
- }
- };
- mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(ACTION_DHCP_RENEW));
-
- addState(mDefaultState);
- addState(mStoppedState, mDefaultState);
- addState(mWaitBeforeStartState, mDefaultState);
- addState(mPollingState, mDefaultState);
- addState(mRunningState, mDefaultState);
- addState(mWaitBeforeRenewalState, mDefaultState);
-
- setInitialState(mStoppedState);
- }
-
- public static DhcpStateMachine makeDhcpStateMachine(Context context, StateMachine controller,
- String intf) {
- DhcpStateMachine dsm = new DhcpStateMachine(context, controller, intf);
- dsm.start();
- return dsm;
- }
-
- /**
- * This sends a notification right before DHCP request/renewal so that the
- * controller can do certain actions before DHCP packets are sent out.
- * When the controller is ready, it sends a CMD_PRE_DHCP_ACTION_COMPLETE message
- * to indicate DHCP can continue
- *
- * This is used by Wifi at this time for the purpose of doing BT-Wifi coex
- * handling during Dhcp
- */
- @Override
- public void registerForPreDhcpNotification() {
- mRegisteredForPreDhcpNotification = true;
- }
-
- /**
- * Quit the DhcpStateMachine.
- *
- * @hide
- */
- @Override
- public void doQuit() {
- quit();
- }
-
- protected void onQuitting() {
- mController.sendMessage(CMD_ON_QUIT);
- }
-
- class DefaultState extends State {
- @Override
- public void exit() {
- mContext.unregisterReceiver(mBroadcastReceiver);
- }
- @Override
- public boolean processMessage(Message message) {
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_RENEW_DHCP:
- Log.e(TAG, "Error! Failed to handle a DHCP renewal on " + mInterfaceName);
- mDhcpRenewWakeLock.release();
- break;
- default:
- Log.e(TAG, "Error! unhandled message " + message);
- break;
- }
- return HANDLED;
- }
- }
-
-
- class StoppedState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- if (!NetworkUtils.stopDhcp(mInterfaceName)) {
- Log.e(TAG, "Failed to stop Dhcp on " + mInterfaceName);
- }
- mDhcpResults = null;
- }
-
- @Override
- public boolean processMessage(Message message) {
- boolean retValue = HANDLED;
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_START_DHCP:
- if (mRegisteredForPreDhcpNotification) {
- /* Notify controller before starting DHCP */
- mController.sendMessage(CMD_PRE_DHCP_ACTION);
- transitionTo(mWaitBeforeStartState);
- } else {
- if (runDhcpStart()) {
- transitionTo(mRunningState);
- }
- }
- break;
- case CMD_STOP_DHCP:
- //ignore
- break;
- default:
- retValue = NOT_HANDLED;
- break;
- }
- return retValue;
- }
- }
-
- class WaitBeforeStartState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
-
- @Override
- public boolean processMessage(Message message) {
- boolean retValue = HANDLED;
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_PRE_DHCP_ACTION_COMPLETE:
- if (runDhcpStart()) {
- transitionTo(mRunningState);
- } else {
- transitionTo(mPollingState);
- }
- break;
- case CMD_STOP_DHCP:
- transitionTo(mStoppedState);
- break;
- case CMD_START_DHCP:
- //ignore
- break;
- default:
- retValue = NOT_HANDLED;
- break;
- }
- return retValue;
- }
- }
-
- class PollingState extends State {
- private static final long MAX_DELAY_SECONDS = 32;
- private long delaySeconds;
-
- private void scheduleNextResultsCheck() {
- sendMessageDelayed(obtainMessage(CMD_GET_DHCP_RESULTS), delaySeconds * 1000);
- delaySeconds *= 2;
- if (delaySeconds > MAX_DELAY_SECONDS) {
- delaySeconds = MAX_DELAY_SECONDS;
- }
- }
-
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, "Entering " + getName() + "\n");
- delaySeconds = 1;
- scheduleNextResultsCheck();
- }
-
- @Override
- public boolean processMessage(Message message) {
- boolean retValue = HANDLED;
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_GET_DHCP_RESULTS:
- if (DBG) Log.d(TAG, "GET_DHCP_RESULTS on " + mInterfaceName);
- if (dhcpSucceeded()) {
- transitionTo(mRunningState);
- } else {
- scheduleNextResultsCheck();
- }
- break;
- case CMD_STOP_DHCP:
- transitionTo(mStoppedState);
- break;
- default:
- retValue = NOT_HANDLED;
- break;
- }
- return retValue;
- }
-
- @Override
- public void exit() {
- if (DBG) Log.d(TAG, "Exiting " + getName() + "\n");
- removeMessages(CMD_GET_DHCP_RESULTS);
- }
- }
-
- class RunningState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
-
- @Override
- public boolean processMessage(Message message) {
- boolean retValue = HANDLED;
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_STOP_DHCP:
- mAlarmManager.cancel(mDhcpRenewalIntent);
- transitionTo(mStoppedState);
- break;
- case CMD_RENEW_DHCP:
- if (mRegisteredForPreDhcpNotification) {
- /* Notify controller before starting DHCP */
- mController.sendMessage(CMD_PRE_DHCP_ACTION);
- transitionTo(mWaitBeforeRenewalState);
- //mDhcpRenewWakeLock is released in WaitBeforeRenewalState
- } else {
- if (!runDhcpRenew()) {
- transitionTo(mStoppedState);
- }
- mDhcpRenewWakeLock.release();
- }
- break;
- case CMD_START_DHCP:
- //ignore
- break;
- default:
- retValue = NOT_HANDLED;
- }
- return retValue;
- }
- }
-
- class WaitBeforeRenewalState extends State {
- @Override
- public void enter() {
- if (DBG) Log.d(TAG, getName() + "\n");
- }
-
- @Override
- public boolean processMessage(Message message) {
- boolean retValue = HANDLED;
- if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
- switch (message.what) {
- case CMD_STOP_DHCP:
- mAlarmManager.cancel(mDhcpRenewalIntent);
- transitionTo(mStoppedState);
- break;
- case CMD_PRE_DHCP_ACTION_COMPLETE:
- if (runDhcpRenew()) {
- transitionTo(mRunningState);
- } else {
- transitionTo(mStoppedState);
- }
- break;
- case CMD_START_DHCP:
- //ignore
- break;
- default:
- retValue = NOT_HANDLED;
- break;
- }
- return retValue;
- }
- @Override
- public void exit() {
- mDhcpRenewWakeLock.release();
- }
- }
-
- private boolean dhcpSucceeded() {
- DhcpResults dhcpResults = new DhcpResults();
- if (!NetworkUtils.getDhcpResults(mInterfaceName, dhcpResults)) {
- return false;
- }
-
- if (DBG) Log.d(TAG, "DHCP results found for " + mInterfaceName);
- long leaseDuration = dhcpResults.leaseDuration; //int to long conversion
-
- //Sanity check for renewal
- if (leaseDuration >= 0) {
- //TODO: would be good to notify the user that his network configuration is
- //bad and that the device cannot renew below MIN_RENEWAL_TIME_SECS
- if (leaseDuration < MIN_RENEWAL_TIME_SECS) {
- leaseDuration = MIN_RENEWAL_TIME_SECS;
- }
- //Do it a bit earlier than half the lease duration time
- //to beat the native DHCP client and avoid extra packets
- //48% for one hour lease time = 29 minutes
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() +
- leaseDuration * 480, //in milliseconds
- mDhcpRenewalIntent);
- } else {
- //infinite lease time, no renewal needed
- }
-
- // Fill in any missing fields in dhcpResults from the previous results.
- // If mDhcpResults is null (i.e. this is the first server response),
- // this is a noop.
- dhcpResults.updateFromDhcpRequest(mDhcpResults);
- mDhcpResults = dhcpResults;
- mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults)
- .sendToTarget();
- return true;
- }
-
- private boolean runDhcpStart() {
- /* Stop any existing DHCP daemon before starting new */
- NetworkUtils.stopDhcp(mInterfaceName);
- mDhcpResults = null;
-
- if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
- if (!NetworkUtils.startDhcp(mInterfaceName) || !dhcpSucceeded()) {
- Log.e(TAG, "DHCP request failed on " + mInterfaceName + ": " +
- NetworkUtils.getDhcpError());
- mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
- .sendToTarget();
- return false;
- }
- return true;
- }
-
- private boolean runDhcpRenew() {
- if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName);
- if (!NetworkUtils.startDhcpRenew(mInterfaceName) || !dhcpSucceeded()) {
- Log.e(TAG, "DHCP renew failed on " + mInterfaceName + ": " +
- NetworkUtils.getDhcpError());
- mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_FAILURE, 0)
- .sendToTarget();
- return false;
- }
- return true;
- }
-}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5ab2b00..9632ff7 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1218,6 +1218,8 @@
* Input: Nothing.
* <p>
* Output: Nothing.
+ *
+ * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index e01f2a0..eb3d031 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -72,6 +72,7 @@
public static final int KM_TAG_NO_AUTH_REQUIRED = KM_BOOL | 503;
public static final int KM_TAG_USER_AUTH_TYPE = KM_ENUM | 504;
public static final int KM_TAG_AUTH_TIMEOUT = KM_UINT | 505;
+ public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index a4cb703..7017ff5 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -775,10 +775,6 @@
mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this);
}
- public boolean isAttached() {
- return mOwningView != null && mOwningView.mAttachInfo != null;
- }
-
public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) {
if (mOwningView == null || mOwningView.mAttachInfo == null) {
throw new IllegalStateException("Cannot start this animator on a detached view!");
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9e9ad67..70a0e01 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -21584,7 +21584,7 @@
*/
public void setPointerIcon(PointerIcon pointerIcon) {
mPointerIcon = pointerIcon;
- if (mAttachInfo == null) {
+ if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
return;
}
try {
@@ -22637,6 +22637,11 @@
boolean mHighContrastText;
/**
+ * Set to true if a pointer event is currently being handled.
+ */
+ boolean mHandlingPointerEvent;
+
+ /**
* Global to the view hierarchy used as a temporary for dealing with
* x/y points in the transparent region computations.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6dc5ccc..0517788 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4311,6 +4311,24 @@
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
+ mAttachInfo.mUnbufferedDispatchRequested = false;
+ final View eventTarget =
+ (event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
+ mCapturingView : mView;
+ mAttachInfo.mHandlingPointerEvent = true;
+ boolean handled = eventTarget.dispatchPointerEvent(event);
+ maybeUpdatePointerIcon(event);
+ mAttachInfo.mHandlingPointerEvent = false;
+ if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
+ mUnbufferedInputDispatch = true;
+ if (mConsumeBatchedInputScheduled) {
+ scheduleConsumeBatchedInputImmediately();
+ }
+ }
+ return handled ? FINISH_HANDLED : FORWARD;
+ }
+
+ private void maybeUpdatePointerIcon(MotionEvent event) {
if (event.getPointerCount() == 1
&& event.isFromSource(InputDevice.SOURCE_MOUSE)) {
if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER
@@ -4327,19 +4345,6 @@
}
}
}
-
- mAttachInfo.mUnbufferedDispatchRequested = false;
- final View eventTarget =
- (event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
- mCapturingView : mView;
- boolean handled = eventTarget.dispatchPointerEvent(event);
- if (mAttachInfo.mUnbufferedDispatchRequested && !mUnbufferedInputDispatch) {
- mUnbufferedInputDispatch = true;
- if (mConsumeBatchedInputScheduled) {
- scheduleConsumeBatchedInputImmediately();
- }
- }
- return handled ? FINISH_HANDLED : FORWARD;
}
private int processTrackballEvent(QueuedInputEvent q) {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4c63941..62e149a 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -985,7 +985,7 @@
}
}
- public List<InputMethodInfo> getEnabledInputMethodListLocked() {
+ public ArrayList<InputMethodInfo> getEnabledInputMethodListLocked() {
return createEnabledInputMethodListLocked(
getEnabledInputMethodsAndSubtypeListLocked());
}
@@ -1092,7 +1092,7 @@
return isRemoved;
}
- private List<InputMethodInfo> createEnabledInputMethodListLocked(
+ private ArrayList<InputMethodInfo> createEnabledInputMethodListLocked(
List<Pair<String, ArrayList<String>>> imsList) {
final ArrayList<InputMethodInfo> res = new ArrayList<>();
for (Pair<String, ArrayList<String>> ims: imsList) {
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index a106f48..5992f7a 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -64,5 +64,6 @@
public static final int BASE_NETWORK_AGENT = 0x00081000;
public static final int BASE_NETWORK_MONITOR = 0x00082000;
public static final int BASE_NETWORK_FACTORY = 0x00083000;
+ public static final int BASE_ETHERNET = 0x00084000;
//TODO: define all used protocols
}
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index 14badb7..7a3c598 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -43,13 +43,12 @@
return env;
}
-static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) {
+static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) {
class AnimationListenerBridge : public AnimationListener {
public:
- AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) {
+ AnimationListenerBridge(JNIEnv* env, jobject finishListener) {
mFinishListener = env->NewGlobalRef(finishListener);
env->GetJavaVM(&mJvm);
- mId = id;
}
virtual ~AnimationListenerBridge() {
@@ -64,7 +63,7 @@
env->CallStaticVoidMethod(
gVectorDrawableAnimatorClassInfo.clazz,
gVectorDrawableAnimatorClassInfo.callOnFinished,
- mFinishListener, mId);
+ mFinishListener);
releaseJavaObject();
}
@@ -77,9 +76,8 @@
JavaVM* mJvm;
jobject mFinishListener;
- jint mId;
};
- return new AnimationListenerBridge(env, finishListener, id);
+ return new AnimationListenerBridge(env, finishListener);
}
static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr,
@@ -144,16 +142,15 @@
holder->setPropertyDataSource(propertyData, length);
env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT);
}
-static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
+static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
- AnimationListener* listener = createAnimationListener(env, finishListener, id);
+ // TODO: keep a ref count in finish listener
+ AnimationListener* listener = createAnimationListener(env, finishListener);
set->start(listener);
}
-static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
- PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
- AnimationListener* listener = createAnimationListener(env, finishListener, id);
- set->reverse(listener);
+static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) {
+ // TODO: implement reverse
}
static void end(JNIEnv*, jobject, jlong animatorSetPtr) {
@@ -175,8 +172,8 @@
{"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
{"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
{"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
- {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)start},
- {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V", (void*)reverse},
+ {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start},
+ {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse},
{"nEnd", "!(J)V", (void*)end},
{"nReset", "!(J)V", (void*)reset},
};
@@ -189,7 +186,7 @@
gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie(
env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished",
- "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;I)V");
+ "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V");
return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable",
gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index c9eac79..0926e9b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -184,7 +184,7 @@
static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) {
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
- animator->cancel();
+ animator->end();
}
// ----------------------------------------------------------------------------
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7699da7..9b989b9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -237,12 +237,21 @@
<protected-broadcast android:name="android.net.nsd.STATE_CHANGED" />
- <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
+ <protected-broadcast android:name="android.nfc.action.ADAPTER_STATE_CHANGED" />
+ <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
+ <protected-broadcast android:name="com.android.nfc.action.LLCP_UP" />
+ <protected-broadcast android:name="com.android.nfc.action.LLCP_DOWN" />
+ <protected-broadcast android:name="com.android.nfc.cardemulation.action.CLOSE_TAP_DIALOG" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.ALLOW_CONNECT" />
+ <protected-broadcast android:name="com.android.nfc.handover.action.DENY_CONNECT" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED" />
<protected-broadcast android:name="com.android.nfc_extras.action.AID_SELECTED" />
-
- <protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
+ <!-- For NFC to BT handover -->
+ <protected-broadcast android:name="android.btopp.intent.action.WHITELIST_DEVICE" />
+ <protected-broadcast android:name="android.btopp.intent.action.STOP_HANDOVER_TRANSFER" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_SEND" />
+ <protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_SEND_MULTIPLE" />
<protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" />
<protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 68afaba..1f0e96d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2922,9 +2922,9 @@
<!-- Title of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
<string name="share_remote_bugreport_notification_title">Share bug report?</string>
<!-- Title of notification shown to indicate that bug report is still being collected after sharing was accepted. -->
- <string name="sharing_remote_bugreport_notification_title">Sharing bug report</string>
+ <string name="sharing_remote_bugreport_notification_title">Sharing bug report\u2026</string>
<!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
- <string name="share_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared. This may temporarily slow down your device.</string>
+ <string name="share_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared and your device may temporarily slow down.</string>
<!-- Message of notification shown to ask for user consent for sharing a bugreport that was requested remotely by the IT administrator. -->
<string name="share_finished_remote_bugreport_notification_message">Your IT admin requested a bug report to help troubleshoot this device. Apps and data may be shared.</string>
<!-- Message of notification shown to shown to indicate that bug report is still being collected after sharing was accepted. -->
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 77748a8..af8ccf5 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -238,6 +238,9 @@
mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas);
}
mAnimatedVectorState.mVectorDrawable.draw(canvas);
+ if (isStarted()) {
+ invalidateSelf();
+ }
}
@Override
@@ -608,6 +611,10 @@
return mAnimatorSet.isRunning();
}
+ private boolean isStarted() {
+ return mAnimatorSet.isStarted();
+ }
+
/**
* Resets the AnimatedVectorDrawable to the start state as specified in the animators.
*/
@@ -619,6 +626,12 @@
@Override
public void start() {
ensureAnimatorSet();
+
+ // If any one of the animator has not ended, do nothing.
+ if (isStarted()) {
+ return;
+ }
+
mAnimatorSet.start();
invalidateSelf();
}
@@ -639,7 +652,6 @@
@Override
public void stop() {
mAnimatorSet.end();
- invalidateSelf();
}
/**
@@ -762,9 +774,6 @@
* @hide
*/
public static class VectorDrawableAnimator {
- private static final int NONE = 0;
- private static final int START_ANIMATION = 1;
- private static final int REVERSE_ANIMATION = 2;
private AnimatorListener mListener = null;
private final LongArray mStartDelays = new LongArray();
private PropertyValuesHolder.PropertyValues mTmpValues =
@@ -773,14 +782,15 @@
private boolean mContainsSequentialAnimators = false;
private boolean mStarted = false;
private boolean mInitialized = false;
+ private boolean mAnimationPending = false;
private boolean mIsReversible = false;
// This needs to be set before parsing starts.
private boolean mShouldIgnoreInvalidAnim;
// TODO: Consider using NativeAllocationRegistery to track native allocation
private final VirtualRefBasePtr mSetRefBasePtr;
+ private WeakReference<RenderNode> mTarget = null;
private WeakReference<RenderNode> mLastSeenTarget = null;
- private int mLastListenerId = 0;
- private int mPendingAnimationAction = NONE;
+
VectorDrawableAnimator() {
mSetPtr = nCreateAnimatorSet();
@@ -800,7 +810,6 @@
mInitialized = true;
// Check reversible.
- mIsReversible = true;
if (mContainsSequentialAnimators) {
mIsReversible = false;
} else {
@@ -812,6 +821,7 @@
}
}
}
+ mIsReversible = true;
}
private void parseAnimatorSet(AnimatorSet set, long startTime) {
@@ -1032,28 +1042,36 @@
* to the last seen RenderNode target and start right away.
*/
protected void recordLastSeenTarget(DisplayListCanvas canvas) {
- mLastSeenTarget = new WeakReference<RenderNode>(
- RenderNodeAnimatorSetHelper.getTarget(canvas));
- if (mPendingAnimationAction != NONE) {
+ if (mAnimationPending) {
+ mLastSeenTarget = new WeakReference<RenderNode>(
+ RenderNodeAnimatorSetHelper.getTarget(canvas));
if (DBG_ANIMATION_VECTOR_DRAWABLE) {
Log.d(LOGTAG, "Target is set in the next frame");
}
- if (mPendingAnimationAction == START_ANIMATION) {
- start();
- } else if (mPendingAnimationAction == REVERSE_ANIMATION) {
- reverse();
- }
- mPendingAnimationAction = NONE;
+ mAnimationPending = false;
+ start();
+ } else {
+ mLastSeenTarget = new WeakReference<RenderNode>(
+ RenderNodeAnimatorSetHelper.getTarget(canvas));
}
+
+ }
+
+ private boolean setTarget(RenderNode node) {
+ if (mTarget != null && mTarget.get() != null) {
+ // TODO: Maybe we want to support target change.
+ throw new IllegalStateException("Target already set!");
+ }
+
+ node.addAnimator(this);
+ mTarget = new WeakReference<RenderNode>(node);
+ return true;
}
private boolean useLastSeenTarget() {
- if (mLastSeenTarget != null) {
- final RenderNode target = mLastSeenTarget.get();
- if (target != null && target.isAttached()) {
- target.addAnimator(this);
- return true;
- }
+ if (mLastSeenTarget != null && mLastSeenTarget.get() != null) {
+ setTarget(mLastSeenTarget.get());
+ return true;
}
return false;
}
@@ -1063,8 +1081,12 @@
return;
}
+ if (mStarted) {
+ return;
+ }
+
if (!useLastSeenTarget()) {
- mPendingAnimationAction = START_ANIMATION;
+ mAnimationPending = true;
return;
}
@@ -1072,45 +1094,38 @@
Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
}
- mStarted = true;
- nStart(mSetPtr, this, ++mLastListenerId);
+ nStart(mSetPtr, this);
if (mListener != null) {
mListener.onAnimationStart(null);
}
+ mStarted = true;
}
public void end() {
- if (mInitialized && useLastSeenTarget()) {
- // If no target has ever been set, no-op
+ if (mInitialized && mStarted) {
nEnd(mSetPtr);
+ onAnimationEnd();
}
}
- public void reset() {
- if (mInitialized && useLastSeenTarget()) {
- // If no target has ever been set, no-op
- nReset(mSetPtr);
+ void reset() {
+ if (!mInitialized) {
+ return;
}
+ // TODO: Need to implement reset.
+ Log.w(LOGTAG, "Reset is yet to be implemented");
+ nReset(mSetPtr);
}
// Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential
// animators or when the animator set has a start delay
void reverse() {
- if (!mIsReversible || !mInitialized) {
+ if (!mIsReversible) {
return;
}
- if (!useLastSeenTarget()) {
- mPendingAnimationAction = REVERSE_ANIMATION;
- return;
- }
- if (DBG_ANIMATION_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
- }
- mStarted = true;
- nReverse(mSetPtr, this, ++mLastListenerId);
- if (mListener != null) {
- mListener.onAnimationStart(null);
- }
+ // TODO: Need to support reverse (non-public API)
+ Log.w(LOGTAG, "Reverse is yet to be implemented");
+ nReverse(mSetPtr, this);
}
public long getAnimatorNativePtr() {
@@ -1140,22 +1155,20 @@
mListener = null;
}
- private void onAnimationEnd(int listenerId) {
- if (listenerId != mLastListenerId) {
- return;
- }
- if (DBG_ANIMATION_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "on finished called from native");
- }
+ private void onAnimationEnd() {
mStarted = false;
if (mListener != null) {
mListener.onAnimationEnd(null);
}
+ mTarget = null;
}
// onFinished: should be called from native
- private static void callOnFinished(VectorDrawableAnimator set, int id) {
- set.onAnimationEnd(id);
+ private static void callOnFinished(VectorDrawableAnimator set) {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "on finished called from native");
+ }
+ set.onAnimationEnd();
}
}
@@ -1175,8 +1188,8 @@
private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
float endValue);
private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
- private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set, int id);
- private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set, int id);
+ private static native void nStart(long animatorSetPtr, VectorDrawableAnimator set);
+ private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set);
private static native void nEnd(long animatorSetPtr);
private static native void nReset(long animatorSetPtr);
}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index e6276a4..1321a83 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -233,7 +233,8 @@
// not set up).
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds());
+ spec.getUserAuthenticationValidityDurationSeconds(),
+ spec.isUserAuthenticationValidWhileOnBody());
} catch (IllegalStateException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -271,7 +272,8 @@
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
KeymasterUtils.addUserAuthArgs(args,
spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds());
+ spec.getUserAuthenticationValidityDurationSeconds(),
+ spec.isUserAuthenticationValidWhileOnBody());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
mKeymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 3a0ff1c..830402a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -344,7 +344,8 @@
// not set up).
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
mSpec.isUserAuthenticationRequired(),
- mSpec.getUserAuthenticationValidityDurationSeconds());
+ mSpec.getUserAuthenticationValidityDurationSeconds(),
+ mSpec.isUserAuthenticationValidWhileOnBody());
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -529,7 +530,8 @@
KeymasterUtils.addUserAuthArgs(args,
mSpec.isUserAuthenticationRequired(),
- mSpec.getUserAuthenticationValidityDurationSeconds());
+ mSpec.getUserAuthenticationValidityDurationSeconds(),
+ mSpec.isUserAuthenticationValidWhileOnBody());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
mSpec.getKeyValidityForOriginationEnd());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 8d606bf..5f5f2c2 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -167,6 +167,8 @@
boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
&& (keymasterHwEnforcedUserAuthenticators != 0)
&& (keymasterSwEnforcedUserAuthenticators == 0);
+ boolean userAuthenticationValidWhileOnBody =
+ keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
return new KeyInfo(entryAlias,
insideSecureHardware,
@@ -182,7 +184,8 @@
blockModes,
userAuthenticationRequired,
(int) userAuthenticationValidityDurationSeconds,
- userAuthenticationRequirementEnforcedBySecureHardware);
+ userAuthenticationRequirementEnforcedBySecureHardware,
+ userAuthenticationValidWhileOnBody);
}
@Override
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index cdcc7a2..d660020 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -498,7 +498,8 @@
KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
KeymasterUtils.addUserAuthArgs(importArgs,
spec.isUserAuthenticationRequired(),
- spec.getUserAuthenticationValidityDurationSeconds());
+ spec.getUserAuthenticationValidityDurationSeconds(),
+ spec.isUserAuthenticationValidWhileOnBody());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME,
spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
@@ -692,7 +693,8 @@
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
KeymasterUtils.addUserAuthArgs(args,
params.isUserAuthenticationRequired(),
- params.getUserAuthenticationValidityDurationSeconds());
+ params.getUserAuthenticationValidityDurationSeconds(),
+ params.isUserAuthenticationValidWhileOnBody());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
args,
keymasterAlgorithm,
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index f3fd129..a84e7f34 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -252,6 +252,7 @@
private final int mUserAuthenticationValidityDurationSeconds;
private final byte[] mAttestationChallenge;
private final boolean mUniqueIdIncluded;
+ private final boolean mUserAuthenticationValidWhileOnBody;
/**
* @hide should be built with Builder
@@ -277,7 +278,8 @@
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
byte[] attestationChallenge,
- boolean uniqueIdIncluded) {
+ boolean uniqueIdIncluded,
+ boolean userAuthenticationValidWhileOnBody) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -321,6 +323,7 @@
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
mUniqueIdIncluded = uniqueIdIncluded;
+ mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
}
/**
@@ -587,6 +590,23 @@
}
/**
+ * Returns {@code true} if the key will remain authorized while the device is on the user's
+ * body, even after the validity duration has expired. This option has no effect on keys that
+ * don't have an authentication validity duration, and has no effect if the device lacks a
+ * secure on-body sensor.
+ *
+ * <p>Authorization applies only to secret key and private key operations. Public key operations
+ * are not restricted.
+ *
+ * @see #isUserAuthenticationRequired()
+ * @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setUserAuthenticationValidWhileOnBody(boolean)
+ */
+ public boolean isUserAuthenticationValidWhileOnBody() {
+ return mUserAuthenticationValidWhileOnBody;
+ }
+
+ /**
* Builder of {@link KeyGenParameterSpec} instances.
*/
public final static class Builder {
@@ -612,6 +632,7 @@
private int mUserAuthenticationValidityDurationSeconds = -1;
private byte[] mAttestationChallenge = null;
private boolean mUniqueIdIncluded = false;
+ private boolean mUserAuthenticationValidWhileOnBody;
/**
* Creates a new instance of the {@code Builder}.
@@ -1061,6 +1082,34 @@
}
/**
+ * Sets whether the key is authorized for use after the authentication validity period is
+ * expired (see {@link #setUserAuthenticationValidityDurationSeconds} and {@link
+ * #setUserAuthenticationRequired}) if the device has a secure on-body sensor and if the
+ * device has not been removed from the user's body since the last successful
+ * authentication.
+ *
+ * <p>On devices that do not have a secure on-body sensor, creating a key with this
+ * parameter set to {@code true} will have no effect; the private or secret key will no
+ * longer be authorized for use after the validity period ends, and a fresh authentication
+ * will be required to use it again.
+ *
+ * <p>Note that "secure" on-body sensors are required by Android to have a secure path to
+ * the secure hardware, but the sensors themselves may not be difficult to fool. It is
+ * recommended that this feature be used to increase slightly the security of keys which
+ * would otherwise have to allow unauthenticated access, or have a very long validity
+ * period. Keys that require high assurance of user authorization should not use this
+ * feature and should set a short validity period.
+ *
+ * @param remainsValid if {@code true}, and if the device supports secure on-body detection,
+ * key will remain valid after authentication validity duration has expired.
+ */
+ @NonNull
+ public Builder setUserAuthenticationValidWhileOnBody(boolean remainsValid) {
+ mUserAuthenticationValidWhileOnBody = remainsValid;
+ return this;
+ }
+
+ /**
* Builds an instance of {@code KeyGenParameterSpec}.
*/
@NonNull
@@ -1086,7 +1135,8 @@
mUserAuthenticationRequired,
mUserAuthenticationValidityDurationSeconds,
mAttestationChallenge,
- mUniqueIdIncluded);
+ mUniqueIdIncluded,
+ mUserAuthenticationValidWhileOnBody);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyInfo.java b/keystore/java/android/security/keystore/KeyInfo.java
index d726880..f77b5ba 100644
--- a/keystore/java/android/security/keystore/KeyInfo.java
+++ b/keystore/java/android/security/keystore/KeyInfo.java
@@ -79,6 +79,7 @@
private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mUserAuthenticationRequirementEnforcedBySecureHardware;
+ private final boolean mUserAuthenticationValidWhileOnBody;
/**
* @hide
@@ -97,7 +98,8 @@
@KeyProperties.BlockModeEnum String[] blockModes,
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
- boolean userAuthenticationRequirementEnforcedBySecureHardware) {
+ boolean userAuthenticationRequirementEnforcedBySecureHardware,
+ boolean userAuthenticationValidWhileOnBody) {
mKeystoreAlias = keystoreKeyAlias;
mInsideSecureHardware = insideSecureHardware;
mOrigin = origin;
@@ -116,6 +118,7 @@
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mUserAuthenticationRequirementEnforcedBySecureHardware =
userAuthenticationRequirementEnforcedBySecureHardware;
+ mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
}
/**
@@ -277,4 +280,14 @@
public boolean isUserAuthenticationRequirementEnforcedBySecureHardware() {
return mUserAuthenticationRequirementEnforcedBySecureHardware;
}
+
+ /**
+ * Returns {@code true} if this key will remain usable after its specified validity duration
+ * for as long as the device remains on the user's body. This is possible only for keys with
+ * a specified validity duration. Always returns {@code false} on devices that lack a secure
+ * on-body sensor.
+ */
+ public boolean isUserAuthenticationValidWhileOnBody() {
+ return mUserAuthenticationValidWhileOnBody;
+ }
}
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index c984439..4700b68 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -214,6 +214,7 @@
private final boolean mRandomizedEncryptionRequired;
private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
+ private final boolean mUserAuthenticationValidWhileOnBody;
private KeyProtection(
Date keyValidityStart,
@@ -226,7 +227,8 @@
@KeyProperties.BlockModeEnum String[] blockModes,
boolean randomizedEncryptionRequired,
boolean userAuthenticationRequired,
- int userAuthenticationValidityDurationSeconds) {
+ int userAuthenticationValidityDurationSeconds,
+ boolean userAuthenticationValidWhileOnBody) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -240,6 +242,7 @@
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
+ mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
}
/**
@@ -392,6 +395,23 @@
}
/**
+ * Returns {@code true} if the key will remain authorized while the device is on the user's
+ * body, even after the validity duration has expired. This option has no effect on keys that
+ * don't have an authentication validity duration, and has no effect if the device lacks a
+ * secure on-body sensor.
+ *
+ * <p>Authorization applies only to secret key and private key operations. Public key operations
+ * are not restricted.
+ *
+ * @see #isUserAuthenticationRequired()
+ * @see #getUserAuthenticationValidityDurationSeconds()
+ * @see Builder#setUserAuthenticationValidWhileOnBody(boolean)
+ */
+ public boolean isUserAuthenticationValidWhileOnBody() {
+ return mUserAuthenticationValidWhileOnBody;
+ }
+
+ /**
* Builder of {@link KeyProtection} instances.
*/
public final static class Builder {
@@ -407,6 +427,7 @@
private boolean mRandomizedEncryptionRequired = true;
private boolean mUserAuthenticationRequired;
private int mUserAuthenticationValidityDurationSeconds = -1;
+ private boolean mUserAuthenticationValidWhileOnBody;
/**
* Creates a new instance of the {@code Builder}.
@@ -680,6 +701,34 @@
}
/**
+ * Sets whether the key is authorized for use after the authentication validity period is
+ * expired (see {@link #setUserAuthenticationValidityDurationSeconds} and {@link
+ * #setUserAuthenticationRequired}) if the device has a secure on-body sensor and if the
+ * device has not been removed from the user's body since the last successful
+ * authentication.
+ *
+ * <p>On devices that do not have a secure on-body sensor, creating a key with this
+ * parameter set to {@code true} will have no effect; the private or secret key will no
+ * longer be authorized for use after the validity period ends, and a fresh authentication
+ * will be required to use it again.
+ *
+ * <p>Note that "secure" on-body sensors are required by Android to have a secure path to
+ * the secure hardware, but the sensors themselves may not be difficult to fool. It is
+ * recommended that this feature be used to increase slightly the security of keys which
+ * would otherwise have to allow unauthenticated access, or have a very long validity
+ * period. Keys that require high assurance of user authorization should not use this
+ * feature and should set a short validity period.
+ *
+ * @param remainsValid if {@code true}, and if the device supports secure on-body detection,
+ * key will remain valid after authentication validity duration has expired.
+ */
+ @NonNull
+ public Builder setUserAuthenticationValidWhileOnBody(boolean remainsValid) {
+ mUserAuthenticationValidWhileOnBody = remainsValid;
+ return this;
+ }
+
+ /**
* Builds an instance of {@link KeyProtection}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -697,7 +746,8 @@
mBlockModes,
mRandomizedEncryptionRequired,
mUserAuthenticationRequired,
- mUserAuthenticationValidityDurationSeconds);
+ mUserAuthenticationValidityDurationSeconds,
+ mUserAuthenticationValidWhileOnBody);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index feafbfa..3a008bc 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -96,7 +96,8 @@
*/
public static void addUserAuthArgs(KeymasterArguments args,
boolean userAuthenticationRequired,
- int userAuthenticationValidityDurationSeconds) {
+ int userAuthenticationValidityDurationSeconds,
+ boolean userAuthenticationValidWhileOnBody) {
if (!userAuthenticationRequired) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
@@ -119,6 +120,10 @@
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
KeymasterArguments.toUint64(fingerprintOnlySid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
+ if (userAuthenticationValidWhileOnBody) {
+ throw new ProviderException("Key validity extension while device is on-body is not "
+ + "supported for keys requiring fingerprint authentication");
+ }
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
@@ -133,6 +138,9 @@
KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
userAuthenticationValidityDurationSeconds);
+ if (userAuthenticationValidWhileOnBody) {
+ args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
+ }
}
}
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 294edb6..7bd2b24 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -33,7 +33,6 @@
BaseRenderNodeAnimator::BaseRenderNodeAnimator(float finalValue)
: mTarget(nullptr)
- , mStagingTarget(nullptr)
, mFinalValue(finalValue)
, mDeltaValue(0)
, mFromValue(0)
@@ -43,8 +42,7 @@
, mStartTime(0)
, mDuration(300)
, mStartDelay(0)
- , mMayRunAsync(true)
- , mPlayTime(0) {
+ , mMayRunAsync(true) {
}
BaseRenderNodeAnimator::~BaseRenderNodeAnimator() {
@@ -83,129 +81,26 @@
}
void BaseRenderNodeAnimator::attach(RenderNode* target) {
- mStagingTarget = target;
+ mTarget = target;
onAttached();
}
-void BaseRenderNodeAnimator::start() {
- mStagingPlayState = PlayState::Running;
- mStagingRequests.push_back(Request::Start);
- onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::cancel() {
- mStagingPlayState = PlayState::Finished;
- mStagingRequests.push_back(Request::Cancel);
- onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::reset() {
- mStagingPlayState = PlayState::Finished;
- mStagingRequests.push_back(Request::Reset);
- onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::reverse() {
- mStagingPlayState = PlayState::Reversing;
- mStagingRequests.push_back(Request::Reverse);
- onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::end() {
- mStagingPlayState = PlayState::Finished;
- mStagingRequests.push_back(Request::End);
- onStagingPlayStateChanged();
-}
-
-void BaseRenderNodeAnimator::resolveStagingRequest(Request request) {
- switch (request) {
- case Request::Start:
- mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
- mPlayTime : 0;
- mPlayState = PlayState::Running;
- break;
- case Request::Reverse:
- mPlayTime = (mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) ?
- mPlayTime : mDuration;
- mPlayState = PlayState::Reversing;
- break;
- case Request::Reset:
- mPlayTime = 0;
- mPlayState = PlayState::Finished;
- break;
- case Request::Cancel:
- mPlayState = PlayState::Finished;
- break;
- case Request::End:
- mPlayTime = mPlayState == PlayState::Reversing ? 0 : mDuration;
- mPlayState = PlayState::Finished;
- break;
- default:
- LOG_ALWAYS_FATAL("Invalid staging request: %d", static_cast<int>(request));
- };
-}
-
void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
- if (mStagingTarget) {
- RenderNode* oldTarget = mTarget;
- mTarget = mStagingTarget;
- mStagingTarget = nullptr;
- if (oldTarget && oldTarget != mTarget) {
- oldTarget->onAnimatorTargetChanged(this);
- }
- }
-
if (!mHasStartValue) {
doSetStartValue(getValue(mTarget));
}
-
- if (!mStagingRequests.empty()) {
- // Keep track of the play state and play time before they are changed when
- // staging requests are resolved.
- nsecs_t currentPlayTime = mPlayTime;
- PlayState prevFramePlayState = mPlayState;
-
- // Resolve staging requests one by one.
- for (Request request : mStagingRequests) {
- resolveStagingRequest(request);
+ if (mStagingPlayState > mPlayState) {
+ if (mStagingPlayState == PlayState::Restarted) {
+ mStagingPlayState = PlayState::Running;
}
- mStagingRequests.clear();
-
- if (mStagingPlayState == PlayState::Finished) {
- // Set the staging play time and end the animation
- updatePlayTime(mPlayTime);
+ mPlayState = mStagingPlayState;
+ // Oh boy, we're starting! Man the battle stations!
+ if (mPlayState == PlayState::Running) {
+ transitionToRunning(context);
+ } else if (mPlayState == PlayState::Finished) {
callOnFinishedListener(context);
- } else if (mStagingPlayState == PlayState::Running
- || mStagingPlayState == PlayState::Reversing) {
- bool changed = currentPlayTime != mPlayTime || prevFramePlayState != mStagingPlayState;
- if (prevFramePlayState != mStagingPlayState) {
- transitionToRunning(context);
- }
- if (changed) {
- // Now we need to seek to the stagingPlayTime (i.e. the animation progress that was
- // requested from UI thread). It is achieved by modifying mStartTime, such that
- // current time - mStartTime = stagingPlayTime (or mDuration -stagingPlayTime in the
- // case of reversing)
- nsecs_t currentFrameTime = context.frameTimeMs();
- if (mPlayState == PlayState::Reversing) {
- // Reverse is not supported for animations with a start delay, so here we
- // assume no start delay.
- mStartTime = currentFrameTime - (mDuration - mPlayTime);
- } else {
- // Animation should play forward
- if (mPlayTime == 0) {
- // If the request is to start from the beginning, include start delay.
- mStartTime = currentFrameTime + mStartDelay;
- } else {
- // If the request is to seek to a non-zero play time, then we skip start
- // delay.
- mStartTime = currentFrameTime - mPlayTime;
- }
- }
- }
}
}
- onPushStaging();
}
void BaseRenderNodeAnimator::transitionToRunning(AnimationContext& context) {
@@ -241,37 +136,37 @@
// This should be set before setValue() so animators can query this time when setValue
// is called.
- nsecs_t currentPlayTime = context.frameTimeMs() - mStartTime;
- bool finished = updatePlayTime(currentPlayTime);
- if (finished && mPlayState != PlayState::Finished) {
- mPlayState = PlayState::Finished;
- callOnFinishedListener(context);
- }
- return finished;
-}
+ nsecs_t currentFrameTime = context.frameTimeMs();
+ onPlayTimeChanged(currentFrameTime - mStartTime);
-bool BaseRenderNodeAnimator::updatePlayTime(nsecs_t playTime) {
- mPlayTime = mPlayState == PlayState::Reversing ? mDuration - playTime : playTime;
- onPlayTimeChanged(mPlayTime);
// If BaseRenderNodeAnimator is handling the delay (not typical), then
// because the staging properties reflect the final value, we always need
// to call setValue even if the animation isn't yet running or is still
// being delayed as we need to override the staging value
- if (playTime < 0) {
+ if (mStartTime > context.frameTimeMs()) {
setValue(mTarget, mFromValue);
return false;
}
float fraction = 1.0f;
- if ((mPlayState == PlayState::Running || mPlayState == PlayState::Reversing) && mDuration > 0) {
- fraction = mPlayTime / (float) mDuration;
+
+ if (mPlayState == PlayState::Running && mDuration > 0) {
+ fraction = (float)(currentFrameTime - mStartTime) / mDuration;
}
- fraction = MathUtils::clamp(fraction, 0.0f, 1.0f);
+ if (fraction >= 1.0f) {
+ fraction = 1.0f;
+ mPlayState = PlayState::Finished;
+ }
fraction = mInterpolator->interpolate(fraction);
setValue(mTarget, mFromValue + (mDeltaValue * fraction));
- return playTime >= mDuration;
+ if (mPlayState == PlayState::Finished) {
+ callOnFinishedListener(context);
+ return true;
+ }
+
+ return false;
}
void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
@@ -320,36 +215,18 @@
void RenderPropertyAnimator::onAttached() {
if (!mHasStartValue
- && mStagingTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
- setStartValue((mStagingTarget->stagingProperties().*mPropertyAccess->getter)());
+ && mTarget->isPropertyFieldDirty(mPropertyAccess->dirtyMask)) {
+ setStartValue((mTarget->stagingProperties().*mPropertyAccess->getter)());
}
}
void RenderPropertyAnimator::onStagingPlayStateChanged() {
if (mStagingPlayState == PlayState::Running) {
- if (mStagingTarget) {
- (mStagingTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
- } else {
- // In the case of start delay where stagingTarget has been sync'ed over and null'ed
- // we delay the properties update to push staging.
- mShouldUpdateStagingProperties = true;
- }
+ (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
} else if (mStagingPlayState == PlayState::Finished) {
// We're being canceled, so make sure that whatever values the UI thread
// is observing for us is pushed over
- mShouldSyncPropertyFields = true;
- }
-}
-
-void RenderPropertyAnimator::onPushStaging() {
- if (mShouldUpdateStagingProperties) {
- (mTarget->mutateStagingProperties().*mPropertyAccess->setter)(finalValue());
- mShouldUpdateStagingProperties = false;
- }
-
- if (mShouldSyncPropertyFields) {
mTarget->setPropertyFieldsDirty(dirtyMask());
- mShouldSyncPropertyFields = false;
}
}
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index fdae0f3..2c9c9c3 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -24,8 +24,6 @@
#include "utils/Macros.h"
-#include <vector>
-
namespace android {
namespace uirenderer {
@@ -61,14 +59,14 @@
mMayRunAsync = mayRunAsync;
}
bool mayRunAsync() { return mMayRunAsync; }
- ANDROID_API void start();
- ANDROID_API void reset();
- ANDROID_API void reverse();
- // Terminates the animation at its current progress.
- ANDROID_API void cancel();
-
- // Terminates the animation and skip to the end of the animation.
- ANDROID_API void end();
+ ANDROID_API void start() {
+ if (mStagingPlayState == PlayState::NotStarted) {
+ mStagingPlayState = PlayState::Running;
+ } else {
+ mStagingPlayState = PlayState::Restarted;
+ }
+ onStagingPlayStateChanged(); }
+ ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); }
void attach(RenderNode* target);
virtual void onAttached() {}
@@ -76,42 +74,36 @@
void pushStaging(AnimationContext& context);
bool animate(AnimationContext& context);
- bool isRunning() { return mPlayState == PlayState::Running
- || mPlayState == PlayState::Reversing; }
+ bool isRunning() { return mPlayState == PlayState::Running; }
bool isFinished() { return mPlayState == PlayState::Finished; }
float finalValue() { return mFinalValue; }
ANDROID_API virtual uint32_t dirtyMask() = 0;
void forceEndNow(AnimationContext& context);
- RenderNode* target() { return mTarget; }
- RenderNode* stagingTarget() { return mStagingTarget; }
protected:
// PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI
// thread and Render Thread animation state, respectively.
// From the UI thread, mStagingPlayState transition looks like
- // NotStarted -> Running/Reversing -> Finished
- // ^ |
- // | |
- // ----------------------
+ // NotStarted -> Running -> Finished
+ // ^ |
+ // | |
+ // Restarted <------
// Note: For mStagingState, the Finished state (optional) is only set when the animation is
// terminated by user.
//
// On Render Thread, mPlayState transition:
- // NotStart -> Running/Reversing-> Finished
- // ^ |
- // | |
- // ------------------
- // Note that if the animation is in Running/Reversing state, calling start or reverse again
- // would do nothing if the animation has the same play direction as the request; otherwise,
- // the animation would start from where it is and change direction (i.e. Reversing <-> Running)
+ // NotStart -> Running -> Finished
+ // ^ |
+ // | |
+ // -------------
enum class PlayState {
NotStarted,
Running,
- Reversing,
Finished,
+ Restarted,
};
BaseRenderNodeAnimator(float finalValue);
@@ -119,15 +111,14 @@
virtual float getValue(RenderNode* target) const = 0;
virtual void setValue(RenderNode* target, float value) = 0;
+ RenderNode* target() { return mTarget; }
void callOnFinishedListener(AnimationContext& context);
virtual void onStagingPlayStateChanged() {}
virtual void onPlayTimeChanged(nsecs_t playTime) {}
- virtual void onPushStaging() {}
RenderNode* mTarget;
- RenderNode* mStagingTarget;
float mFinalValue;
float mDeltaValue;
@@ -141,28 +132,13 @@
nsecs_t mDuration;
nsecs_t mStartDelay;
bool mMayRunAsync;
- // Play Time tracks the progress of animation, it should always be [0, mDuration], 0 being
- // the beginning of the animation, will reach mDuration at the end of an animation.
- nsecs_t mPlayTime;
sp<AnimationListener> mListener;
private:
- enum class Request {
- Start,
- Reverse,
- Reset,
- Cancel,
- End
- };
inline void checkMutable();
virtual void transitionToRunning(AnimationContext& context);
void doSetStartValue(float value);
- bool updatePlayTime(nsecs_t playTime);
- void resolveStagingRequest(Request request);
-
- std::vector<Request> mStagingRequests;
-
};
class RenderPropertyAnimator : public BaseRenderNodeAnimator {
@@ -191,7 +167,6 @@
virtual void setValue(RenderNode* target, float value) override;
virtual void onAttached() override;
virtual void onStagingPlayStateChanged() override;
- virtual void onPushStaging() override;
private:
typedef bool (RenderProperties::*SetFloatProperty)(float value);
@@ -201,8 +176,6 @@
const PropertyAccessors* mPropertyAccess;
static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
- bool mShouldSyncPropertyFields = false;
- bool mShouldUpdateStagingProperties = false;
};
class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 2198fcc..cd30b18 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -27,8 +27,9 @@
using namespace std;
-static void detach(sp<BaseRenderNodeAnimator>& animator) {
+static void unref(BaseRenderNodeAnimator* animator) {
animator->detach();
+ animator->decStrong(nullptr);
}
AnimatorManager::AnimatorManager(RenderNode& parent)
@@ -37,28 +38,14 @@
}
AnimatorManager::~AnimatorManager() {
- for_each(mNewAnimators.begin(), mNewAnimators.end(), detach);
- for_each(mAnimators.begin(), mAnimators.end(), detach);
+ for_each(mNewAnimators.begin(), mNewAnimators.end(), unref);
+ for_each(mAnimators.begin(), mAnimators.end(), unref);
}
void AnimatorManager::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
- RenderNode* stagingTarget = animator->stagingTarget();
- if (stagingTarget == &mParent) {
- return;
- }
- mNewAnimators.emplace_back(animator.get());
- // If the animator is already attached to other RenderNode, remove it from that RenderNode's
- // new animator list. This ensures one animator only ends up in one newAnimatorList during one
- // frame, even when it's added multiple times to multiple targets.
- if (stagingTarget) {
- stagingTarget->removeAnimator(animator);
- }
+ animator->incStrong(nullptr);
animator->attach(&mParent);
-}
-
-void AnimatorManager::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
- mNewAnimators.erase(std::remove(mNewAnimators.begin(), mNewAnimators.end(), animator),
- mNewAnimators.end());
+ mNewAnimators.push_back(animator.get());
}
void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
@@ -69,40 +56,38 @@
&mParent, mParent.getName());
}
+template<typename T>
+static void move_all(T& source, T& dest) {
+ dest.reserve(source.size() + dest.size());
+ for (typename T::iterator it = source.begin(); it != source.end(); it++) {
+ dest.push_back(*it);
+ }
+ source.clear();
+}
+
void AnimatorManager::pushStaging() {
if (mNewAnimators.size()) {
LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
"Trying to start new animators on %p (%s) without an animation handle!",
&mParent, mParent.getName());
-
- // Only add new animators that are not already in the mAnimators list
- for (auto& anim : mNewAnimators) {
- if (anim->target() != &mParent) {
- mAnimators.push_back(std::move(anim));
- }
- }
- mNewAnimators.clear();
+ // Since this is a straight move, we don't need to inc/dec the ref count
+ move_all(mNewAnimators, mAnimators);
}
- for (auto& animator : mAnimators) {
- animator->pushStaging(mAnimationHandle->context());
+ for (vector<BaseRenderNodeAnimator*>::iterator it = mAnimators.begin(); it != mAnimators.end(); it++) {
+ (*it)->pushStaging(mAnimationHandle->context());
}
}
-void AnimatorManager::onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
- LOG_ALWAYS_FATAL_IF(animator->target() == &mParent, "Target has not been changed");
- mAnimators.erase(std::remove(mAnimators.begin(), mAnimators.end(), animator), mAnimators.end());
-}
-
class AnimateFunctor {
public:
AnimateFunctor(TreeInfo& info, AnimationContext& context)
: dirtyMask(0), mInfo(info), mContext(context) {}
- bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+ bool operator() (BaseRenderNodeAnimator* animator) {
dirtyMask |= animator->dirtyMask();
bool remove = animator->animate(mContext);
if (remove) {
- animator->detach();
+ animator->decStrong(nullptr);
} else {
if (animator->isRunning()) {
mInfo.out.hasAnimations = true;
@@ -144,18 +129,20 @@
uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
AnimateFunctor functor(info, mAnimationHandle->context());
- auto newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
+ std::vector< BaseRenderNodeAnimator* >::iterator newEnd;
+ newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mAnimationHandle->notifyAnimationsRan();
mParent.mProperties.updateMatrix();
return functor.dirtyMask;
}
-static void endStagingAnimator(sp<BaseRenderNodeAnimator>& animator) {
- animator->cancel();
+static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
+ animator->end();
if (animator->listener()) {
- animator->listener()->onAnimationFinished(animator.get());
+ animator->listener()->onAnimationFinished(animator);
}
+ animator->decStrong(nullptr);
}
void AnimatorManager::endAllStagingAnimators() {
@@ -170,8 +157,9 @@
public:
EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
- void operator() (sp<BaseRenderNodeAnimator>& animator) {
+ void operator() (BaseRenderNodeAnimator* animator) {
animator->forceEndNow(mContext);
+ animator->decStrong(nullptr);
}
private:
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index 61f6179..fb75eb8 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -39,13 +39,11 @@
~AnimatorManager();
void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
- void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
void setAnimationHandle(AnimationHandle* handle);
bool hasAnimationHandle() { return mAnimationHandle; }
void pushStaging();
- void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator);
// Returns the combined dirty mask of all animators run
uint32_t animate(TreeInfo& info);
@@ -68,8 +66,9 @@
AnimationHandle* mAnimationHandle;
// To improve the efficiency of resizing & removing from the vector
- std::vector< sp<BaseRenderNodeAnimator> > mNewAnimators;
- std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
+ // use manual ref counting instead of sp<>.
+ std::vector<BaseRenderNodeAnimator*> mNewAnimators;
+ std::vector<BaseRenderNodeAnimator*> mAnimators;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp
index b29f91f..eca1afcc 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.cpp
+++ b/libs/hwui/PropertyValuesAnimatorSet.cpp
@@ -17,8 +17,6 @@
#include "PropertyValuesAnimatorSet.h"
#include "RenderNode.h"
-#include <algorithm>
-
namespace android {
namespace uirenderer {
@@ -55,26 +53,16 @@
}
void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) {
- if (playTime == 0 && mDuration > 0) {
- // Reset all the animators
- for (auto it = mAnimators.rbegin(); it != mAnimators.rend(); it++) {
- // Note that this set may containing animators modifying the same property, so when we
- // reset the animators, we need to make sure the animators that end the first will
- // have the final say on what the property value should be.
- (*it)->setFraction(0);
- }
- } else if (playTime >= mDuration) {
- // Skip all the animators to end
- for (auto& anim : mAnimators) {
- anim->setFraction(1);
- }
- } else {
- for (auto& anim : mAnimators) {
- anim->setCurrentPlayTime(playTime);
- }
+ for (size_t i = 0; i < mAnimators.size(); i++) {
+ mAnimators[i]->setCurrentPlayTime(playTime);
}
}
+void PropertyValuesAnimatorSet::reset() {
+ // TODO: implement reset through adding a play state because we need to support reset() even
+ // during an animation run.
+}
+
void PropertyValuesAnimatorSet::start(AnimationListener* listener) {
init();
mOneShotListener = listener;
@@ -82,23 +70,20 @@
}
void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) {
- init();
- mOneShotListener = listener;
- BaseRenderNodeAnimator::reverse();
+// TODO: implement reverse
}
void PropertyValuesAnimatorSet::init() {
if (mInitialized) {
return;
}
-
- // Sort the animators by their total duration. Note that all the animators in the set start at
- // the same time, so the ones with longer total duration (which includes start delay) will
- // be the ones that end later.
- std::sort(mAnimators.begin(), mAnimators.end(), [](auto& a, auto&b) {
- return a->getTotalDuration() < b->getTotalDuration();
- });
- mDuration = mAnimators[mAnimators.size() - 1]->getTotalDuration();
+ nsecs_t maxDuration = 0;
+ for (size_t i = 0; i < mAnimators.size(); i++) {
+ if (maxDuration < mAnimators[i]->getTotalDuration()) {
+ maxDuration = mAnimators[i]->getTotalDuration();
+ }
+ }
+ mDuration = maxDuration;
mInitialized = true;
}
@@ -121,19 +106,18 @@
void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) {
if (playTime >= mStartDelay && playTime < mTotalDuration) {
nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration;
- float fraction = currentIterationPlayTime / (float) mDuration;
- setFraction(fraction);
+ mLatestFraction = currentIterationPlayTime / (float) mDuration;
} else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) {
- // This makes sure we only set the fraction = 1 once. It is needed because there might
- // be another animator modifying the same property after this animator finishes, we need
- // to make sure we don't set conflicting values on the same property within one frame.
- setFraction(1.0f);
+ mLatestFraction = 1.0f;
+ } else {
+ return;
}
+
+ setFraction(mLatestFraction);
}
void PropertyAnimator::setFraction(float fraction) {
- mLatestFraction = fraction;
- float interpolatedFraction = mInterpolator->interpolate(fraction);
+ float interpolatedFraction = mInterpolator->interpolate(mLatestFraction);
mPropertyValuesHolder->setFraction(interpolatedFraction);
}
diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h
index c7ae7c0..4c7ce52 100644
--- a/libs/hwui/PropertyValuesAnimatorSet.h
+++ b/libs/hwui/PropertyValuesAnimatorSet.h
@@ -50,6 +50,7 @@
void start(AnimationListener* listener);
void reverse(AnimationListener* listener);
+ void reset();
void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder,
Interpolator* interpolators, int64_t startDelays,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 9ac76a4..bade216 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -218,10 +218,6 @@
mAnimatorManager.addAnimator(animator);
}
-void RenderNode::removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
- mAnimatorManager.removeAnimator(animator);
-}
-
void RenderNode::damageSelf(TreeInfo& info) {
if (isRenderable()) {
if (properties().getClipDamageToBounds()) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index e037645..f248de54 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -187,12 +187,6 @@
// UI thread only!
ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
- void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);
-
- // This can only happen during pushStaging()
- void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
- mAnimatorManager.onAnimatorTargetChanged(animator);
- }
AnimatorManager& animators() { return mAnimatorManager; }
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml b/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
index 6f98509..6f153c1 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
@@ -41,26 +41,6 @@
</FrameLayout>
- <FrameLayout
- android:id="@+id/lights_out"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@+id/ends_group_lightsout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal" />
-
- <LinearLayout
- android:id="@+id/center_group_lightsout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="horizontal" />
-
- </FrameLayout>
-
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index 142d13a..2bf4d9c 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -42,26 +42,6 @@
</FrameLayout>
- <FrameLayout
- android:id="@+id/lights_out"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@+id/ends_group_lightsout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal" />
-
- <LinearLayout
- android:id="@+id/center_group_lightsout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="horizontal" />
-
- </FrameLayout>
-
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
index 3b7b369..7601efc 100644
--- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_rot90.xml
@@ -42,26 +42,6 @@
</FrameLayout>
- <FrameLayout
- android:id="@+id/lights_out"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.android.systemui.statusbar.phone.ReverseLinearLayout
- android:id="@+id/ends_group_lightsout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" />
-
- <com.android.systemui.statusbar.phone.ReverseLinearLayout
- android:id="@+id/center_group_lightsout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="vertical" />
-
- </FrameLayout>
-
<com.android.systemui.statusbar.policy.DeadZone
android:id="@+id/deadzone"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index bed8f1b..858f487 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -50,30 +50,6 @@
android:layout_height="0dp"
android:layout_weight="1" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingEnd="8dp"
- android:gravity="end">
+ <include layout="@layout/qs_detail_buttons" />
- <TextView
- android:id="@android:id/button2"
- style="@style/QSBorderlessButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginEnd="8dp"
- android:minWidth="132dp"
- android:textAppearance="@style/TextAppearance.QS.DetailButton"
- android:focusable="true" />
-
- <TextView
- android:id="@android:id/button1"
- style="@style/QSBorderlessButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:minWidth="88dp"
- android:textAppearance="@style/TextAppearance.QS.DetailButton"
- android:focusable="true"/>
-
- </LinearLayout>
</com.android.systemui.qs.QSDetail>
diff --git a/packages/SystemUI/res/layout/qs_detail_buttons.xml b/packages/SystemUI/res/layout/qs_detail_buttons.xml
new file mode 100644
index 0000000..03ed62b
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_buttons.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="8dp"
+ android:gravity="end">
+
+ <TextView
+ android:id="@android:id/button2"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:minWidth="132dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:focusable="true" />
+
+ <TextView
+ android:id="@android:id/button1"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="88dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton"
+ android:focusable="true"/>
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/tuner_zen_mode_panel.xml b/packages/SystemUI/res/layout/tuner_zen_mode_panel.xml
new file mode 100644
index 0000000..efe63d7
--- /dev/null
+++ b/packages/SystemUI/res/layout/tuner_zen_mode_panel.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2016 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.
+-->
+<!-- extends LinearLayout -->
+<com.android.systemui.tuner.TunerZenModePanel
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/tuner_zen_mode_panel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:visibility="gone"
+ android:orientation="vertical" >
+
+ <View
+ android:id="@+id/zen_embedded_divider"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginBottom="12dp"
+ android:layout_marginTop="8dp"
+ android:background="@color/qs_tile_divider" />
+
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:layout_marginStart="16dp"
+ android:id="@+id/tuner_zen_switch"
+ layout="@layout/qs_detail_header" />
+
+ <include layout="@layout/zen_mode_panel" />
+
+ <include
+ android:id="@+id/tuner_zen_buttons"
+ layout="@layout/qs_detail_buttons" />
+
+</com.android.systemui.tuner.TunerZenModePanel>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 34796cd..e4effd4 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -46,7 +46,7 @@
<include layout="@layout/volume_zen_footer" />
<!-- Only shown from Tuner setting -->
- <include layout="@layout/zen_mode_panel" />
+ <include layout="@layout/tuner_zen_mode_panel" />
</LinearLayout>
</RelativeLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index fa5b1a9..6135dc6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -810,12 +810,6 @@
<!-- Interruption level: Alarms only. Optimized for narrow two-line display. [CHAR LIMIT=40] -->
<string name="interruption_level_alarms_twoline">Alarms\nonly</string>
- <!-- Interruption level: All interruptions. [CHAR LIMIT=40] -->
- <string name="interruption_level_all">All</string>
-
- <!-- Interruption level: All interruptions. Optimized for narrow two-line display. [CHAR LIMIT=40] -->
- <string name="interruption_level_all_twoline">All\n</string>
-
<!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=40]-->
<string name="keyguard_indication_charging_time">Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 90d56f7..6029c23 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -758,7 +758,7 @@
mPendingLock = false;
}
}
- doKeyguardLaterLockedForChildProfiles();
+ doKeyguardForChildProfilesLocked();
KeyguardUpdateMonitor.getInstance(mContext).dispatchFinishedGoingToSleep(why);
}
@@ -781,8 +781,7 @@
long timeout;
- if ((mLockPatternUtils.isSeparateProfileChallengeEnabled(userId))
- || policyTimeout <= 0) {
+ if (policyTimeout <= 0) {
timeout = lockAfterTimeout;
} else {
// From DisplaySettings
@@ -815,23 +814,31 @@
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender);
if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = "
+ mDelayedShowingSequence);
- doKeyguardLaterLockedForChildProfiles();
+ doKeyguardLaterForChildProfilesLocked();
}
- private void doKeyguardLaterLockedForChildProfiles() {
+ private void doKeyguardLaterForChildProfilesLocked() {
UserManager um = UserManager.get(mContext);
List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
- if (profiles.size() > 1) {
- for (UserInfo info : profiles) {
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
- long userTimeout = getLockTimeout(info.id);
- long userWhen = SystemClock.elapsedRealtime() + userTimeout;
- Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
- lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id);
- PendingIntent lockSender = PendingIntent.getBroadcast(
- mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, userWhen, lockSender);
- }
+ for (UserInfo info : profiles) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
+ long userTimeout = getLockTimeout(info.id);
+ long userWhen = SystemClock.elapsedRealtime() + userTimeout;
+ Intent lockIntent = new Intent(DELAYED_LOCK_PROFILE_ACTION);
+ lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id);
+ PendingIntent lockSender = PendingIntent.getBroadcast(
+ mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, userWhen, lockSender);
+ }
+ }
+ }
+
+ private void doKeyguardForChildProfilesLocked() {
+ UserManager um = UserManager.get(mContext);
+ List<UserInfo> profiles = um.getEnabledProfiles(UserHandle.myUserId());
+ for (UserInfo info : profiles) {
+ if (mLockPatternUtils.isSeparateProfileChallengeEnabled(info.id)) {
+ lockProfile(info.id);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index a58fa86..8a93c5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -23,6 +23,7 @@
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.support.v4.util.SimpleArrayMap;
+import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.LinearLayout;
@@ -71,6 +72,7 @@
private int mCurrentFacetIndex;
private String mCurrentPackageName;
+ private SparseBooleanArray mFacetHasMultipleAppsCache = new SparseBooleanArray();
public CarNavigationBarController(Context context,
CarNavigationBarView navBar,
@@ -96,6 +98,21 @@
}
}
+ public void onPackageChange(String packageName) {
+ if (mFacetPackageMap.containsKey(packageName)) {
+ int index = mFacetPackageMap.get(packageName);
+ mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index));
+ // No need to check categories because we've already refreshed the cache.
+ return;
+ }
+
+ String category = getPackageCategory(packageName);
+ if (mFacetCategoryMap.containsKey(category)) {
+ int index = mFacetCategoryMap.get(packageName);
+ mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index));
+ }
+ }
+
private void bind() {
// Read up arrays_car.xml and populate the navigation bar here.
Resources r = mContext.getResources();
@@ -138,6 +155,7 @@
initFacetFilterMaps(i,
facetPackageNames.getString(i).split(FACET_FILTER_DEMILITER),
facetCategories.getString(i).split(FACET_FILTER_DEMILITER));
+ mFacetHasMultipleAppsCache.put(i, facetHasMultiplePackages(i));
} catch (URISyntaxException e) {
throw new RuntimeException("Malformed intent uri", e);
}
@@ -229,7 +247,7 @@
if (mNavButtons.get(index) != null) {
mNavButtons.get(index).setSelected(true /* selected */,
- facetHasMultiplePackages(index) /* showMoreIcon */);
+ mFacetHasMultipleAppsCache.get(index) /* showMoreIcon */);
}
mCurrentFacetIndex = index;
}
@@ -268,7 +286,7 @@
private void startActivity(Intent intent) {
if (mActivityStarter != null && intent != null) {
- mActivityStarter.startActivity(intent, true);
+ mActivityStarter.startActivity(intent, false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 08cd053..c32ef0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -18,7 +18,10 @@
import android.app.ActivityManager;
import android.app.ITaskStackListener;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Looper;
@@ -52,6 +55,7 @@
mTaskStackListener = new TaskStackListenerImpl(mHandler);
mSystemServicesProxy = new SystemServicesProxy(mContext);
mSystemServicesProxy.registerTaskStackListener(mTaskStackListener);
+ registerPackageChangeReceivers();
}
@Override
@@ -81,6 +85,26 @@
mController = new CarNavigationBarController(context, mCarNavigationBar,
this /* ActivityStarter*/);
mNavigationBarView = mCarNavigationBar;
+
+ }
+
+ private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getData() == null || mController == null) {
+ return;
+ }
+ String packageName = intent.getData().getSchemeSpecificPart();
+ mController.onPackageChange(packageName);
+ }
+ };
+
+ private void registerPackageChangeReceivers() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addDataScheme("package");
+ mContext.registerReceiver(mPackageChangeReceiver, filter);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index d625fc2..260c969 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -163,68 +163,29 @@
String[] start = sets[0].split(BUTTON_SEPARATOR);
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
- inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group),
- (ViewGroup) mRot0.findViewById(R.id.ends_group_lightsout), false);
- inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group),
- (ViewGroup) mRot90.findViewById(R.id.ends_group_lightsout), true);
+ inflateButtons(start, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
+ inflateButtons(start, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
- inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group),
- (ViewGroup) mRot0.findViewById(R.id.center_group_lightsout), false);
- inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group),
- (ViewGroup) mRot90.findViewById(R.id.center_group_lightsout), true);
+ inflateButtons(center, (ViewGroup) mRot0.findViewById(R.id.center_group), false);
+ inflateButtons(center, (ViewGroup) mRot90.findViewById(R.id.center_group), true);
addGravitySpacer((LinearLayout) mRot0.findViewById(R.id.ends_group));
addGravitySpacer((LinearLayout) mRot90.findViewById(R.id.ends_group));
- inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group),
- (ViewGroup) mRot0.findViewById(R.id.ends_group_lightsout), false);
- inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group),
- (ViewGroup) mRot90.findViewById(R.id.ends_group_lightsout), true);
+ inflateButtons(end, (ViewGroup) mRot0.findViewById(R.id.ends_group), false);
+ inflateButtons(end, (ViewGroup) mRot90.findViewById(R.id.ends_group), true);
}
private void addGravitySpacer(LinearLayout layout) {
layout.addView(new Space(mContext), new LinearLayout.LayoutParams(0, 0, 1));
}
- private void inflateButtons(String[] buttons, ViewGroup parent, ViewGroup lightsOutParent,
- boolean landscape) {
+ private void inflateButtons(String[] buttons, ViewGroup parent, boolean landscape) {
for (int i = 0; i < buttons.length; i++) {
- copyToLightsout(inflateButton(buttons[i], parent, landscape), lightsOutParent);
+ inflateButton(buttons[i], parent, landscape);
}
}
- private void copyToLightsout(View view, ViewGroup lightsOutParent) {
- if (view == null) return;
-
- if (view instanceof FrameLayout) {
- // The only ViewGroup we support in here is a FrameLayout, so copy those manually.
- FrameLayout original = (FrameLayout) view;
- FrameLayout layout = new FrameLayout(view.getContext());
- for (int i = 0; i < original.getChildCount(); i++) {
- copyToLightsout(original.getChildAt(i), layout);
- }
- lightsOutParent.addView(layout, copy(view.getLayoutParams()));
- } else if (view instanceof Space) {
- lightsOutParent.addView(new Space(view.getContext()), copy(view.getLayoutParams()));
- } else {
- lightsOutParent.addView(generateLightsOutView(view), copy(view.getLayoutParams()));
- }
- }
-
- private View generateLightsOutView(View view) {
- ImageView imageView = new ImageView(view.getContext());
- // Copy everything we can about the original view.
- imageView.setPadding(view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(),
- view.getPaddingBottom());
- imageView.setContentDescription(view.getContentDescription());
- imageView.setId(view.getId());
- // Only home gets a big dot, everything else will be little.
- imageView.setImageResource(view.getId() == R.id.home
- ? R.drawable.ic_sysbar_lights_out_dot_large
- : R.drawable.ic_sysbar_lights_out_dot_small);
- return imageView;
- }
-
private ViewGroup.LayoutParams copy(ViewGroup.LayoutParams layoutParams) {
if (layoutParams instanceof LinearLayout.LayoutParams) {
return new LinearLayout.LayoutParams(layoutParams.width, layoutParams.height,
@@ -348,9 +309,7 @@
}
}
clearAllChildren((ViewGroup) mRot0.findViewById(R.id.nav_buttons));
- clearAllChildren((ViewGroup) mRot0.findViewById(R.id.lights_out));
clearAllChildren((ViewGroup) mRot90.findViewById(R.id.nav_buttons));
- clearAllChildren((ViewGroup) mRot90.findViewById(R.id.lights_out));
}
private void clearAllChildren(ViewGroup group) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 134c579..1fe0115 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -64,42 +64,20 @@
mLightsOut = lightsOut;
final View navButtons = mView.getCurrentView().findViewById(R.id.nav_buttons);
- final View lowLights = mView.getCurrentView().findViewById(R.id.lights_out);
// ok, everyone, stop it right there
navButtons.animate().cancel();
- lowLights.animate().cancel();
- final float navButtonsAlpha = lightsOut ? 0f : 1f;
- final float lowLightsAlpha = lightsOut ? 1f : 0f;
+ final float navButtonsAlpha = lightsOut ? 0.5f : 1f;
if (!animate) {
navButtons.setAlpha(navButtonsAlpha);
- lowLights.setAlpha(lowLightsAlpha);
- lowLights.setVisibility(lightsOut ? View.VISIBLE : View.GONE);
} else {
final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION;
navButtons.animate()
.alpha(navButtonsAlpha)
.setDuration(duration)
.start();
-
- lowLights.setOnTouchListener(mLightsOutListener);
- if (lowLights.getVisibility() == View.GONE) {
- lowLights.setAlpha(0f);
- lowLights.setVisibility(View.VISIBLE);
- }
- lowLights.animate()
- .alpha(lowLightsAlpha)
- .setDuration(duration)
- .setInterpolator(new AccelerateInterpolator(2.0f))
- .setListener(lightsOut ? null : new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator _a) {
- lowLights.setVisibility(View.GONE);
- }
- })
- .start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 97d7dd5..6698076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -79,7 +79,7 @@
private Drawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
private Drawable mHomeDefaultIcon, mHomeCarModeIcon;
private Drawable mRecentIcon;
- private Drawable mRecentLandIcon;
+ private Drawable mDockedIcon;
private NavigationBarGestureHelper mGestureHelper;
private DeadZone mDeadZone;
@@ -97,6 +97,7 @@
private boolean mLayoutTransitionsEnabled = true;
private boolean mWakeAndUnlocking;
private boolean mCarMode = false;
+ private boolean mDockedStackExists;
private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
@@ -280,7 +281,7 @@
mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
- mRecentLandIcon = mRecentIcon;
+ mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
getCarModeIcons(ctx);
}
@@ -335,8 +336,7 @@
getBackButton().setImageDrawable(backIcon);
- getRecentsButton().setImageDrawable(
- mVertical ? mRecentLandIcon : mRecentIcon);
+ updateRecentsIcon();
if (mCarMode) {
getHomeButton().setImageDrawable(mHomeCarModeIcon);
@@ -507,7 +507,8 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- updateRecentsIcon(exists);
+ mDockedStackExists = exists;
+ updateRecentsIcon();
}
});
}
@@ -517,10 +518,8 @@
}
}
- private void updateRecentsIcon(boolean dockedStackExists) {
- getRecentsButton().setImageResource(dockedStackExists
- ? R.drawable.ic_sysbar_docked
- : R.drawable.ic_sysbar_recent);
+ private void updateRecentsIcon() {
+ getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
}
public boolean isVertical() {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index 5ded885..ad42459 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -117,13 +117,9 @@
if (isRotated) {
mPreview.findViewById(R.id.rot0).setVisibility(View.GONE);
final View rot90 = mPreview.findViewById(R.id.rot90);
- rot90.findViewById(R.id.ends_group_lightsout).setVisibility(View.GONE);
- rot90.findViewById(R.id.center_group_lightsout).setVisibility(View.GONE);
} else {
mPreview.findViewById(R.id.rot90).setVisibility(View.GONE);
final View rot0 = mPreview.findViewById(R.id.rot0);
- rot0.findViewById(R.id.ends_group_lightsout).setVisibility(View.GONE);
- rot0.findViewById(R.id.center_group_lightsout).setVisibility(View.GONE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
new file mode 100644
index 0000000..cc0ffb0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 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.tuner;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Checkable;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.systemui.Prefs;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.volume.ZenModePanel;
+import com.android.systemui.volume.ZenModePanel.Callback;
+
+public class TunerZenModePanel extends LinearLayout implements OnClickListener {
+ private static final String TAG = "TunerZenModePanel";
+
+ private Callback mCallback;
+ private ZenModePanel mZenModePanel;
+ private View mHeaderSwitch;
+ private int mZenMode;
+ private ZenModeController mController;
+ private View mButtons;
+ private View mMoreSettings;
+ private View mDone;
+ private OnClickListener mDoneListener;
+ private boolean mEditing;
+
+ public TunerZenModePanel(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void init(ZenModeController zenModeController) {
+ mController = zenModeController;
+ mHeaderSwitch = findViewById(R.id.tuner_zen_switch);
+ mHeaderSwitch.setVisibility(View.VISIBLE);
+ mHeaderSwitch.setOnClickListener(this);
+ mHeaderSwitch.findViewById(com.android.internal.R.id.up).setVisibility(View.GONE);
+ ((TextView) mHeaderSwitch.findViewById(android.R.id.title)).setText(
+ R.string.quick_settings_dnd_label);
+ mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel);
+ mZenModePanel.init(zenModeController);
+ mButtons = findViewById(R.id.tuner_zen_buttons);
+ mMoreSettings = mButtons.findViewById(android.R.id.button2);
+ mMoreSettings.setOnClickListener(this);
+ ((TextView) mMoreSettings).setText(R.string.quick_settings_more_settings);
+ mDone = mButtons.findViewById(android.R.id.button1);
+ mDone.setOnClickListener(this);
+ ((TextView) mDone).setText(R.string.quick_settings_done);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mEditing = false;
+ }
+
+ public void setCallback(Callback zenPanelCallback) {
+ mCallback = zenPanelCallback;
+ mZenModePanel.setCallback(zenPanelCallback);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mHeaderSwitch) {
+ mEditing = true;
+ if (mZenMode == Global.ZEN_MODE_OFF) {
+ mZenMode = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN,
+ Global.ZEN_MODE_ALARMS);
+ mController.setZen(mZenMode, null, TAG);
+ postUpdatePanel();
+ } else {
+ mZenMode = Global.ZEN_MODE_OFF;
+ mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
+ postUpdatePanel();
+ }
+ } else if (v == mMoreSettings) {
+ Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(intent);
+ } else if (v == mDone) {
+ mEditing = false;
+ setVisibility(View.GONE);
+ mDoneListener.onClick(v);
+ }
+ }
+
+ public boolean isEditing() {
+ return mEditing;
+ }
+
+ public void setZenState(int zenMode) {
+ mZenMode = zenMode;
+ postUpdatePanel();
+ }
+
+ private void postUpdatePanel() {
+ // The complicated structure from reusing the same ZenPanel has resulted in some
+ // unstableness/flickering from callbacks coming in quickly. To solve this just
+ // post the UI updates a little bit.
+ removeCallbacks(mUpdate);
+ postDelayed(mUpdate, 40);
+ }
+
+ public void setDoneListener(OnClickListener onClickListener) {
+ mDoneListener = onClickListener;
+ }
+
+ private void updatePanel() {
+ boolean zenOn = mZenMode != Global.ZEN_MODE_OFF;
+ ((Checkable) mHeaderSwitch.findViewById(android.R.id.toggle)).setChecked(zenOn);
+ mZenModePanel.setVisibility(zenOn ? View.VISIBLE : View.GONE);
+ mButtons.setVisibility(zenOn ? View.VISIBLE : View.GONE);
+ }
+
+ private final Runnable mUpdate = new Runnable() {
+ @Override
+ public void run() {
+ updatePanel();
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index 7b1764f..56a604d 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -37,7 +37,8 @@
private View mGuideOverlayView;
private final Runnable mHideGuideOverlayRunnable = new Runnable() {
public void run() {
- mGuideOverlayView.setVisibility(View.INVISIBLE);
+ // TODO: Uncomment this after the b/27224884 is fixed.
+ //mGuideOverlayView.setVisibility(View.INVISIBLE);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 6aae9bd..1810c1c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -67,6 +67,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerZenModePanel;
import com.android.systemui.volume.VolumeDialogController.State;
import com.android.systemui.volume.VolumeDialogController.StreamState;
@@ -133,7 +134,7 @@
private int mLastActiveStream;
private boolean mShowFullZen;
- private final ZenModePanel mZenPanel;
+ private final TunerZenModePanel mZenPanel;
public VolumeDialog(Context context, int windowType, VolumeDialogController controller,
ZenModeController zenModeController, Callback callback) {
@@ -225,8 +226,7 @@
mExpandButtonAnimationDuration = res.getInteger(R.integer.volume_expand_animation_duration);
mZenFooter = (ZenFooter) mDialog.findViewById(R.id.volume_zen_footer);
mZenFooter.init(zenModeController);
- mZenPanel = (ZenModePanel) mDialog.findViewById(R.id.zen_mode_panel);
- mZenPanel.addNoneButton();
+ mZenPanel = (TunerZenModePanel) mDialog.findViewById(R.id.tuner_zen_mode_panel);
mZenPanel.init(zenModeController);
mZenPanel.setCallback(mZenPanelCallback);
@@ -671,7 +671,7 @@
final boolean wasVisible = mZenFooter.getVisibility() == View.VISIBLE;
final boolean visible = mState.zenMode != Global.ZEN_MODE_OFF
&& (mAudioManager.isStreamAffectedByRingerMode(mActiveStream) || mExpanded)
- && !mShowFullZen;
+ && !mZenPanel.isEditing();
if (wasVisible != visible && !visible) {
prepareForCollapse();
}
@@ -679,12 +679,21 @@
mZenFooter.update();
final boolean fullWasVisible = mZenPanel.getVisibility() == View.VISIBLE;
- final boolean fullVisible = mShowFullZen && (mState.zenMode != Global.ZEN_MODE_OFF
- || mExpanded);
+ final boolean fullVisible = mShowFullZen && !visible;
if (fullWasVisible != fullVisible && !fullVisible) {
prepareForCollapse();
}
Util.setVisOrGone(mZenPanel, fullVisible);
+ if (fullVisible) {
+ mZenPanel.setZenState(mState.zenMode);
+ mZenPanel.setDoneListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ prepareForCollapse();
+ mHandler.sendEmptyMessage(H.UPDATE_FOOTER);
+ }
+ });
+ }
}
private void updateVolumeRowH(VolumeRow row) {
@@ -978,6 +987,7 @@
private static final int RESCHEDULE_TIMEOUT = 6;
private static final int STATE_CHANGED = 7;
private static final int UPDATE_BOTTOM_MARGIN = 8;
+ private static final int UPDATE_FOOTER = 9;
public H() {
super(Looper.getMainLooper());
@@ -994,6 +1004,7 @@
case RESCHEDULE_TIMEOUT: rescheduleTimeoutH(); break;
case STATE_CHANGED: onStateChangedH(mState); break;
case UPDATE_BOTTOM_MARGIN: updateDialogBottomMarginH(); break;
+ case UPDATE_FOOTER: updateFooterH(); break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 5ca24f7..6976c0b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -190,12 +190,6 @@
mZenAlarmWarning = (TextView) findViewById(R.id.zen_alarm_warning);
}
- public void addNoneButton() {
- mZenButtons.addButton(R.string.interruption_level_all_twoline,
- R.string.interruption_level_all,
- Global.ZEN_MODE_OFF);
- }
-
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 9e6cd00..3ecff40 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -467,17 +467,18 @@
if (mCurrentState == STATE_GESTURE_DETECTING) {
endGestureDetection();
} else if (mCurrentState == STATE_TOUCH_EXPLORING) {
- final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
- final int pointerIdBits = (1 << pointerId);
+ // If the finger is still moving, pass the event on.
+ if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
+ final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
+ final int pointerIdBits = (1 << pointerId);
- // Cache the event until we discern exploration from gesturing.
- mSendHoverEnterAndMoveDelayed.addEvent(event);
-
- // We have just decided that the user is touch,
- // exploring so start sending events.
- mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
- mSendHoverExitDelayed.cancel();
- sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
+ // We have just decided that the user is touch,
+ // exploring so start sending events.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
+ mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+ mSendHoverExitDelayed.cancel();
+ sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags);
+ }
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 7770d53..507ac22 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -940,35 +940,18 @@
private void resetDefaultImeLocked(Context context) {
// Do not reset the default (current) IME when it is a 3rd-party IME
- if (mCurMethodId != null
- && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
+ if (mCurMethodId != null && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
return;
}
-
- InputMethodInfo defIm = null;
- for (InputMethodInfo imi : mMethodList) {
- if (defIm == null && mSystemReady) {
- final Locale systemLocale = context.getResources().getConfiguration().locale;
- if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
- true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
- InputMethodUtils.SUBTYPE_MODE_ANY)) {
- defIm = imi;
- Slog.i(TAG, "Selected default: " + imi.getId());
- }
- }
+ final List<InputMethodInfo> suitableImes = InputMethodUtils.getDefaultEnabledImes(
+ context, mSystemReady, mSettings.getEnabledInputMethodListLocked());
+ if (suitableImes.isEmpty()) {
+ Slog.i(TAG, "No default found");
+ return;
}
- if (defIm == null && mMethodList.size() > 0) {
- defIm = InputMethodUtils.getMostApplicableDefaultIME(
- mSettings.getEnabledInputMethodListLocked());
- if (defIm != null) {
- Slog.i(TAG, "Default found, using " + defIm.getId());
- } else {
- Slog.i(TAG, "No default found");
- }
- }
- if (defIm != null) {
- setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
- }
+ final InputMethodInfo defIm = suitableImes.get(0);
+ Slog.i(TAG, "Default found, using " + defIm.getId());
+ setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
}
private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 12c70a3..2ca5534 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -149,8 +149,9 @@
}
try {
- final ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(
- sbn.getPackageName(), 0);
+ final ApplicationInfo applicationInfo =
+ mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
+ 0, sbn.getUser().getIdentifier());
if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.N) {
if (isNoisy) {
if (importance >= IMPORTANCE_HIGH) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cc5b80e..bf0073a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3340,11 +3340,6 @@
+ " with flags 0x" + Integer.toHexString(flags), new Throwable());
}
- // Safe mode means we shouldn't match any third-party components
- if (mSafeMode) {
- flags |= PackageManager.MATCH_SYSTEM_ONLY;
- }
-
return updateFlags(flags, userId);
}
@@ -3352,6 +3347,11 @@
* Update given flags when being used to request {@link ResolveInfo}.
*/
int updateFlagsForResolve(int flags, int userId, Object cookie) {
+ // Safe mode means we shouldn't match any third-party components
+ if (mSafeMode) {
+ flags |= PackageManager.MATCH_SYSTEM_ONLY;
+ }
+
return updateFlagsForComponent(flags, userId, cookie);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 79d2307..6ec0ba1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5396,6 +5396,9 @@
}
synchronized (this) {
enforceCanSetDeviceOwnerLocked(userId);
+ if (getActiveAdminUncheckedLocked(admin, userId) == null) {
+ throw new IllegalArgumentException("Not active admin: " + admin);
+ }
// Shutting down backup manager service permanently.
long ident = mInjector.binderClearCallingIdentity();
@@ -5571,6 +5574,11 @@
}
synchronized (this) {
enforceCanSetProfileOwnerLocked(userHandle);
+
+ if (getActiveAdminUncheckedLocked(who, userHandle) == null) {
+ throw new IllegalArgumentException("Not active admin: " + who);
+ }
+
mOwners.setProfileOwner(who, ownerName, userHandle);
mOwners.writeProfileOwner(userHandle);
return true;
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 38551b6..5229b40 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -25,7 +25,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.net.BaseDhcpStateMachine;
import android.net.DhcpResults;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
@@ -83,7 +82,7 @@
*
* @hide
*/
-public class DhcpClient extends BaseDhcpStateMachine {
+public class DhcpClient extends StateMachine {
private static final String TAG = "DhcpClient";
private static final boolean DBG = true;
@@ -240,16 +239,10 @@
mOneshotTimeoutAlarm = makeWakeupMessage("ONESHOT_TIMEOUT", CMD_ONESHOT_TIMEOUT);
}
- @Override
public void registerForPreDhcpNotification() {
mRegisteredForPreDhcpNotification = true;
}
- public static BaseDhcpStateMachine makeDhcpStateMachine(
- Context context, StateMachine controller, String intf) {
- return makeDhcpClient(context, controller, intf);
- }
-
public static DhcpClient makeDhcpClient(
Context context, StateMachine controller, String intf) {
DhcpClient client = new DhcpClient(context, controller, intf);
@@ -446,12 +439,12 @@
*
* @hide
*/
- @Override
public void doQuit() {
Log.d(TAG, "doQuit");
quit();
}
+ @Override
protected void onQuitting() {
Log.d(TAG, "onQuitting");
mController.sendMessage(CMD_ON_QUIT);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index b23ad50..6d168b0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1668,7 +1668,12 @@
// that the test user is not affiliated anymore.
dpm.clearProfileOwner(admin2);
final ComponentName admin = new ComponentName("test", "test");
- markPackageAsInstalled(admin.getPackageName(), null, DpmMockContext.CALLER_USER_HANDLE);
+
+ setUpPackageManagerForFakeAdmin(admin, DpmMockContext.CALLER_UID,
+ /* enabledSetting =*/ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ /* appTargetSdk = */ null, admin2);
+
+ dpm.setActiveAdmin(admin, /* refreshing =*/ true, DpmMockContext.CALLER_USER_HANDLE);
assertTrue(dpm.setProfileOwner(admin, "owner-name", DpmMockContext.CALLER_USER_HANDLE));
assertFalse(dpm.isAffiliatedUser());
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index 53ca45d..ca43644 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -19,6 +19,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -96,12 +97,26 @@
protected void setUpPackageManagerForAdmin(ComponentName admin, int packageUid,
Integer enabledSetting, Integer appTargetSdk) throws Exception {
+ setUpPackageManagerForFakeAdmin(admin, packageUid, enabledSetting, appTargetSdk,
+ admin);
+ }
+
+ /**
+ * Set up a component in the mock package manager to be an active admin.
+ *
+ * @param admin ComponentName that's visible to the test code, which doesn't have to exist.
+ * @param copyFromAdmin package information for {@code admin} will be built based on this
+ * component's information.
+ */
+ protected void setUpPackageManagerForFakeAdmin(ComponentName admin, int packageUid,
+ Integer enabledSetting, Integer appTargetSdk, ComponentName copyFromAdmin)
+ throws Exception {
// Set up getApplicationInfo().
final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
mRealTestContext.getPackageManager().getApplicationInfo(
- admin.getPackageName(),
+ copyFromAdmin.getPackageName(),
PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
ai.enabledSetting = enabledSetting == null
@@ -111,6 +126,8 @@
ai.targetSdkVersion = appTargetSdk;
}
ai.uid = packageUid;
+ ai.packageName = admin.getPackageName();
+ ai.name = admin.getClassName();
doReturn(ai).when(mMockContext.ipackageManager).getApplicationInfo(
eq(admin.getPackageName()),
@@ -120,7 +137,7 @@
// Set up queryBroadcastReceivers().
final Intent resolveIntent = new Intent();
- resolveIntent.setComponent(admin);
+ resolveIntent.setComponent(copyFromAdmin);
final List<ResolveInfo> realResolveInfo =
mRealTestContext.getPackageManager().queryBroadcastReceivers(
resolveIntent,
@@ -132,7 +149,10 @@
realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
// We need to rewrite the UID in the activity info.
- realResolveInfo.get(0).activityInfo.applicationInfo = ai;
+ final ActivityInfo aci = realResolveInfo.get(0).activityInfo;
+ aci.applicationInfo = ai;
+ aci.packageName = admin.getPackageName();
+ aci.name = admin.getClassName();
doReturn(realResolveInfo).when(mMockContext.packageManager).queryBroadcastReceiversAsUser(
MockUtils.checkIntentComponent(admin),
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 5e57a25..c2ad9ef 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -16,6 +16,8 @@
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
#
# Define rules to build temp_layoutlib.jar, which contains a subset of
# the classes in framework.jar. The layoutlib_create tool is used to
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 3dd8002..16e5913 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -18,6 +18,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAVA_RESOURCE_DIRS := resources
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_JAVA_LIBRARIES := \
layoutlib_api-prebuilt \
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index 0e66baa..746ef36 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -73,7 +73,7 @@
private static final Map<String, FontInfo> sCache =
new LinkedHashMap<String, FontInfo>(CACHE_SIZE) {
@Override
- protected boolean removeEldestEntry(Entry<String, FontInfo> eldest) {
+ protected boolean removeEldestEntry(Map.Entry<String, FontInfo> eldest) {
return size() > CACHE_SIZE;
}
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 8a81d0b..5c062d0 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -16,6 +16,8 @@
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_RESOURCE_DIRS := res
diff --git a/tools/layoutlib/create/Android.mk b/tools/layoutlib/create/Android.mk
index c7f2c41..47377ae 100644
--- a/tools/layoutlib/create/Android.mk
+++ b/tools/layoutlib/create/Android.mk
@@ -16,6 +16,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAR_MANIFEST := manifest.txt
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 189ecdc..9e390f6 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -308,6 +308,10 @@
"java.nio.charset.Charsets", "java.nio.charset.StandardCharsets",
"java.lang.IntegralToString", "com.android.tools.layoutlib.java.IntegralToString",
"java.lang.UnsafeByteSequence", "com.android.tools.layoutlib.java.UnsafeByteSequence",
+ // Use android.icu.text versions of DateFormat and SimpleDateFormat since the
+ // original ones do not match the Android implementation
+ "java.text.DateFormat", "android.icu.text.DateFormat",
+ "java.text.SimpleDateFormat", "android.icu.text.SimpleDateFormat"
};
private final static String[] EXCLUDED_CLASSES =
diff --git a/tools/layoutlib/create/tests/Android.mk b/tools/layoutlib/create/tests/Android.mk
index dafb9c6..c59528e8 100644
--- a/tools/layoutlib/create/tests/Android.mk
+++ b/tools/layoutlib/create/tests/Android.mk
@@ -15,6 +15,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, com)