Merge "Clean up message dispatch in FingerprintService"
diff --git a/api/current.txt b/api/current.txt
index 4a3b3dc..5f4d6e9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19687,6 +19687,7 @@
 
   public final class NfcEvent {
     field public final android.nfc.NfcAdapter nfcAdapter;
+    field public final byte peerLlcpVersion;
   }
 
   public final class NfcManager {
diff --git a/api/system-current.txt b/api/system-current.txt
index e6b4c60..e44ee6e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21575,6 +21575,7 @@
 
   public final class NfcEvent {
     field public final android.nfc.NfcAdapter nfcAdapter;
+    field public final byte peerLlcpVersion;
   }
 
   public final class NfcManager {
@@ -30942,7 +30943,8 @@
 
   public class TrustAgentService extends android.app.Service {
     ctor public TrustAgentService();
-    method public final void grantTrust(java.lang.CharSequence, long, boolean);
+    method public final deprecated void grantTrust(java.lang.CharSequence, long, boolean);
+    method public final void grantTrust(java.lang.CharSequence, long, int);
     method public final android.os.IBinder onBind(android.content.Intent);
     method public boolean onConfigure(java.util.List<android.os.PersistableBundle>);
     method public void onDeviceLocked();
@@ -30951,6 +30953,8 @@
     method public void onUnlockAttempt(boolean);
     method public final void revokeTrust();
     method public final void setManagingTrust(boolean);
+    field public static final int FLAG_GRANT_TRUST_DISMISS_KEYGUARD = 2; // 0x2
+    field public static final int FLAG_GRANT_TRUST_INITIATED_BY_USER = 1; // 0x1
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.trust.TrustAgentService";
     field public static final java.lang.String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
   }
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index fa28143..8ba2a5a 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -857,6 +857,11 @@
                             "Error: Activity not started, voice control not allowed for: "
                                     + intent);
                     break;
+                case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
+                    out.println(
+                            "Error: Not allowed to start background user activity"
+                            + " that shouldn't be displayed for all users.");
+                    break;
                 default:
                     out.println(
                             "Error: Activity not started, unknown error code " + res);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 134ecdd..576a046 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -86,6 +86,13 @@
     public static final String META_HOME_ALTERNATE = "android.app.home.alternate";
 
     /**
+     * Result for IActivityManager.startActivity: trying to start a background user
+     * activity that shouldn't be displayed for all users.
+     * @hide
+     */
+    public static final int START_NOT_CURRENT_USER_ACTIVITY = -8;
+
+    /**
      * Result for IActivityManager.startActivity: trying to start an activity under voice
      * control when that activity does not support the VOICE category.
      * @hide
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index fc96464..b77dec5 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1797,6 +1797,10 @@
             case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                 throw new SecurityException(
                         "Starting under voice control not allowed for: " + intent);
+            case ActivityManager.START_NOT_CURRENT_USER_ACTIVITY:
+                throw new SecurityException(
+                        "Not allowed to start background user activity that shouldn't be"
+                        + " displayed for all users.");
             default:
                 throw new AndroidRuntimeException("Unknown error code "
                         + res + " when starting " + intent);
diff --git a/core/java/android/app/trust/ITrustListener.aidl b/core/java/android/app/trust/ITrustListener.aidl
index d80f58c..506dd12 100644
--- a/core/java/android/app/trust/ITrustListener.aidl
+++ b/core/java/android/app/trust/ITrustListener.aidl
@@ -22,6 +22,6 @@
  * {@hide}
  */
 oneway interface ITrustListener {
-    void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser);
+    void onTrustChanged(boolean enabled, int userId, int flags);
     void onTrustManagedChanged(boolean managed, int userId);
 }
\ No newline at end of file
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 705a144..b5c5317 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -34,7 +34,7 @@
     private static final int MSG_TRUST_MANAGED_CHANGED = 2;
 
     private static final String TAG = "TrustManager";
-    private static final String DATA_INITIATED_BY_USER = "initiatedByUser";
+    private static final String DATA_FLAGS = "initiatedByUser";
 
     private final ITrustManager mService;
     private final ArrayMap<TrustListener, ITrustListener> mTrustListeners;
@@ -109,11 +109,11 @@
         try {
             ITrustListener.Stub iTrustListener = new ITrustListener.Stub() {
                 @Override
-                public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
+                public void onTrustChanged(boolean enabled, int userId, int flags) {
                     Message m = mHandler.obtainMessage(MSG_TRUST_CHANGED, (enabled ? 1 : 0), userId,
                             trustListener);
-                    if (initiatedByUser) {
-                        m.getData().putBoolean(DATA_INITIATED_BY_USER, initiatedByUser);
+                    if (flags != 0) {
+                        m.getData().putInt(DATA_FLAGS, flags);
                     }
                     m.sendToTarget();
                 }
@@ -156,11 +156,8 @@
         public void handleMessage(Message msg) {
             switch(msg.what) {
                 case MSG_TRUST_CHANGED:
-                    boolean initiatedByUser = msg.peekData() != null &&
-                            msg.peekData().getBoolean(DATA_INITIATED_BY_USER);
-                    ((TrustListener)msg.obj).onTrustChanged(
-                            msg.arg1 != 0, msg.arg2, initiatedByUser);
-
+                    int flags = msg.peekData() != null ? msg.peekData().getInt(DATA_FLAGS) : 0;
+                    ((TrustListener)msg.obj).onTrustChanged(msg.arg1 != 0, msg.arg2, flags);
                     break;
                 case MSG_TRUST_MANAGED_CHANGED:
                     ((TrustListener)msg.obj).onTrustManagedChanged(msg.arg1 != 0, msg.arg2);
@@ -174,10 +171,11 @@
          * Reports that the trust state has changed.
          * @param enabled if true, the system believes the environment to be trusted.
          * @param userId the user, for which the trust changed.
-         * @param initiatedByUser indicates that the user has explicitly initiated an action that
-         *                        proves the user is about to use the device.
+         * @param flags flags specified by the trust agent when granting trust. See
+         *     {@link android.service.trust.TrustAgentService#grantTrust(CharSequence, long, int)
+         *                 TrustAgentService.grantTrust(CharSequence, long, int)}.
          */
-        void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser);
+        void onTrustChanged(boolean enabled, int userId, int flags);
 
         /**
          * Reports that whether trust is managed has changed
diff --git a/core/java/android/nfc/IAppCallback.aidl b/core/java/android/nfc/IAppCallback.aidl
index 9599308..c027d54 100644
--- a/core/java/android/nfc/IAppCallback.aidl
+++ b/core/java/android/nfc/IAppCallback.aidl
@@ -24,7 +24,7 @@
  */
 interface IAppCallback
 {
-    BeamShareData createBeamShareData();
-    void onNdefPushComplete();
+    BeamShareData createBeamShareData(byte peerLlcpVersion);
+    void onNdefPushComplete(byte peerLlcpVersion);
     void onTagDiscovered(in Tag tag);
 }
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index d009295..76bd0ec 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -46,7 +46,6 @@
     static final Boolean DBG = false;
 
     final NfcAdapter mAdapter;
-    final NfcEvent mDefaultEvent;  // cached NfcEvent (its currently always the same)
 
     // All objects in the lists are protected by this
     final List<NfcApplicationState> mApps;  // Application(s) that have NFC state. Usually one
@@ -200,7 +199,6 @@
         mAdapter = adapter;
         mActivities = new LinkedList<NfcActivityState>();
         mApps = new ArrayList<NfcApplicationState>(1);  // Android VM usually has 1 app
-        mDefaultEvent = new NfcEvent(mAdapter);
     }
 
     public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,
@@ -354,13 +352,14 @@
 
     /** Callback from NFC service, usually on binder thread */
     @Override
-    public BeamShareData createBeamShareData() {
+    public BeamShareData createBeamShareData(byte peerLlcpVersion) {
         NfcAdapter.CreateNdefMessageCallback ndefCallback;
         NfcAdapter.CreateBeamUrisCallback urisCallback;
         NdefMessage message;
         Activity activity;
         Uri[] uris;
         int flags;
+        NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
         synchronized (NfcActivityManager.this) {
             NfcActivityState state = findResumedActivityState();
             if (state == null) return null;
@@ -375,10 +374,10 @@
 
         // Make callbacks without lock
         if (ndefCallback != null) {
-            message  = ndefCallback.createNdefMessage(mDefaultEvent);
+            message  = ndefCallback.createNdefMessage(event);
         }
         if (urisCallback != null) {
-            uris = urisCallback.createBeamUris(mDefaultEvent);
+            uris = urisCallback.createBeamUris(event);
             if (uris != null) {
                 ArrayList<Uri> validUris = new ArrayList<Uri>();
                 for (Uri uri : uris) {
@@ -412,7 +411,7 @@
 
     /** Callback from NFC service, usually on binder thread */
     @Override
-    public void onNdefPushComplete() {
+    public void onNdefPushComplete(byte peerLlcpVersion) {
         NfcAdapter.OnNdefPushCompleteCallback callback;
         synchronized (NfcActivityManager.this) {
             NfcActivityState state = findResumedActivityState();
@@ -420,10 +419,10 @@
 
             callback = state.onNdefPushCompleteCallback;
         }
-
+        NfcEvent event = new NfcEvent(mAdapter, peerLlcpVersion);
         // Make callback without lock
         if (callback != null) {
-            callback.onNdefPushComplete(mDefaultEvent);
+            callback.onNdefPushComplete(event);
         }
     }
 
diff --git a/core/java/android/nfc/NfcEvent.java b/core/java/android/nfc/NfcEvent.java
index 860700a..cf1d71a 100644
--- a/core/java/android/nfc/NfcEvent.java
+++ b/core/java/android/nfc/NfcEvent.java
@@ -38,7 +38,14 @@
      */
     public final NfcAdapter nfcAdapter;
 
-    NfcEvent(NfcAdapter nfcAdapter) {
+    /**
+     * The LLCP version of the peer associated with the NFC event.
+     * The major version is in the top nibble, the minor version is in the bottom nibble.
+     */
+    public final byte peerLlcpVersion;
+
+    NfcEvent(NfcAdapter nfcAdapter, byte peerLlcpVersion) {
         this.nfcAdapter = nfcAdapter;
+        this.peerLlcpVersion = peerLlcpVersion;
     }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 22e7952..4dfe0de 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -183,7 +183,9 @@
     private static final String BATTERY_DATA = "bt";
     private static final String BATTERY_DISCHARGE_DATA = "dc";
     private static final String BATTERY_LEVEL_DATA = "lv";
+    private static final String GLOBAL_WIFI_DATA = "gwfl";
     private static final String WIFI_DATA = "wfl";
+    private static final String GLOBAL_BLUETOOTH_DATA = "gble";
     private static final String MISC_DATA = "m";
     private static final String GLOBAL_NETWORK_DATA = "gn";
     private static final String HISTORY_STRING_POOL = "hsp";
@@ -200,8 +202,6 @@
     private static final String WIFI_SUPPL_STATE_COUNT_DATA = "wssc";
     private static final String WIFI_SIGNAL_STRENGTH_TIME_DATA = "wsgt";
     private static final String WIFI_SIGNAL_STRENGTH_COUNT_DATA = "wsgc";
-    private static final String BLUETOOTH_STATE_TIME_DATA = "bst";
-    private static final String BLUETOOTH_STATE_COUNT_DATA = "bsc";
     private static final String POWER_USE_SUMMARY_DATA = "pws";
     private static final String POWER_USE_ITEM_DATA = "pwi";
     private static final String DISCHARGE_STEP_DATA = "dsd";
@@ -1898,43 +1898,6 @@
     public abstract int getWifiSignalStrengthCount(int strengthBin, int which);
 
     /**
-     * Returns the time in microseconds that bluetooth has been on while the device was
-     * running on battery.
-     * 
-     * {@hide}
-     */
-    public abstract long getBluetoothOnTime(long elapsedRealtimeUs, int which);
-    
-    public abstract int getBluetoothPingCount();
-
-    public static final int BLUETOOTH_STATE_INACTIVE = 0;
-    public static final int BLUETOOTH_STATE_LOW = 1;
-    public static final int BLUETOOTH_STATE_MEDIUM = 2;
-    public static final int BLUETOOTH_STATE_HIGH = 3;
-
-    static final String[] BLUETOOTH_STATE_NAMES = {
-        "inactive", "low", "med", "high"
-    };
-
-    public static final int NUM_BLUETOOTH_STATES = BLUETOOTH_STATE_HIGH +1;
-
-    /**
-     * Returns the time in microseconds that Bluetooth has been running in the
-     * given active state.
-     *
-     * {@hide}
-     */
-    public abstract long getBluetoothStateTime(int bluetoothState,
-            long elapsedRealtimeUs, int which);
-
-    /**
-     * Returns the number of times that Bluetooth has entered the given active state.
-     *
-     * {@hide}
-     */
-    public abstract int getBluetoothStateCount(int bluetoothState, int which);
-
-    /**
      * Returns the time in microseconds that the flashlight has been on while the device was
      * running on battery.
      *
@@ -2446,9 +2409,6 @@
         final long deviceIdlingTime = getDeviceIdlingTime(rawRealtime, which);
         final int connChanges = getNumConnectivityChange(which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
-        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
-        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
-        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
 
         final StringBuilder sb = new StringBuilder(128);
         
@@ -2490,7 +2450,8 @@
                 }
             }
         }
-        
+
+        // Dump network stats
         final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
         final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
         final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
@@ -2499,19 +2460,34 @@
         final long mobileTxTotalPackets = getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
         final long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
         final long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
-
-        // Dump network stats
         dumpLine(pw, 0 /* uid */, category, GLOBAL_NETWORK_DATA,
                 mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
                 mobileRxTotalPackets, mobileTxTotalPackets, wifiRxTotalPackets, wifiTxTotalPackets);
 
+        // Dump Wifi controller stats
+        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
+        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
+        final long wifiIdleTimeMs = getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
+        final long wifiRxTimeMs = getWifiControllerActivity(CONTROLLER_RX_TIME, which);
+        final long wifiTxTimeMs = getWifiControllerActivity(CONTROLLER_TX_TIME, which);
+        final long wifiPowerMaMs = getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which);
+        dumpLine(pw, 0 /* uid */, category, GLOBAL_WIFI_DATA,
+                wifiOnTime / 1000, wifiRunningTime / 1000,
+                wifiIdleTimeMs, wifiRxTimeMs, wifiTxTimeMs, wifiPowerMaMs / (1000*60*60));
+
+        // Dump Bluetooth controller stats
+        final long btIdleTimeMs = getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
+        final long btRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
+        final long btTxTimeMs = getBluetoothControllerActivity(CONTROLLER_TX_TIME, which);
+        final long btPowerMaMs = getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which);
+        dumpLine(pw, 0 /* uid */, category, GLOBAL_BLUETOOTH_DATA,
+                btIdleTimeMs, btRxTimeMs, btTxTimeMs, btPowerMaMs / (1000*60*60));
+
         // Dump misc stats
         dumpLine(pw, 0 /* uid */, category, MISC_DATA,
-                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
-                wifiRunningTime / 1000, bluetoothOnTime / 1000,
-                mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
+                screenOnTime / 1000, phoneOnTime / 1000,
                 fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
-                0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000,
+                getMobileRadioActiveTime(rawRealtime, which) / 1000,
                 getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
                 powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000,
                 getDeviceIdleModeEnabledCount(which), deviceIdlingTime / 1000,
@@ -2581,17 +2557,6 @@
         }
         dumpLine(pw, 0 /* uid */, category, WIFI_SIGNAL_STRENGTH_COUNT_DATA, args);
 
-        // Dump bluetooth state stats
-        args = new Object[NUM_BLUETOOTH_STATES];
-        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
-            args[i] = getBluetoothStateTime(i, rawRealtime, which) / 1000;
-        }
-        dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_TIME_DATA, args);
-        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
-            args[i] = getBluetoothStateCount(i, which);
-        }
-        dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_COUNT_DATA, args);
-
         if (which == STATS_SINCE_UNPLUGGED) {
             dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
                     getDischargeCurrentLevel());
@@ -2696,6 +2661,7 @@
                 continue;
             }
             final Uid u = uidStats.valueAt(iu);
+
             // Dump Network stats per uid, if any
             final long mobileBytesRx = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
             final long mobileBytesTx = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
@@ -2707,11 +2673,6 @@
             final int mobileActiveCount = u.getMobileRadioActiveCount(which);
             final long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
             final long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
-            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
-            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
-            final int wifiScanCount = u.getWifiScanCount(which);
-            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
-
             if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
                     || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
                     || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
@@ -2722,10 +2683,19 @@
                         mobileActiveTime, mobileActiveCount);
             }
 
+            final long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
+            final long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
+            final int wifiScanCount = u.getWifiScanCount(which);
+            final long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
+            final long uidWifiIdleTimeMs = u.getWifiControllerActivity(CONTROLLER_IDLE_TIME, which);
+            final long uidWifiRxTimeMs = u.getWifiControllerActivity(CONTROLLER_RX_TIME, which);
+            final long uidWifiTxTimeMs = u.getWifiControllerActivity(CONTROLLER_TX_TIME, which);
             if (fullWifiLockOnTime != 0 || wifiScanTime != 0 || wifiScanCount != 0
-                    || uidWifiRunningTime != 0) {
+                    || uidWifiRunningTime != 0 || uidWifiIdleTimeMs != 0 || uidWifiRxTimeMs != 0
+                    || uidWifiTxTimeMs != 0) {
                 dumpLine(pw, uid, category, WIFI_DATA,
-                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount);
+                        fullWifiLockOnTime, wifiScanTime, uidWifiRunningTime, wifiScanCount,
+                        uidWifiIdleTimeMs, uidWifiRxTimeMs, uidWifiTxTimeMs);
             }
 
             if (u.hasUserActivity()) {
@@ -2983,7 +2953,6 @@
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
         final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
         final long wifiOnTime = getWifiOnTime(rawRealtime, which);
-        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
         sb.setLength(0);
         sb.append(prefix);
                 sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
@@ -3332,42 +3301,11 @@
 
         sb.setLength(0);
         sb.append(prefix);
-        sb.append("  WiFi Energy use: ").append(BatteryStatsHelper.makemAh(
+        sb.append("  WiFi Power drain: ").append(BatteryStatsHelper.makemAh(
                 getWifiControllerActivity(CONTROLLER_POWER_DRAIN, which) / (double)(1000*60*60)));
         sb.append(" mAh");
         pw.println(sb.toString());
 
-        sb.setLength(0);
-        sb.append(prefix);
-                sb.append("  Bluetooth on: "); formatTimeMs(sb, bluetoothOnTime / 1000);
-                sb.append("("); sb.append(formatRatioLocked(bluetoothOnTime, whichBatteryRealtime));
-                sb.append(")");
-        pw.println(sb.toString());
-
-        sb.setLength(0);
-        sb.append(prefix);
-        sb.append("  Bluetooth states:");
-        didOne = false;
-        for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
-            final long time = getBluetoothStateTime(i, rawRealtime, which);
-            if (time == 0) {
-                continue;
-            }
-            sb.append("\n    ");
-            didOne = true;
-            sb.append(BLUETOOTH_STATE_NAMES[i]);
-            sb.append(" ");
-            formatTimeMs(sb, time/1000);
-            sb.append("(");
-            sb.append(formatRatioLocked(time, whichBatteryRealtime));
-            sb.append(") ");
-            sb.append(getPhoneDataConnectionCount(i, which));
-            sb.append("x");
-        }
-
-        if (!didOne) sb.append(" (no activity)");
-        pw.println(sb.toString());
-
         final long bluetoothIdleTimeMs =
                 getBluetoothControllerActivity(CONTROLLER_IDLE_TIME, which);
         final long bluetoothRxTimeMs = getBluetoothControllerActivity(CONTROLLER_RX_TIME, which);
@@ -3399,6 +3337,14 @@
         sb.append(")");
         pw.println(sb.toString());
 
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("  Bluetooth Power drain: ").append(BatteryStatsHelper.makemAh(
+                getBluetoothControllerActivity(CONTROLLER_POWER_DRAIN, which) /
+                        (double)(1000*60*60)));
+        sb.append(" mAh");
+        pw.println(sb.toString());
+
         pw.println();
 
         if (which == STATS_SINCE_UNPLUGGED) {
diff --git a/core/java/android/service/gatekeeper/IGateKeeperService.aidl b/core/java/android/service/gatekeeper/IGateKeeperService.aidl
index 9edd04d..4f46701 100644
--- a/core/java/android/service/gatekeeper/IGateKeeperService.aidl
+++ b/core/java/android/service/gatekeeper/IGateKeeperService.aidl
@@ -69,4 +69,11 @@
      * @param uid the Android user id
      */
     long getSecureUserId(int uid);
+
+    /**
+     * Clears secure user id associated with the provided Android ID.
+     * Must be called when password is set to NONE.
+     * @param uid the Android user id.
+     */
+    void clearSecureUserId(int uid);
 }
diff --git a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index 76b2be0..ec66cc8 100644
--- a/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -24,7 +24,7 @@
  * @hide
  */
 oneway interface ITrustAgentServiceCallback {
-    void grantTrust(CharSequence message, long durationMs, boolean initiatedByUser);
+    void grantTrust(CharSequence message, long durationMs, int flags);
     void revokeTrust();
     void setManagingTrust(boolean managingTrust);
     void onConfigureCompleted(boolean result, IBinder token);
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index a3178e2..9d7ffad 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -17,6 +17,7 @@
 package android.service.trust;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.app.Service;
@@ -32,6 +33,8 @@
 import android.util.Log;
 import android.util.Slog;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
 /**
@@ -69,6 +72,7 @@
  */
 @SystemApi
 public class TrustAgentService extends Service {
+
     private final String TAG = TrustAgentService.class.getSimpleName() +
             "[" + getClass().getSimpleName() + "]";
     private static final boolean DEBUG = false;
@@ -86,6 +90,34 @@
      */
     public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
 
+
+    /**
+     * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that trust is being granted
+     * as the direct result of user action - such as solving a security challenge. The hint is used
+     * by the system to optimize the experience. Behavior may vary by device and release, so
+     * one should only set this parameter if it meets the above criteria rather than relying on
+     * the behavior of any particular device or release.
+     */
+    public static final int FLAG_GRANT_TRUST_INITIATED_BY_USER = 1 << 0;
+
+    /**
+     * Flag for {@link #grantTrust(CharSequence, long, int)} indicating that the agent would like
+     * to dismiss the keyguard. When using this flag, the {@code TrustAgentService} must ensure
+     * it is only set in response to a direct user action with the expectation of dismissing the
+     * keyguard.
+     */
+    public static final int FLAG_GRANT_TRUST_DISMISS_KEYGUARD = 1 << 1;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true,
+            value = {
+                    FLAG_GRANT_TRUST_INITIATED_BY_USER,
+                    FLAG_GRANT_TRUST_DISMISS_KEYGUARD,
+            })
+    public @interface GrantTrustFlags {}
+
+
     private static final int MSG_UNLOCK_ATTEMPT = 1;
     private static final int MSG_CONFIGURE = 2;
     private static final int MSG_TRUST_TIMEOUT = 3;
@@ -228,11 +260,35 @@
      *    direct result of user action - such as solving a security challenge. The hint is used
      *    by the system to optimize the experience. Behavior may vary by device and release, so
      *    one should only set this parameter if it meets the above criteria rather than relying on
-     *    the behavior of any particular device or release.
+     *    the behavior of any particular device or release. Corresponds to
+     *    {@link #FLAG_GRANT_TRUST_INITIATED_BY_USER}.
+     * @throws IllegalStateException if the agent is not currently managing trust.
+     *
+     * @deprecated use {@link #grantTrust(CharSequence, long, int)} instead.
+     */
+    @Deprecated
+    public final void grantTrust(
+            final CharSequence message, final long durationMs, final boolean initiatedByUser) {
+        grantTrust(message, durationMs, initiatedByUser ? FLAG_GRANT_TRUST_INITIATED_BY_USER : 0);
+    }
+
+    /**
+     * Call to grant trust on the device.
+     *
+     * @param message describes why the device is trusted, e.g. "Trusted by location".
+     * @param durationMs amount of time in milliseconds to keep the device in a trusted state.
+     *    Trust for this agent will automatically be revoked when the timeout expires unless
+     *    extended by a subsequent call to this function. The timeout is measured from the
+     *    invocation of this function as dictated by {@link SystemClock#elapsedRealtime())}.
+     *    For security reasons, the value should be no larger than necessary.
+     *    The value may be adjusted by the system as necessary to comply with a policy controlled
+     *    by the system or {@link DevicePolicyManager} restrictions. See {@link #onTrustTimeout()}
+     *    for determining when trust expires.
+     * @param flags TBDocumented
      * @throws IllegalStateException if the agent is not currently managing trust.
      */
     public final void grantTrust(
-            final CharSequence message, final long durationMs, final boolean initiatedByUser) {
+            final CharSequence message, final long durationMs, @GrantTrustFlags final int flags) {
         synchronized (mLock) {
             if (!mManagingTrust) {
                 throw new IllegalStateException("Cannot grant trust if agent is not managing trust."
@@ -240,7 +296,7 @@
             }
             if (mCallback != null) {
                 try {
-                    mCallback.grantTrust(message.toString(), durationMs, initiatedByUser);
+                    mCallback.grantTrust(message.toString(), durationMs, flags);
                 } catch (RemoteException e) {
                     onError("calling enableTrust()");
                 }
@@ -250,7 +306,7 @@
                 mPendingGrantTrustTask = new Runnable() {
                     @Override
                     public void run() {
-                        grantTrust(message, durationMs, initiatedByUser);
+                        grantTrust(message, durationMs, flags);
                     }
                 };
             }
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 1674950..016541f 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -17,6 +17,7 @@
 package android.service.wallpaper;
 
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
 import android.os.SystemProperties;
 import android.view.WindowInsets;
 
@@ -185,6 +186,7 @@
 
         DisplayManager mDisplayManager;
         Display mDisplay;
+        private int mDisplayState;
 
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
             {
@@ -228,7 +230,19 @@
                 throw new UnsupportedOperationException(
                         "Wallpapers do not support keep screen on");
             }
-            
+
+            @Override
+            public Canvas lockCanvas() {
+                if (mDisplayState == Display.STATE_DOZE
+                        || mDisplayState == Display.STATE_DOZE_SUSPEND) {
+                    try {
+                        mSession.pokeDrawLock(mWindow);
+                    } catch (RemoteException e) {
+                        // System server died, can be ignored.
+                    }
+                }
+                return super.lockCanvas();
+            }
         };
 
         final class WallpaperInputEventReceiver extends InputEventReceiver {
@@ -831,9 +845,12 @@
             
             mWindow.setSession(mSession);
 
+            mLayout.packageName = getPackageName();
+
             mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
             mDisplayManager.registerDisplayListener(mDisplayListener, mCaller.getHandler());
             mDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+            mDisplayState = mDisplay.getState();
 
             if (DEBUG) Log.v(TAG, "onCreate(): " + this);
             onCreate(mSurfaceHolder);
@@ -873,8 +890,8 @@
 
         void reportVisibility() {
             if (!mDestroyed) {
-                boolean visible = mVisible
-                        & mDisplay != null && mDisplay.getState() != Display.STATE_OFF;
+                mDisplayState = mDisplay == null ? Display.STATE_UNKNOWN : mDisplay.getState();
+                boolean visible = mVisible && mDisplayState != Display.STATE_OFF;
                 if (mReportedVisible != visible) {
                     mReportedVisible = visible;
                     if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 10724b0..8f2be99 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -494,6 +494,11 @@
      */
     private int mNestedScrollAxes;
 
+    // Used to manage the list of transient views, added by addTransientView()
+    private List<Integer> mTransientIndices = null;
+    private List<View> mTransientViews = null;
+
+
     /**
      * Empty ActionMode used as a sentinel in recursive entries to startActionModeForChild.
      *
@@ -2822,6 +2827,11 @@
             child.dispatchAttachedToWindow(info,
                     visibility | (child.mViewFlags & VISIBILITY_MASK));
         }
+        final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
+        for (int i = 0; i < transientCount; ++i) {
+            View view = mTransientViews.get(i);
+            view.dispatchAttachedToWindow(info, visibility | (view.mViewFlags & VISIBILITY_MASK));
+        }
     }
 
     @Override
@@ -2991,6 +3001,11 @@
             children[i].dispatchDetachedFromWindow();
         }
         clearDisappearingChildren();
+        final int transientCount = mTransientViews == null ? 0 : mTransientIndices.size();
+        for (int i = 0; i < transientCount; ++i) {
+            View view = mTransientViews.get(i);
+            view.dispatchDetachedFromWindow();
+        }
         super.dispatchDetachedFromWindow();
     }
 
@@ -3291,6 +3306,8 @@
         final long drawingTime = getDrawingTime();
 
         if (usingRenderNodeProperties) canvas.insertReorderBarrier();
+        final int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
+        int transientIndex = transientCount != 0 ? 0 : -1;
         // Only use the preordered list if not HW accelerated, since the HW pipeline will do the
         // draw reordering internally
         final ArrayList<View> preorderedList = usingRenderNodeProperties
@@ -3298,6 +3315,17 @@
         final boolean customOrder = preorderedList == null
                 && isChildrenDrawingOrderEnabled();
         for (int i = 0; i < childrenCount; i++) {
+            while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
+                final View transientChild = mTransientViews.get(transientIndex);
+                if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
+                        transientChild.getAnimation() != null) {
+                    more |= drawChild(canvas, transientChild, drawingTime);
+                }
+                transientIndex++;
+                if (transientIndex >= transientCount) {
+                    transientIndex = -1;
+                }
+            }
             int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;
             final View child = (preorderedList == null)
                     ? children[childIndex] : preorderedList.get(childIndex);
@@ -3305,6 +3333,18 @@
                 more |= drawChild(canvas, child, drawingTime);
             }
         }
+        while (transientIndex >= 0) {
+            // there may be additional transient views after the normal views
+            final View transientChild = mTransientViews.get(transientIndex);
+            if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
+                    transientChild.getAnimation() != null) {
+                more |= drawChild(canvas, transientChild, drawingTime);
+            }
+            transientIndex++;
+            if (transientIndex >= transientCount) {
+                break;
+            }
+        }
         if (preorderedList != null) preorderedList.clear();
 
         // Draw any disappearing views that have animations
@@ -3785,6 +3825,145 @@
     }
 
     /**
+     * This method adds a view to this container at the specified index purely for the
+     * purposes of allowing that view to draw even though it is not a normal child of
+     * the container. That is, the view does not participate in layout, focus, accessibility,
+     * input, or other normal view operations; it is purely an item to be drawn during the normal
+     * rendering operation of this container. The index that it is added at is the order
+     * in which it will be drawn, with respect to the other views in the container.
+     * For example, a transient view added at index 0 will be drawn before all other views
+     * in the container because it will be drawn first (including before any real view
+     * at index 0). There can be more than one transient view at any particular index;
+     * these views will be drawn in the order in which they were added to the list of
+     * transient views. The index of transient views can also be greater than the number
+     * of normal views in the container; that just means that they will be drawn after all
+     * other views are drawn.
+     *
+     * <p>Note that since transient views do not participate in layout, they must be sized
+     * manually or, more typically, they should just use the size that they had before they
+     * were removed from their container.</p>
+     *
+     * <p>Transient views are useful for handling animations of views that have been removed
+     * from the container, but which should be animated out after the removal. Adding these
+     * views as transient views allows them to participate in drawing without side-effecting
+     * the layout of the container.</p>
+     *
+     * <p>Transient views must always be explicitly {@link #removeTransientView(View) removed}
+     * from the container when they are no longer needed. For example, a transient view
+     * which is added in order to fade it out in its old location should be removed
+     * once the animation is complete.</p>
+     *
+     * @param view The view to be added
+     * @param index The index at which this view should be drawn, must be >= 0.
+     * This value is relative to the {@link #getChildAt(int) index} values in the normal
+     * child list of this container, where any transient view at a particular index will
+     * be drawn before any normal child at that same index.
+     *
+     * @hide
+     */
+    public void addTransientView(View view, int index) {
+        if (index < 0) {
+            return;
+        }
+        if (mTransientIndices == null) {
+            mTransientIndices = new ArrayList<Integer>();
+            mTransientViews = new ArrayList<View>();
+        }
+        final int oldSize = mTransientIndices.size();
+        if (oldSize > 0) {
+            int insertionIndex;
+            for (insertionIndex = 0; insertionIndex < oldSize; ++insertionIndex) {
+                if (index < mTransientIndices.get(insertionIndex)) {
+                    break;
+                }
+            }
+            mTransientIndices.add(insertionIndex, index);
+            mTransientViews.add(insertionIndex, view);
+        } else {
+            mTransientIndices.add(index);
+            mTransientViews.add(view);
+        }
+        view.mParent = this;
+        view.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
+        invalidate(true);
+    }
+
+    /**
+     * Removes a view from the list of transient views in this container. If there is no
+     * such transient view, this method does nothing.
+     *
+     * @param view The transient view to be removed
+     *
+     * @hide
+     */
+    public void removeTransientView(View view) {
+        if (mTransientViews == null) {
+            return;
+        }
+        final int size = mTransientViews.size();
+        for (int i = 0; i < size; ++i) {
+            if (view == mTransientViews.get(i)) {
+                mTransientViews.remove(i);
+                mTransientIndices.remove(i);
+                view.mParent = null;
+                view.dispatchDetachedFromWindow();
+                invalidate(true);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Returns the number of transient views in this container. Specific transient
+     * views and the index at which they were added can be retrieved via
+     * {@link #getTransientView(int)} and {@link #getTransientViewIndex(int)}.
+     *
+     * @see #addTransientView(View, int)
+     * @return The number of transient views in this container
+     *
+     * @hide
+     */
+    public int getTransientViewCount() {
+        return mTransientIndices == null ? 0 : mTransientIndices.size();
+    }
+
+    /**
+     * Given a valid position within the list of transient views, returns the index of
+     * the transient view at that position.
+     *
+     * @param position The position of the index being queried. Must be at least 0
+     * and less than the value returned by {@link #getTransientViewCount()}.
+     * @return The index of the transient view stored in the given position if the
+     * position is valid, otherwise -1
+     *
+     * @hide
+     */
+    public int getTransientViewIndex(int position) {
+        if (position < 0 || mTransientIndices == null || position >= mTransientIndices.size()) {
+            return -1;
+        }
+        return mTransientIndices.get(position);
+    }
+
+    /**
+     * Given a valid position within the list of transient views, returns the
+     * transient view at that position.
+     *
+     * @param position The position of the view being queried. Must be at least 0
+     * and less than the value returned by {@link #getTransientViewCount()}.
+     * @return The transient view stored in the given position if the
+     * position is valid, otherwise null
+     *
+     * @hide
+     */
+    public View getTransientView(int position) {
+        if (mTransientViews == null || position >= mTransientViews.size()) {
+            return null;
+        }
+        return mTransientViews.get(position);
+    }
+
+    /**
      * <p>Adds a child view. If no layout parameters are already set on the child, the
      * default parameters for this ViewGroup are set on the child.</p>
      * 
@@ -4096,6 +4275,16 @@
         if (child.getVisibility() != View.GONE) {
             notifySubtreeAccessibilityStateChangedIfNeeded();
         }
+
+        if (mTransientIndices != null) {
+            final int transientCount = mTransientIndices.size();
+            for (int i = 0; i < transientCount; ++i) {
+                final int oldIndex = mTransientIndices.get(i);
+                if (index <= oldIndex) {
+                    mTransientIndices.set(i, oldIndex + 1);
+                }
+            }
+        }
     }
 
     private void addInArray(View child, int index) {
@@ -4340,6 +4529,14 @@
         if (view.getVisibility() != View.GONE) {
             notifySubtreeAccessibilityStateChangedIfNeeded();
         }
+
+        int transientCount = mTransientIndices == null ? 0 : mTransientIndices.size();
+        for (int i = 0; i < transientCount; ++i) {
+            final int oldIndex = mTransientIndices.get(i);
+            if (index < oldIndex) {
+                mTransientIndices.set(i, oldIndex - 1);
+            }
+        }
     }
 
     /**
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 4f0e29e..7c5c565 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -95,9 +95,6 @@
     void noteWifiState(int wifiState, String accessPoint);
     void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth);
     void noteWifiRssiChanged(int newRssi);
-    void noteBluetoothOn();
-    void noteBluetoothOff();
-    void noteBluetoothState(int bluetoothState);
     void noteFullWifiLockAcquired(int uid);
     void noteFullWifiLockReleased(int uid);
     void noteWifiScanStarted(int uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 59dbec6..a53d46c 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -136,6 +136,14 @@
                 profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX) != 0;
     }
 
+    public static boolean checkHasBluetoothPowerReporting(BatteryStats stats,
+                                                          PowerProfile profile) {
+        return stats.hasBluetoothActivityReporting() &&
+                profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE) != 0 &&
+                profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX) != 0 &&
+                profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX) != 0;
+    }
+
     public BatteryStatsHelper(Context context) {
         this(context, true);
     }
@@ -256,7 +264,8 @@
     }
 
     public static String makemAh(double power) {
-        if (power < .00001) return String.format("%.8f", power);
+        if (power == 0) return "0";
+        else if (power < .00001) return String.format("%.8f", power);
         else if (power < .0001) return String.format("%.7f", power);
         else if (power < .001) return String.format("%.6f", power);
         else if (power < .01) return String.format("%.5f", power);
@@ -342,7 +351,11 @@
         mWifiPowerCalculator.reset();
 
         if (mBluetoothPowerCalculator == null) {
-            mBluetoothPowerCalculator = new BluetoothPowerCalculator();
+            if (checkHasBluetoothPowerReporting(mStats, mPowerProfile)) {
+                mBluetoothPowerCalculator = new BluetoothPowerCalculator();
+            } else {
+                mBluetoothPowerCalculator = new BluetoothPowerCalculator();
+            }
         }
         mBluetoothPowerCalculator.reset();
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9e5a54d..405c861 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -19,8 +19,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothActivityEnergyInfo;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
@@ -84,7 +82,6 @@
 import java.util.Calendar;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
@@ -107,7 +104,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 124 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 125 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -386,12 +383,6 @@
     final StopwatchTimer[] mWifiSignalStrengthsTimer =
             new StopwatchTimer[NUM_WIFI_SIGNAL_STRENGTH_BINS];
 
-    boolean mBluetoothOn;
-    StopwatchTimer mBluetoothOnTimer;
-
-    int mBluetoothState = -1;
-    final StopwatchTimer[] mBluetoothStateTimer = new StopwatchTimer[NUM_BLUETOOTH_STATES];
-
     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
     long mMobileRadioActiveStartTime;
     StopwatchTimer mMobileRadioActiveTimer;
@@ -402,9 +393,6 @@
 
     int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
 
-    /** Bluetooth headset object */
-    BluetoothHeadset mBtHeadset;
-
     /**
      * These provide time bases that discount the time the device is plugged
      * in to power.
@@ -462,9 +450,6 @@
 
     long mLastWriteTime = 0; // Milliseconds
 
-    private int mBluetoothPingCount;
-    private int mBluetoothPingStart = -1;
-
     private int mPhoneServiceState = -1;
     private int mPhoneServiceStateRaw = -1;
     private int mPhoneSimStateRaw = -1;
@@ -1807,32 +1792,6 @@
         return kwlt;
     }
 
-    private int getCurrentBluetoothPingCount() {
-        if (mBtHeadset != null) {
-            List<BluetoothDevice> deviceList = mBtHeadset.getConnectedDevices();
-            if (deviceList.size() > 0) {
-                return mBtHeadset.getBatteryUsageHint(deviceList.get(0));
-            }
-        }
-        return -1;
-    }
-
-    public int getBluetoothPingCount() {
-        if (mBluetoothPingStart == -1) {
-            return mBluetoothPingCount;
-        } else if (mBtHeadset != null) {
-            return getCurrentBluetoothPingCount() - mBluetoothPingStart;
-        }
-        return 0;
-    }
-
-    public void setBtHeadset(BluetoothHeadset headset) {
-        if (headset != null && mBtHeadset == null && isOnBattery() && mBluetoothPingStart == -1) {
-            mBluetoothPingStart = getCurrentBluetoothPingCount();
-        }
-        mBtHeadset = headset;
-    }
-
     private int writeHistoryTag(HistoryTag tag) {
         Integer idxObj = mHistoryTagPool.get(tag);
         int idx;
@@ -2550,17 +2509,7 @@
 
     public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime,
             long realtime) {
-        if (mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime)) {
-            if (unplugged) {
-                // Track bt headset ping count
-                mBluetoothPingStart = getCurrentBluetoothPingCount();
-                mBluetoothPingCount = 0;
-            } else {
-                // Track bt headset ping count
-                mBluetoothPingCount = getBluetoothPingCount();
-                mBluetoothPingStart = -1;
-            }
-        }
+        mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
 
         boolean unpluggedScreenOff = unplugged && screenOff;
         if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
@@ -3967,46 +3916,6 @@
         }
     }
 
-    public void noteBluetoothOnLocked() {
-        if (!mBluetoothOn) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            final long uptime = SystemClock.uptimeMillis();
-            mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_ON_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth on to: "
-                    + Integer.toHexString(mHistoryCur.states));
-            addHistoryRecordLocked(elapsedRealtime, uptime);
-            mBluetoothOn = true;
-            mBluetoothOnTimer.startRunningLocked(elapsedRealtime);
-            scheduleSyncExternalStatsLocked("bluetooth-on");
-        }
-    }
-
-    public void noteBluetoothOffLocked() {
-        if (mBluetoothOn) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            final long uptime = SystemClock.uptimeMillis();
-            mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_ON_FLAG;
-            if (DEBUG_HISTORY) Slog.v(TAG, "Bluetooth off to: "
-                    + Integer.toHexString(mHistoryCur.states));
-            addHistoryRecordLocked(elapsedRealtime, uptime);
-            mBluetoothOn = false;
-            mBluetoothOnTimer.stopRunningLocked(elapsedRealtime);
-            scheduleSyncExternalStatsLocked("bluetooth-off");
-        }
-    }
-
-    public void noteBluetoothStateLocked(int bluetoothState) {
-        if (DEBUG) Log.i(TAG, "Bluetooth state -> " + bluetoothState);
-        if (mBluetoothState != bluetoothState) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            if (mBluetoothState >= 0) {
-                mBluetoothStateTimer[mBluetoothState].stopRunningLocked(elapsedRealtime);
-            }
-            mBluetoothState = bluetoothState;
-            mBluetoothStateTimer[bluetoothState].startRunningLocked(elapsedRealtime);
-        }
-    }
-
     int mWifiFullLockNesting = 0;
 
     public void noteFullWifiLockAcquiredLocked(int uid) {
@@ -4361,20 +4270,6 @@
         return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
     }
 
-    @Override public long getBluetoothOnTime(long elapsedRealtimeUs, int which) {
-        return mBluetoothOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
-    }
-
-    @Override public long getBluetoothStateTime(int bluetoothState,
-            long elapsedRealtimeUs, int which) {
-        return mBluetoothStateTimer[bluetoothState].getTotalTimeLocked(
-                elapsedRealtimeUs, which);
-    }
-
-    @Override public int getBluetoothStateCount(int bluetoothState, int which) {
-        return mBluetoothStateTimer[bluetoothState].getCountLocked(which);
-    }
-
     @Override public boolean hasBluetoothActivityReporting() {
         return mHasBluetoothEnergyReporting;
     }
@@ -6828,10 +6723,6 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i, null,
                     mOnBatteryTimeBase);
         }
-        mBluetoothOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mOnBatteryTimeBase);
-        }
         mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
         mVideoOnTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
         mFlashlightOnTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase);
@@ -7447,10 +7338,6 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].reset(false);
         }
-        mBluetoothOnTimer.reset(false);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].reset(false);
-        }
         for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mBluetoothActivityCounters[i].reset(false);
             mWifiActivityCounters[i].reset(false);
@@ -7775,16 +7662,12 @@
             mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
                     info.getControllerIdleTimeMillis());
 
-            final double powerDrainMaMs;
-            if (mPowerProfile.getAveragePower(
-                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) == 0) {
-                powerDrainMaMs = 0.0;
-            } else {
-                powerDrainMaMs = info.getControllerEnergyUsed()
-                        / mPowerProfile.getAveragePower(
-                        PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE);
+            final double opVoltage = mPowerProfile.getAveragePower(
+                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE);
+            if (opVoltage != 0) {
+                mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
+                        (long)(info.getControllerEnergyUsed() / opVoltage));
             }
-            mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked((long) powerDrainMaMs);
         }
     }
 
@@ -7872,8 +7755,13 @@
                     info.getControllerTxTimeMillis());
             mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
                     info.getControllerIdleTimeMillis());
-            mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
-                    info.getControllerEnergyUsed());
+
+            final double opVoltage = mPowerProfile.getAveragePower(
+                    PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE);
+            if (opVoltage != 0) {
+                mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
+                        (long) (info.getControllerEnergyUsed() / opVoltage));
+            }
         }
     }
 
@@ -8972,16 +8860,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
         }
-        mBluetoothOn = false;
-        mBluetoothOnTimer.readSummaryFromParcelLocked(in);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].readSummaryFromParcelLocked(in);
-        }
-
         for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mBluetoothActivityCounters[i].readSummaryFromParcelLocked(in);
         }
-
         for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mWifiActivityCounters[i].readSummaryFromParcelLocked(in);
         }
@@ -9295,10 +9176,6 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
-        mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
-        }
         for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mBluetoothActivityCounters[i].writeSummaryFromParcelLocked(out);
         }
@@ -9608,17 +9485,9 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(null, -800-i,
                     null, mOnBatteryTimeBase, in);
         }
-        mBluetoothOn = false;
-        mBluetoothOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase, in);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
-                    null, mOnBatteryTimeBase, in);
-        }
-
         for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mBluetoothActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
         }
-
         for (int i = 0; i < NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mWifiActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
         }
@@ -9648,9 +9517,6 @@
         mChargeStepTracker.readFromParcel(in);
         mLastWriteTime = in.readLong();
 
-        mBluetoothPingCount = in.readInt();
-        mBluetoothPingStart = -1;
-
         mKernelWakelockStats.clear();
         int NKW = in.readInt();
         for (int ikw = 0; ikw < NKW; ikw++) {
@@ -9768,10 +9634,6 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
         }
-        mBluetoothOnTimer.writeToParcel(out, uSecRealtime);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
-        }
         for (int i=0; i< NUM_CONTROLLER_ACTIVITY_TYPES; i++) {
             mBluetoothActivityCounters[i].writeToParcel(out);
         }
@@ -9798,8 +9660,6 @@
         mChargeStepTracker.writeToParcel(out);
         out.writeLong(mLastWriteTime);
 
-        out.writeInt(getBluetoothPingCount());
-
         if (inclUids) {
             out.writeInt(mKernelWakelockStats.size());
             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
@@ -9918,12 +9778,6 @@
                 pr.println("*** Wifi signal strength #" + i + ":");
                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
             }
-            pr.println("*** Bluetooth timer:");
-            mBluetoothOnTimer.logState(pr, "  ");
-            for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-                pr.println("*** Bluetooth active type #" + i + ":");
-                mBluetoothStateTimer[i].logState(pr, "  ");
-            }
             pr.println("*** Flashlight timer:");
             mFlashlightOnTimer.logState(pr, "  ");
         }
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 4fb8b55..961b0df 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -71,7 +71,7 @@
         app.wifiRunningTimeMs = idleTimeMs + rxTimeMs + txTimeMs;
 
         double powerDrain = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_POWER_DRAIN,
-                statsType) / (1000*60*60);
+                statsType) / (double)(1000*60*60);
         if (powerDrain == 0) {
             // Some controllers do not report power drain, so we can calculate it here.
             powerDrain = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
diff --git a/core/java/com/android/internal/os/WifiPowerEstimator.java b/core/java/com/android/internal/os/WifiPowerEstimator.java
index 0172367..c4e2ef6 100644
--- a/core/java/com/android/internal/os/WifiPowerEstimator.java
+++ b/core/java/com/android/internal/os/WifiPowerEstimator.java
@@ -63,7 +63,7 @@
         mTotalAppWifiRunningTimeMs += app.wifiRunningTimeMs;
         final double wifiLockPower = (app.wifiRunningTimeMs * mWifiPowerOn) / (1000*60*60);
 
-        final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType);
+        final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
         final double wifiScanPower = (wifiScanTimeMs * mWifiPowerScan) / (1000*60*60);
 
         double wifiBatchScanPower = 0;
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 0b1e0e5..1e96945 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -1070,7 +1070,8 @@
     private static PopupWindow createPopupWindow(View content) {
         ViewGroup popupContentHolder = new LinearLayout(content.getContext());
         PopupWindow popupWindow = new PopupWindow(popupContentHolder);
-        popupWindow.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL);
+        popupWindow.setWindowLayoutType(
+                WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL);
         popupWindow.setAnimationStyle(0);
         popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         content.setLayoutParams(new ViewGroup.LayoutParams(
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 123d1ac..aa60eba 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -472,6 +472,8 @@
             updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null);
         }
 
+        setCredentialRequiredToDecrypt(false);
+
         getDevicePolicyManager().setActivePasswordState(
                 DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0, userHandle);
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index aa722d0..d06534e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1009,12 +1009,13 @@
         TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
         TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
     }
+    Rect modelRect = Rect(rect.getWidth(), rect.getHeight());
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
             .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
             .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
             .setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
-            .setModelViewOffsetRectSnap(0, 0, rect)
+            .setModelViewOffsetRectSnap(rect.left, rect.top, modelRect)
             .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index a88497c..be71b034 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -23,6 +23,7 @@
 import android.graphics.Canvas;
 import android.media.AudioManager;
 import android.os.SystemClock;
+import android.service.trust.TrustAgentService;
 import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -69,14 +70,27 @@
         }
 
         @Override
-        public void onTrustInitiatedByUser(int userId) {
+        public void onTrustGrantedWithFlags(int flags, int userId) {
             if (userId != mLockPatternUtils.getCurrentUser()) return;
             if (!isAttachedToWindow()) return;
+            boolean bouncerVisible = isVisibleToUser();
+            boolean initiatedByUser =
+                    (flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0;
+            boolean dismissKeyguard =
+                    (flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0;
 
-            if (isVisibleToUser()) {
-                dismiss(false /* authenticated */);
-            } else {
-                mViewMediatorCallback.playTrustedSound();
+            if (initiatedByUser || dismissKeyguard) {
+                if (mViewMediatorCallback.isScreenOn() && (bouncerVisible || dismissKeyguard)) {
+                    if (!bouncerVisible) {
+                        // The trust agent dismissed the keyguard without the user proving
+                        // that they are present (by swiping up to show the bouncer). That's fine if
+                        // the user proved presence via some other way to the trust agent.
+                        Log.i(TAG, "TrustAgent dismissed Keyguard.");
+                    }
+                    dismiss(false /* authenticated */);
+                } else {
+                    mViewMediatorCallback.playTrustedSound();
+                }
             }
         }
     };
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 50c9f2d..1eec5325 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -58,12 +58,12 @@
 import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
 import android.hardware.fingerprint.FingerprintUtils;
 import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
+import android.service.trust.TrustAgentService;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseBooleanArray;
 
 import com.google.android.collect.Lists;
@@ -245,15 +245,14 @@
     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
 
     @Override
-    public void onTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
+    public void onTrustChanged(boolean enabled, int userId, int flags) {
         mUserHasTrust.put(userId, enabled);
-
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
                 cb.onTrustChanged(userId);
-                if (enabled && initiatedByUser) {
-                    cb.onTrustInitiatedByUser(userId);
+                if (enabled && flags != 0) {
+                    cb.onTrustGrantedWithFlags(flags, userId);
                 }
             }
         }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 756a7a4..26e6973 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -171,9 +171,9 @@
     public void onTrustManagedChanged(int userId) { }
 
     /**
-     * Called when the user has proved to a trust agent that they want to use the device.
+     * Called after trust was granted with non-zero flags.
      */
-    public void onTrustInitiatedByUser(int userId) { }
+    public void onTrustGrantedWithFlags(int flags, int userId) { }
 
     /**
      * Called when a fingerprint is recognized.
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index 5bbcc8c..f5c809a 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -76,4 +76,9 @@
      *         (legacy API)
      */
     boolean isInputRestricted();
+
+    /**
+     * @return true if the screen is on
+     */
+    boolean isScreenOn();
 }
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
index e6a0dd7..b8f16e7 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -38,7 +38,7 @@
      * <pre>
      * $ adb shell am broadcast -a action.sample_trust_agent.grant_trust\
      *  -e extra.message SampleTrust\
-     *  --el extra.duration 1000 --ez extra.init_by_user false
+     *  --el extra.duration 1000 --ez extra.init_by_user false --ez extra.dismiss_keyguard false
      * </pre>
      */
     private static final boolean ALLOW_EXTERNAL_BROADCASTS = false;
@@ -51,6 +51,7 @@
     private static final String EXTRA_MESSAGE = "extra.message";
     private static final String EXTRA_DURATION = "extra.duration";
     private static final String EXTRA_INITIATED_BY_USER = "extra.init_by_user";
+    private static final String EXTRA_DISMISS_KEYGUARD = "extra.dismiss_keyguard";
 
     private static final String PREFERENCE_REPORT_UNLOCK_ATTEMPTS
             = "preference.report_unlock_attempts";
@@ -141,10 +142,17 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (ACTION_GRANT_TRUST.equals(action)) {
+                int flags = 0;
+                if (intent.getBooleanExtra(EXTRA_INITIATED_BY_USER, false)) {
+                    flags |= TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER;
+                }
+                if (intent.getBooleanExtra(EXTRA_DISMISS_KEYGUARD, false)) {
+                    flags |= TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD;
+                }
+
                 try {
                     grantTrust(intent.getStringExtra(EXTRA_MESSAGE),
-                            intent.getLongExtra(EXTRA_DURATION, 0),
-                            intent.getBooleanExtra(EXTRA_INITIATED_BY_USER, false));
+                            intent.getLongExtra(EXTRA_DURATION, 0), flags);
                 } catch (IllegalStateException e) {
                     logAndShowToast("IllegalStateException: " + e.getMessage());
                 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsInfo.java b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsInfo.java
new file mode 100644
index 0000000..60b5ba5
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PermissionsInfo.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.applications;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class PermissionsInfo {
+
+    private static final String TAG = "PermissionsInfo";
+
+    private final PackageManager mPm;
+    private final ArrayList<PermissionGroup> mGroups = new ArrayList<>();
+    private final Map<String, PermissionGroup> mGroupLookup = new ArrayMap<>();
+    private final Callback mCallback;
+    private final Context mContext;
+    // Count of apps that request runtime permissions.
+    private int mRuntimePermAppsCt;
+    // Count of apps that are granted runtime permissions.
+    private int mRuntimePermAppsGrantedCt;
+
+    public PermissionsInfo(Context context, Callback callback) {
+        mContext = context;
+        mPm = context.getPackageManager();
+        mCallback = callback;
+        new PermissionsLoader().execute();
+    }
+
+    public List<PermissionGroup> getGroups() {
+        synchronized (mGroups) {
+            return new ArrayList<>(mGroups);
+        }
+    }
+
+    public int getRuntimePermAppsCount() {
+        return mRuntimePermAppsCt;
+    }
+
+    public int getRuntimePermAppsGrantedCount() {
+        return mRuntimePermAppsGrantedCt;
+    }
+
+    private PermissionGroup getOrCreateGroup(String permission) {
+        PermissionGroup group = mGroupLookup.get(permission);
+        if (group == null) {
+            // Some permissions don't have a group, in that case treat them like a group
+            // and create their own PermissionGroup (only if they are runtime).
+            try {
+                PermissionInfo info = mPm.getPermissionInfo(permission, 0);
+                if (info.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS) {
+                    group = new PermissionGroup();
+                    // TODO: Add default permission icon.
+                    group.icon = info.icon != 0 ? info.loadIcon(mPm) : new ShapeDrawable();
+                    group.name = info.name;
+                    group.label = info.loadLabel(mPm).toString();
+                    mGroups.add(group);
+                    mGroupLookup.put(permission, group);
+                }
+            } catch (NameNotFoundException e) {
+                Log.w(TAG, "Unknown permission " + permission, e);
+            }
+        }
+        return group;
+    }
+
+    private class PermissionsLoader extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            List<PermissionGroupInfo> groups =
+                    mPm.getAllPermissionGroups(PackageManager.GET_META_DATA);
+            // Get the groups.
+            for (PermissionGroupInfo groupInfo : groups) {
+                PermissionGroup group = new PermissionGroup();
+                // TODO: Add default permission icon.
+                group.icon = groupInfo.icon != 0 ? groupInfo.loadIcon(mPm) : new ShapeDrawable();
+                group.name = groupInfo.name;
+                group.label = groupInfo.loadLabel(mPm).toString();
+                synchronized (mGroups) {
+                    mGroups.add(group);
+                }
+            }
+            // Load permissions and which are runtime.
+            for (PermissionGroup group : mGroups) {
+                try {
+                    List<PermissionInfo> permissions =
+                            mPm.queryPermissionsByGroup(group.name, 0);
+                    for (PermissionInfo info : permissions) {
+                        if (info.protectionLevel != PermissionInfo.PROTECTION_DANGEROUS) continue;
+                        mGroupLookup.put(info.name, group);
+                    }
+                } catch (NameNotFoundException e) {
+                    Log.w(TAG, "Problem getting permissions", e);
+                }
+            }
+            // Load granted info.
+            for (UserHandle user : UserManager.get(mContext).getUserProfiles()) {
+                List<PackageInfo> allApps = mPm.getInstalledPackages(
+                        PackageManager.GET_PERMISSIONS, user.getIdentifier());
+                for (PackageInfo info : allApps) {
+                    if (info.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1
+                            || info.requestedPermissions == null)  {
+                        continue;
+                    }
+                    final int N = info.requestedPermissionsFlags.length;
+                    boolean appHasRuntimePerms = false;
+                    boolean appGrantedRuntimePerms = false;
+                    for (int i = 0; i < N; i++) {
+                        boolean granted = (info.requestedPermissionsFlags[i]
+                                & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
+                        PermissionGroup group = getOrCreateGroup(info.requestedPermissions[i]);
+                        String key = Integer.toString(info.applicationInfo.uid);
+                        if (group != null && !group.possibleApps.contains(key)) {
+                            appHasRuntimePerms = true;
+                            group.possibleApps.add(key);
+                            if (granted) {
+                                appGrantedRuntimePerms = true;
+                                group.grantedApps.add(key);
+                            }
+                        }
+                    }
+                    if (appHasRuntimePerms) {
+                        mRuntimePermAppsCt++;
+                        if (appGrantedRuntimePerms) {
+                            mRuntimePermAppsGrantedCt++;
+                        }
+                    }
+                }
+            }
+            Collections.sort(mGroups);
+
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            mCallback.onPermissionLoadComplete();
+        }
+    }
+
+    public static class PermissionGroup implements Comparable<PermissionGroup> {
+        public final List<String> possibleApps = new ArrayList<>();
+        public final List<String> grantedApps = new ArrayList<>();
+        public String name;
+        public String label;
+        public Drawable icon;
+
+        @Override
+        public int compareTo(PermissionGroup another) {
+            return label.compareTo(another.label);
+        }
+    }
+
+    public interface Callback {
+        void onPermissionLoadComplete();
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 97a4c55..f16fb5c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -505,6 +505,11 @@
         public boolean isInputRestricted() {
             return KeyguardViewMediator.this.isInputRestricted();
         }
+
+        @Override
+        public boolean isScreenOn() {
+            return mScreenOn;
+        }
     };
 
     public void userActivity() {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index ee73b1a..16689ee 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -388,7 +388,9 @@
         byte[] currentHandle = getCurrentHandle(userId);
 
         if (pattern == null) {
+            getGateKeeperService().clearSecureUserId(userId);
             mStorage.writePatternHash(null, userId);
+            maybeUpdateKeystore(null, userId);
             return;
         }
 
@@ -414,7 +416,9 @@
         byte[] currentHandle = getCurrentHandle(userId);
 
         if (password == null) {
+            getGateKeeperService().clearSecureUserId(userId);
             mStorage.writePasswordHash(null, userId);
+            maybeUpdateKeystore(null, userId);
             return;
         }
 
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 4c937f7..7e4df58 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -61,6 +61,7 @@
 import android.os.storage.StorageVolume;
 import android.os.storage.VolumeInfo;
 import android.text.TextUtils;
+import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.DebugUtils;
@@ -533,7 +534,11 @@
                     break;
                 }
                 case H_FSTRIM: {
-                    waitForReady();
+                    if (!isReady()) {
+                        Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again");
+                        sendMessageDelayed(obtainMessage(H_FSTRIM), DateUtils.SECOND_IN_MILLIS);
+                    }
+
                     Slog.i(TAG, "Running fstrim idle maintenance");
 
                     // Remember when we kicked it off
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5b1543e..33f915f 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -363,19 +363,9 @@
         mOverrideConfig = Configuration.EMPTY;
     }
 
-    /**
-     * Checks whether the userid is a profile of the current user.
-     */
-    private boolean isCurrentProfileLocked(int userId) {
-        if (userId == mCurrentUser) return true;
-        for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
-            if (mService.mCurrentProfileIds[i] == userId) return true;
-        }
-        return false;
-    }
-
     boolean okToShowLocked(ActivityRecord r) {
-        return isCurrentProfileLocked(r.userId) || (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
+        return mStackSupervisor.isCurrentProfileLocked(r.userId)
+                || (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
     }
 
     final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
@@ -619,7 +609,8 @@
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            final boolean notCurrentUserTask = !isCurrentProfileLocked(task.userId);
+            final boolean notCurrentUserTask =
+                    !mStackSupervisor.isCurrentProfileLocked(task.userId);
             final ArrayList<ActivityRecord> activities = task.mActivities;
 
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
@@ -655,7 +646,7 @@
 
             // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
             // okay to show the activity when locked.
-            if (isCurrentProfileLocked(task.userId)
+            if (mStackSupervisor.isCurrentProfileLocked(task.userId)
                     || task.topRunningActivityLocked(null) != null) {
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() +
                         " moving " + task + " to top");
@@ -817,8 +808,14 @@
     final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
             boolean dontWait) {
         if (mPausingActivity != null) {
-            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity);
-            completePauseLocked(false);
+            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+                    + " state=" + mPausingActivity.state);
+            if (!mService.isSleeping()) {
+                // Avoid recursion among check for sleep and complete pause during sleeping.
+                // Because activity will be paused immediately after resume, just let pause
+                // be completed by the order of activity paused from clients.
+                completePauseLocked(false);
+            }
         }
         ActivityRecord prev = mResumedActivity;
         if (prev == null) {
@@ -2026,11 +2023,11 @@
         final boolean notShownWhenLocked =
                 (newActivity != null && (newActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0)
                 || (newActivity == null && task.topRunningActivityLocked(null) == null);
-        if (!isCurrentProfileLocked(task.userId) && notShownWhenLocked) {
+        if (!mStackSupervisor.isCurrentProfileLocked(task.userId) && notShownWhenLocked) {
             // Put non-current user tasks below current user tasks.
             while (--taskNdx >= 0) {
                 final TaskRecord tmpTask = mTaskHistory.get(taskNdx);
-                if (!isCurrentProfileLocked(tmpTask.userId)
+                if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId)
                         || tmpTask.topRunningActivityLocked(null) == null) {
                     break;
                 }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 58bdc28..1585f61 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -24,6 +24,7 @@
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static com.android.server.am.ActivityManagerDebugConfig.*;
@@ -1381,8 +1382,9 @@
             }
         }
 
+        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
+
         if (err == ActivityManager.START_SUCCESS) {
-            final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
             Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                     + "} from uid " + callingUid
                     + " on display " + (container == null ? (mFocusedStack == null ?
@@ -1406,7 +1408,7 @@
 
         final int launchFlags = intent.getFlags();
 
-        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
+        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
             // Transfer the result target from the source activity to the new
             // one being started, including any failures.
             if (requestCode >= 0) {
@@ -1450,6 +1452,13 @@
             err = ActivityManager.START_CLASS_NOT_FOUND;
         }
 
+        if (err == ActivityManager.START_SUCCESS
+                && !isCurrentProfileLocked(userId)
+                && (aInfo.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) {
+            // Trying to launch a background activity that doesn't show for all users.
+            err = ActivityManager.START_NOT_CURRENT_USER_ACTIVITY;
+        }
+
         if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                 && sourceRecord.task.voiceSession != null) {
             // If this activity is being launched as part of a voice session, we need
@@ -3231,6 +3240,15 @@
         mStartingBackgroundUsers.add(uss);
     }
 
+    /** Checks whether the userid is a profile of the current user. */
+    boolean isCurrentProfileLocked(int userId) {
+        if (userId == mCurrentUser) return true;
+        for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
+            if (mService.mCurrentProfileIds[i] == userId) return true;
+        }
+        return false;
+    }
+
     final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
         ArrayList<ActivityRecord> stops = null;
 
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 6dbe869..905adc0 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -18,8 +18,6 @@
 
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -40,7 +38,6 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
-import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
@@ -71,8 +68,6 @@
     final BatteryStatsImpl mStats;
     final BatteryStatsHandler mHandler;
     Context mContext;
-    private boolean mBluetoothPendingStats;
-    private BluetoothHeadset mBluetoothHeadset;
     PowerManagerInternal mPowerManagerInternal;
 
     class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
@@ -618,56 +613,6 @@
         }
     }
 
-    public void noteBluetoothOn() {
-        enforceCallingPermission();
-        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter != null) {
-            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
-                                    BluetoothProfile.HEADSET);
-        }
-        synchronized (mStats) {
-            if (mBluetoothHeadset != null) {
-                mStats.noteBluetoothOnLocked();
-                mStats.setBtHeadset(mBluetoothHeadset);
-            } else {
-                mBluetoothPendingStats = true;
-            }
-        }
-    }
-
-    private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
-        new BluetoothProfile.ServiceListener() {
-        public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            mBluetoothHeadset = (BluetoothHeadset) proxy;
-            synchronized (mStats) {
-                if (mBluetoothPendingStats) {
-                    mStats.noteBluetoothOnLocked();
-                    mStats.setBtHeadset(mBluetoothHeadset);
-                    mBluetoothPendingStats = false;
-                }
-            }
-        }
-
-        public void onServiceDisconnected(int profile) {
-            mBluetoothHeadset = null;
-        }
-    };
-
-    public void noteBluetoothOff() {
-        enforceCallingPermission();
-        synchronized (mStats) {
-            mBluetoothPendingStats = false;
-            mStats.noteBluetoothOffLocked();
-        }
-    }
-    
-    public void noteBluetoothState(int bluetoothState) {
-        enforceCallingPermission();
-        synchronized (mStats) {
-            mStats.noteBluetoothStateLocked(bluetoothState);
-        }
-    }
-
     public void noteFullWifiLockAcquired(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index dec195d..fb7d186 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -116,7 +116,7 @@
                     }
                     mTrusted = true;
                     mMessage = (CharSequence) msg.obj;
-                    boolean initiatedByUser = msg.arg1 != 0;
+                    int flags = msg.arg1;
                     long durationMs = msg.getData().getLong(DATA_DURATION);
                     if (durationMs > 0) {
                         final long duration;
@@ -141,8 +141,8 @@
                     }
                     mTrustManagerService.mArchive.logGrantTrust(mUserId, mName,
                             (mMessage != null ? mMessage.toString() : null),
-                            durationMs, initiatedByUser);
-                    mTrustManagerService.updateTrust(mUserId, initiatedByUser);
+                            durationMs, flags);
+                    mTrustManagerService.updateTrust(mUserId, flags);
                     break;
                 case MSG_TRUST_TIMEOUT:
                     if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString());
@@ -156,7 +156,7 @@
                     if (msg.what == MSG_REVOKE_TRUST) {
                         mTrustManagerService.mArchive.logRevokeTrust(mUserId, mName);
                     }
-                    mTrustManagerService.updateTrust(mUserId, false);
+                    mTrustManagerService.updateTrust(mUserId, 0);
                     break;
                 case MSG_RESTART_TIMEOUT:
                     destroy();
@@ -171,7 +171,7 @@
                             if (DEBUG) Log.v(TAG, "Re-enabling agent because it acknowledged "
                                     + "enabled features: " + mName);
                             mTrustDisabledByDpm = false;
-                            mTrustManagerService.updateTrust(mUserId, false);
+                            mTrustManagerService.updateTrust(mUserId, 0);
                         }
                     } else {
                         if (DEBUG) Log.w(TAG, "Ignoring MSG_SET_TRUST_AGENT_FEATURES_COMPLETED "
@@ -185,7 +185,7 @@
                         mMessage = null;
                     }
                     mTrustManagerService.mArchive.logManagingTrust(mUserId, mName, mManagingTrust);
-                    mTrustManagerService.updateTrust(mUserId, false);
+                    mTrustManagerService.updateTrust(mUserId, 0);
                     break;
             }
         }
@@ -194,12 +194,12 @@
     private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() {
 
         @Override
-        public void grantTrust(CharSequence userMessage, long durationMs, boolean initiatedByUser) {
+        public void grantTrust(CharSequence userMessage, long durationMs, int flags) {
             if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs
-                        + ", initiatedByUser = " + initiatedByUser + ")");
+                        + ", flags = " + flags + ")");
 
             Message msg = mHandler.obtainMessage(
-                    MSG_GRANT_TRUST, initiatedByUser ? 1 : 0, 0, userMessage);
+                    MSG_GRANT_TRUST, flags, 0, userMessage);
             msg.getData().putLong(DATA_DURATION, durationMs);
             msg.sendToTarget();
         }
@@ -381,7 +381,7 @@
         }
         if (mTrustDisabledByDpm != trustDisabled) {
             mTrustDisabledByDpm = trustDisabled;
-            mTrustManagerService.updateTrust(mUserId, false);
+            mTrustManagerService.updateTrust(mUserId, 0);
         }
         return trustDisabled;
     }
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index 7253716..fd63d48 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.service.trust.TrustAgentService;
 import android.util.TimeUtils;
 
 import java.io.PrintWriter;
@@ -48,20 +49,20 @@
         // grantTrust
         final String message;
         final long duration;
-        final boolean userInitiated;
+        final int flags;
 
         // managingTrust
         final boolean managingTrust;
 
         private Event(int type, int userId, ComponentName agent, String message,
-                long duration, boolean userInitiated, boolean managingTrust) {
+                long duration, int flags, boolean managingTrust) {
             this.type = type;
             this.userId = userId;
             this.agent = agent;
             this.elapsedTimestamp = SystemClock.elapsedRealtime();
             this.message = message;
             this.duration = duration;
-            this.userInitiated = userInitiated;
+            this.flags = flags;
             this.managingTrust = managingTrust;
         }
     }
@@ -69,33 +70,33 @@
     ArrayDeque<Event> mEvents = new ArrayDeque<Event>();
 
     public void logGrantTrust(int userId, ComponentName agent, String message,
-            long duration, boolean userInitiated) {
+            long duration, int flags) {
         addEvent(new Event(TYPE_GRANT_TRUST, userId, agent, message, duration,
-                userInitiated, false));
+                flags, false));
     }
 
     public void logRevokeTrust(int userId, ComponentName agent) {
-        addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, false, false));
+        addEvent(new Event(TYPE_REVOKE_TRUST, userId, agent, null, 0, 0, false));
     }
 
     public void logTrustTimeout(int userId, ComponentName agent) {
-        addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, false, false));
+        addEvent(new Event(TYPE_TRUST_TIMEOUT, userId, agent, null, 0, 0, false));
     }
 
     public void logAgentDied(int userId, ComponentName agent) {
-        addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, false, false));
+        addEvent(new Event(TYPE_AGENT_DIED, userId, agent, null, 0, 0, false));
     }
 
     public void logAgentConnected(int userId, ComponentName agent) {
-        addEvent(new Event(TYPE_AGENT_CONNECTED, userId, agent, null, 0, false, false));
+        addEvent(new Event(TYPE_AGENT_CONNECTED, userId, agent, null, 0, 0, false));
     }
 
     public void logAgentStopped(int userId, ComponentName agent) {
-        addEvent(new Event(TYPE_AGENT_STOPPED, userId, agent, null, 0, false, false));
+        addEvent(new Event(TYPE_AGENT_STOPPED, userId, agent, null, 0, 0, false));
     }
 
     public void logManagingTrust(int userId, ComponentName agent, boolean managing) {
-        addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, false, managing));
+        addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, 0, managing));
     }
 
     private void addEvent(Event e) {
@@ -129,8 +130,8 @@
             }
             switch (ev.type) {
                 case TYPE_GRANT_TRUST:
-                    writer.printf(", message=\"%s\", duration=%s, initiatedByUser=%d",
-                            ev.message, formatDuration(ev.duration), ev.userInitiated ? 1 : 0);
+                    writer.printf(", message=\"%s\", duration=%s, flags=%s",
+                            ev.message, formatDuration(ev.duration), dumpGrantFlags(ev.flags));
                     break;
                 case TYPE_MANAGING_TRUST:
                     writer.printf(", managingTrust=" + ev.managingTrust);
@@ -184,4 +185,20 @@
                 return "Unknown(" + type + ")";
         }
     }
+
+    private String dumpGrantFlags(int flags) {
+        StringBuilder sb = new StringBuilder();
+        if ((flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0) {
+            if (sb.length() != 0) sb.append('|');
+            sb.append("INITIATED_BY_USER");
+        }
+        if ((flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0) {
+            if (sb.length() != 0) sb.append('|');
+            sb.append("DISMISS_KEYGUARD");
+        }
+        if (sb.length() == 0) {
+            sb.append('0');
+        }
+        return sb.toString();
+    }
 }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index b38d33d..7d2fb43 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -179,11 +179,11 @@
     private void updateTrustAll() {
         List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
         for (UserInfo userInfo : userInfos) {
-            updateTrust(userInfo.id, false);
+            updateTrust(userInfo.id, 0);
         }
     }
 
-    public void updateTrust(int userId, boolean initiatedByUser) {
+    public void updateTrust(int userId, int flags) {
         dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
         boolean trusted = aggregateIsTrusted(userId);
         boolean changed;
@@ -191,7 +191,7 @@
             changed = mUserIsTrusted.get(userId) != trusted;
             mUserIsTrusted.put(userId, trusted);
         }
-        dispatchOnTrustChanged(trusted, userId, initiatedByUser);
+        dispatchOnTrustChanged(trusted, userId, flags);
         if (changed) {
             refreshDeviceLockedForUser(userId);
         }
@@ -281,7 +281,7 @@
             if (userId == UserHandle.USER_ALL) {
                 updateTrustAll();
             } else {
-                updateTrust(userId, false /* initiatedByUser */);
+                updateTrust(userId, 0);
             }
         }
     }
@@ -394,7 +394,7 @@
             }
         }
         if (trustMayHaveChanged) {
-            updateTrust(userId, false);
+            updateTrust(userId, 0);
         }
         refreshAgentList(userId);
     }
@@ -587,11 +587,11 @@
         }
     }
 
-    private void dispatchOnTrustChanged(boolean enabled, int userId, boolean initiatedByUser) {
-        if (!enabled) initiatedByUser = false;
+    private void dispatchOnTrustChanged(boolean enabled, int userId, int flags) {
+        if (!enabled) flags = 0;
         for (int i = 0; i < mTrustListeners.size(); i++) {
             try {
-                mTrustListeners.get(i).onTrustChanged(enabled, userId, initiatedByUser);
+                mTrustListeners.get(i).onTrustChanged(enabled, userId, flags);
             } catch (DeadObjectException e) {
                 Slog.d(TAG, "Removing dead TrustListener.");
                 mTrustListeners.remove(i);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 7c5980a..f3edbd1 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -752,7 +752,7 @@
 
 void NativeInputManager::reloadCalibration() {
     mInputManager->getReader()->requestRefreshConfiguration(
-            InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION);
+            InputReaderConfiguration::CHANGE_TOUCH_AFFINE_TRANSFORMATION);
 }
 
 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(