Merge changes from topic 'keyguard_refactor'

* changes:
  The big keyguard transition refactor (6/n)
  The big keyguard transition refactor (5/n)
  The big keyguard transition refactor (4/n)
  The big keyguard transition refactor (3/n)
  The big keyguard transition refactor (2/n)
  The big keyguard transition refactor (1/n)
diff --git a/Android.mk b/Android.mk
index db63739..b34d2ff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -118,9 +118,10 @@
 	core/java/android/bluetooth/IBluetoothPan.aidl \
 	core/java/android/bluetooth/IBluetoothManager.aidl \
 	core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
+	core/java/android/bluetooth/IBluetoothMap.aidl \
+	core/java/android/bluetooth/IBluetoothMapClient.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
 	core/java/android/bluetooth/IBluetoothPbapClient.aidl \
-	core/java/android/bluetooth/IBluetoothMap.aidl \
 	core/java/android/bluetooth/IBluetoothSap.aidl \
 	core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
 	core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \
diff --git a/api/current.txt b/api/current.txt
index 643240c..5077168 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5335,16 +5335,20 @@
   }
 
   public final class NotificationChannel implements android.os.Parcelable {
-    ctor public NotificationChannel(java.lang.String, java.lang.CharSequence);
+    ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
     ctor protected NotificationChannel(android.os.Parcel);
     method public boolean canBypassDnd();
     method public int describeContents();
-    method public android.net.Uri getDefaultRingtone();
     method public java.lang.String getId();
     method public int getImportance();
+    method public int getLockscreenVisibility();
     method public java.lang.CharSequence getName();
-    method public void setDefaultRingtone(android.net.Uri);
+    method public android.net.Uri getRingtone();
+    method public void setBypassDnd(boolean);
+    method public void setImportance(int);
     method public void setLights(boolean);
+    method public void setLockscreenVisibility(int);
+    method public void setRingtone(android.net.Uri);
     method public void setVibration(boolean);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5376,7 +5380,6 @@
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
-    method public void updateNotificationChannel(android.app.NotificationChannel);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
diff --git a/api/system-current.txt b/api/system-current.txt
index d231154..35024b7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5481,22 +5481,23 @@
   }
 
   public final class NotificationChannel implements android.os.Parcelable {
-    ctor public NotificationChannel(java.lang.String, java.lang.CharSequence);
+    ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
     ctor protected NotificationChannel(android.os.Parcel);
     method public boolean canBypassDnd();
     method public int describeContents();
-    method public android.net.Uri getDefaultRingtone();
     method public java.lang.String getId();
     method public int getImportance();
     method public int getLockscreenVisibility();
     method public java.lang.CharSequence getName();
+    method public android.net.Uri getRingtone();
+    method public int getUserLockedFields();
+    method public void lockFields(int);
     method public void populateFromXml(org.xmlpull.v1.XmlPullParser);
     method public void setBypassDnd(boolean);
-    method public void setDefaultRingtone(android.net.Uri);
     method public void setImportance(int);
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
-    method public void setName(java.lang.CharSequence);
+    method public void setRingtone(android.net.Uri);
     method public void setVibration(boolean);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5505,6 +5506,12 @@
     method public void writeXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
     field public static final android.os.Parcelable.Creator<android.app.NotificationChannel> CREATOR;
     field public static final java.lang.String DEFAULT_CHANNEL_ID = "miscellaneous";
+    field public static final int USER_LOCKED_IMPORTANCE = 4; // 0x4
+    field public static final int USER_LOCKED_LIGHTS = 8; // 0x8
+    field public static final int USER_LOCKED_PRIORITY = 1; // 0x1
+    field public static final int USER_LOCKED_RINGTONE = 32; // 0x20
+    field public static final int USER_LOCKED_VIBRATION = 16; // 0x10
+    field public static final int USER_LOCKED_VISIBILITY = 2; // 0x2
   }
 
   public class NotificationManager {
@@ -5530,7 +5537,6 @@
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
-    method public void updateNotificationChannel(android.app.NotificationChannel);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
diff --git a/api/test-current.txt b/api/test-current.txt
index 3021b25..acb74e7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5338,16 +5338,20 @@
   }
 
   public final class NotificationChannel implements android.os.Parcelable {
-    ctor public NotificationChannel(java.lang.String, java.lang.CharSequence);
+    ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
     ctor protected NotificationChannel(android.os.Parcel);
     method public boolean canBypassDnd();
     method public int describeContents();
-    method public android.net.Uri getDefaultRingtone();
     method public java.lang.String getId();
     method public int getImportance();
+    method public int getLockscreenVisibility();
     method public java.lang.CharSequence getName();
-    method public void setDefaultRingtone(android.net.Uri);
+    method public android.net.Uri getRingtone();
+    method public void setBypassDnd(boolean);
+    method public void setImportance(int);
     method public void setLights(boolean);
+    method public void setLockscreenVisibility(int);
+    method public void setRingtone(android.net.Uri);
     method public void setVibration(boolean);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5379,7 +5383,6 @@
     method public final void setInterruptionFilter(int);
     method public void setNotificationPolicy(android.app.NotificationManager.Policy);
     method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
-    method public void updateNotificationChannel(android.app.NotificationChannel);
     field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
diff --git a/cmds/am/am b/cmds/am/am
index 1d426bc..54c2d39 100755
--- a/cmds/am/am
+++ b/cmds/am/am
@@ -1,9 +1,9 @@
 #!/system/bin/sh
-#
-# Script to start "am" on the device, which has a very rudimentary
-# shell.
-#
-base=/system
-export CLASSPATH=$base/framework/am.jar
-exec app_process $base/bin com.android.commands.am.Am "$@"
 
+if [ "$1" != "instrument" ] ; then
+    cmd activity "$@"
+else
+    base=/system
+    export CLASSPATH=$base/framework/am.jar
+    exec app_process $base/bin com.android.commands.am.Am "$@"
+fi
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 91a4549..470a0fa 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -84,34 +84,9 @@
 
 public class Am extends BaseCommand {
 
-    private static final String SHELL_PACKAGE_NAME = "com.android.shell";
-
-    // Is the object moving in a positive direction?
-    private static final boolean MOVING_FORWARD = true;
-    // Is the object moving in the horizontal plan?
-    private static final boolean MOVING_HORIZONTALLY = true;
-    // Is the object current point great then its target point?
-    private static final boolean GREATER_THAN_TARGET = true;
-    // Amount we reduce the stack size by when testing a task re-size.
-    private static final int STACK_BOUNDS_INSET = 10;
-
-    public static final String NO_CLASS_ERROR_CODE = "Error type 3";
     private IActivityManager mAm;
     private IPackageManager mPm;
 
-    private int mStartFlags = 0;
-    private boolean mWaitOption = false;
-    private boolean mStopOption = false;
-
-    private int mRepeat = 0;
-    private int mUserId;
-    private String mReceiverPermission;
-
-    private String mProfileFile;
-    private int mSamplingInterval;
-    private boolean mAutoStop;
-    private int mStackId;
-
     /**
      * Command-line entry point.
      *
@@ -123,249 +98,11 @@
 
     @Override
     public void onShowUsage(PrintStream out) {
-        PrintWriter pw = new PrintWriter(out);
-        pw.println(
-                "usage: am [subcommand] [options]\n" +
-                "usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
-                "               [--sampling INTERVAL] [-R COUNT] [-S]\n" +
-                "               [--track-allocation] [--user <USER_ID> | current] <INTENT>\n" +
-                "       am startservice [--user <USER_ID> | current] <INTENT>\n" +
-                "       am stopservice [--user <USER_ID> | current] <INTENT>\n" +
-                "       am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
-                "       am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
-                "       am kill-all\n" +
-                "       am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
-                "       am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
-                "               [--user <USER_ID> | current]\n" +
-                "               [--no-window-animation] [--abi <ABI>] <COMPONENT>\n" +
-                "       am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE>\n" +
-                "       am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
-                "       am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
-                "       am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
-                "       am clear-debug-app\n" +
-                "       am set-watch-heap <PROCESS> <MEM-LIMIT>\n" +
-                "       am clear-watch-heap\n" +
-                "       am bug-report [--progress]\n" +
-                "       am monitor [--gdb <port>]\n" +
-                "       am hang [--allow-restart]\n" +
-                "       am restart\n" +
-                "       am idle-maintenance\n" +
-                "       am screen-compat [on|off] <PACKAGE>\n" +
-                "       am package-importance <PACKAGE>\n" +
-                "       am to-uri [INTENT]\n" +
-                "       am to-intent-uri [INTENT]\n" +
-                "       am to-app-uri [INTENT]\n" +
-                "       am switch-user <USER_ID>\n" +
-                "       am start-user <USER_ID>\n" +
-                "       am unlock-user <USER_ID> [TOKEN_HEX]\n" +
-                "       am stop-user [-w] [-f] <USER_ID>\n" +
-                "       am stack start <DISPLAY_ID> <INTENT>\n" +
-                "       am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
-                "       am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
-                "       am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
-                "       am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]\n" +
-                "       am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]\n" +
-                "       am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
-                "       am stack positiontask <TASK_ID> <STACK_ID> <POSITION>\n" +
-                "       am stack list\n" +
-                "       am stack info <STACK_ID>\n" +
-                "       am stack remove <STACK_ID>\n" +
-                "       am task lock <TASK_ID>\n" +
-                "       am task lock stop\n" +
-                "       am task resizeable <TASK_ID> [0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)]\n" +
-                "       am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
-                "       am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" +
-                "       am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" +
-                "       am get-config\n" +
-                "       am suppress-resize-config-changes <true|false>\n" +
-                "       am set-inactive [--user <USER_ID>] <PACKAGE> true|false\n" +
-                "       am get-inactive [--user <USER_ID>] <PACKAGE>\n" +
-                "       am send-trim-memory [--user <USER_ID>] <PROCESS>\n" +
-                "               [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]\n" +
-                "       am get-current-user\n" +
-                "\n" +
-                "am start: start an Activity.  Options are:\n" +
-                "    -D: enable debugging\n" +
-                "    -N: enable native debugging\n" +
-                "    -W: wait for launch to complete\n" +
-                "    --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
-                "    --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" +
-                "        between samples (use with --start-profiler)\n" +
-                "    -P <FILE>: like above, but profiling stops when app goes idle\n" +
-                "    -R: repeat the activity launch <COUNT> times.  Prior to each repeat,\n" +
-                "        the top activity will be finished.\n" +
-                "    -S: force stop the target app before starting the activity\n" +
-                "    --track-allocation: enable tracking of object allocations\n" +
-                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
-                "        specified then run as the current user.\n" +
-                "    --stack <STACK_ID>: Specify into which stack should the activity be put.\n" +
-                "\n" +
-                "am startservice: start a Service.  Options are:\n" +
-                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
-                "        specified then run as the current user.\n" +
-                "\n" +
-                "am stopservice: stop a Service.  Options are:\n" +
-                "    --user <USER_ID> | current: Specify which user to run as; if not\n" +
-                "        specified then run as the current user.\n" +
-                "\n" +
-                "am force-stop: force stop everything associated with <PACKAGE>.\n" +
-                "    --user <USER_ID> | all | current: Specify user to force stop;\n" +
-                "        all users if not specified.\n" +
-                "\n" +
-                "am kill: Kill all processes associated with <PACKAGE>.  Only kills.\n" +
-                "  processes that are safe to kill -- that is, will not impact the user\n" +
-                "  experience.\n" +
-                "    --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
-                "        all users if not specified.\n" +
-                "\n" +
-                "am kill-all: Kill all background processes.\n" +
-                "\n" +
-                "am broadcast: send a broadcast Intent.  Options are:\n" +
-                "    --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
-                "        specified then send to all users.\n" +
-                "    --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
-                "\n" +
-                "am instrument: start an Instrumentation.  Typically this target <COMPONENT>\n" +
-                "  is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there \n" +
-                "  is only one instrumentation.  Options are:\n" +
-                "    -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with\n" +
-                "        [-e perf true] to generate raw output for performance measurements.\n" +
-                "    -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a\n" +
-                "        common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
-                "    -p <FILE>: write profiling data to <FILE>\n" +
-                "    -m: Write output as protobuf (machine readable)\n" +
-                "    -w: wait for instrumentation to finish before returning.  Required for\n" +
-                "        test runners.\n" +
-                "    --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
-                "        current user if not specified.\n" +
-                "    --no-window-animation: turn off window animations while running.\n" +
-                "    --abi <ABI>: Launch the instrumented process with the selected ABI.\n"  +
-                "        This assumes that the process supports the selected ABI.\n" +
-                "\n" +
-                "am trace-ipc: Trace IPC transactions.\n" +
-                "  start: start tracing IPC transactions.\n" +
-                "  stop: stop tracing IPC transactions and dump the results to file.\n" +
-                "    --dump-file <FILE>: Specify the file the trace should be dumped to.\n" +
-                "\n" +
-                "am profile: start and stop profiler on a process.  The given <PROCESS> argument\n" +
-                "  may be either a process name or pid.  Options are:\n" +
-                "    --user <USER_ID> | current: When supplying a process name,\n" +
-                "        specify user of process to profile; uses current user if not specified.\n" +
-                "\n" +
-                "am dumpheap: dump the heap of a process.  The given <PROCESS> argument may\n" +
-                "  be either a process name or pid.  Options are:\n" +
-                "    -n: dump native heap instead of managed heap\n" +
-                "    --user <USER_ID> | current: When supplying a process name,\n" +
-                "        specify user of process to dump; uses current user if not specified.\n" +
-                "\n" +
-                "am set-debug-app: set application <PACKAGE> to debug.  Options are:\n" +
-                "    -w: wait for debugger when application starts\n" +
-                "    --persistent: retain this value\n" +
-                "\n" +
-                "am clear-debug-app: clear the previously set-debug-app.\n" +
-                "\n" +
-                "am set-watch-heap: start monitoring pss size of <PROCESS>, if it is at or\n" +
-                "    above <HEAP-LIMIT> then a heap dump is collected for the user to report\n" +
-                "\n" +
-                "am clear-watch-heap: clear the previously set-watch-heap.\n" +
-                "\n" +
-                "am bug-report: request bug report generation; will launch a notification\n" +
-                "    when done to select where it should be delivered. Options are: \n" +
-                "   --progress: will launch a notification right away to show its progress.\n" +
-                "\n" +
-                "am monitor: start monitoring for crashes or ANRs.\n" +
-                "    --gdb: start gdbserv on the given port at crash/ANR\n" +
-                "\n" +
-                "am hang: hang the system.\n" +
-                "    --allow-restart: allow watchdog to perform normal system restart\n" +
-                "\n" +
-                "am restart: restart the user-space system.\n" +
-                "\n" +
-                "am idle-maintenance: perform idle maintenance now.\n" +
-                "\n" +
-                "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
-                "\n" +
-                "am package-importance: print current importance of <PACKAGE>.\n" +
-                "\n" +
-                "am to-uri: print the given Intent specification as a URI.\n" +
-                "\n" +
-                "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
-                "\n" +
-                "am to-app-uri: print the given Intent specification as an android-app: URI.\n" +
-                "\n" +
-                "am switch-user: switch to put USER_ID in the foreground, starting\n" +
-                "  execution of that user if it is currently stopped.\n" +
-                "\n" +
-                "am start-user: start USER_ID in background if it is currently stopped,\n" +
-                "  use switch-user if you want to start the user in foreground.\n" +
-                "\n" +
-                "am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
-                "  code until a later explicit start or switch to it.\n" +
-                "  -w: wait for stop-user to complete.\n" +
-                "  -f: force stop even if there are related users that cannot be stopped.\n" +
-                "\n" +
-                "am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
-                "\n" +
-                "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" +
-                "   bottom (false) of <STACK_ID>.\n" +
-                "\n" +
-                "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" +
-                "\n" +
-                "am stack resize-docked-stack: change docked stack to <LEFT,TOP,RIGHT,BOTTOM>\n" +
-                "   and supplying temporary different task bounds indicated by\n" +
-                "   <TASK_LEFT,TOP,RIGHT,BOTTOM>\n" +
-                "\n" +
-                "am stack size-docked-stack-test: test command for sizing docked stack by\n" +
-                "   <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom\n" +
-                "   applying the optional [DELAY_MS] between each step.\n" +
-                "\n" +
-                "am stack move-top-activity-to-pinned-stack: moves the top activity from\n" +
-                "   <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the\n" +
-                "   bounds of the pinned stack.\n" +
-                "\n" +
-                "am stack positiontask: place <TASK_ID> in <STACK_ID> at <POSITION>" +
-                "\n" +
-                "am stack list: list all of the activity stacks and their sizes.\n" +
-                "\n" +
-                "am stack info: display the information about activity stack <STACK_ID>.\n" +
-                "\n" +
-                "am stack remove: remove stack <STACK_ID>.\n" +
-                "\n" +
-                "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.\n" +
-                "\n" +
-                "am task lock stop: end the current task lock.\n" +
-                "\n" +
-                "am task resizeable: change resizeable mode of <TASK_ID>.\n" +
-                "   0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)\n" +
-                "\n" +
-                "am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.\n" +
-                "   Forces the task to be resizeable and creates a stack if no existing stack\n" +
-                "   has the specified bounds.\n" +
-                "\n" +
-                "am task drag-task-test: test command for dragging/moving <TASK_ID> by\n" +
-                "   <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]\n" +
-                "   between each step.\n" +
-                "\n" +
-                "am task size-task-test: test command for sizing <TASK_ID> by <STEP_SIZE>" +
-                "   increments within the screen applying the optional [DELAY_MS] between\n" +
-                "   each step.\n" +
-                "\n" +
-                "am get-config: retrieve the configuration and any recent configurations\n" +
-                "  of the device.\n" +
-                "am suppress-resize-config-changes: suppresses configuration changes due to\n" +
-                "  user resizing an activity/task.\n" +
-                "\n" +
-                "am set-inactive: sets the inactive state of an app.\n" +
-                "\n" +
-                "am get-inactive: returns the inactive state of an app.\n" +
-                "\n" +
-                "am send-trim-memory: send a memory trim event to a <PROCESS>.\n" +
-                "\n" +
-                "am get-current-user: returns id of the current foreground user.\n" +
-                "\n"
-        );
-        Intent.printIntentArgsHelp(pw, "");
-        pw.flush();
+        try {
+            runAmCmd(new String[] { "help" });
+        } catch (AndroidException e) {
+            e.printStackTrace(System.err);
+        }
     }
 
     @Override
@@ -385,9 +122,7 @@
 
         String op = nextArgRequired();
 
-        if (op.equals("broadcast")) {
-            sendBroadcast();
-        } else if (op.equals("instrument")) {
+        if (op.equals("instrument")) {
             runInstrument();
         } else {
             runAmCmd(getRawArgs());
@@ -458,90 +193,6 @@
         }
     }
 
-    private Intent makeIntent(int defUser) throws URISyntaxException {
-        mStartFlags = 0;
-        mWaitOption = false;
-        mStopOption = false;
-        mRepeat = 0;
-        mProfileFile = null;
-        mSamplingInterval = 0;
-        mAutoStop = false;
-        mUserId = defUser;
-        mStackId = INVALID_STACK_ID;
-
-        return Intent.parseCommandArgs(mArgs, new Intent.CommandOptionHandler() {
-            @Override
-            public boolean handleOption(String opt, ShellCommand cmd) {
-                if (opt.equals("-D")) {
-                    mStartFlags |= ActivityManager.START_FLAG_DEBUG;
-                } else if (opt.equals("-N")) {
-                    mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING;
-                } else if (opt.equals("-W")) {
-                    mWaitOption = true;
-                } else if (opt.equals("-P")) {
-                    mProfileFile = nextArgRequired();
-                    mAutoStop = true;
-                } else if (opt.equals("--start-profiler")) {
-                    mProfileFile = nextArgRequired();
-                    mAutoStop = false;
-                } else if (opt.equals("--sampling")) {
-                    mSamplingInterval = Integer.parseInt(nextArgRequired());
-                } else if (opt.equals("-R")) {
-                    mRepeat = Integer.parseInt(nextArgRequired());
-                } else if (opt.equals("-S")) {
-                    mStopOption = true;
-                } else if (opt.equals("--track-allocation")) {
-                    mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
-                } else if (opt.equals("--user")) {
-                    mUserId = UserHandle.parseUserArg(nextArgRequired());
-                } else if (opt.equals("--receiver-permission")) {
-                    mReceiverPermission = nextArgRequired();
-                } else if (opt.equals("--stack")) {
-                    mStackId = Integer.parseInt(nextArgRequired());
-                } else {
-                    return false;
-                }
-                return true;
-            }
-        });
-    }
-
-    private class IntentReceiver extends IIntentReceiver.Stub {
-        private boolean mFinished = false;
-
-        @Override
-        public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
-                boolean ordered, boolean sticky, int sendingUser) {
-            String line = "Broadcast completed: result=" + resultCode;
-            if (data != null) line = line + ", data=\"" + data + "\"";
-            if (extras != null) line = line + ", extras: " + extras;
-            System.out.println(line);
-            synchronized (this) {
-                mFinished = true;
-                notifyAll();
-            }
-        }
-
-        public synchronized void waitForFinish() {
-            try {
-                while (!mFinished) wait();
-            } catch (InterruptedException e) {
-                throw new IllegalStateException(e);
-            }
-        }
-    }
-
-    private void sendBroadcast() throws Exception {
-        Intent intent = makeIntent(UserHandle.USER_CURRENT);
-        IntentReceiver receiver = new IntentReceiver();
-        String[] requiredPermissions = mReceiverPermission == null ? null
-                : new String[] {mReceiverPermission};
-        System.out.println("Broadcasting: " + intent);
-        mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, requiredPermissions,
-                android.app.AppOpsManager.OP_NONE, null, true, false, mUserId);
-        receiver.waitForFinish();
-    }
-
     public void runInstrument() throws Exception {
         Instrument instrument = new Instrument(mAm, mPm);
 
diff --git a/cmds/appops/appops b/cmds/appops/appops
index 25d2031..5dc85aa 100755
--- a/cmds/appops/appops
+++ b/cmds/appops/appops
@@ -1 +1,2 @@
-cmd appops $@
+#!/system/bin/sh
+cmd appops "$@"
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c87eef9..ee81c58 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -59,7 +59,6 @@
     int getPackageImportance(String pkg);
 
     void createNotificationChannel(String pkg, in NotificationChannel channel);
-    void updateNotificationChannel(String pkg, in NotificationChannel channel);
     void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
     NotificationChannel getNotificationChannel(String pkg, String channelId);
     NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 4150172..f259c6d 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package android.app;
 
 import org.json.JSONException;
@@ -33,12 +48,45 @@
     private static final String ATT_IMPORTANCE = "importance";
     private static final String ATT_LIGHTS = "lights";
     private static final String ATT_VIBRATION = "vibration";
-    private static final String ATT_DEFAULT_RINGTONE = "ringtone";
+    private static final String ATT_RINGTONE = "ringtone";
+    private static final String ATT_USER_APPROVED = "approved";
+    private static final String ATT_USER_LOCKED = "locked";
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_LOCKED_PRIORITY = 0x00000001;
+    /**
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_LOCKED_VISIBILITY = 0x00000002;
+    /**
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_LOCKED_IMPORTANCE = 0x00000004;
+    /**
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_LOCKED_LIGHTS = 0x00000008;
+    /**
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_LOCKED_VIBRATION = 0x00000010;
+    /**
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_LOCKED_RINGTONE = 0x00000020;
 
     private static final int DEFAULT_VISIBILITY =
-            NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+            NotificationManager.VISIBILITY_NO_OVERRIDE;
     private static final int DEFAULT_IMPORTANCE =
-            NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+            NotificationManager.IMPORTANCE_UNSPECIFIED;
 
     private final String mId;
     private CharSequence mName;
@@ -48,16 +96,21 @@
     private Uri mRingtone;
     private boolean mLights;
     private boolean mVibration;
+    private int mUserLockedFields;
 
     /**
      * Creates a notification channel.
      *
      * @param id The id of the channel. Must be unique per package.
      * @param name The user visible name of the channel.
+     * @param importance The importance of the channel. This controls how interruptive notifications
+     *                   posted to this channel are. See e.g.
+     *                   {@link NotificationManager#IMPORTANCE_DEFAULT}.
      */
-    public NotificationChannel(String id, CharSequence name) {
+    public NotificationChannel(String id, CharSequence name, int importance) {
         this.mId = id;
         this.mName = name;
+        this.mImportance = importance;
     }
 
     protected NotificationChannel(Parcel in) {
@@ -77,6 +130,7 @@
         }
         mLights = in.readByte() != 0;
         mVibration = in.readByte() != 0;
+        mUserLockedFields = in.readInt();
     }
 
     @Override
@@ -99,54 +153,67 @@
         }
         dest.writeByte(mLights ? (byte) 1 : (byte) 0);
         dest.writeByte(mVibration ? (byte) 1 : (byte) 0);
-    }
-
-    // Only modifiable by users.
-    /**
-     * @hide
-     */
-    @SystemApi
-    public void setName(CharSequence name) {
-        this.mName = name;
+        dest.writeInt(mUserLockedFields);
     }
 
     /**
      * @hide
      */
     @SystemApi
-    public void setImportance(int importance) {
-        this.mImportance = importance;
+    public void lockFields(int field) {
+        mUserLockedFields |= field;
     }
 
+    // Modifiable by a notification ranker.
+
     /**
-     * @hide
+     * Only modifiable by the system and notification ranker.
+     *
+     * Sets whether or not this notification can interrupt the user in
+     * {@link android.app.NotificationManager.Policy#INTERRUPTION_FILTER_PRIORITY} mode.
      */
-    @SystemApi
     public void setBypassDnd(boolean bypassDnd) {
         this.mBypassDnd = bypassDnd;
     }
 
     /**
-     * @hide
+     * Only modifiable by the system and notification ranker.
+     *
+     * Sets whether this notification appears on the lockscreen or not, and if so, whether it
+     * appears in a redacted form. See e.g. {@link Notification#VISIBILITY_SECRET}.
      */
-    @SystemApi
     public void setLockscreenVisibility(int lockscreenVisibility) {
         this.mLockscreenVisibility = lockscreenVisibility;
     }
 
+    /**
+     * Only modifiable by the system and notification ranker.
+     *
+     * Sets the level of interruption of this notification channel.
+     *
+     * @param importance the amount the user should be interrupted by notifications from this
+     *                   channel. See e.g.
+     *                   {@link android.app.NotificationManager#IMPORTANCE_DEFAULT}.
+     */
+    public void setImportance(int importance) {
+        this.mImportance = importance;
+    }
+
     // Modifiable by apps on channel creation.
 
     /**
      * Sets the ringtone that should be played for notifications posted to this channel if
-     * the notifications don't supply a ringtone. Only modifiable on channel creation.
+     * the notifications don't supply a ringtone. Only modifiable before the channel is submitted
+     * to the NotificationManager.
      */
-    public void setDefaultRingtone(Uri defaultRingtone) {
-        this.mRingtone = defaultRingtone;
+    public void setRingtone(Uri ringtone) {
+        this.mRingtone = ringtone;
     }
 
     /**
      * Sets whether notifications posted to this channel should display notification lights,
-     * on devices that support that feature. Only modifiable on channel creation.
+     * on devices that support that feature. Only modifiable before the channel is submitted to
+     * the NotificationManager.
      */
     public void setLights(boolean lights) {
         this.mLights = lights;
@@ -154,7 +221,8 @@
 
     /**
      * Sets whether notification posted to this channel should vibrate, even if individual
-     * notifications are marked as having vibration only modifiable on channel creation.
+     * notifications are marked as having vibration only modifiable before the channel is submitted
+     * to the NotificationManager.
      */
     public void setVibration(boolean vibration) {
         this.mVibration = vibration;
@@ -193,7 +261,7 @@
     /**
      * Returns the notification sound for this channel.
      */
-    public Uri getDefaultRingtone() {
+    public Uri getRingtone() {
         return mRingtone;
     }
 
@@ -212,9 +280,9 @@
     }
 
     /**
-     * @hide
+     * Returns whether or not notifications posted to this channel are shown on the lockscreen in
+     * full or redacted form.
      */
-    @SystemApi
     public int getLockscreenVisibility() {
         return mLockscreenVisibility;
     }
@@ -223,15 +291,23 @@
      * @hide
      */
     @SystemApi
+    public int getUserLockedFields() {
+        return mUserLockedFields;
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi
     public void populateFromXml(XmlPullParser parser) {
-        // Name and id are set in the constructor.
-        setImportance(safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE));
+        // Name, id, and importance are set in the constructor.
         setBypassDnd(Notification.PRIORITY_DEFAULT
                 != safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT));
         setLockscreenVisibility(safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
-        setDefaultRingtone(safeUri(parser, ATT_DEFAULT_RINGTONE));
+        setRingtone(safeUri(parser, ATT_RINGTONE));
         setLights(safeBool(parser, ATT_LIGHTS, false));
         setVibration(safeBool(parser, ATT_VIBRATION, false));
+        lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
     }
 
     /**
@@ -254,8 +330,8 @@
             out.attribute(null, ATT_VISIBILITY,
                     Integer.toString(getLockscreenVisibility()));
         }
-        if (getDefaultRingtone() != null) {
-            out.attribute(null, ATT_DEFAULT_RINGTONE, getDefaultRingtone().toString());
+        if (getRingtone() != null) {
+            out.attribute(null, ATT_RINGTONE, getRingtone().toString());
         }
         if (shouldShowLights()) {
             out.attribute(null, ATT_LIGHTS, Boolean.toString(shouldShowLights()));
@@ -263,6 +339,10 @@
         if (shouldVibrate()) {
             out.attribute(null, ATT_VIBRATION, Boolean.toString(shouldVibrate()));
         }
+        if (getUserLockedFields() != 0) {
+            out.attribute(null, ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
+        }
+
         out.endTag(null, TAG_CHANNEL);
     }
 
@@ -284,11 +364,12 @@
         if (getLockscreenVisibility() != DEFAULT_VISIBILITY) {
             record.put(ATT_VISIBILITY, Notification.visibilityToString(getLockscreenVisibility()));
         }
-        if (getDefaultRingtone() != null) {
-            record.put(ATT_DEFAULT_RINGTONE, getDefaultRingtone().toString());
+        if (getRingtone() != null) {
+            record.put(ATT_RINGTONE, getRingtone().toString());
         }
         record.put(ATT_LIGHTS, Boolean.toString(shouldShowLights()));
         record.put(ATT_VIBRATION, Boolean.toString(shouldVibrate()));
+        record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
 
         return record;
     }
@@ -342,15 +423,32 @@
 
         NotificationChannel that = (NotificationChannel) o;
 
-        if (mImportance != that.mImportance) return false;
+        if (getImportance() != that.getImportance()) return false;
         if (mBypassDnd != that.mBypassDnd) return false;
-        if (mLockscreenVisibility != that.mLockscreenVisibility) return false;
+        if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
         if (mLights != that.mLights) return false;
         if (mVibration != that.mVibration) return false;
-        if (!mId.equals(that.mId)) return false;
-        if (mName != null ? !mName.equals(that.mName) : that.mName != null) return false;
-        return mRingtone != null ? mRingtone.equals(
-                that.mRingtone) : that.mRingtone == null;
+        if (getUserLockedFields() != that.getUserLockedFields()) return false;
+        if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
+        if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null)
+            return false;
+        return getRingtone() != null ? getRingtone().equals(
+                that.getRingtone()) : that.getRingtone() == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = getId() != null ? getId().hashCode() : 0;
+        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+        result = 31 * result + getImportance();
+        result = 31 * result + (mBypassDnd ? 1 : 0);
+        result = 31 * result + getLockscreenVisibility();
+        result = 31 * result + (getRingtone() != null ? getRingtone().hashCode() : 0);
+        result = 31 * result + (mLights ? 1 : 0);
+        result = 31 * result + (mVibration ? 1 : 0);
+        result = 31 * result + getUserLockedFields();
+        return result;
     }
 
     @Override
@@ -361,22 +459,10 @@
                 ", mImportance=" + mImportance +
                 ", mBypassDnd=" + mBypassDnd +
                 ", mLockscreenVisibility=" + mLockscreenVisibility +
-                ", mRingtone='" + mRingtone + '\'' +
+                ", mRingtone=" + mRingtone +
                 ", mLights=" + mLights +
                 ", mVibration=" + mVibration +
+                ", mUserLockedFields=" + mUserLockedFields +
                 '}';
     }
-
-    @Override
-    public int hashCode() {
-        int result = mId.hashCode();
-        result = 31 * result + (mName != null ? mName.hashCode() : 0);
-        result = 31 * result + mImportance;
-        result = 31 * result + (mBypassDnd ? 1 : 0);
-        result = 31 * result + mLockscreenVisibility;
-        result = 31 * result + (mRingtone != null ? mRingtone.hashCode() : 0);
-        result = 31 * result + (mLights ? 1 : 0);
-        result = 31 * result + (mVibration ? 1 : 0);
-        return result;
-    }
 }
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 39cd2b5..2234a38 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -181,15 +181,15 @@
     public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
 
     /** @hide */
-    @IntDef({VISIBILITY_NO_OVERRIDE, IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
-            IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH,
-            IMPORTANCE_MAX})
+    @IntDef({IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
+            IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Importance {}
 
     /** Value signifying that the user has not expressed a per-app visibility override value.
      * @hide */
     public static final int VISIBILITY_NO_OVERRIDE = -1000;
+
     /**
      * Value signifying that the user has not expressed an importance.
      *
@@ -214,19 +214,19 @@
     public static final int IMPORTANCE_LOW = 2;
 
     /**
-     * Default notification importance: shows everywhere, allowed to makes noise,
-     * but does not visually intrude.
+     * Default notification importance: shows everywhere, makes noise, but does not visually
+     * intrude.
      */
     public static final int IMPORTANCE_DEFAULT = 3;
 
     /**
-     * Higher notification importance: shows everywhere, allowed to makes noise and peek.
+     * Higher notification importance: shows everywhere, makes noise and peeks. May use full screen
+     * intents.
      */
     public static final int IMPORTANCE_HIGH = 4;
 
     /**
-     * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
-     * use full screen intents.
+     * Unused.
      */
     public static final int IMPORTANCE_MAX = 5;
 
@@ -402,7 +402,7 @@
     }
 
     /**
-     * Returns all notification channels created by the calling app.
+     * Returns all notification channels belonging to the calling app.
      */
     public List<NotificationChannel> getNotificationChannels() {
         INotificationManager service = getService();
@@ -414,18 +414,6 @@
     }
 
     /**
-     * Updates settings for a given channel.
-     */
-    public void updateNotificationChannel(NotificationChannel channel) {
-        INotificationManager service = getService();
-        try {
-            service.updateNotificationChannel(mContext.getPackageName(), channel);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Deletes the given notification channel.
      */
     public void deleteNotificationChannel(String channelId) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 542b06b..bb344a6 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1976,6 +1976,9 @@
         } else if (profile == BluetoothProfile.PBAP_CLIENT) {
             BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
             return true;
+        } else if (profile == BluetoothProfile.MAP_CLIENT) {
+            BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
+            return true;
         } else {
             return false;
         }
@@ -2048,6 +2051,10 @@
                 BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
                 pbapClient.close();
                 break;
+            case BluetoothProfile.MAP_CLIENT:
+                BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
+                mapClient.close();
+                break;
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
new file mode 100644
index 0000000..4252482
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the APIs to control the Bluetooth MAP MCE Profile.
+ *
+ * @hide
+ */
+public final class BluetoothMapClient implements BluetoothProfile {
+
+    private static final String TAG = "BluetoothMapClient";
+    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
+
+    public static final String ACTION_CONNECTION_STATE_CHANGED =
+            "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
+    public static final String ACTION_MESSAGE_RECEIVED =
+            "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED";
+    /* Actions to be used for pending intents */
+    public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY =
+            "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY";
+    public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
+            "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
+
+    private IBluetoothMapClient mService;
+    private final Context mContext;
+    private ServiceListener mServiceListener;
+    private BluetoothAdapter mAdapter;
+
+    /** There was an error trying to obtain the state */
+    public static final int STATE_ERROR = -1;
+
+    public static final int RESULT_FAILURE = 0;
+    public static final int RESULT_SUCCESS = 1;
+    /** Connection canceled before completion. */
+    public static final int RESULT_CANCELED = 2;
+
+    final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+            new IBluetoothStateChangeCallback.Stub() {
+                public void onBluetoothStateChange(boolean up) {
+                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+                    if (!up) {
+                        if (VDBG) Log.d(TAG, "Unbinding service...");
+                        synchronized (mConnection) {
+                            try {
+                                mService = null;
+                                mContext.unbindService(mConnection);
+                            } catch (Exception re) {
+                                Log.e(TAG, "", re);
+                            }
+                        }
+                    } else {
+                        synchronized (mConnection) {
+                            try {
+                                if (mService == null) {
+                                    if (VDBG) Log.d(TAG, "Binding service...");
+                                    doBind();
+                                }
+                            } catch (Exception re) {
+                                Log.e(TAG, "", re);
+                            }
+                        }
+                    }
+                }
+            };
+
+    /**
+     * Create a BluetoothMapClient proxy object.
+     */
+    /*package*/ BluetoothMapClient(Context context, ServiceListener l) {
+        if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
+        mContext = context;
+        mServiceListener = l;
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "", e);
+            }
+        }
+        doBind();
+    }
+
+    boolean doBind() {
+        Intent intent = new Intent(IBluetoothMapClient.class.getName());
+        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+        intent.setComponent(comp);
+        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+                android.os.Process.myUserHandle())) {
+            Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent);
+            return false;
+        }
+        return true;
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Close the connection to the backing service.
+     * Other public functions of BluetoothMap will return default error
+     * results once close() has been called. Multiple invocations of close()
+     * are ok.
+     */
+    public void close() {
+        IBluetoothManager mgr = mAdapter.getBluetoothManager();
+        if (mgr != null) {
+            try {
+                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+            } catch (Exception e) {
+                Log.e(TAG, "", e);
+            }
+        }
+
+        synchronized (mConnection) {
+            if (mService != null) {
+                try {
+                    mService = null;
+                    mContext.unbindService(mConnection);
+                } catch (Exception re) {
+                    Log.e(TAG, "", re);
+                }
+            }
+        }
+        mServiceListener = null;
+    }
+
+    /**
+     * Returns true if the specified Bluetooth device is connected.
+     * Returns false if not connected, or if this proxy object is not
+     * currently connected to the Map service.
+     */
+    public boolean isConnected(BluetoothDevice device) {
+        if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
+        if (mService != null) {
+            try {
+                return mService.isConnected(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
+     * Initiate connection. Initiation of outgoing connections is not
+     * supported for MAP server.
+     */
+    public boolean connect(BluetoothDevice device) {
+        if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
+        if (mService != null) {
+            try {
+                return mService.connect(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
+     * Initiate disconnect.
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on error, true otherwise
+     */
+    public boolean disconnect(BluetoothDevice device) {
+        if (DBG) Log.d(TAG, "disconnect(" + device + ")");
+        if (mService != null && isEnabled() &&
+                isValidDevice(device)) {
+            try {
+                return mService.disconnect(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Get the list of connected devices. Currently at most one.
+     *
+     * @return list of connected devices
+     */
+    @Override
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (DBG) Log.d(TAG, "getConnectedDevices()");
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getConnectedDevices();
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return new ArrayList<>();
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return new ArrayList<>();
+    }
+
+    /**
+     * Get the list of devices matching specified states. Currently at most one.
+     *
+     * @return list of matching devices
+     */
+    @Override
+    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+        if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getDevicesMatchingConnectionStates(states);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return new ArrayList<>();
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return new ArrayList<>();
+    }
+
+    /**
+     * Get connection state of device
+     *
+     * @return device connection state
+     */
+    @Override
+    public int getConnectionState(BluetoothDevice device) {
+        if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
+        if (mService != null && isEnabled() &&
+                isValidDevice(device)) {
+            try {
+                return mService.getConnectionState(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return BluetoothProfile.STATE_DISCONNECTED;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return BluetoothProfile.STATE_DISCONNECTED;
+    }
+
+    /**
+     * Set priority of the profile
+     *
+     * <p> The device should already be paired.  Priority can be one of {@link #PRIORITY_ON} or
+     * {@link #PRIORITY_OFF},
+     *
+     * @param device Paired bluetooth device
+     * @return true if priority is set, false on error
+     */
+    public boolean setPriority(BluetoothDevice device, int priority) {
+        if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
+        if (mService != null && isEnabled() &&
+                isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF &&
+                    priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
+            }
+            try {
+                return mService.setPriority(device, priority);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Get the priority of the profile.
+     *
+     * <p> The priority can be any of:
+     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
+     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     *
+     * @param device Bluetooth device
+     * @return priority of the device
+     */
+    public int getPriority(BluetoothDevice device) {
+        if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
+        if (mService != null && isEnabled() &&
+                isValidDevice(device)) {
+            try {
+                return mService.getPriority(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return PRIORITY_OFF;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return PRIORITY_OFF;
+    }
+
+    /**
+     * Send a message.
+     *
+     * Send an SMS message to either the contacts primary number or the telephone number specified.
+     *
+     * @param device          Bluetooth device
+     * @param contacts        Uri[] of the contacts
+     * @param message         Message to be sent
+     * @param sentIntent      intent issued when message is sent
+     * @param deliveredIntent intent issued when message is delivered
+     * @return true if the message is enqueued, false on error
+     */
+    public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
+            PendingIntent sentIntent, PendingIntent deliveredIntent) {
+        if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get unread messages.  Unread messages will be published via {@link #ACTION_MESSAGE_RECEIVED}.
+     *
+     * @param device Bluetooth device
+     * @return true if the message is enqueued, false on error
+     */
+    public boolean getUnreadMessages(BluetoothDevice device) {
+        if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                return mService.getUnreadMessages(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, Log.getStackTraceString(new Throwable()));
+                return false;
+            }
+        }
+        return false;
+    }
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            if (DBG) Log.d(TAG, "Proxy object connected");
+            mService = IBluetoothMapClient.Stub.asInterface(service);
+            if (mServiceListener != null) {
+                mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
+                    BluetoothMapClient.this);
+            }
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            if (DBG) Log.d(TAG, "Proxy object disconnected");
+            mService = null;
+            if (mServiceListener != null) {
+                mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
+            }
+        }
+    };
+
+    private boolean isEnabled() {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
+        if (DBG) Log.d(TAG, "Bluetooth is Not enabled");
+        return false;
+    }
+
+    private boolean isValidDevice(BluetoothDevice device) {
+        if (device == null) return false;
+
+        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+        return false;
+    }
+
+
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 20d95cc..f363607 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2014 The Android Open Source Project
+ * Copyright (C) 2010-2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -137,6 +137,12 @@
     public static final int PBAP_CLIENT = 17;
 
     /**
+     * MAP Messaging Client Equipment (MCE)
+     * @hide
+     */
+    public static final int MAP_CLIENT = 18;
+
+    /**
      * Max profile ID. This value should be updated whenever a new profile is added to match
      * the largest value assigned to a profile.
      * @hide
diff --git a/core/java/android/bluetooth/IBluetoothMapClient.aidl b/core/java/android/bluetooth/IBluetoothMapClient.aidl
new file mode 100644
index 0000000..df45af9
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothMapClient.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.net.Uri;
+
+/**
+ * System private API for Bluetooth MAP MCE service
+ *
+ * {@hide}
+ */
+interface IBluetoothMapClient {
+    boolean connect(in BluetoothDevice device);
+    boolean disconnect(in BluetoothDevice device);
+    boolean isConnected(in BluetoothDevice device);
+    List<BluetoothDevice> getConnectedDevices();
+    List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+    int getConnectionState(in BluetoothDevice device);
+    boolean setPriority(in BluetoothDevice device,in int priority);
+    int getPriority(in BluetoothDevice device);
+    boolean sendMessage(in BluetoothDevice device, in Uri[] contacts, in  String message,
+        in PendingIntent sentIntent, in PendingIntent deliveryIntent);
+    boolean getUnreadMessages(in BluetoothDevice device);
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 68b7b3a..89c6eb2 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8289,6 +8289,9 @@
                 BLUETOOTH_MAP_PRIORITY_PREFIX = "bluetooth_map_priority_";
         /** {@hide} */
         public static final String
+                BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX = "bluetooth_map_client_priority_";
+        /** {@hide} */
+        public static final String
                 BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX = "bluetooth_pbap_client_priority_";
         /** {@hide} */
         public static final String
@@ -8489,6 +8492,14 @@
         }
 
         /**
+         * Get the key that retrieves a bluetooth map client priority.
+         * @hide
+         */
+        public static final String getBluetoothMapClientPriorityKey(String address) {
+            return BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
+        }
+
+        /**
          * Get the key that retrieves a bluetooth pbap client priority.
          * @hide
          */
@@ -8497,7 +8508,7 @@
         }
 
         /**
-         * Get the key that retrieves a bluetooth map priority.
+         * Get the key that retrieves a bluetooth sap priority.
          * @hide
          */
         public static final String getBluetoothSapPriorityKey(String address) {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e6f58f5..e606ebf 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1037,60 +1037,6 @@
          * @hide */
         public static final int VISIBILITY_NO_OVERRIDE = NotificationManager.VISIBILITY_NO_OVERRIDE;
 
-        /**
-         * Value signifying that the user has not expressed an importance.
-         *
-         * This value is for persisting preferences, and should never be associated with
-         * an actual notification.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_UNSPECIFIED = NotificationManager.IMPORTANCE_UNSPECIFIED;
-
-        /**
-         * A notification with no importance: shows nowhere, is blocked.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_NONE = NotificationManager.IMPORTANCE_NONE;
-
-        /**
-         * Min notification importance: only shows in the shade, below the fold.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_MIN = NotificationManager.IMPORTANCE_MIN;
-
-        /**
-         * Low notification importance: shows everywhere, but is not intrusive.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_LOW = NotificationManager.IMPORTANCE_LOW;
-
-        /**
-         * Default notification importance: shows everywhere, allowed to makes noise,
-         * but does not visually intrude.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_DEFAULT = NotificationManager.IMPORTANCE_DEFAULT;
-
-        /**
-         * Higher notification importance: shows everywhere, allowed to makes noise and peek.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_HIGH = NotificationManager.IMPORTANCE_HIGH;
-
-        /**
-         * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
-         * use full screen intents.
-         *
-         * @hide
-         */
-        public static final int IMPORTANCE_MAX = NotificationManager.IMPORTANCE_MAX;
-
         private String mKey;
         private int mRank = -1;
         private boolean mIsAmbient;
@@ -1192,7 +1138,7 @@
                 CharSequence explanation, String overrideGroupKey) {
             mKey = key;
             mRank = rank;
-            mIsAmbient = importance < IMPORTANCE_LOW;
+            mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
             mMatchesInterruptionFilter = matchesInterruptionFilter;
             mVisibilityOverride = visibilityOverride;
             mSuppressedVisualEffects = suppressedVisualEffects;
@@ -1206,20 +1152,19 @@
          */
         public static String importanceToString(int importance) {
             switch (importance) {
-                case IMPORTANCE_UNSPECIFIED:
+                case NotificationManager.IMPORTANCE_UNSPECIFIED:
                     return "UNSPECIFIED";
-                case IMPORTANCE_NONE:
+                case NotificationManager.IMPORTANCE_NONE:
                     return "NONE";
-                case IMPORTANCE_MIN:
+                case NotificationManager.IMPORTANCE_MIN:
                     return "MIN";
-                case IMPORTANCE_LOW:
+                case NotificationManager.IMPORTANCE_LOW:
                     return "LOW";
-                case IMPORTANCE_DEFAULT:
+                case NotificationManager.IMPORTANCE_DEFAULT:
                     return "DEFAULT";
-                case IMPORTANCE_HIGH:
+                case NotificationManager.IMPORTANCE_HIGH:
+                case NotificationManager.IMPORTANCE_MAX:
                     return "HIGH";
-                case IMPORTANCE_MAX:
-                    return "MAX";
                 default:
                     return "UNKNOWN(" + String.valueOf(importance) + ")";
             }
@@ -1326,7 +1271,7 @@
             }
             Integer importance = mImportance.get(key);
             if (importance == null) {
-                return Ranking.IMPORTANCE_DEFAULT;
+                return NotificationManager.IMPORTANCE_DEFAULT;
             }
             return importance.intValue();
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20876a9..ba26926 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7194,7 +7194,6 @@
 
     /**
      * Gets the unique identifier of this view on the screen for accessibility purposes.
-     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
      *
      * @return The view accessibility id.
      *
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 87b330d..5a6cf7d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -19,7 +19,6 @@
 import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
 import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
@@ -3542,20 +3541,7 @@
                     mWinFrame.bottom = t + h;
 
                     mPendingBackDropFrame.set(mWinFrame);
-
-                    // Suppress layouts during resizing - a correct layout will happen when resizing
-                    // is done, and this just increases system load.
-                    boolean isDockedDivider = mWindowAttributes.type == TYPE_DOCK_DIVIDER;
-                    boolean suppress = (mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER)
-                            || isDockedDivider;
-                    if (!suppress) {
-                        if (mView != null) {
-                            forceLayout(mView);
-                        }
-                        requestLayout();
-                    } else {
-                        maybeHandleWindowMove(mWinFrame);
-                    }
+                    maybeHandleWindowMove(mWinFrame);
                 }
                 break;
             case MSG_WINDOW_FOCUS_CHANGED: {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 567e920..0678dfd 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2635,4 +2635,11 @@
 
     <!-- An array of packages for which notifications cannot be blocked. -->
     <string-array translatable="false" name="config_nonBlockableNotificationPackages" />
+
+    <!-- The default value for transition animation scale found in developer settings.
+         1.0 corresponds to 1x animator scale, 0 means that there will be no transition
+         animations. Note that this is only a default and will be overridden by a
+         user-set value if toggled by settings so the "Transition animation scale" setting
+         should also be hidden if intended to be permanent. -->
+    <item name="config_appTransitionAnimationDurationScaleDefault" format="float" type="dimen">1.0</item>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e946136..0073f53 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2731,4 +2731,6 @@
   <!-- Screen-size-dependent modes for picker dialogs. -->
   <java-symbol type="integer" name="time_picker_mode" />
   <java-symbol type="integer" name="date_picker_mode" />
+
+  <java-symbol type="dimen" name="config_appTransitionAnimationDurationScaleDefault" />
 </resources>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Ranker.java b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
index 63fc157..2feb51f 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Ranker.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
@@ -16,8 +16,6 @@
 
 package android.ext.services.notification;
 
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.service.notification.Adjustment;
@@ -36,6 +34,7 @@
 
 /**
  * Class that provides an updatable ranker module for the notification manager.
+ * TODO: delete
  */
 public final class Ranker extends NotificationRankerService {
     private static final String TAG = "RocketRanker";
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 7f0e27a..1ea592d 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -22,6 +22,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothHeadsetClient;
 import android.bluetooth.BluetoothMap;
+import android.bluetooth.BluetoothMapClient;
 import android.bluetooth.BluetoothInputDevice;
 import android.bluetooth.BluetoothPan;
 import android.bluetooth.BluetoothPbapClient;
@@ -81,12 +82,14 @@
     private HeadsetProfile mHeadsetProfile;
     private HfpClientProfile mHfpClientProfile;
     private MapProfile mMapProfile;
+    private MapClientProfile mMapClientProfile;
     private final HidProfile mHidProfile;
     private OppProfile mOppProfile;
     private final PanProfile mPanProfile;
     private PbapClientProfile mPbapClientProfile;
     private final PbapServerProfile mPbapProfile;
     private final boolean mUsePbapPce;
+    private final boolean mUseMapClient;
 
     /**
      * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -104,6 +107,8 @@
         mDeviceManager = deviceManager;
         mEventManager = eventManager;
         mUsePbapPce = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
+        // MAP Client is typically used in the same situations as PBAP Client
+        mUseMapClient = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
         // pass this reference to adapter and event manager (circular dependency)
         mLocalAdapter.setProfileManager(this);
         mEventManager.setProfileManager(this);
@@ -125,10 +130,15 @@
                 BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
 
         if(DEBUG) Log.d(TAG, "Adding local MAP profile");
-        mMapProfile = new MapProfile(mContext, mLocalAdapter,
-                mDeviceManager, this);
-        addProfile(mMapProfile, MapProfile.NAME,
-                BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
+        if (mUseMapClient) {
+            mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mMapClientProfile, MapClientProfile.NAME,
+                BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
+        } else {
+            mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
+            addProfile(mMapProfile, MapProfile.NAME,
+                    BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
+        }
 
        //Create PBAP server profile, but do not add it to list of profiles
        // as we do not need to monitor the profile as part of profile list
@@ -199,6 +209,22 @@
             Log.d(TAG, "Handsfree Uuid not found.");
         }
 
+        // Message Access Profile Client
+        if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
+            if (mMapClientProfile == null) {
+                if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
+                mMapClientProfile =
+                        new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+                addProfile(mMapClientProfile, MapClientProfile.NAME,
+                        BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
+            }
+        } else if (mMapClientProfile != null) {
+            Log.w(TAG,
+                    "Warning: MAP Client profile was previously added but the UUID is now missing.");
+        } else {
+            Log.d(TAG, "MAP Client Uuid not found.");
+        }
+
         // OPP
         if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
             if (mOppProfile == null) {
@@ -383,6 +409,10 @@
         return mMapProfile;
     }
 
+    public MapClientProfile getMapClientProfile() {
+        return mMapClientProfile;
+    }
+
     /**
      * Fill in a list of LocalBluetoothProfile objects that are supported by
      * the local device and the remote device.
@@ -465,6 +495,11 @@
             mMapProfile.setPreferred(device, true);
         }
 
+        if (mMapClientProfile != null) {
+            profiles.add(mMapClientProfile);
+            removedProfiles.remove(mMapClientProfile);
+        }
+
         if (mUsePbapPce) {
             profiles.add(mPbapClientProfile);
             removedProfiles.remove(mPbapClientProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
new file mode 100644
index 0000000..a7621fc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothMapClient;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MapClientProfile handles Bluetooth MAP profile.
+ */
+public final class MapClientProfile implements LocalBluetoothProfile {
+    private static final String TAG = "MapClientProfile";
+    private static boolean V = false;
+
+    private BluetoothMapClient mService;
+    private boolean mIsProfileReady;
+
+    private final LocalBluetoothAdapter mLocalAdapter;
+    private final CachedBluetoothDeviceManager mDeviceManager;
+    private final LocalBluetoothProfileManager mProfileManager;
+
+    static final ParcelUuid[] UUIDS = {
+        BluetoothUuid.MAP,
+        BluetoothUuid.MNS,
+        BluetoothUuid.MAS,
+    };
+
+    static final String NAME = "MAP Client";
+
+    // Order of this profile in device profiles list
+    private static final int ORDINAL = 0;
+
+    // These callbacks run on the main thread.
+    private final class MapClientServiceListener
+            implements BluetoothProfile.ServiceListener {
+
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            if (V) Log.d(TAG,"Bluetooth service connected");
+            mService = (BluetoothMapClient) proxy;
+            // We just bound to the service, so refresh the UI for any connected MAP devices.
+            List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+            while (!deviceList.isEmpty()) {
+                BluetoothDevice nextDevice = deviceList.remove(0);
+                CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+                // we may add a new device here, but generally this should not happen
+                if (device == null) {
+                    Log.w(TAG, "MapProfile found new device: " + nextDevice);
+                    device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+                }
+                device.onProfileStateChanged(MapClientProfile.this,
+                        BluetoothProfile.STATE_CONNECTED);
+                device.refresh();
+            }
+
+            mProfileManager.callServiceConnectedListeners();
+            mIsProfileReady=true;
+        }
+
+        public void onServiceDisconnected(int profile) {
+            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            mProfileManager.callServiceDisconnectedListeners();
+            mIsProfileReady=false;
+        }
+    }
+
+    public boolean isProfileReady() {
+        if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
+        return mIsProfileReady;
+    }
+
+    MapClientProfile(Context context, LocalBluetoothAdapter adapter,
+            CachedBluetoothDeviceManager deviceManager,
+            LocalBluetoothProfileManager profileManager) {
+        mLocalAdapter = adapter;
+        mDeviceManager = deviceManager;
+        mProfileManager = profileManager;
+        mLocalAdapter.getProfileProxy(context, new MapClientServiceListener(),
+                BluetoothProfile.MAP_CLIENT);
+    }
+
+    public boolean isConnectable() {
+        return true;
+    }
+
+    public boolean isAutoConnectable() {
+        return true;
+    }
+
+    public boolean connect(BluetoothDevice device) {
+        if (mService == null) return false;
+        List<BluetoothDevice> connectedDevices = getConnectedDevices();
+        if (connectedDevices != null) {
+            for (BluetoothDevice connectedDevice : connectedDevices) {
+                mService.disconnect(connectedDevice);
+            }
+        }
+        return mService.connect(device);
+    }
+
+    public boolean disconnect(BluetoothDevice device) {
+        if (mService == null) return false;
+        // Downgrade priority as user is disconnecting.
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+            mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+        }
+        return mService.disconnect(device);
+    }
+
+    public int getConnectionStatus(BluetoothDevice device) {
+        if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
+
+        return mService.getConnectionState(device);
+    }
+
+    public boolean isPreferred(BluetoothDevice device) {
+        if (mService == null) return false;
+        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+    }
+
+    public int getPreferred(BluetoothDevice device) {
+        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        return mService.getPriority(device);
+    }
+
+    public void setPreferred(BluetoothDevice device, boolean preferred) {
+        if (mService == null) return;
+        if (preferred) {
+            if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+                mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+            }
+        } else {
+            mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+        }
+    }
+
+    public List<BluetoothDevice> getConnectedDevices() {
+        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        return mService.getDevicesMatchingConnectionStates(
+              new int[] {BluetoothProfile.STATE_CONNECTED,
+                         BluetoothProfile.STATE_CONNECTING,
+                         BluetoothProfile.STATE_DISCONNECTING});
+    }
+
+    public String toString() {
+        return NAME;
+    }
+
+    public int getOrdinal() {
+        return ORDINAL;
+    }
+
+    public int getNameResource(BluetoothDevice device) {
+        return R.string.bluetooth_profile_map;
+    }
+
+    public int getSummaryResourceForDevice(BluetoothDevice device) {
+        int state = getConnectionStatus(device);
+        switch (state) {
+            case BluetoothProfile.STATE_DISCONNECTED:
+                return R.string.bluetooth_map_profile_summary_use_for;
+
+            case BluetoothProfile.STATE_CONNECTED:
+                return R.string.bluetooth_map_profile_summary_connected;
+
+            default:
+                return Utils.getConnectionStateSummary(state);
+        }
+    }
+
+    public int getDrawableResource(BluetoothClass btClass) {
+        return R.drawable.ic_bt_cellphone;
+    }
+
+    protected void finalize() {
+        if (V) Log.d(TAG, "finalize()");
+        if (mService != null) {
+            try {
+                BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
+                                                                       mService);
+                mService = null;
+            }catch (Throwable t) {
+                Log.w(TAG, "Error cleaning up MAP Client proxy", t);
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index d7c9eab..72a3b3a 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -145,7 +145,7 @@
                 }
             }
             for (BluetoothDevice src : srcs) {
-                mService.disconnect(device);
+                mService.disconnect(src);
             }
         }
         Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index fd1ac8e..81dfafc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -30,13 +30,10 @@
 import android.hardware.SensorManager;
 import android.hardware.TriggerEvent;
 import android.hardware.TriggerEventListener;
-import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.PowerManager;
-import android.os.SystemClock;
 import android.os.UserHandle;
-import android.os.Vibrator;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
@@ -104,7 +101,7 @@
         return null;
     }
 
-    public void setListen(boolean listen) {
+    public void setListening(boolean listen) {
         for (TriggerSensor s : mSensors) {
             s.setListening(listen);
             if (listen) {
@@ -209,8 +206,7 @@
         @AnyThread
         public void onTrigger(TriggerEvent event) {
             mHandler.post(mWakeLock.wrap(() -> {
-                if (DEBUG)
-                    Log.d(TAG, "onTrigger: " + triggerEventToString(event));
+                if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
                 boolean sensorPerformsProxCheck = false;
                 if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
                     int subType = (int) event.values[0];
@@ -250,6 +246,12 @@
     }
 
     public interface Callback {
+
+        /**
+         * Called when a sensor requests a pulse
+         * @param pulseReason Requesting sensor, e.g. {@link DozeLog#PULSE_REASON_SENSOR_PICKUP}
+         * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
+         */
         void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index cbaf232..2bb1d6a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -36,8 +36,6 @@
 import android.view.Display;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.internal.util.Preconditions;
-import com.android.systemui.DejankUtils;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.Assert;
@@ -298,7 +296,7 @@
 
     private void listenForPulseSignals(boolean listen) {
         if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
-        mDozeSensors.setListen(listen);
+        mDozeSensors.setListening(listen);
         listenForBroadcasts(listen);
         listenForNotifications(listen);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f2f7993..70e21d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -119,8 +119,6 @@
 import java.util.Locale;
 import java.util.Set;
 
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-
 public abstract class BaseStatusBar extends SystemUI implements
         CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
         ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
@@ -2540,7 +2538,7 @@
             return false;
         }
 
-        if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_HIGH) {
+        if (mNotificationData.getImportance(sbn.getKey()) < NotificationManager.IMPORTANCE_HIGH) {
             if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
             return false;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index bae16f3..7019880 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
@@ -186,8 +187,8 @@
         public int compare(Entry a, Entry b) {
             final StatusBarNotification na = a.notification;
             final StatusBarNotification nb = b.notification;
-            int aImportance = Ranking.IMPORTANCE_DEFAULT;
-            int bImportance = Ranking.IMPORTANCE_DEFAULT;
+            int aImportance = NotificationManager.IMPORTANCE_DEFAULT;
+            int bImportance = NotificationManager.IMPORTANCE_DEFAULT;
             int aRank = 0;
             int bRank = 0;
 
@@ -205,13 +206,13 @@
 
             // IMPORTANCE_MIN media streams are allowed to drift to the bottom
             final boolean aMedia = a.key.equals(mediaNotification)
-                    && aImportance > Ranking.IMPORTANCE_MIN;
+                    && aImportance > NotificationManager.IMPORTANCE_MIN;
             final boolean bMedia = b.key.equals(mediaNotification)
-                    && bImportance > Ranking.IMPORTANCE_MIN;
+                    && bImportance > NotificationManager.IMPORTANCE_MIN;
 
-            boolean aSystemMax = aImportance >= Ranking.IMPORTANCE_MAX &&
+            boolean aSystemMax = aImportance >= NotificationManager.IMPORTANCE_HIGH &&
                     isSystemNotification(na);
-            boolean bSystemMax = bImportance >= Ranking.IMPORTANCE_MAX &&
+            boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH &&
                     isSystemNotification(nb);
 
             boolean isHeadsUp = a.row.isHeadsUp();
@@ -318,7 +319,7 @@
             mRankingMap.getRanking(key, mTmpRanking);
             return mTmpRanking.getImportance();
         }
-        return Ranking.IMPORTANCE_UNSPECIFIED;
+        return NotificationManager.IMPORTANCE_UNSPECIFIED;
     }
 
     public String getOverrideGroupKey(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 62d730a..b10fb31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.INotificationManager;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -30,7 +31,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.view.View;
@@ -178,7 +178,7 @@
             final Set<String> nonBlockablePkgs, final int importance) {
         mINotificationManager = INotificationManager.Stub.asInterface(
                 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-        mStartingUserImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+        mStartingUserImportance = NotificationManager.IMPORTANCE_UNSPECIFIED;
         try {
             mStartingUserImportance =
                     mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
@@ -229,15 +229,15 @@
             if (mSeekBar.isEnabled()) {
                 return mSeekBar.getProgress();
             } else {
-                return Ranking.IMPORTANCE_UNSPECIFIED;
+                return NotificationManager.IMPORTANCE_UNSPECIFIED;
             }
         } else {
             if (mBlock.isChecked()) {
-                return Ranking.IMPORTANCE_NONE;
+                return NotificationManager.IMPORTANCE_NONE;
             } else if (mSilent.isChecked()) {
-                return Ranking.IMPORTANCE_LOW;
+                return NotificationManager.IMPORTANCE_LOW;
             } else {
-                return Ranking.IMPORTANCE_UNSPECIFIED;
+                return NotificationManager.IMPORTANCE_UNSPECIFIED;
             }
         }
     }
@@ -262,7 +262,7 @@
         }
         mBlock.setText(mContext.getString(R.string.block));
         mSilent.setText(mContext.getString(R.string.show_silently));
-        if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
+        if (importance == NotificationManager.IMPORTANCE_LOW) {
             mSilent.setChecked(true);
         } else {
             mReset.setChecked(true);
@@ -278,9 +278,9 @@
         mSeekBar = (SeekBar) importanceSlider.findViewById(R.id.seekbar);
 
         final int minProgress = nonBlockable ?
-                NotificationListenerService.Ranking.IMPORTANCE_MIN
-                : NotificationListenerService.Ranking.IMPORTANCE_NONE;
-        mSeekBar.setMax(NotificationListenerService.Ranking.IMPORTANCE_MAX);
+                NotificationManager.IMPORTANCE_MIN
+                : NotificationManager.IMPORTANCE_NONE;
+        mSeekBar.setMax(NotificationManager.IMPORTANCE_HIGH);
         mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
             @Override
             public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
@@ -317,7 +317,7 @@
                 applyAuto();
             }
         });
-        mAuto = mStartingUserImportance == Ranking.IMPORTANCE_UNSPECIFIED;
+        mAuto = mStartingUserImportance == NotificationManager.IMPORTANCE_UNSPECIFIED;
         applyAuto();
     }
 
@@ -344,36 +344,32 @@
 
     private void updateTitleAndSummary(int progress) {
         switch (progress) {
-            case Ranking.IMPORTANCE_NONE:
+            case NotificationManager.IMPORTANCE_NONE:
                 mImportanceSummary.setText(mContext.getString(
                         R.string.notification_importance_blocked));
                 mImportanceTitle.setText(mContext.getString(R.string.blocked_importance));
                 break;
-            case Ranking.IMPORTANCE_MIN:
+            case NotificationManager.IMPORTANCE_MIN:
                 mImportanceSummary.setText(mContext.getString(
                         R.string.notification_importance_min));
                 mImportanceTitle.setText(mContext.getString(R.string.min_importance));
                 break;
-            case Ranking.IMPORTANCE_LOW:
+            case NotificationManager.IMPORTANCE_LOW:
                 mImportanceSummary.setText(mContext.getString(
                         R.string.notification_importance_low));
                 mImportanceTitle.setText(mContext.getString(R.string.low_importance));
                 break;
-            case Ranking.IMPORTANCE_DEFAULT:
+            case NotificationManager.IMPORTANCE_DEFAULT:
                 mImportanceSummary.setText(mContext.getString(
                         R.string.notification_importance_default));
                 mImportanceTitle.setText(mContext.getString(R.string.default_importance));
                 break;
-            case Ranking.IMPORTANCE_HIGH:
+            case NotificationManager.IMPORTANCE_HIGH:
+            case NotificationManager.IMPORTANCE_MAX:
                 mImportanceSummary.setText(mContext.getString(
                         R.string.notification_importance_high));
                 mImportanceTitle.setText(mContext.getString(R.string.high_importance));
                 break;
-            case Ranking.IMPORTANCE_MAX:
-                mImportanceSummary.setText(mContext.getString(
-                        R.string.notification_importance_max));
-                mImportanceTitle.setText(mContext.getString(R.string.max_importance));
-                break;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 213fba7..669a512 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -38,6 +38,7 @@
 import android.app.ActivityOptions;
 import android.app.IActivityManager;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
@@ -1560,7 +1561,7 @@
                     Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
                 }
             } else if (mNotificationData.getImportance(notification.getKey())
-                    < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
+                    < NotificationManager.IMPORTANCE_HIGH) {
                 if (DEBUG) {
                     Log.d(TAG, "No Fullscreen intent: not important enough: "
                             + notification.getKey());
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 1484420..8234f35 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -141,7 +141,8 @@
                 case "broadcast":
                     return runSendBroadcast(pw);
                 case "instrument":
-                    return runInstrument(pw);
+                    getOutPrintWriter().println("Error: must be invoked through 'am instrument'.");
+                    return -1;
                 case "trace-ipc":
                     return runTraceIpc(pw);
                 case "profile":
@@ -561,224 +562,6 @@
         return 0;
     }
 
-    final static class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
-        private final IActivityManager mInterface;
-        private final PrintWriter mPw;
-        private boolean mFinished = false;
-        private boolean mRawMode = false;
-
-        InstrumentationWatcher(IActivityManager iam, PrintWriter pw) {
-            mInterface = iam;
-            mPw = pw;
-        }
-
-        /**
-         * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode",
-         * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
-         * @param rawMode true for raw mode, false for pretty mode.
-         */
-        public void setRawOutput(boolean rawMode) {
-            mRawMode = rawMode;
-        }
-
-        @Override
-        public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
-            synchronized (this) {
-                // pretty printer mode?
-                String pretty = null;
-                if (!mRawMode && results != null) {
-                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
-                }
-                if (pretty != null) {
-                    mPw.print(pretty);
-                } else {
-                    if (results != null) {
-                        for (String key : results.keySet()) {
-                            mPw.println(
-                                    "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
-                        }
-                    }
-                    mPw.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
-                }
-                mPw.flush();
-                notifyAll();
-            }
-        }
-
-        @Override
-        public void instrumentationFinished(ComponentName name, int resultCode,
-                Bundle results) {
-            synchronized (this) {
-                // pretty printer mode?
-                String pretty = null;
-                if (!mRawMode && results != null) {
-                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
-                }
-                if (pretty != null) {
-                    mPw.println(pretty);
-                } else {
-                    if (results != null) {
-                        for (String key : results.keySet()) {
-                            mPw.println(
-                                    "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
-                        }
-                    }
-                    mPw.println("INSTRUMENTATION_CODE: " + resultCode);
-                }
-                mPw.flush();
-                mFinished = true;
-                notifyAll();
-            }
-        }
-
-        public boolean waitForFinish() {
-            synchronized (this) {
-                while (!mFinished) {
-                    try {
-                        if (!mInterface.asBinder().pingBinder()) {
-                            return false;
-                        }
-                        wait(1000);
-                    } catch (InterruptedException e) {
-                        throw new IllegalStateException(e);
-                    }
-                }
-            }
-            return true;
-        }
-    }
-
-    int runInstrument(PrintWriter pw) throws RemoteException {
-        final PrintWriter err = getErrPrintWriter();
-        String profileFile = null;
-        boolean wait = false;
-        boolean rawMode = false;
-        boolean no_window_animation = false;
-        int userId = UserHandle.USER_CURRENT;
-        Bundle args = new Bundle();
-        String argKey = null, argValue = null;
-        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
-        String abi = null;
-
-        String opt;
-        while ((opt=getNextOption()) != null) {
-            if (opt.equals("-p")) {
-                profileFile = getNextArgRequired();
-            } else if (opt.equals("-w")) {
-                wait = true;
-            } else if (opt.equals("-r")) {
-                rawMode = true;
-            } else if (opt.equals("-e")) {
-                argKey = getNextArgRequired();
-                argValue = getNextArgRequired();
-                args.putString(argKey, argValue);
-            } else if (opt.equals("--no_window_animation")
-                    || opt.equals("--no-window-animation")) {
-                no_window_animation = true;
-            } else if (opt.equals("--user")) {
-                userId = UserHandle.parseUserArg(getNextArgRequired());
-            } else if (opt.equals("--abi")) {
-                abi = getNextArgRequired();
-            } else {
-                err.println("Error: Unknown option: " + opt);
-                return -1;
-            }
-        }
-
-        if (userId == UserHandle.USER_ALL) {
-            err.println("Error: Can't start instrumentation with user 'all'");
-            return -1;
-        }
-
-        String cnArg = getNextArgRequired();
-
-        ComponentName cn;
-        if (cnArg.contains("/")) {
-            cn = ComponentName.unflattenFromString(cnArg);
-            if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
-        } else {
-            List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
-
-            final int numInfos = infos == null ? 0: infos.size();
-            List<ComponentName> cns = new ArrayList<>();
-            for (int i = 0; i < numInfos; i++) {
-                InstrumentationInfo info = infos.get(i);
-
-                ComponentName c = new ComponentName(info.packageName, info.name);
-                if (cnArg.equals(info.packageName)) {
-                    cns.add(c);
-                }
-            }
-
-            if (cns.size() == 0) {
-                throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
-            } else if (cns.size() == 1) {
-                cn = cns.get(0);
-            } else {
-                StringBuilder cnsStr = new StringBuilder();
-                final int numCns = cns.size();
-                for (int i = 0; i < numCns; i++) {
-                    cnsStr.append(cns.get(i).flattenToString());
-                    cnsStr.append(", ");
-                }
-
-                // Remove last ", "
-                cnsStr.setLength(cnsStr.length() - 2);
-
-                throw new IllegalArgumentException("Found multiple instrumentations: "
-                        + cnsStr.toString());
-            }
-        }
-
-        InstrumentationWatcher watcher = null;
-        UiAutomationConnection connection = null;
-        if (wait) {
-            watcher = new InstrumentationWatcher(mInterface, pw);
-            watcher.setRawOutput(rawMode);
-            // Don't yet know how to support this.
-            connection = null; //new UiAutomationConnection();
-        }
-
-        float[] oldAnims = null;
-        if (no_window_animation) {
-            oldAnims = wm.getAnimationScales();
-            wm.setAnimationScale(0, 0.0f);
-            wm.setAnimationScale(1, 0.0f);
-        }
-
-        if (abi != null) {
-            final String[] supportedAbis = Build.SUPPORTED_ABIS;
-            boolean matched = false;
-            for (String supportedAbi : supportedAbis) {
-                if (supportedAbi.equals(abi)) {
-                    matched = true;
-                    break;
-                }
-            }
-
-            if (!matched) {
-                throw new RuntimeException(
-                        "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi);
-            }
-        }
-
-        if (!mInterface.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId,
-                abi)) {
-            throw new RuntimeException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
-        }
-
-        if (watcher != null) {
-            if (!watcher.waitForFinish()) {
-                pw.println("INSTRUMENTATION_ABORTED: System has crashed.");
-            }
-        }
-
-        if (oldAnims != null) {
-            wm.setAnimationScales(oldAnims);
-        }
-        return 0;
-    }
-
     int runTraceIpc(PrintWriter pw) throws RemoteException {
         String op = getNextArgRequired();
         if (op.equals("start")) {
@@ -2550,6 +2333,25 @@
             pw.println("      --user <USER_ID> | all | current: Specify which user to send to; if not");
             pw.println("          specified then send to all users.");
             pw.println("      --receiver-permission <PERMISSION>: Require receiver to hold permission.");
+            pw.println("  instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
+            pw.println("          [--user <USER_ID> | current]");
+            pw.println("          [--no-window-animation] [--abi <ABI>] <COMPONENT>");
+            pw.println("      Start an Instrumentation.  Typically this target <COMPONENT> is in the");
+            pw.println("      form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there");
+            pw.println("      is only one instrumentation.  Options are:");
+            pw.println("      -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with");
+            pw.println("          [-e perf true] to generate raw output for performance measurements.");
+            pw.println("      -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a");
+            pw.println("          common form is [-e <testrunner_flag> <value>[,<value>...]].");
+            pw.println("      -p <FILE>: write profiling data to <FILE>");
+            pw.println("      -m: Write output as protobuf (machine readable)");
+            pw.println("      -w: wait for instrumentation to finish before returning.  Required for");
+            pw.println("          test runners.");
+            pw.println("      --user <USER_ID> | current: Specify user instrumentation runs in;");
+            pw.println("          current user if not specified.");
+            pw.println("      --no-window-animation: turn off window animations while running.");
+            pw.println("      --abi <ABI>: Launch the instrumented process with the selected ABI.");
+            pw.println("          This assumes that the process supports the selected ABI.");
             pw.println("  trace-ipc [start|stop] [--dump-file <FILE>]");
             pw.println("      Trace IPC transactions.");
             pw.println("      start: start tracing IPC transactions.");
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index cda063d..49c4140 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -46,7 +46,9 @@
 import android.os.UserManager;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
+import com.android.server.FgThread;
 import com.android.server.SystemService;
 
 import org.json.JSONArray;
@@ -111,6 +113,7 @@
     private Context mContext;
     private long mHalDeviceId;
     private int mFailedAttempts;
+    @GuardedBy("this")
     private IFingerprintDaemon mDaemon;
     private final PowerManager mPowerManager;
     private final AlarmManager mAlarmManager;
@@ -195,35 +198,41 @@
     public void binderDied() {
         Slog.v(TAG, "fingerprintd died");
         MetricsLogger.count(mContext, "fingerprintd_died", 1);
-        mDaemon = null;
+        synchronized (this) {
+            mDaemon = null;
+        }
         mCurrentUserId = UserHandle.USER_CURRENT;
         handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
     }
 
     public IFingerprintDaemon getFingerprintDaemon() {
-        if (mDaemon == null) {
-            mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));
-            if (mDaemon != null) {
-                try {
-                    mDaemon.asBinder().linkToDeath(this, 0);
-                    mDaemon.init(mDaemonCallback);
-                    mHalDeviceId = mDaemon.openHal();
-                    if (mHalDeviceId != 0) {
-                        updateActiveGroup(ActivityManager.getCurrentUser(), null);
-                    } else {
-                        Slog.w(TAG, "Failed to open Fingerprint HAL!");
-                        MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
-                        mDaemon = null;
+        synchronized (this) {
+            if (mDaemon == null) {
+                mDaemon = IFingerprintDaemon.Stub
+                        .asInterface(ServiceManager.getService(FINGERPRINTD));
+                if (mDaemon != null) {
+                    try {
+                        mDaemon.asBinder().linkToDeath(this, 0);
+                        mDaemon.init(mDaemonCallback);
+                        mHalDeviceId = mDaemon.openHal();
+                        if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
+                        if (mHalDeviceId != 0) {
+                            updateActiveGroup(ActivityManager.getCurrentUser(), null);
+                        } else {
+                            Slog.w(TAG, "Failed to open Fingerprint HAL!");
+                            MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
+                            mDaemon = null;
+                        }
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to open fingeprintd HAL", e);
+                        mDaemon = null; // try again later!
                     }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Failed to open fingeprintd HAL", e);
-                    mDaemon = null; // try again later!
+                } else {
+                    Slog.w(TAG, "fingerprint service not available");
                 }
-            } else {
-                Slog.w(TAG, "fingerprint service not available");
             }
+            return mDaemon;
         }
-        return mDaemon;
     }
 
     protected void handleEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {
@@ -1005,8 +1014,7 @@
     @Override
     public void onStart() {
         publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
-        IFingerprintDaemon daemon = getFingerprintDaemon();
-        if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
+        FgThread.getHandler().post(() -> getFingerprintDaemon());
         listenForUserSwitches();
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index bcdeb66..31ed350 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -17,6 +17,7 @@
 package com.android.server.notification;
 
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.service.notification.NotificationListenerService;
 import android.util.Log;
@@ -44,7 +45,7 @@
             return null;
         }
 
-        if (record.getImportance() >= NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
+        if (record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT) {
             final Notification notification = record.getNotification();
             if ((notification.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
                     notification.vibrate != null ||
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4e50567..d782211 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.notification;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL;
 import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL_ALL;
 import static android.service.notification.NotificationRankerService.REASON_CHANNEL_BANNED;
@@ -40,8 +42,6 @@
 import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
 import static android.service.notification.NotificationListenerService.TRIM_FULL;
 import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 
@@ -975,6 +975,7 @@
         mUsageStats = new NotificationUsageStats(getContext());
         mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
         mRankingHelper = new RankingHelper(getContext(),
+                getContext().getPackageManager(),
                 mRankingHandler,
                 mUsageStats,
                 extractorNames);
@@ -1538,8 +1539,7 @@
         @Override
         public void setImportance(String pkg, int uid, int importance) {
             enforceSystemOrSystemUI("Caller not system or systemui");
-            setNotificationsEnabledForPackageImpl(pkg, uid,
-                    importance != NotificationListenerService.Ranking.IMPORTANCE_NONE);
+            setNotificationsEnabledForPackageImpl(pkg, uid, importance != IMPORTANCE_NONE);
             mRankingHelper.setImportance(pkg, uid, importance);
             savePolicyFile();
         }
@@ -1567,21 +1567,6 @@
         }
 
         @Override
-        public void updateNotificationChannel(String pkg, NotificationChannel channel) {
-            Preconditions.checkNotNull(channel);
-            Preconditions.checkNotNull(channel.getId());
-            checkCallerIsSystemOrSameApp(pkg);
-            if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
-                // cancel
-                cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
-                        UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
-            }
-            mRankingHelper.updateNotificationChannel(Binder.getCallingUid(), pkg,
-                    Binder.getCallingUid(), channel);
-            savePolicyFile();
-        }
-
-        @Override
         public NotificationChannel getNotificationChannel(String pkg, String channelId) {
             Preconditions.checkNotNull(channelId);
             checkCallerIsSystemOrSameApp(pkg);
@@ -1620,7 +1605,7 @@
                 cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
                         UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
             }
-            mRankingHelper.updateNotificationChannel(Binder.getCallingUid(), pkg, uid, channel);
+            mRankingHelper.updateNotificationChannel(pkg, uid, channel);
             savePolicyFile();
         }
 
@@ -2814,7 +2799,7 @@
 
         // setup local book-keeping
         final NotificationRecord r = new NotificationRecord(getContext(), n,
-                mRankingHelper.getNotificationChannel(pkg, callingUid,
+                mRankingHelper.getNotificationChannelWithFallback(pkg, callingUid,
                         n.getNotification().getNotificationChannel()));
         mHandler.post(new EnqueueNotificationRunnable(userId, r));
 
@@ -3022,7 +3007,8 @@
         final String key = record.getKey();
 
         // Should this notification make noise, vibe, or use the LED?
-        final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_DEFAULT;
+        final boolean aboveThreshold =
+                record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT;
         final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
         if (DBG || record.isIntercepted())
             Slog.v(TAG,
@@ -3076,8 +3062,8 @@
             } else if (notification.sound != null) {
                 soundUri = notification.sound;
                 hasValidSound = (soundUri != null);
-            } else if (record.getChannel().getDefaultRingtone() != null) {
-                soundUri = record.getChannel().getDefaultRingtone();
+            } else if (record.getChannel().getRingtone() != null) {
+                soundUri = record.getChannel().getRingtone();
                 hasValidSound = (soundUri != null);
             }
 
@@ -3094,9 +3080,7 @@
             // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
             final boolean useDefaultVibrate =
                     (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
-
             final boolean hasChannelVibration = record.getChannel().shouldVibrate();
-
             hasValidVibrate = useDefaultVibrate || convertSoundToVibration ||
                     hasCustomVibrate || hasChannelVibration;
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index c5de93e..a1256db 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,12 +15,11 @@
  */
 package com.android.server.notification;
 
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -30,7 +29,6 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
-import android.net.Uri;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
@@ -140,10 +138,8 @@
                 importance = IMPORTANCE_DEFAULT;
                 break;
             case Notification.PRIORITY_HIGH:
-                importance = IMPORTANCE_HIGH;
-                break;
             case Notification.PRIORITY_MAX:
-                importance = IMPORTANCE_MAX;
+                importance = IMPORTANCE_HIGH;
                 break;
         }
         stats.requestedImportance = importance;
@@ -153,7 +149,7 @@
                 || n.sound != null
                 || n.vibrate != null
                 || mNotificationChannel.shouldVibrate()
-                || mNotificationChannel.getDefaultRingtone() != null;
+                || mNotificationChannel.getRingtone() != null;
         stats.isNoisy = isNoisy;
 
         if (!isNoisy && importance > IMPORTANCE_LOW) {
@@ -167,7 +163,7 @@
         }
 
         if (n.fullScreenIntent != null) {
-            importance = IMPORTANCE_MAX;
+            importance = IMPORTANCE_HIGH;
         }
 
         stats.naturalImportance = importance;
@@ -319,10 +315,11 @@
     @Override
     public final String toString() {
         return String.format(
-                "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s: %s)",
+                "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s" +
+                        " channel=%s: %s)",
                 System.identityHashCode(this),
                 this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
-                this.sbn.getTag(), this.mImportance, this.sbn.getKey(),
+                this.sbn.getTag(), this.mImportance, this.sbn.getKey(), this.getChannel().getId(),
                 this.sbn.getNotification());
     }
 
@@ -384,7 +381,7 @@
     }
 
     private void applyUserImportance() {
-        if (mUserImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+        if (mUserImportance != IMPORTANCE_UNSPECIFIED) {
             mImportance = mUserImportance;
             mImportanceExplanation = getUserExplanation();
         }
@@ -395,7 +392,7 @@
     }
 
     public void setImportance(int importance, CharSequence explanation) {
-        if (importance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+        if (importance != IMPORTANCE_UNSPECIFIED) {
             mImportance = importance;
             mImportanceExplanation = explanation;
         }
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 34c5283..e8cf6a1 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -16,7 +16,7 @@
 
 package com.android.server.notification;
 
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
 
 import android.app.Notification;
 import android.content.ContentValues;
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 2df4043..cb5fb0d 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -33,8 +33,10 @@
     int getImportance(String packageName, int uid);
 
     void createNotificationChannel(String pkg, int uid, NotificationChannel channel);
-    void updateNotificationChannel(int callingUid, String pkg, int uid, NotificationChannel channel);
+    void updateNotificationChannel(String pkg, int uid, NotificationChannel channel);
+    void updateNotificationChannelFromRanker(String pkg, int uid, NotificationChannel channel);
     NotificationChannel getNotificationChannel(String pkg, int uid, String channelId);
+    NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId);
     void deleteNotificationChannel(String pkg, int uid, String channelId);
     ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid);
 }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index d59115e..d11d4de 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,12 +15,17 @@
  */
 package com.android.server.notification;
 
+import com.android.internal.R;
+
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
+import android.os.Build;
 import android.os.Process;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService.Ranking;
@@ -28,8 +33,6 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
-import com.android.internal.R;
-
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -63,8 +66,8 @@
     private static final String ATT_IMPORTANCE = "importance";
 
     private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
-    private static final int DEFAULT_VISIBILITY = Ranking.VISIBILITY_NO_OVERRIDE;
-    private static final int DEFAULT_IMPORTANCE = Ranking.IMPORTANCE_UNSPECIFIED;
+    private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
+    private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
 
     private final NotificationSignalExtractor[] mSignalExtractors;
     private final NotificationComparator mPreliminaryComparator = new NotificationComparator();
@@ -76,11 +79,13 @@
 
     private final Context mContext;
     private final RankingHandler mRankingHandler;
+    private final PackageManager mPm;
 
-    public RankingHelper(Context context, RankingHandler rankingHandler,
+    public RankingHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             NotificationUsageStats usageStats, String[] extractorNames) {
         mContext = context;
         mRankingHandler = rankingHandler;
+        mPm = pm;
 
         final int N = extractorNames.length;
         mSignalExtractors = new NotificationSignalExtractor[N];
@@ -131,7 +136,6 @@
 
     public void readXml(XmlPullParser parser, boolean forRestore)
             throws XmlPullParserException, IOException {
-        final PackageManager pm = mContext.getPackageManager();
         int type = parser.getEventType();
         if (type != XmlPullParser.START_TAG) return;
         String tag = parser.getName();
@@ -147,31 +151,24 @@
                 if (TAG_PACKAGE.equals(tag)) {
                     int uid = safeInt(parser, ATT_UID, Record.UNKNOWN_UID);
                     String name = parser.getAttributeValue(null, ATT_NAME);
+                    int importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
 
                     if (!TextUtils.isEmpty(name)) {
                         if (forRestore) {
                             try {
                                 //TODO: http://b/22388012
-                                uid = pm.getPackageUidAsUser(name, UserHandle.USER_SYSTEM);
+                                uid = mPm.getPackageUidAsUser(name, UserHandle.USER_SYSTEM);
                             } catch (NameNotFoundException e) {
                                 // noop
                             }
                         }
-                        Record r = null;
-                        if (uid == Record.UNKNOWN_UID) {
-                            r = mRestoredWithoutUids.get(name);
-                            if (r == null) {
-                                r = new Record();
-                                r.pkg = name;
-                                mRestoredWithoutUids.put(name, r);
-                            }
-                        } else {
-                            r = getOrCreateRecord(name, uid);
-                        }
-                        r.importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
-                        r.priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY);
-                        r.visibility = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
 
+                        Record r = getOrCreateRecord(name, uid,
+                                safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE),
+                                safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY),
+                                safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
+
+                        // Channels
                         final int innerDepth = parser.getDepth();
                         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                                 && (type != XmlPullParser.END_TAG
@@ -184,15 +181,19 @@
                             if (TAG_CHANNEL.equals(tagName)) {
                                 String id = parser.getAttributeValue(null, ATT_ID);
                                 CharSequence channelName = parser.getAttributeValue(null, ATT_NAME);
+                                int channelImportance =
+                                        safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
 
                                 if (!TextUtils.isEmpty(id)) {
-                                    final NotificationChannel channel =
-                                            new NotificationChannel(id, channelName);
+                                    final NotificationChannel channel = new NotificationChannel(id,
+                                            channelName, channelImportance);
                                     channel.populateFromXml(parser);
                                     r.channels.put(id, channel);
                                 }
                             }
                         }
+
+                        clampDefaultChannel(r);
                     }
                 }
             }
@@ -204,23 +205,77 @@
         return pkg + "|" + uid;
     }
 
-    private Record getOrCreateRecord(String pkg, int uid) {
+    private Record getRecord(String pkg, int uid) {
         final String key = recordKey(pkg, uid);
-        Record r = mRecords.get(key);
+        return mRecords.get(key);
+    }
+
+    private Record getOrCreateRecord(String pkg, int uid) {
+        return getOrCreateRecord(pkg, uid,
+                DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY);
+    }
+
+    private Record getOrCreateRecord(String pkg, int uid, int importance, int priority,
+            int visibility) {
+        final String key = recordKey(pkg, uid);
+        Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(key);
         if (r == null) {
             r = new Record();
             r.pkg = pkg;
             r.uid = uid;
-            NotificationChannel defaultChannel = createDefaultChannel();
-            r.channels.put(defaultChannel.getId(), defaultChannel);
-            mRecords.put(key, r);
+            r.importance = importance;
+            r.priority = priority;
+            r.visibility = visibility;
+            createDefaultChannelIfMissing(r);
+            if (r.uid == Record.UNKNOWN_UID) {
+                mRestoredWithoutUids.put(pkg, r);
+            } else {
+                mRecords.put(key, r);
+            }
         }
+        clampDefaultChannel(r);
         return r;
     }
 
-    private NotificationChannel createDefaultChannel() {
-        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID,
-                mContext.getString(R.string.default_notification_channel_label));
+    // Clamp the importance level of the default channel for apps targeting the new SDK version,
+    // unless the user has already changed the importance.
+    private void clampDefaultChannel(Record r) {
+        try {
+            final ApplicationInfo applicationInfo = mPm.getApplicationInfo(r.pkg, 0);
+            if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+                final NotificationChannel defaultChannel =
+                        r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
+                if ((defaultChannel.getUserLockedFields()
+                        & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0) {
+                    defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+                    updateConfig();
+                }
+            }
+        } catch (NameNotFoundException e) {
+            // oh well.
+        }
+    }
+
+    private void createDefaultChannelIfMissing(Record r) {
+        if (!r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+            NotificationChannel channel;
+            channel = new NotificationChannel(
+                    NotificationChannel.DEFAULT_CHANNEL_ID,
+                    mContext.getString(R.string.default_notification_channel_label),
+                    r.importance);
+            channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
+            channel.setLockscreenVisibility(r.visibility);
+            if (r.importance != NotificationManager.IMPORTANCE_UNSPECIFIED) {
+                channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+            }
+            if (r.priority != DEFAULT_PRIORITY) {
+                channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
+            }
+            if (r.visibility != DEFAULT_VISIBILITY) {
+                channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
+            }
+            r.channels.put(channel.getId(), channel);
+        }
     }
 
     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
@@ -397,6 +452,10 @@
                 mContext.getString(R.string.default_notification_channel_label))) {
             throw new IllegalArgumentException("Channel already exists");
         }
+        if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
+                || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
+            throw new IllegalArgumentException("Invalid importance level");
+        }
         if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
             channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
         }
@@ -405,17 +464,12 @@
     }
 
     @Override
-    public void updateNotificationChannel(int callingUid, String pkg, int uid,
-            NotificationChannel updatedChannel) {
+    public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel) {
         Record r = getOrCreateRecord(pkg, uid);
         NotificationChannel channel = r.channels.get(updatedChannel.getId());
         if (channel == null) {
             throw new IllegalArgumentException("Channel does not exist");
         }
-        if (!isUidSystem(callingUid)) {
-            updatedChannel.setImportance(channel.getImportance());
-            updatedChannel.setName(channel.getName());
-        }
         if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
             updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
         }
@@ -424,6 +478,57 @@
     }
 
     @Override
+    public void updateNotificationChannelFromRanker(String pkg, int uid,
+            NotificationChannel updatedChannel) {
+        Record r = getOrCreateRecord(pkg, uid);
+        NotificationChannel channel = r.channels.get(updatedChannel.getId());
+        if (channel == null) {
+            throw new IllegalArgumentException("Channel does not exist");
+        }
+
+        if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0) {
+            channel.setImportance(updatedChannel.getImportance());
+        }
+        if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_LIGHTS) == 0) {
+            channel.setLights(updatedChannel.shouldShowLights());
+        }
+        if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_PRIORITY) == 0) {
+            channel.setBypassDnd(updatedChannel.canBypassDnd());
+        }
+        if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_RINGTONE) == 0) {
+            channel.setRingtone(updatedChannel.getRingtone());
+        }
+        if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_VIBRATION) == 0) {
+            channel.setVibration(updatedChannel.shouldVibrate());
+        }
+        if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_VISIBILITY) == 0) {
+            if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
+                channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
+            } else {
+                channel.setLockscreenVisibility(updatedChannel.getLockscreenVisibility());
+            }
+        }
+
+        r.channels.put(channel.getId(), channel);
+        updateConfig();
+    }
+
+    @Override
+    public NotificationChannel getNotificationChannelWithFallback(String pkg, int uid,
+            String channelId) {
+        Record r = getOrCreateRecord(pkg, uid);
+        if (channelId == null) {
+            channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
+        }
+        NotificationChannel channel = r.channels.get(channelId);
+        if (channel != null) {
+            return channel;
+        } else {
+            return r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
+        }
+    }
+
+    @Override
     public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId) {
         Record r = getOrCreateRecord(pkg, uid);
         if (channelId == null) {
@@ -434,8 +539,10 @@
 
     @Override
     public void deleteNotificationChannel(String pkg, int uid, String channelId) {
-        Record r = getOrCreateRecord(pkg, uid);
-        r.channels.remove(channelId);
+        Record r = getRecord(pkg, uid);
+        if (r != null) {
+            r.channels.remove(channelId);
+        }
     }
 
     @Override
@@ -446,7 +553,7 @@
         for (int i = 0; i < N; i++) {
             channels.add(r.channels.valueAt(i));
         }
-        return new ParceledListSlice<NotificationChannel>(channels);
+        return new ParceledListSlice<>(channels);
     }
 
     /**
@@ -459,11 +566,12 @@
     }
 
     public void setEnabled(String packageName, int uid, boolean enabled) {
-        boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE;
+        boolean wasEnabled = getImportance(packageName, uid) != NotificationManager.IMPORTANCE_NONE;
         if (wasEnabled == enabled) {
             return;
         }
-        setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE);
+        setImportance(packageName, uid,
+                enabled ? DEFAULT_IMPORTANCE : NotificationManager.IMPORTANCE_NONE);
     }
 
     public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
@@ -599,7 +707,7 @@
         ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
         for (int i = 0; i < N; i++) {
             final Record r = mRecords.valueAt(i);
-            if (r.importance == Ranking.IMPORTANCE_NONE) {
+            if (r.importance == NotificationManager.IMPORTANCE_NONE) {
                 packageBans.put(r.uid, r.pkg);
             }
         }
@@ -611,14 +719,13 @@
                 || mRestoredWithoutUids.isEmpty()) {
             return; // nothing to do
         }
-        final PackageManager pm = mContext.getPackageManager();
         boolean updated = false;
         for (String pkg : pkgList) {
             final Record r = mRestoredWithoutUids.get(pkg);
             if (r != null) {
                 try {
                     //TODO: http://b/22388012
-                    r.uid = pm.getPackageUidAsUser(r.pkg, UserHandle.USER_SYSTEM);
+                    r.uid = mPm.getPackageUidAsUser(r.pkg, UserHandle.USER_SYSTEM);
                     mRestoredWithoutUids.remove(pkg);
                     mRecords.put(recordKey(r.pkg, r.uid), r);
                     updated = true;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 06401e0..2fef928 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1035,7 +1035,10 @@
         mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
         mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
-                Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
+                Settings.Global.TRANSITION_ANIMATION_SCALE,
+                context.getResources().getFloat(
+                        R.dimen.config_appTransitionAnimationDurationScaleDefault));
+
         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
 
diff --git a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 5fe000a..4570a4b 100644
--- a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -229,7 +229,8 @@
         StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
                 mScore, n, mUser, System.currentTimeMillis());
         NotificationRecord r = new NotificationRecord(getContext(), sbn,
-                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "misc"));
+                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "misc",
+                        NotificationManager.IMPORTANCE_DEFAULT));
         mService.addNotification(r);
         return r;
     }
@@ -334,7 +335,7 @@
     @Test
     public void testBeepFromChannel() throws Exception {
         NotificationRecord r = getQuietNotification();
-        r.getChannel().setDefaultRingtone(Settings.System.DEFAULT_NOTIFICATION_URI);
+        r.getChannel().setRingtone(Settings.System.DEFAULT_NOTIFICATION_URI);
         r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
 
         mService.buzzBeepBlinkLocked(r);
@@ -388,7 +389,7 @@
     @Test
     public void testChannelNoOverwriteCustomBeep() throws Exception {
         NotificationRecord r = getCustomBeepyNotification();
-        r.getChannel().setDefaultRingtone(Settings.System.DEFAULT_RINGTONE_URI);
+        r.getChannel().setRingtone(Settings.System.DEFAULT_RINGTONE_URI);
 
         mService.buzzBeepBlinkLocked(r);
 
@@ -408,7 +409,7 @@
     @Test
     public void testNoInterruptionForMin() throws Exception {
         NotificationRecord r = getBeepyNotification();
-        r.setImportance(Ranking.IMPORTANCE_MIN, "foo");
+        r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
 
         mService.buzzBeepBlinkLocked(r);
 
diff --git a/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java
index 3cbde1d..305b5e0 100644
--- a/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -90,8 +90,8 @@
 
         when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
           NotificationManager.IMPORTANCE_MIN);
-        NotificationChannel channel = new NotificationChannel("a", "a");
-        channel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
+        NotificationChannel channel =
+                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
 
         NotificationRecord r = getNotificationRecord(channel);
 
@@ -107,8 +107,8 @@
 
         when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
           NotificationManager.IMPORTANCE_MIN);
-        NotificationChannel channel = new NotificationChannel("a", "a");
-        channel.setImportance(NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel =
+                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_HIGH);
 
         NotificationRecord r = getNotificationRecord(channel);
 
@@ -124,8 +124,8 @@
 
         when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
           NotificationManager.IMPORTANCE_HIGH);
-        NotificationChannel channel = new NotificationChannel("a", "a");
-        channel.setImportance(NotificationManager.IMPORTANCE_MIN);
+        NotificationChannel channel =
+                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_MIN);
 
         NotificationRecord r = getNotificationRecord(channel);
 
@@ -141,8 +141,8 @@
 
         when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
           NotificationManager.IMPORTANCE_UNSPECIFIED);
-        NotificationChannel channel = new NotificationChannel("a", "a");
-        channel.setImportance(NotificationManager.IMPORTANCE_MIN);
+        NotificationChannel channel =
+                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_MIN);
 
         NotificationRecord r = getNotificationRecord(channel);
 
@@ -158,8 +158,8 @@
 
         when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
           NotificationManager.IMPORTANCE_UNSPECIFIED);
-        NotificationChannel channel = new NotificationChannel("a", "a");
-        channel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
+        NotificationChannel channel =
+                new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
 
         NotificationRecord r = getNotificationRecord(channel);
 
diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
index ee33dcc..ad432d1 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -29,7 +29,10 @@
 import android.content.Context;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.net.Uri;
+import android.os.Build;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
@@ -44,14 +47,19 @@
 import java.util.ArrayList;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RankingHelperTest {
     @Mock NotificationUsageStats mUsageStats;
     @Mock RankingHandler handler;
+    @Mock PackageManager mPm;
 
     private Notification mNotiGroupGSortA;
     private Notification mNotiGroupGSortB;
@@ -64,6 +72,8 @@
     private NotificationRecord mRecordNoGroup2;
     private NotificationRecord mRecordNoGroupSortA;
     private RankingHelper mHelper;
+    private final String pkg = "com.android.server.notification";
+    private final int uid = 0;
 
     private Context getContext() {
         return InstrumentationRegistry.getTargetContext();
@@ -74,7 +84,7 @@
         MockitoAnnotations.initMocks(this);
         UserHandle user = UserHandle.ALL;
 
-        mHelper = new RankingHelper(getContext(), handler, mUsageStats,
+        mHelper = new RankingHelper(getContext(), mPm, handler, mUsageStats,
                 new String[] {ImportanceExtractor.class.getName()});
 
         mNotiGroupGSortA = new Notification.Builder(getContext())
@@ -121,11 +131,36 @@
         mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
                 "package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user), 
                 getDefaultChannel());
+
+        final ApplicationInfo legacy = new ApplicationInfo();
+        legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+        try {
+            when(mPm.getApplicationInfo(anyString(), anyInt())).thenReturn(legacy);
+        } catch (PackageManager.NameNotFoundException e) {}
     }
 
     private NotificationChannel getDefaultChannel() {
-        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name");
-    }    
+        return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+                NotificationManager.IMPORTANCE_LOW);
+    }
+
+    private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, String... channelIds)
+            throws Exception {
+        XmlSerializer serializer = new FastXmlSerializer();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        serializer.startTag(null, "ranking");
+        mHelper.writeXml(serializer, false);
+        serializer.endTag(null, "ranking");
+        serializer.endDocument();
+        serializer.flush();
+
+        for (String channelId : channelIds) {
+            mHelper.deleteNotificationChannel(pkg, uid, channelId);
+        }
+        return baos;
+    }
 
     @Test
     public void testFindAfterRankingWithASplitGroup() throws Exception {
@@ -179,12 +214,11 @@
 
     @Test
     public void testChannelXml() throws Exception {
-        String pkg = "com.android.server.notification";
-        int uid = 0;
-        NotificationChannel channel1 = new NotificationChannel("id1", "name1");
-        NotificationChannel channel2 = new NotificationChannel("id2", "name2");
-        channel2.setImportance(NotificationManager.IMPORTANCE_LOW);
-        channel2.setDefaultRingtone(new Uri.Builder().scheme("test").build());
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel2.setRingtone(new Uri.Builder().scheme("test").build());
         channel2.setLights(true);
         channel2.setBypassDnd(true);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -192,23 +226,16 @@
         mHelper.createNotificationChannel(pkg, uid, channel1);
         mHelper.createNotificationChannel(pkg, uid, channel2);
 
-        byte[] data;
-        XmlSerializer serializer = new FastXmlSerializer();
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
-        serializer.startDocument(null, true);
-        serializer.startTag(null, "ranking");
-        mHelper.writeXml(serializer, false);
-        serializer.endTag(null, "ranking");
-        serializer.endDocument();
-        serializer.flush();
+        ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(), channel2.getId(),
+                NotificationChannel.DEFAULT_CHANNEL_ID);
 
         mHelper.deleteNotificationChannel(pkg, uid, channel1.getId());
         mHelper.deleteNotificationChannel(pkg, uid, channel2.getId());
         mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
 
         XmlPullParser parser = Xml.newPullParser();
-        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), null);
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+                null);
         parser.nextTag();
         mHelper.readXml(parser, false);
 
@@ -217,4 +244,146 @@
         assertNotNull(
                 mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID));
     }
+
+    @Test
+    public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception {
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT);
+
+        mHelper.createNotificationChannel(pkg, uid, channel1);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
+                NotificationChannel.DEFAULT_CHANNEL_ID);
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+                null);
+        parser.nextTag();
+        mHelper.readXml(parser, false);
+
+        final NotificationChannel updated =
+                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
+        assertFalse(updated.canBypassDnd());
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,updated.getLockscreenVisibility());
+        assertEquals(0, updated.getUserLockedFields());
+    }
+
+    @Test
+    public void testChannelXml_defaultChannelUpdatedApp() throws Exception {
+        final ApplicationInfo updated = new ApplicationInfo();
+        updated.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        when(mPm.getApplicationInfo(anyString(), anyInt())).thenReturn(updated);
+
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
+
+        mHelper.createNotificationChannel(pkg, uid, channel1);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
+                NotificationChannel.DEFAULT_CHANNEL_ID);
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+                null);
+        parser.nextTag();
+        mHelper.readXml(parser, false);
+
+        assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
+                pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID).getImportance());
+    }
+
+    // TODO: test with hardcoded N xml.
+    @Test
+    public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
+        mHelper.setImportance(pkg, uid, NotificationManager.IMPORTANCE_HIGH);
+        mHelper.setPriority(pkg, uid, Notification.PRIORITY_MAX);
+        mHelper.setVisibilityOverride(pkg, uid, Notification.VISIBILITY_SECRET);
+        // pre-O xml won't have channels.
+        mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+
+        ByteArrayOutputStream baos =
+                writeXmlAndPurge(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+                null);
+        parser.nextTag();
+        mHelper.readXml(parser, false);
+
+        final NotificationChannel updated =
+                mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, updated.getImportance());
+        assertTrue(updated.canBypassDnd());
+        assertEquals(Notification.VISIBILITY_SECRET, updated.getLockscreenVisibility());
+        assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
+                | NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_VISIBILITY, updated.getUserLockedFields());
+    }
+
+    // TODO: test lock individually.
+    @Test
+    public void testUpdate_userLockedChannelFields() throws Exception {
+        // all fields locked by user
+        final NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setRingtone(new Uri.Builder().scheme("test").build());
+        channel.setLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE
+                | NotificationChannel.USER_LOCKED_VISIBILITY
+                | NotificationChannel.USER_LOCKED_VIBRATION
+                | NotificationChannel.USER_LOCKED_LIGHTS
+                | NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_RINGTONE);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update all fields
+        final NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setRingtone(new Uri.Builder().scheme("test2").build());
+        channel2.setLights(false);
+        channel2.setBypassDnd(false);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+        mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+        // no fields should be changed
+        assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testUpdate() throws Exception {
+        // no fields locked by user
+        final NotificationChannel channel =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setRingtone(new Uri.Builder().scheme("test").build());
+        channel.setLights(true);
+        channel.setBypassDnd(true);
+        channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+        mHelper.createNotificationChannel(pkg, uid, channel);
+
+        // same id, try to update all fields
+        final NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setRingtone(new Uri.Builder().scheme("test2").build());
+        channel2.setLights(false);
+        channel2.setBypassDnd(false);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+        mHelper.updateNotificationChannel(pkg, uid, channel2);
+
+        // all fields should be changed
+        assertEquals(channel2, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+    }
+
+    @Test
+    public void testGetChannelWithFallback() throws Exception {
+        NotificationChannel channel =
+                mHelper.getNotificationChannelWithFallback(pkg, uid, "garbage");
+        assertEquals(NotificationChannel.DEFAULT_CHANNEL_ID, channel.getId());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
index ec1fdad..ffc45ea 100644
--- a/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -24,6 +24,7 @@
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.os.UserHandle;
@@ -178,7 +179,8 @@
                 .build();
         return new NotificationRecord(getContext(), new StatusBarNotification(
                 pkg, pkg, id, tag, 0, 0, 0, n, user),
-                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name"));
+                new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+                        NotificationManager.IMPORTANCE_HIGH));
     }
 
 }
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index af8c314..3daa87c 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -597,7 +597,6 @@
                             mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
 
             if (mConfigured && enteringAccessoryMode) {
-                mAccessoryModeRequestTime = 0;
                 // successfully entered accessory mode
 
                 if (mAccessoryStrings != null) {