Merge "Rename matrices for consistency"
diff --git a/Android.mk b/Android.mk
index 99d73fa..5e634c1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,8 +76,8 @@
 	core/java/android/app/ISearchManagerCallback.aidl \
 	core/java/android/app/IServiceConnection.aidl \
 	core/java/android/app/IStopUserCallback.aidl \
-        core/java/android/app/task/ITaskCallback.aidl \
-        core/java/android/app/task/ITaskService.aidl \
+	core/java/android/app/task/ITaskCallback.aidl \
+	core/java/android/app/task/ITaskService.aidl \
 	core/java/android/app/IThumbnailRetriever.aidl \
 	core/java/android/app/ITransientNotification.aidl \
 	core/java/android/app/IUiAutomationConnection.aidl \
diff --git a/api/current.txt b/api/current.txt
index d96ab71..d90116f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3258,6 +3258,7 @@
     method public boolean onContextItemSelected(android.view.MenuItem);
     method public void onContextMenuClosed(android.view.Menu);
     method protected void onCreate(android.os.Bundle);
+    method protected void onCreate(android.os.Bundle, android.os.PersistableBundle);
     method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
     method public java.lang.CharSequence onCreateDescription();
     method protected deprecated android.app.Dialog onCreateDialog(int);
@@ -3288,6 +3289,7 @@
     method public void onPanelClosed(int, android.view.Menu);
     method protected void onPause();
     method protected void onPostCreate(android.os.Bundle);
+    method protected void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
     method protected void onPostResume();
     method protected deprecated void onPrepareDialog(int, android.app.Dialog);
     method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle);
@@ -3297,9 +3299,11 @@
     method public void onProvideAssistData(android.os.Bundle);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
+    method protected void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
     method public deprecated java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
+    method protected void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested();
     method protected void onStart();
     method protected void onStop();
@@ -4195,14 +4199,18 @@
     method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
     method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
     method public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnDestroy(android.app.Activity);
     method public void callActivityOnNewIntent(android.app.Activity, android.content.Intent);
     method public void callActivityOnPause(android.app.Activity);
     method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnRestart(android.app.Activity);
     method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnResume(android.app.Activity);
     method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnStart(android.app.Activity);
     method public void callActivityOnStop(android.app.Activity);
     method public void callActivityOnUserLeaving(android.app.Activity);
@@ -5050,6 +5058,7 @@
     method public boolean isActivePasswordSufficient();
     method public boolean isAdminActive(android.content.ComponentName);
     method public boolean isDeviceOwnerApp(java.lang.String);
+    method public boolean isLockTaskPermitted(android.content.ComponentName);
     method public boolean isProfileOwnerApp(java.lang.String);
     method public void lockNow();
     method public void removeActiveAdmin(android.content.ComponentName);
@@ -5058,6 +5067,7 @@
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
+    method public void setLockTaskComponents(android.content.ComponentName[]) throws java.lang.SecurityException;
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
     method public void setMaximumTimeToLock(android.content.ComponentName, long);
     method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
@@ -8047,6 +8057,7 @@
     field public static final java.lang.String FEATURE_CAMERA = "android.hardware.camera";
     field public static final java.lang.String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
     field public static final java.lang.String FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus";
+    field public static final java.lang.String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external";
     field public static final java.lang.String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
     field public static final java.lang.String FEATURE_CAMERA_FRONT = "android.hardware.camera.front";
     field public static final java.lang.String FEATURE_CONSUMER_IR = "android.hardware.consumerir";
@@ -12867,6 +12878,7 @@
     method public void onStartInputView(android.view.inputmethod.EditorInfo, boolean);
     method public void onUnbindInput();
     method public void onUpdateCursor(android.graphics.Rect);
+    method public void onUpdateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
     method public void onUpdateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public void onUpdateExtractingViews(android.view.inputmethod.EditorInfo);
     method public void onUpdateExtractingVisibility(android.view.inputmethod.EditorInfo);
@@ -12916,6 +12928,7 @@
     method public void finishInput();
     method public void toggleSoftInput(int, int);
     method public void updateCursor(android.graphics.Rect);
+    method public void updateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
     method public void updateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(int, int, int, int, int, int);
     method public void viewClicked(boolean);
@@ -13361,6 +13374,7 @@
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
     field public static final int ENCODING_PCM_8BIT = 3; // 0x3
+    field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
   }
 
   public class AudioManager {
@@ -13578,6 +13592,7 @@
     method public void stop() throws java.lang.IllegalStateException;
     method public int write(byte[], int, int);
     method public int write(short[], int, int);
+    method public int write(float[], int, int, int);
     method public int write(java.nio.ByteBuffer, int, int);
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
@@ -17133,6 +17148,7 @@
   }
 
   public final class CardEmulation {
+    method public boolean categoryAllowsForegroundPreference(java.lang.String);
     method public android.nfc.cardemulation.AidGroup getAidGroupForService(android.content.ComponentName, java.lang.String);
     method public static synchronized android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
     method public int getSelectionModeForCategory(java.lang.String);
@@ -17140,6 +17156,8 @@
     method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String);
     method public boolean registerAidGroupForService(android.content.ComponentName, android.nfc.cardemulation.AidGroup);
     method public boolean removeAidGroupForService(android.content.ComponentName, java.lang.String);
+    method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
+    method public boolean unsetPreferredService(android.app.Activity);
     field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
     field public static final java.lang.String CATEGORY_OTHER = "other";
     field public static final java.lang.String CATEGORY_PAYMENT = "payment";
@@ -20546,6 +20564,7 @@
     method public void setUserRestrictions(android.os.Bundle);
     method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
     field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user";
+    field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
     field public static final java.lang.String DISALLOW_CONFIG_APPS = "no_config_apps";
     field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
     field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
@@ -20559,9 +20578,11 @@
     field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
     field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
     field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
+    field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
     field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
     field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
     field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
+    field public static final java.lang.String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
     field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
     field public static final java.lang.String ENSURE_VERIFY_APPS = "ensure_verify_apps";
   }
@@ -25713,6 +25734,636 @@
 
 }
 
+package android.system {
+
+  public final class ErrnoException extends java.lang.Exception {
+    ctor public ErrnoException(java.lang.String, int);
+    ctor public ErrnoException(java.lang.String, int, java.lang.Throwable);
+    field public final int errno;
+  }
+
+  public final class Os {
+    method public static java.io.FileDescriptor accept(java.io.FileDescriptor, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static boolean access(java.lang.String, int) throws android.system.ErrnoException;
+    method public static void bind(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void chmod(java.lang.String, int) throws android.system.ErrnoException;
+    method public static void chown(java.lang.String, int, int) throws android.system.ErrnoException;
+    method public static void close(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static void connect(java.io.FileDescriptor, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+    method public static java.io.FileDescriptor dup(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static java.io.FileDescriptor dup2(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+    method public static java.lang.String[] environ();
+    method public static void execv(java.lang.String, java.lang.String[]) throws android.system.ErrnoException;
+    method public static void execve(java.lang.String, java.lang.String[], java.lang.String[]) throws android.system.ErrnoException;
+    method public static void fchmod(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+    method public static void fchown(java.io.FileDescriptor, int, int) throws android.system.ErrnoException;
+    method public static void fdatasync(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static android.system.StructStat fstat(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static android.system.StructStatVfs fstatvfs(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static void fsync(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static void ftruncate(java.io.FileDescriptor, long) throws android.system.ErrnoException;
+    method public static java.lang.String gai_strerror(int);
+    method public static int getegid();
+    method public static java.lang.String getenv(java.lang.String);
+    method public static int geteuid();
+    method public static int getgid();
+    method public static java.net.SocketAddress getpeername(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static int getpid();
+    method public static int getppid();
+    method public static java.net.SocketAddress getsockname(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static int gettid();
+    method public static int getuid();
+    method public static java.lang.String if_indextoname(int);
+    method public static java.net.InetAddress inet_pton(int, java.lang.String);
+    method public static boolean isatty(java.io.FileDescriptor);
+    method public static void kill(int, int) throws android.system.ErrnoException;
+    method public static void lchown(java.lang.String, int, int) throws android.system.ErrnoException;
+    method public static void listen(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+    method public static long lseek(java.io.FileDescriptor, long, int) throws android.system.ErrnoException;
+    method public static android.system.StructStat lstat(java.lang.String) throws android.system.ErrnoException;
+    method public static void mincore(long, long, byte[]) throws android.system.ErrnoException;
+    method public static void mkdir(java.lang.String, int) throws android.system.ErrnoException;
+    method public static void mkfifo(java.lang.String, int) throws android.system.ErrnoException;
+    method public static void mlock(long, long) throws android.system.ErrnoException;
+    method public static long mmap(long, long, int, int, java.io.FileDescriptor, long) throws android.system.ErrnoException;
+    method public static void msync(long, long, int) throws android.system.ErrnoException;
+    method public static void munlock(long, long) throws android.system.ErrnoException;
+    method public static void munmap(long, long) throws android.system.ErrnoException;
+    method public static java.io.FileDescriptor open(java.lang.String, int, int) throws android.system.ErrnoException;
+    method public static java.io.FileDescriptor[] pipe() throws android.system.ErrnoException;
+    method public static int poll(android.system.StructPollfd[], int) throws android.system.ErrnoException;
+    method public static void posix_fallocate(java.io.FileDescriptor, long, long) throws android.system.ErrnoException;
+    method public static int prctl(int, long, long, long, long) throws android.system.ErrnoException;
+    method public static int pread(java.io.FileDescriptor, java.nio.ByteBuffer, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int pread(java.io.FileDescriptor, byte[], int, int, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int pwrite(java.io.FileDescriptor, java.nio.ByteBuffer, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int pwrite(java.io.FileDescriptor, byte[], int, int, long) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int read(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int read(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static java.lang.String readlink(java.lang.String) throws android.system.ErrnoException;
+    method public static int readv(java.io.FileDescriptor, java.lang.Object[], int[], int[]) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int recvfrom(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static int recvfrom(java.io.FileDescriptor, byte[], int, int, int, java.net.InetSocketAddress) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void remove(java.lang.String) throws android.system.ErrnoException;
+    method public static void rename(java.lang.String, java.lang.String) throws android.system.ErrnoException;
+    method public static long sendfile(java.io.FileDescriptor, java.io.FileDescriptor, android.util.MutableLong, long) throws android.system.ErrnoException;
+    method public static int sendto(java.io.FileDescriptor, java.nio.ByteBuffer, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+    method public static int sendto(java.io.FileDescriptor, byte[], int, int, int, java.net.InetAddress, int) throws android.system.ErrnoException, java.net.SocketException;
+    method public static void setegid(int) throws android.system.ErrnoException;
+    method public static void setenv(java.lang.String, java.lang.String, boolean) throws android.system.ErrnoException;
+    method public static void seteuid(int) throws android.system.ErrnoException;
+    method public static void setgid(int) throws android.system.ErrnoException;
+    method public static int setsid() throws android.system.ErrnoException;
+    method public static void setuid(int) throws android.system.ErrnoException;
+    method public static void shutdown(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+    method public static java.io.FileDescriptor socket(int, int, int) throws android.system.ErrnoException;
+    method public static void socketpair(int, int, int, java.io.FileDescriptor, java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static android.system.StructStat stat(java.lang.String) throws android.system.ErrnoException;
+    method public static android.system.StructStatVfs statvfs(java.lang.String) throws android.system.ErrnoException;
+    method public static java.lang.String strerror(int);
+    method public static java.lang.String strsignal(int);
+    method public static void symlink(java.lang.String, java.lang.String) throws android.system.ErrnoException;
+    method public static long sysconf(int);
+    method public static void tcdrain(java.io.FileDescriptor) throws android.system.ErrnoException;
+    method public static void tcsendbreak(java.io.FileDescriptor, int) throws android.system.ErrnoException;
+    method public static int umask(int);
+    method public static android.system.StructUtsname uname();
+    method public static void unsetenv(java.lang.String) throws android.system.ErrnoException;
+    method public static int waitpid(int, android.util.MutableInt, int) throws android.system.ErrnoException;
+    method public static int write(java.io.FileDescriptor, java.nio.ByteBuffer) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int write(java.io.FileDescriptor, byte[], int, int) throws android.system.ErrnoException, java.io.InterruptedIOException;
+    method public static int writev(java.io.FileDescriptor, java.lang.Object[], int[], int[]) throws android.system.ErrnoException, java.io.InterruptedIOException;
+  }
+
+  public final class OsConstants {
+    method public static boolean S_ISBLK(int);
+    method public static boolean S_ISCHR(int);
+    method public static boolean S_ISDIR(int);
+    method public static boolean S_ISFIFO(int);
+    method public static boolean S_ISLNK(int);
+    method public static boolean S_ISREG(int);
+    method public static boolean S_ISSOCK(int);
+    method public static boolean WCOREDUMP(int);
+    method public static int WEXITSTATUS(int);
+    method public static boolean WIFEXITED(int);
+    method public static boolean WIFSIGNALED(int);
+    method public static boolean WIFSTOPPED(int);
+    method public static int WSTOPSIG(int);
+    method public static int WTERMSIG(int);
+    method public static java.lang.String errnoName(int);
+    method public static java.lang.String gaiName(int);
+    field public static final int AF_INET;
+    field public static final int AF_INET6;
+    field public static final int AF_UNIX;
+    field public static final int AF_UNSPEC;
+    field public static final int AI_ADDRCONFIG;
+    field public static final int AI_ALL;
+    field public static final int AI_CANONNAME;
+    field public static final int AI_NUMERICHOST;
+    field public static final int AI_NUMERICSERV;
+    field public static final int AI_PASSIVE;
+    field public static final int AI_V4MAPPED;
+    field public static final int CAP_AUDIT_CONTROL;
+    field public static final int CAP_AUDIT_WRITE;
+    field public static final int CAP_BLOCK_SUSPEND;
+    field public static final int CAP_CHOWN;
+    field public static final int CAP_DAC_OVERRIDE;
+    field public static final int CAP_DAC_READ_SEARCH;
+    field public static final int CAP_FOWNER;
+    field public static final int CAP_FSETID;
+    field public static final int CAP_IPC_LOCK;
+    field public static final int CAP_IPC_OWNER;
+    field public static final int CAP_KILL;
+    field public static final int CAP_LAST_CAP;
+    field public static final int CAP_LEASE;
+    field public static final int CAP_LINUX_IMMUTABLE;
+    field public static final int CAP_MAC_ADMIN;
+    field public static final int CAP_MAC_OVERRIDE;
+    field public static final int CAP_MKNOD;
+    field public static final int CAP_NET_ADMIN;
+    field public static final int CAP_NET_BIND_SERVICE;
+    field public static final int CAP_NET_BROADCAST;
+    field public static final int CAP_NET_RAW;
+    field public static final int CAP_SETFCAP;
+    field public static final int CAP_SETGID;
+    field public static final int CAP_SETPCAP;
+    field public static final int CAP_SETUID;
+    field public static final int CAP_SYSLOG;
+    field public static final int CAP_SYS_ADMIN;
+    field public static final int CAP_SYS_BOOT;
+    field public static final int CAP_SYS_CHROOT;
+    field public static final int CAP_SYS_MODULE;
+    field public static final int CAP_SYS_NICE;
+    field public static final int CAP_SYS_PACCT;
+    field public static final int CAP_SYS_PTRACE;
+    field public static final int CAP_SYS_RAWIO;
+    field public static final int CAP_SYS_RESOURCE;
+    field public static final int CAP_SYS_TIME;
+    field public static final int CAP_SYS_TTY_CONFIG;
+    field public static final int CAP_WAKE_ALARM;
+    field public static final int E2BIG;
+    field public static final int EACCES;
+    field public static final int EADDRINUSE;
+    field public static final int EADDRNOTAVAIL;
+    field public static final int EAFNOSUPPORT;
+    field public static final int EAGAIN;
+    field public static final int EAI_AGAIN;
+    field public static final int EAI_BADFLAGS;
+    field public static final int EAI_FAIL;
+    field public static final int EAI_FAMILY;
+    field public static final int EAI_MEMORY;
+    field public static final int EAI_NODATA;
+    field public static final int EAI_NONAME;
+    field public static final int EAI_OVERFLOW;
+    field public static final int EAI_SERVICE;
+    field public static final int EAI_SOCKTYPE;
+    field public static final int EAI_SYSTEM;
+    field public static final int EALREADY;
+    field public static final int EBADF;
+    field public static final int EBADMSG;
+    field public static final int EBUSY;
+    field public static final int ECANCELED;
+    field public static final int ECHILD;
+    field public static final int ECONNABORTED;
+    field public static final int ECONNREFUSED;
+    field public static final int ECONNRESET;
+    field public static final int EDEADLK;
+    field public static final int EDESTADDRREQ;
+    field public static final int EDOM;
+    field public static final int EDQUOT;
+    field public static final int EEXIST;
+    field public static final int EFAULT;
+    field public static final int EFBIG;
+    field public static final int EHOSTUNREACH;
+    field public static final int EIDRM;
+    field public static final int EILSEQ;
+    field public static final int EINPROGRESS;
+    field public static final int EINTR;
+    field public static final int EINVAL;
+    field public static final int EIO;
+    field public static final int EISCONN;
+    field public static final int EISDIR;
+    field public static final int ELOOP;
+    field public static final int EMFILE;
+    field public static final int EMLINK;
+    field public static final int EMSGSIZE;
+    field public static final int EMULTIHOP;
+    field public static final int ENAMETOOLONG;
+    field public static final int ENETDOWN;
+    field public static final int ENETRESET;
+    field public static final int ENETUNREACH;
+    field public static final int ENFILE;
+    field public static final int ENOBUFS;
+    field public static final int ENODATA;
+    field public static final int ENODEV;
+    field public static final int ENOENT;
+    field public static final int ENOEXEC;
+    field public static final int ENOLCK;
+    field public static final int ENOLINK;
+    field public static final int ENOMEM;
+    field public static final int ENOMSG;
+    field public static final int ENOPROTOOPT;
+    field public static final int ENOSPC;
+    field public static final int ENOSR;
+    field public static final int ENOSTR;
+    field public static final int ENOSYS;
+    field public static final int ENOTCONN;
+    field public static final int ENOTDIR;
+    field public static final int ENOTEMPTY;
+    field public static final int ENOTSOCK;
+    field public static final int ENOTSUP;
+    field public static final int ENOTTY;
+    field public static final int ENXIO;
+    field public static final int EOPNOTSUPP;
+    field public static final int EOVERFLOW;
+    field public static final int EPERM;
+    field public static final int EPIPE;
+    field public static final int EPROTO;
+    field public static final int EPROTONOSUPPORT;
+    field public static final int EPROTOTYPE;
+    field public static final int ERANGE;
+    field public static final int EROFS;
+    field public static final int ESPIPE;
+    field public static final int ESRCH;
+    field public static final int ESTALE;
+    field public static final int ETIME;
+    field public static final int ETIMEDOUT;
+    field public static final int ETXTBSY;
+    field public static final int EXDEV;
+    field public static final int EXIT_FAILURE;
+    field public static final int EXIT_SUCCESS;
+    field public static final int FD_CLOEXEC;
+    field public static final int FIONREAD;
+    field public static final int F_DUPFD;
+    field public static final int F_GETFD;
+    field public static final int F_GETFL;
+    field public static final int F_GETLK;
+    field public static final int F_GETLK64;
+    field public static final int F_GETOWN;
+    field public static final int F_OK;
+    field public static final int F_RDLCK;
+    field public static final int F_SETFD;
+    field public static final int F_SETFL;
+    field public static final int F_SETLK;
+    field public static final int F_SETLK64;
+    field public static final int F_SETLKW;
+    field public static final int F_SETLKW64;
+    field public static final int F_SETOWN;
+    field public static final int F_UNLCK;
+    field public static final int F_WRLCK;
+    field public static final int IFA_F_DADFAILED;
+    field public static final int IFA_F_DEPRECATED;
+    field public static final int IFA_F_HOMEADDRESS;
+    field public static final int IFA_F_NODAD;
+    field public static final int IFA_F_OPTIMISTIC;
+    field public static final int IFA_F_PERMANENT;
+    field public static final int IFA_F_SECONDARY;
+    field public static final int IFA_F_TEMPORARY;
+    field public static final int IFA_F_TENTATIVE;
+    field public static final int IFF_ALLMULTI;
+    field public static final int IFF_AUTOMEDIA;
+    field public static final int IFF_BROADCAST;
+    field public static final int IFF_DEBUG;
+    field public static final int IFF_DYNAMIC;
+    field public static final int IFF_LOOPBACK;
+    field public static final int IFF_MASTER;
+    field public static final int IFF_MULTICAST;
+    field public static final int IFF_NOARP;
+    field public static final int IFF_NOTRAILERS;
+    field public static final int IFF_POINTOPOINT;
+    field public static final int IFF_PORTSEL;
+    field public static final int IFF_PROMISC;
+    field public static final int IFF_RUNNING;
+    field public static final int IFF_SLAVE;
+    field public static final int IFF_UP;
+    field public static final int IPPROTO_ICMP;
+    field public static final int IPPROTO_ICMPV6;
+    field public static final int IPPROTO_IP;
+    field public static final int IPPROTO_IPV6;
+    field public static final int IPPROTO_RAW;
+    field public static final int IPPROTO_TCP;
+    field public static final int IPPROTO_UDP;
+    field public static final int IPV6_CHECKSUM;
+    field public static final int IPV6_MULTICAST_HOPS;
+    field public static final int IPV6_MULTICAST_IF;
+    field public static final int IPV6_MULTICAST_LOOP;
+    field public static final int IPV6_RECVDSTOPTS;
+    field public static final int IPV6_RECVHOPLIMIT;
+    field public static final int IPV6_RECVHOPOPTS;
+    field public static final int IPV6_RECVPKTINFO;
+    field public static final int IPV6_RECVRTHDR;
+    field public static final int IPV6_RECVTCLASS;
+    field public static final int IPV6_TCLASS;
+    field public static final int IPV6_UNICAST_HOPS;
+    field public static final int IPV6_V6ONLY;
+    field public static final int IP_MULTICAST_IF;
+    field public static final int IP_MULTICAST_LOOP;
+    field public static final int IP_MULTICAST_TTL;
+    field public static final int IP_TOS;
+    field public static final int IP_TTL;
+    field public static final int MAP_FIXED;
+    field public static final int MAP_PRIVATE;
+    field public static final int MAP_SHARED;
+    field public static final int MCAST_BLOCK_SOURCE;
+    field public static final int MCAST_JOIN_GROUP;
+    field public static final int MCAST_JOIN_SOURCE_GROUP;
+    field public static final int MCAST_LEAVE_GROUP;
+    field public static final int MCAST_LEAVE_SOURCE_GROUP;
+    field public static final int MCAST_UNBLOCK_SOURCE;
+    field public static final int MCL_CURRENT;
+    field public static final int MCL_FUTURE;
+    field public static final int MSG_CTRUNC;
+    field public static final int MSG_DONTROUTE;
+    field public static final int MSG_EOR;
+    field public static final int MSG_OOB;
+    field public static final int MSG_PEEK;
+    field public static final int MSG_TRUNC;
+    field public static final int MSG_WAITALL;
+    field public static final int MS_ASYNC;
+    field public static final int MS_INVALIDATE;
+    field public static final int MS_SYNC;
+    field public static final int NI_DGRAM;
+    field public static final int NI_NAMEREQD;
+    field public static final int NI_NOFQDN;
+    field public static final int NI_NUMERICHOST;
+    field public static final int NI_NUMERICSERV;
+    field public static final int O_ACCMODE;
+    field public static final int O_APPEND;
+    field public static final int O_CREAT;
+    field public static final int O_EXCL;
+    field public static final int O_NOCTTY;
+    field public static final int O_NOFOLLOW;
+    field public static final int O_NONBLOCK;
+    field public static final int O_RDONLY;
+    field public static final int O_RDWR;
+    field public static final int O_SYNC;
+    field public static final int O_TRUNC;
+    field public static final int O_WRONLY;
+    field public static final int POLLERR;
+    field public static final int POLLHUP;
+    field public static final int POLLIN;
+    field public static final int POLLNVAL;
+    field public static final int POLLOUT;
+    field public static final int POLLPRI;
+    field public static final int POLLRDBAND;
+    field public static final int POLLRDNORM;
+    field public static final int POLLWRBAND;
+    field public static final int POLLWRNORM;
+    field public static final int PROT_EXEC;
+    field public static final int PROT_NONE;
+    field public static final int PROT_READ;
+    field public static final int PROT_WRITE;
+    field public static final int PR_SET_NO_NEW_PRIVS;
+    field public static final int RT_SCOPE_HOST;
+    field public static final int RT_SCOPE_LINK;
+    field public static final int RT_SCOPE_NOWHERE;
+    field public static final int RT_SCOPE_SITE;
+    field public static final int RT_SCOPE_UNIVERSE;
+    field public static final int R_OK;
+    field public static final int SEEK_CUR;
+    field public static final int SEEK_END;
+    field public static final int SEEK_SET;
+    field public static final int SHUT_RD;
+    field public static final int SHUT_RDWR;
+    field public static final int SHUT_WR;
+    field public static final int SIGABRT;
+    field public static final int SIGALRM;
+    field public static final int SIGBUS;
+    field public static final int SIGCHLD;
+    field public static final int SIGCONT;
+    field public static final int SIGFPE;
+    field public static final int SIGHUP;
+    field public static final int SIGILL;
+    field public static final int SIGINT;
+    field public static final int SIGIO;
+    field public static final int SIGKILL;
+    field public static final int SIGPIPE;
+    field public static final int SIGPROF;
+    field public static final int SIGPWR;
+    field public static final int SIGQUIT;
+    field public static final int SIGRTMAX;
+    field public static final int SIGRTMIN;
+    field public static final int SIGSEGV;
+    field public static final int SIGSTKFLT;
+    field public static final int SIGSTOP;
+    field public static final int SIGSYS;
+    field public static final int SIGTERM;
+    field public static final int SIGTRAP;
+    field public static final int SIGTSTP;
+    field public static final int SIGTTIN;
+    field public static final int SIGTTOU;
+    field public static final int SIGURG;
+    field public static final int SIGUSR1;
+    field public static final int SIGUSR2;
+    field public static final int SIGVTALRM;
+    field public static final int SIGWINCH;
+    field public static final int SIGXCPU;
+    field public static final int SIGXFSZ;
+    field public static final int SIOCGIFADDR;
+    field public static final int SIOCGIFBRDADDR;
+    field public static final int SIOCGIFDSTADDR;
+    field public static final int SIOCGIFNETMASK;
+    field public static final int SOCK_DGRAM;
+    field public static final int SOCK_RAW;
+    field public static final int SOCK_SEQPACKET;
+    field public static final int SOCK_STREAM;
+    field public static final int SOL_SOCKET;
+    field public static final int SO_BINDTODEVICE;
+    field public static final int SO_BROADCAST;
+    field public static final int SO_DEBUG;
+    field public static final int SO_DONTROUTE;
+    field public static final int SO_ERROR;
+    field public static final int SO_KEEPALIVE;
+    field public static final int SO_LINGER;
+    field public static final int SO_OOBINLINE;
+    field public static final int SO_PASSCRED;
+    field public static final int SO_PEERCRED;
+    field public static final int SO_RCVBUF;
+    field public static final int SO_RCVLOWAT;
+    field public static final int SO_RCVTIMEO;
+    field public static final int SO_REUSEADDR;
+    field public static final int SO_SNDBUF;
+    field public static final int SO_SNDLOWAT;
+    field public static final int SO_SNDTIMEO;
+    field public static final int SO_TYPE;
+    field public static final int STDERR_FILENO;
+    field public static final int STDIN_FILENO;
+    field public static final int STDOUT_FILENO;
+    field public static final int S_IFBLK;
+    field public static final int S_IFCHR;
+    field public static final int S_IFDIR;
+    field public static final int S_IFIFO;
+    field public static final int S_IFLNK;
+    field public static final int S_IFMT;
+    field public static final int S_IFREG;
+    field public static final int S_IFSOCK;
+    field public static final int S_IRGRP;
+    field public static final int S_IROTH;
+    field public static final int S_IRUSR;
+    field public static final int S_IRWXG;
+    field public static final int S_IRWXO;
+    field public static final int S_IRWXU;
+    field public static final int S_ISGID;
+    field public static final int S_ISUID;
+    field public static final int S_ISVTX;
+    field public static final int S_IWGRP;
+    field public static final int S_IWOTH;
+    field public static final int S_IWUSR;
+    field public static final int S_IXGRP;
+    field public static final int S_IXOTH;
+    field public static final int S_IXUSR;
+    field public static final int TCP_NODELAY;
+    field public static final int WCONTINUED;
+    field public static final int WEXITED;
+    field public static final int WNOHANG;
+    field public static final int WNOWAIT;
+    field public static final int WSTOPPED;
+    field public static final int WUNTRACED;
+    field public static final int W_OK;
+    field public static final int X_OK;
+    field public static final int _SC_2_CHAR_TERM;
+    field public static final int _SC_2_C_BIND;
+    field public static final int _SC_2_C_DEV;
+    field public static final int _SC_2_C_VERSION;
+    field public static final int _SC_2_FORT_DEV;
+    field public static final int _SC_2_FORT_RUN;
+    field public static final int _SC_2_LOCALEDEF;
+    field public static final int _SC_2_SW_DEV;
+    field public static final int _SC_2_UPE;
+    field public static final int _SC_2_VERSION;
+    field public static final int _SC_AIO_LISTIO_MAX;
+    field public static final int _SC_AIO_MAX;
+    field public static final int _SC_AIO_PRIO_DELTA_MAX;
+    field public static final int _SC_ARG_MAX;
+    field public static final int _SC_ASYNCHRONOUS_IO;
+    field public static final int _SC_ATEXIT_MAX;
+    field public static final int _SC_AVPHYS_PAGES;
+    field public static final int _SC_BC_BASE_MAX;
+    field public static final int _SC_BC_DIM_MAX;
+    field public static final int _SC_BC_SCALE_MAX;
+    field public static final int _SC_BC_STRING_MAX;
+    field public static final int _SC_CHILD_MAX;
+    field public static final int _SC_CLK_TCK;
+    field public static final int _SC_COLL_WEIGHTS_MAX;
+    field public static final int _SC_DELAYTIMER_MAX;
+    field public static final int _SC_EXPR_NEST_MAX;
+    field public static final int _SC_FSYNC;
+    field public static final int _SC_GETGR_R_SIZE_MAX;
+    field public static final int _SC_GETPW_R_SIZE_MAX;
+    field public static final int _SC_IOV_MAX;
+    field public static final int _SC_JOB_CONTROL;
+    field public static final int _SC_LINE_MAX;
+    field public static final int _SC_LOGIN_NAME_MAX;
+    field public static final int _SC_MAPPED_FILES;
+    field public static final int _SC_MEMLOCK;
+    field public static final int _SC_MEMLOCK_RANGE;
+    field public static final int _SC_MEMORY_PROTECTION;
+    field public static final int _SC_MESSAGE_PASSING;
+    field public static final int _SC_MQ_OPEN_MAX;
+    field public static final int _SC_MQ_PRIO_MAX;
+    field public static final int _SC_NGROUPS_MAX;
+    field public static final int _SC_NPROCESSORS_CONF;
+    field public static final int _SC_NPROCESSORS_ONLN;
+    field public static final int _SC_OPEN_MAX;
+    field public static final int _SC_PAGESIZE;
+    field public static final int _SC_PAGE_SIZE;
+    field public static final int _SC_PASS_MAX;
+    field public static final int _SC_PHYS_PAGES;
+    field public static final int _SC_PRIORITIZED_IO;
+    field public static final int _SC_PRIORITY_SCHEDULING;
+    field public static final int _SC_REALTIME_SIGNALS;
+    field public static final int _SC_RE_DUP_MAX;
+    field public static final int _SC_RTSIG_MAX;
+    field public static final int _SC_SAVED_IDS;
+    field public static final int _SC_SEMAPHORES;
+    field public static final int _SC_SEM_NSEMS_MAX;
+    field public static final int _SC_SEM_VALUE_MAX;
+    field public static final int _SC_SHARED_MEMORY_OBJECTS;
+    field public static final int _SC_SIGQUEUE_MAX;
+    field public static final int _SC_STREAM_MAX;
+    field public static final int _SC_SYNCHRONIZED_IO;
+    field public static final int _SC_THREADS;
+    field public static final int _SC_THREAD_ATTR_STACKADDR;
+    field public static final int _SC_THREAD_ATTR_STACKSIZE;
+    field public static final int _SC_THREAD_DESTRUCTOR_ITERATIONS;
+    field public static final int _SC_THREAD_KEYS_MAX;
+    field public static final int _SC_THREAD_PRIORITY_SCHEDULING;
+    field public static final int _SC_THREAD_PRIO_INHERIT;
+    field public static final int _SC_THREAD_PRIO_PROTECT;
+    field public static final int _SC_THREAD_SAFE_FUNCTIONS;
+    field public static final int _SC_THREAD_STACK_MIN;
+    field public static final int _SC_THREAD_THREADS_MAX;
+    field public static final int _SC_TIMERS;
+    field public static final int _SC_TIMER_MAX;
+    field public static final int _SC_TTY_NAME_MAX;
+    field public static final int _SC_TZNAME_MAX;
+    field public static final int _SC_VERSION;
+    field public static final int _SC_XBS5_ILP32_OFF32;
+    field public static final int _SC_XBS5_ILP32_OFFBIG;
+    field public static final int _SC_XBS5_LP64_OFF64;
+    field public static final int _SC_XBS5_LPBIG_OFFBIG;
+    field public static final int _SC_XOPEN_CRYPT;
+    field public static final int _SC_XOPEN_ENH_I18N;
+    field public static final int _SC_XOPEN_LEGACY;
+    field public static final int _SC_XOPEN_REALTIME;
+    field public static final int _SC_XOPEN_REALTIME_THREADS;
+    field public static final int _SC_XOPEN_SHM;
+    field public static final int _SC_XOPEN_UNIX;
+    field public static final int _SC_XOPEN_VERSION;
+    field public static final int _SC_XOPEN_XCU_VERSION;
+  }
+
+  public final class StructPollfd {
+    ctor public StructPollfd();
+    field public short events;
+    field public java.io.FileDescriptor fd;
+    field public short revents;
+    field public java.lang.Object userData;
+  }
+
+  public final class StructStat {
+    ctor public StructStat(long, long, int, long, int, int, long, long, long, long, long, long, long);
+    field public final long st_atime;
+    field public final long st_blksize;
+    field public final long st_blocks;
+    field public final long st_ctime;
+    field public final long st_dev;
+    field public final int st_gid;
+    field public final long st_ino;
+    field public final int st_mode;
+    field public final long st_mtime;
+    field public final long st_nlink;
+    field public final long st_rdev;
+    field public final long st_size;
+    field public final int st_uid;
+  }
+
+  public final class StructStatVfs {
+    ctor public StructStatVfs(long, long, long, long, long, long, long, long, long, long, long);
+    field public final long f_bavail;
+    field public final long f_bfree;
+    field public final long f_blocks;
+    field public final long f_bsize;
+    field public final long f_favail;
+    field public final long f_ffree;
+    field public final long f_files;
+    field public final long f_flag;
+    field public final long f_frsize;
+    field public final long f_fsid;
+    field public final long f_namemax;
+  }
+
+  public final class StructUtsname {
+    ctor public StructUtsname(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
+    field public final java.lang.String machine;
+    field public final java.lang.String nodename;
+    field public final java.lang.String release;
+    field public final java.lang.String sysname;
+    field public final java.lang.String version;
+  }
+
+}
+
 package android.telephony {
 
   public final class CellIdentityCdma implements android.os.Parcelable {
@@ -28872,6 +29523,46 @@
     method public void previousMonth();
   }
 
+  public final class MutableBoolean {
+    ctor public MutableBoolean(boolean);
+    field public boolean value;
+  }
+
+  public final class MutableByte {
+    ctor public MutableByte(byte);
+    field public byte value;
+  }
+
+  public final class MutableChar {
+    ctor public MutableChar(char);
+    field public char value;
+  }
+
+  public final class MutableDouble {
+    ctor public MutableDouble(double);
+    field public double value;
+  }
+
+  public final class MutableFloat {
+    ctor public MutableFloat(float);
+    field public float value;
+  }
+
+  public final class MutableInt {
+    ctor public MutableInt(int);
+    field public int value;
+  }
+
+  public final class MutableLong {
+    ctor public MutableLong(long);
+    field public long value;
+  }
+
+  public final class MutableShort {
+    ctor public MutableShort(short);
+    field public short value;
+  }
+
   public class NoSuchPropertyException extends java.lang.RuntimeException {
     ctor public NoSuchPropertyException(java.lang.String);
   }
@@ -32545,6 +33236,34 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
+  public final class CursorAnchorInfo implements android.os.Parcelable {
+    ctor public CursorAnchorInfo(android.os.Parcel);
+    method public int describeContents();
+    method public int getCandidatesEnd();
+    method public int getCandidatesStart();
+    method public android.graphics.RectF getCharacterRect(int);
+    method public float getInsertionMarkerBaseline();
+    method public float getInsertionMarkerBottom();
+    method public float getInsertionMarkerHorizontal();
+    method public float getInsertionMarkerTop();
+    method public android.graphics.Matrix getMatrix();
+    method public int getSelectionEnd();
+    method public int getSelectionStart();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static final class CursorAnchorInfo.CursorAnchorInfoBuilder {
+    ctor public CursorAnchorInfo.CursorAnchorInfoBuilder();
+    method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder addCharacterRect(int, float, float, float, float);
+    method public android.view.inputmethod.CursorAnchorInfo build();
+    method public void reset();
+    method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setCandidateRange(int, int);
+    method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setInsertionMarkerLocation(float, float, float, float);
+    method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setMatrix(android.graphics.Matrix);
+    method public android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder setSelectionRange(int, int);
+  }
+
   public class EditorInfo implements android.text.InputType android.os.Parcelable {
     ctor public EditorInfo();
     method public int describeContents();
@@ -32753,6 +33472,7 @@
     method public void toggleSoftInput(int, int);
     method public void toggleSoftInputFromWindow(android.os.IBinder, int, int);
     method public void updateCursor(android.view.View, int, int, int, int);
+    method public void updateCursorAnchorInfo(android.view.View, android.view.inputmethod.CursorAnchorInfo);
     method public void updateExtractedText(android.view.View, int, android.view.inputmethod.ExtractedText);
     method public void updateSelection(android.view.View, int, int, int, int);
     method public void viewClicked(android.view.View);
@@ -32775,6 +33495,7 @@
     method public abstract void finishInput();
     method public abstract void toggleSoftInput(int, int);
     method public abstract void updateCursor(android.graphics.Rect);
+    method public abstract void updateCursorAnchorInfo(android.view.inputmethod.CursorAnchorInfo);
     method public abstract void updateExtractedText(int, android.view.inputmethod.ExtractedText);
     method public abstract void updateSelection(int, int, int, int, int, int);
     method public abstract void viewClicked(boolean);
@@ -33024,7 +33745,6 @@
     method public abstract long getResources();
     method public abstract void grant(long);
     field public static final long RESOURCE_AUDIO_CAPTURE = 4L; // 0x4L
-    field public static final long RESOURCE_GEOLOCATION = 1L; // 0x1L
     field public static final long RESOURCE_VIDEO_CAPTURE = 2L; // 0x2L
   }
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 36f9f4b..66b82eb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.NonNull;
+import android.os.PersistableBundle;
 import android.transition.Scene;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
@@ -922,6 +923,30 @@
     }
 
     /**
+     * Same as {@link #onCreate(android.os.Bundle)} but called for those activities created with
+     * the attribute {@link android.R.attr#persistable} set true.
+     *
+     * @param savedInstanceState if the activity is being re-initialized after
+     *     previously being shut down then this Bundle contains the data it most
+     *     recently supplied in {@link #onSaveInstanceState}.
+     *     <b><i>Note: Otherwise it is null.</i></b>
+     * @param persistentState if the activity is being re-initialized after
+     *     previously being shut down or powered off then this Bundle contains the data it most
+     *     recently supplied to outPersistentState in {@link #onSaveInstanceState}.
+     *     <b><i>Note: Otherwise it is null.</i></b>
+     *
+     * @see #onCreate(android.os.Bundle)
+     * @see #onStart
+     * @see #onSaveInstanceState
+     * @see #onRestoreInstanceState
+     * @see #onPostCreate
+     */
+    protected void onCreate(@Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
+        onCreate(savedInstanceState);
+    }
+
+    /**
      * The hook for {@link ActivityThread} to restore the state of this activity.
      *
      * Calls {@link #onSaveInstanceState(android.os.Bundle)} and
@@ -935,6 +960,23 @@
     }
 
     /**
+     * The hook for {@link ActivityThread} to restore the state of this activity.
+     *
+     * Calls {@link #onSaveInstanceState(android.os.Bundle)} and
+     * {@link #restoreManagedDialogs(android.os.Bundle)}.
+     *
+     * @param savedInstanceState contains the saved state
+     * @param persistentState contains the persistable saved state
+     */
+    final void performRestoreInstanceState(Bundle savedInstanceState,
+            PersistableBundle persistentState) {
+        onRestoreInstanceState(savedInstanceState, persistentState);
+        if (savedInstanceState != null) {
+            restoreManagedDialogs(savedInstanceState);
+        }
+    }
+
+    /**
      * This method is called after {@link #onStart} when the activity is
      * being re-initialized from a previously saved state, given here in
      * <var>savedInstanceState</var>.  Most implementations will simply use {@link #onCreate}
@@ -962,7 +1004,34 @@
             }
         }
     }
-    
+
+    /**
+     * This is the same as {@link #onRestoreInstanceState(Bundle)} but is called for activities
+     * created with the attribute {@link android.R.attr#persistable}. The {@link
+     * android.os.PersistableBundle} passed came from the restored PersistableBundle first
+     * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}.
+     *
+     * <p>This method is called between {@link #onStart} and
+     * {@link #onPostCreate}.
+     *
+     * <p>If this method is called {@link #onRestoreInstanceState(Bundle)} will not be called.
+     *
+     * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
+     * @param persistentState the data most recently supplied in {@link #onSaveInstanceState}.
+     *
+     * @see #onRestoreInstanceState(Bundle)
+     * @see #onCreate
+     * @see #onPostCreate
+     * @see #onResume
+     * @see #onSaveInstanceState
+     */
+    protected void onRestoreInstanceState(Bundle savedInstanceState,
+            PersistableBundle persistentState) {
+        if (savedInstanceState != null) {
+            onRestoreInstanceState(savedInstanceState);
+        }
+    }
+
     /**
      * Restore the state of any saved managed dialogs.
      *
@@ -1039,6 +1108,21 @@
     }
 
     /**
+     * This is the same as {@link #onPostCreate(Bundle)} but is called for activities
+     * created with the attribute {@link android.R.attr#persistable}.
+     *
+     * @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState}
+     * @param persistentState The data caming from the PersistableBundle first
+     * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}.
+     *
+     * @see #onCreate
+     */
+    protected void onPostCreate(@Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
+        onPostCreate(savedInstanceState);
+    }
+
+    /**
      * Called after {@link #onCreate} &mdash; or after {@link #onRestart} when  
      * the activity had been stopped, but is now again being displayed to the 
      * user.  It will be followed by {@link #onResume}.
@@ -1194,6 +1278,22 @@
     }
 
     /**
+     * The hook for {@link ActivityThread} to save the state of this activity.
+     *
+     * Calls {@link #onSaveInstanceState(android.os.Bundle)}
+     * and {@link #saveManagedDialogs(android.os.Bundle)}.
+     *
+     * @param outState The bundle to save the state to.
+     * @param outPersistentState The bundle to save persistent state to.
+     */
+    final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+        onSaveInstanceState(outState, outPersistentState);
+        saveManagedDialogs(outState);
+        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
+                ", " + outPersistentState);
+    }
+
+    /**
      * Called to retrieve per-instance state from an activity before being killed
      * so that the state can be restored in {@link #onCreate} or
      * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method
@@ -1248,6 +1348,25 @@
     }
 
     /**
+     * This is the same as {@link #onSaveInstanceState} but is called for activities
+     * created with the attribute {@link android.R.attr#persistable}. The {@link
+     * android.os.PersistableBundle} passed in will be saved and presented in
+     * {@link #onCreate(Bundle, PersistableBundle)} the first time that this activity
+     * is restarted following the next device reboot.
+     *
+     * @param outState Bundle in which to place your saved state.
+     * @param outPersistentState State which will be saved across reboots.
+     *
+     * @see #onSaveInstanceState(Bundle)
+     * @see #onCreate
+     * @see #onRestoreInstanceState(Bundle, PersistableBundle)
+     * @see #onPause
+     */
+    protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+        onSaveInstanceState(outState);
+    }
+
+    /**
      * Save the state of any managed dialogs.
      *
      * @param outState place to store the saved state.
@@ -4807,6 +4926,7 @@
     public void setRecentsActivityValues(ActivityManager.RecentsActivityValues values) {
         ActivityManager.RecentsActivityValues activityValues =
                 new ActivityManager.RecentsActivityValues(values);
+        // Scale the icon down to something reasonable
         if (values.icon != null) {
             final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
             activityValues.icon = Bitmap.createScaledBitmap(values.icon, size, size, true);
@@ -5488,13 +5608,22 @@
         return mParent != null ? mParent.getActivityToken() : mToken;
     }
 
-    final void performCreate(Bundle icicle) {
-        onCreate(icicle);
+    final void performCreateCommon() {
         mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                 com.android.internal.R.styleable.Window_windowNoDisplay, false);
         mFragments.dispatchActivityCreated();
     }
 
+    final void performCreate(Bundle icicle) {
+        onCreate(icicle);
+        performCreateCommon();
+    }
+
+    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
+        onCreate(icicle, persistentState);
+        performCreateCommon();
+    }
+
     final void performStart() {
         mFragments.noteStateNotSaved();
         mCalled = false;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5d809d8..044727d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -20,7 +20,6 @@
 import android.os.IBinder;
 import com.android.internal.app.IUsageStats;
 import com.android.internal.app.ProcessStats;
-import com.android.internal.os.PkgUsageStats;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.util.FastPrintWriter;
 
@@ -2130,14 +2129,15 @@
                 return new HashMap<String, Integer>();
             }
 
-            PkgUsageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats();
+            UsageStats.PackageStats[] allPkgUsageStats = usageStatsService.getAllPkgUsageStats(
+                    ActivityThread.currentPackageName());
             if (allPkgUsageStats == null) {
                 return new HashMap<String, Integer>();
             }
 
             Map<String, Integer> launchCounts = new HashMap<String, Integer>();
-            for (PkgUsageStats pkgUsageStats : allPkgUsageStats) {
-                launchCounts.put(pkgUsageStats.packageName, pkgUsageStats.launchCount);
+            for (UsageStats.PackageStats pkgUsageStats : allPkgUsageStats) {
+                launchCounts.put(pkgUsageStats.getPackageName(), pkgUsageStats.getLaunchCount());
             }
 
             return launchCounts;
@@ -2251,17 +2251,17 @@
      *
      * @hide
      */
-    public PkgUsageStats[] getAllPackageUsageStats() {
+    public UsageStats.PackageStats[] getAllPackageUsageStats() {
         try {
             IUsageStats usageStatsService = IUsageStats.Stub.asInterface(
                     ServiceManager.getService("usagestats"));
             if (usageStatsService != null) {
-                return usageStatsService.getAllPkgUsageStats();
+                return usageStatsService.getAllPkgUsageStats(ActivityThread.currentPackageName());
             }
         } catch (RemoteException e) {
             Log.w(TAG, "Could not query usage stats", e);
         }
-        return new PkgUsageStats[0];
+        return new UsageStats.PackageStats[0];
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 57da21e..ec2868a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -40,6 +40,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -454,7 +455,8 @@
         case ACTIVITY_PAUSED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            activityPaused(token);
+            PersistableBundle persistentState = data.readPersistableBundle();
+            activityPaused(token, persistentState);
             reply.writeNoException();
             return true;
         }
@@ -463,10 +465,9 @@
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
             Bundle map = data.readBundle();
-            Bitmap thumbnail = data.readInt() != 0
-                ? Bitmap.CREATOR.createFromParcel(data) : null;
+            PersistableBundle persistentState = data.readPersistableBundle();
             CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            activityStopped(token, map, thumbnail, description);
+            activityStopped(token, map, persistentState, description);
             reply.writeNoException();
             return true;
         }
@@ -2583,31 +2584,27 @@
         data.recycle();
         reply.recycle();
     }
-    public void activityPaused(IBinder token) throws RemoteException
+    public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
+        data.writePersistableBundle(persistentState);
         mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
     }
     public void activityStopped(IBinder token, Bundle state,
-            Bitmap thumbnail, CharSequence description) throws RemoteException
+            PersistableBundle persistentState, CharSequence description) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
         data.writeBundle(state);
-        if (thumbnail != null) {
-            data.writeInt(1);
-            thumbnail.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
+        data.writePersistableBundle(persistentState);
         TextUtils.writeToParcel(description, data, 0);
         mRemote.transact(ACTIVITY_STOPPED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
         reply.readException();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b606088..161cb76 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -56,11 +56,11 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.IRemoteCallback;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -69,8 +69,6 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.transition.Scene;
-import android.transition.TransitionManager;
 import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
@@ -268,6 +266,7 @@
         Intent intent;
         IVoiceInteractor voiceInteractor;
         Bundle state;
+        PersistableBundle persistentState;
         Activity activity;
         Window window;
         Activity parent;
@@ -317,6 +316,10 @@
             return false;
         }
 
+        public boolean isPersistable() {
+            return (activityInfo.flags & ActivityInfo.FLAG_PERSISTABLE) != 0;
+        }
+
         public String toString() {
             ComponentName componentName = intent != null ? intent.getComponent() : null;
             return "ActivityRecord{"
@@ -605,8 +608,8 @@
         // activity itself back to the activity manager. (matters more with ipc)
         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-                IVoiceInteractor voiceInteractor,
-                int procState, Bundle state, List<ResultInfo> pendingResults,
+                IVoiceInteractor voiceInteractor, int procState, Bundle state,
+                PersistableBundle persistentState, List<ResultInfo> pendingResults,
                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                 Bundle resumeArgs) {
@@ -622,6 +625,7 @@
             r.activityInfo = info;
             r.compatInfo = compatInfo;
             r.state = state;
+            r.persistentState = persistentState;
 
             r.pendingResults = pendingResults;
             r.pendingIntents = pendingNewIntents;
@@ -2205,7 +2209,11 @@
                 }
 
                 activity.mCalled = false;
-                mInstrumentation.callActivityOnCreate(activity, r.state);
+                if (r.isPersistable()) {
+                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
+                } else {
+                    mInstrumentation.callActivityOnCreate(activity, r.state);
+                }
                 if (!activity.mCalled) {
                     throw new SuperNotCalledException(
                         "Activity " + r.intent.getComponent().toShortString() +
@@ -2218,13 +2226,23 @@
                     r.stopped = false;
                 }
                 if (!r.activity.mFinished) {
-                    if (r.state != null) {
+                    if (r.isPersistable()) {
+                        if (r.state != null || r.persistentState != null) {
+                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
+                                    r.persistentState);
+                        }
+                    } else if (r.state != null) {
                         mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                     }
                 }
                 if (!r.activity.mFinished) {
                     activity.mCalled = false;
-                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
+                    if (r.isPersistable()) {
+                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
+                                r.persistentState);
+                    } else {
+                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
+                    }
                     if (!activity.mCalled) {
                         throw new SuperNotCalledException(
                             "Activity " + r.intent.getComponent().toShortString() +
@@ -2842,6 +2860,7 @@
                 r.paused = false;
                 r.stopped = false;
                 r.state = null;
+                r.persistentState = null;
             } catch (Exception e) {
                 if (!mInstrumentation.onException(r.activity, e)) {
                     throw new RuntimeException(
@@ -3069,7 +3088,7 @@
 
             // Tell the activity manager we have paused.
             try {
-                ActivityManagerNative.getDefault().activityPaused(token);
+                ActivityManagerNative.getDefault().activityPaused(token, r.persistentState);
             } catch (RemoteException ex) {
             }
         }
@@ -3099,17 +3118,13 @@
                     + r.intent.getComponent().toShortString());
             Slog.e(TAG, e.getMessage(), e);
         }
-        Bundle state = null;
         if (finished) {
             r.activity.mFinished = true;
         }
         try {
             // Next have the activity save its current state and managed dialogs...
             if (!r.activity.mFinished && saveState) {
-                state = new Bundle();
-                state.setAllowFds(false);
-                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
-                r.state = state;
+                callCallActivityOnSaveInstanceState(r);
             }
             // Now we are idle.
             r.activity.mCalled = false;
@@ -3145,7 +3160,7 @@
             listeners.get(i).onPaused(r.activity);
         }
 
-        return state;
+        return !r.activity.mFinished && saveState ? r.state : null;
     }
 
     final void performStopActivity(IBinder token, boolean saveState) {
@@ -3156,7 +3171,7 @@
     private static class StopInfo implements Runnable {
         ActivityClientRecord activity;
         Bundle state;
-        Bitmap thumbnail;
+        PersistableBundle persistentState;
         CharSequence description;
 
         @Override public void run() {
@@ -3164,7 +3179,7 @@
             try {
                 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
                 ActivityManagerNative.getDefault().activityStopped(
-                    activity.token, state, thumbnail, description);
+                    activity.token, state, persistentState, description);
             } catch (RemoteException ex) {
             }
         }
@@ -3203,7 +3218,6 @@
     private void performStopActivityInner(ActivityClientRecord r,
             StopInfo info, boolean keepShown, boolean saveState) {
         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
-        Bundle state = null;
         if (r != null) {
             if (!keepShown && r.stopped) {
                 if (r.activity.mFinished) {
@@ -3223,7 +3237,6 @@
                     // First create a thumbnail for the activity...
                     // For now, don't create the thumbnail here; we are
                     // doing that by doing a screen snapshot.
-                    info.thumbnail = null; //createThumbnailBitmap(r);
                     info.description = r.activity.onCreateDescription();
                 } catch (Exception e) {
                     if (!mInstrumentation.onException(r.activity, e)) {
@@ -3238,12 +3251,7 @@
             // Next have the activity save its current state and managed dialogs...
             if (!r.activity.mFinished && saveState) {
                 if (r.state == null) {
-                    state = new Bundle();
-                    state.setAllowFds(false);
-                    mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
-                    r.state = state;
-                } else {
-                    state = r.state;
+                    callCallActivityOnSaveInstanceState(r);
                 }
             }
 
@@ -3319,6 +3327,7 @@
         // manager to proceed and allow us to go fully into the background.
         info.activity = r;
         info.state = r.state;
+        info.persistentState = r.persistentState;
         mH.post(info);
     }
 
@@ -3775,9 +3784,7 @@
             performPauseActivity(r.token, false, r.isPreHoneycomb());
         }
         if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
-            r.state = new Bundle();
-            r.state.setAllowFds(false);
-            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
+            callCallActivityOnSaveInstanceState(r);
         }
 
         handleDestroyActivity(r.token, false, configChanges, true);
@@ -3807,6 +3814,18 @@
         handleLaunchActivity(r, currentIntent);
     }
 
+    private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
+        r.state = new Bundle();
+        r.state.setAllowFds(false);
+        if (r.isPersistable()) {
+            r.persistentState = new PersistableBundle();
+            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
+                    r.persistentState);
+        } else {
+            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
+        }
+    }
+
     ArrayList<ComponentCallbacks2> collectComponentCallbacks(
             boolean allActivities, Configuration newConfig) {
         ArrayList<ComponentCallbacks2> callbacks
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index b616c1e..d813dab 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.Manifest;
 import android.os.Binder;
 import android.os.IBinder;
 import android.util.ArrayMap;
@@ -184,8 +185,10 @@
     public static final int OP_MONITOR_LOCATION = 41;
     /** @hide Continually monitoring location data with a relatively high power request. */
     public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
+    /** @hide Retrieve current usage stats via {@link UsageStatsManager}. */
+    public static final int OP_GET_USAGE_STATS = 43;
     /** @hide */
-    public static final int _NUM_OP = 43;
+    public static final int _NUM_OP = 44;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION =
@@ -252,6 +255,7 @@
             OP_WAKE_LOCK,
             OP_COARSE_LOCATION,
             OP_COARSE_LOCATION,
+            OP_GET_USAGE_STATS,
     };
 
     /**
@@ -302,6 +306,7 @@
             null,
             OPSTR_MONITOR_LOCATION,
             OPSTR_MONITOR_HIGH_POWER_LOCATION,
+            null,
     };
 
     /**
@@ -352,6 +357,7 @@
             "WAKE_LOCK",
             "MONITOR_LOCATION",
             "MONITOR_HIGH_POWER_LOCATION",
+            "GET_USAGE_STATS"
     };
 
     /**
@@ -402,6 +408,7 @@
             android.Manifest.permission.WAKE_LOCK,
             null, // no permission for generic location monitoring
             null, // no permission for high power location monitoring
+            android.Manifest.permission.PACKAGE_USAGE_STATS,
     };
 
     /**
@@ -451,6 +458,7 @@
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
             AppOpsManager.MODE_ALLOWED,
+            AppOpsManager.MODE_IGNORED, // OP_GET_USAGE_STATS
     };
 
     /**
@@ -504,6 +512,7 @@
             false,
             false,
             false,
+            false,
     };
 
     private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 7f2fb59..e7902a9 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -29,6 +29,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -141,6 +142,7 @@
                     data.readStrongBinder());
             int procState = data.readInt();
             Bundle state = data.readBundle();
+            PersistableBundle persistentState = data.readPersistableBundle();
             List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
             List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
             boolean notResumed = data.readInt() != 0;
@@ -151,9 +153,9 @@
             boolean autoStopProfiler = data.readInt() != 0;
             Bundle resumeArgs = data.readBundle();
             scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo,
-                    voiceInteractor, procState, state,
-                    ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler,
-                    resumeArgs);
+                    voiceInteractor, procState, state, persistentState,
+                    ri, pi, notResumed, isForward, profileName, profileFd,
+                    autoStopProfiler, resumeArgs);
             return true;
         }
         
@@ -731,8 +733,8 @@
 
     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-            IVoiceInteractor voiceInteractor,
-            int procState, Bundle state, List<ResultInfo> pendingResults,
+            IVoiceInteractor voiceInteractor, int procState, Bundle state,
+            PersistableBundle persistentState, List<ResultInfo> pendingResults,
             List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
             String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
             Bundle resumeArgs)
@@ -748,6 +750,7 @@
         data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
         data.writeInt(procState);
         data.writeBundle(state);
+        data.writePersistableBundle(persistentState);
         data.writeTypedList(pendingResults);
         data.writeTypedList(pendingNewIntents);
         data.writeInt(notResumed ? 1 : 0);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 5ed5030..801182d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -678,6 +678,11 @@
                 return new NetworkScoreManager(ctx);
             }
         });
+
+        registerService(USAGE_STATS_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                return new UsageStatsManager(ctx.getOuterContext());
+        }});
     }
 
     static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2e9cdf3b7..074b427 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -45,6 +45,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.service.voice.IVoiceInteractionSession;
@@ -104,9 +105,9 @@
     public void activityResumed(IBinder token) throws RemoteException;
     public void activityIdle(IBinder token, Configuration config,
             boolean stopProfiling) throws RemoteException;
-    public void activityPaused(IBinder token) throws RemoteException;
+    public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException;
     public void activityStopped(IBinder token, Bundle state,
-            Bitmap thumbnail, CharSequence description) throws RemoteException;
+            PersistableBundle persistentState, CharSequence description) throws RemoteException;
     public void activitySlept(IBinder token) throws RemoteException;
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index fefba8a..a832034 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -28,6 +28,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
@@ -58,8 +59,8 @@
     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
             IVoiceInteractor voiceInteractor, int procState, Bundle state,
-            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed,
-            boolean isForward,
+            PersistableBundle persistentState, List<ResultInfo> pendingResults,
+            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
             String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
             Bundle resumeArgs)
             throws RemoteException;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e58ccb8..bb3e002 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -30,6 +30,7 @@
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.PerformanceCollector;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -1061,15 +1062,7 @@
         return (Activity)cl.loadClass(className).newInstance();
     }
 
-    /**
-     * Perform calling of an activity's {@link Activity#onCreate}
-     * method.  The default implementation simply calls through to that method.
-     * 
-     * @param activity The activity being created.
-     * @param icicle The previously frozen state (or null) to pass through to
-     *               onCreate().
-     */
-    public void callActivityOnCreate(Activity activity, Bundle icicle) {
+    private void prePerformCreate(Activity activity) {
         if (mWaitingActivities != null) {
             synchronized (mSync) {
                 final int N = mWaitingActivities.size();
@@ -1083,9 +1076,9 @@
                 }
             }
         }
-        
-        activity.performCreate(icicle);
-        
+    }
+
+    private void postPerformCreate(Activity activity) {
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -1096,6 +1089,33 @@
             }
         }
     }
+
+    /**
+     * Perform calling of an activity's {@link Activity#onCreate}
+     * method.  The default implementation simply calls through to that method.
+     *
+     * @param activity The activity being created.
+     * @param icicle The previously frozen state (or null) to pass through to onCreate().
+     */
+    public void callActivityOnCreate(Activity activity, Bundle icicle) {
+        prePerformCreate(activity);
+        activity.performCreate(icicle);
+        postPerformCreate(activity);
+    }
+
+    /**
+     * Perform calling of an activity's {@link Activity#onCreate}
+     * method.  The default implementation simply calls through to that method.
+     *  @param activity The activity being created.
+     * @param icicle The previously frozen state (or null) to pass through to
+     * @param persistentState The previously persisted state (or null)
+     */
+    public void callActivityOnCreate(Activity activity, Bundle icicle,
+            PersistableBundle persistentState) {
+        prePerformCreate(activity);
+        activity.performCreate(icicle, persistentState);
+        postPerformCreate(activity);
+    }
     
     public void callActivityOnDestroy(Activity activity) {
       // TODO: the following block causes intermittent hangs when using startActivity
@@ -1130,7 +1150,7 @@
     /**
      * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
      * method.  The default implementation simply calls through to that method.
-     * 
+     *
      * @param activity The activity being restored.
      * @param savedInstanceState The previously saved state being restored.
      */
@@ -1139,9 +1159,22 @@
     }
 
     /**
+     * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
+     * method.  The default implementation simply calls through to that method.
+     *
+     * @param activity The activity being restored.
+     * @param savedInstanceState The previously saved state being restored.
+     * @param persistentState The previously persisted state (or null)
+     */
+    public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
+            PersistableBundle persistentState) {
+        activity.performRestoreInstanceState(savedInstanceState, persistentState);
+    }
+
+    /**
      * Perform calling of an activity's {@link Activity#onPostCreate} method.
      * The default implementation simply calls through to that method.
-     * 
+     *
      * @param activity The activity being created.
      * @param icicle The previously frozen state (or null) to pass through to
      *               onPostCreate().
@@ -1151,6 +1184,19 @@
     }
 
     /**
+     * Perform calling of an activity's {@link Activity#onPostCreate} method.
+     * The default implementation simply calls through to that method.
+     *
+     * @param activity The activity being created.
+     * @param icicle The previously frozen state (or null) to pass through to
+     *               onPostCreate().
+     */
+    public void callActivityOnPostCreate(Activity activity, Bundle icicle,
+            PersistableBundle persistentState) {
+        activity.onPostCreate(icicle, persistentState);
+    }
+
+    /**
      * Perform calling of an activity's {@link Activity#onNewIntent}
      * method.  The default implementation simply calls through to that method.
      * 
@@ -1215,7 +1261,7 @@
     /**
      * Perform calling of an activity's {@link Activity#onSaveInstanceState}
      * method.  The default implementation simply calls through to that method.
-     * 
+     *
      * @param activity The activity being saved.
      * @param outState The bundle to pass to the call.
      */
@@ -1224,6 +1270,18 @@
     }
 
     /**
+     * Perform calling of an activity's {@link Activity#onSaveInstanceState}
+     * method.  The default implementation simply calls through to that method.
+     *  @param activity The activity being saved.
+     * @param outState The bundle to pass to the call.
+     * @param outPersistentState The persistent bundle to pass to the call.
+     */
+    public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
+            PersistableBundle outPersistentState) {
+        activity.performSaveInstanceState(outState, outPersistentState);
+    }
+
+    /**
      * Perform calling of an activity's {@link Activity#onPause} method.  The
      * default implementation simply calls through to that method.
      * 
@@ -1428,7 +1486,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity},
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
      * but accepts an array of activities to be started.  Note that active
      * {@link ActivityMonitor} objects only match against the first activity in
      * the array.
@@ -1442,7 +1500,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity},
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
      * but accepts an array of activities to be started.  Note that active
      * {@link ActivityMonitor} objects only match against the first activity in
      * the array.
@@ -1545,7 +1603,8 @@
     }
 
     /**
-     * Like {@link #execStartActivity}, but for starting as a particular user.
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
+     * but for starting as a particular user.
      *
      * @param who The Context from which the activity is being started.
      * @param contextThread The main thread of the Context from which the activity
diff --git a/core/java/android/app/UsageStats.aidl b/core/java/android/app/UsageStats.aidl
new file mode 100644
index 0000000..7dee70a
--- /dev/null
+++ b/core/java/android/app/UsageStats.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+parcelable UsageStats;
+parcelable UsageStats.PackageStats;
diff --git a/core/java/android/app/UsageStats.java b/core/java/android/app/UsageStats.java
new file mode 100644
index 0000000..0aeba59
--- /dev/null
+++ b/core/java/android/app/UsageStats.java
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Snapshot of current usage stats data.
+ * @hide
+ */
+public class UsageStats implements Parcelable {
+    /** @hide */
+    public final ArrayMap<String, PackageStats> mPackages = new ArrayMap<String, PackageStats>();
+    /** @hide */
+    public final ArrayMap<Configuration, ConfigurationStats> mConfigurations
+            = new ArrayMap<Configuration, ConfigurationStats>();
+
+    public static class PackageStats implements Parcelable {
+        private final String mPackageName;
+        private int mLaunchCount;
+        private long mUsageTime;
+        private long mResumedTime;
+
+        /** @hide */
+        public final ArrayMap<String, Long> componentResumeTimes;
+
+        public static final Parcelable.Creator<PackageStats> CREATOR
+                = new Parcelable.Creator<PackageStats>() {
+            public PackageStats createFromParcel(Parcel in) {
+                return new PackageStats(in);
+            }
+
+            public PackageStats[] newArray(int size) {
+                return new PackageStats[size];
+            }
+        };
+
+        public String toString() {
+            return "PackageStats{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + mPackageName + "}";
+        }
+
+        /** @hide */
+        public PackageStats(String pkgName) {
+            mPackageName = pkgName;
+            componentResumeTimes = new ArrayMap<String, Long>();
+        }
+
+        /** @hide */
+        public PackageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
+            mPackageName = pkgName;
+            mLaunchCount = count;
+            mUsageTime = time;
+            componentResumeTimes = new ArrayMap<String, Long>();
+            componentResumeTimes.putAll(lastResumeTimes);
+        }
+
+        /** @hide */
+        public PackageStats(Parcel source) {
+            mPackageName = source.readString();
+            mLaunchCount = source.readInt();
+            mUsageTime = source.readLong();
+            final int N = source.readInt();
+            componentResumeTimes = new ArrayMap<String, Long>(N);
+            for (int i = 0; i < N; i++) {
+                String component = source.readString();
+                long lastResumeTime = source.readLong();
+                componentResumeTimes.put(component, lastResumeTime);
+            }
+        }
+
+        /** @hide */
+        public PackageStats(PackageStats pStats) {
+            mPackageName = pStats.mPackageName;
+            mLaunchCount = pStats.mLaunchCount;
+            mUsageTime = pStats.mUsageTime;
+            componentResumeTimes = new ArrayMap<String, Long>(pStats.componentResumeTimes);
+        }
+
+        /** @hide */
+        public void resume(boolean launched) {
+            if (launched) {
+                mLaunchCount++;
+            }
+            mResumedTime = SystemClock.elapsedRealtime();
+        }
+
+        /** @hide */
+        public void pause() {
+            if (mResumedTime > 0) {
+                mUsageTime += SystemClock.elapsedRealtime() - mResumedTime;
+            }
+            mResumedTime = 0;
+        }
+
+        public final String getPackageName() {
+            return mPackageName;
+        }
+
+        public final long getUsageTime(long elapsedRealtime) {
+            return mUsageTime + (mResumedTime > 0 ? (elapsedRealtime- mResumedTime) : 0);
+        }
+
+        public final int getLaunchCount() {
+            return mLaunchCount;
+        }
+
+        /** @hide */
+        public boolean clearUsageTimes() {
+            mLaunchCount = 0;
+            mUsageTime = 0;
+            return mResumedTime <= 0 && componentResumeTimes.isEmpty();
+        }
+
+        public final int describeContents() {
+            return 0;
+        }
+
+        public final void writeToParcel(Parcel dest, int parcelableFlags) {
+            writeToParcel(dest, parcelableFlags, 0);
+        }
+
+        final void writeToParcel(Parcel dest, int parcelableFlags, long elapsedRealtime) {
+            dest.writeString(mPackageName);
+            dest.writeInt(mLaunchCount);
+            dest.writeLong(elapsedRealtime > 0 ? getUsageTime(elapsedRealtime) : mUsageTime);
+            dest.writeInt(componentResumeTimes.size());
+            for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
+                dest.writeString(ent.getKey());
+                dest.writeLong(ent.getValue());
+            }
+        }
+
+        /** @hide */
+        public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+        }
+    }
+
+    public static class ConfigurationStats implements Parcelable {
+        private final Configuration mConfiguration;
+        private long mLastUsedTime;
+        private int mUsageCount;
+        private long mUsageTime;
+        private long mStartedTime;
+
+        public static final Parcelable.Creator<ConfigurationStats> CREATOR
+                = new Parcelable.Creator<ConfigurationStats>() {
+            public ConfigurationStats createFromParcel(Parcel in) {
+                return new ConfigurationStats(in);
+            }
+
+            public ConfigurationStats[] newArray(int size) {
+                return new ConfigurationStats[size];
+            }
+        };
+
+        public String toString() {
+            return "ConfigurationStats{"
+            + Integer.toHexString(System.identityHashCode(this))
+            + " " + mConfiguration + "}";
+        }
+
+        /** @hide */
+        public ConfigurationStats(Configuration config) {
+            mConfiguration = config;
+        }
+
+        /** @hide */
+        public ConfigurationStats(Parcel source) {
+            mConfiguration = Configuration.CREATOR.createFromParcel(source);
+            mLastUsedTime = source.readLong();
+            mUsageCount = source.readInt();
+            mUsageTime = source.readLong();
+        }
+
+        /** @hide */
+        public ConfigurationStats(ConfigurationStats pStats) {
+            mConfiguration = pStats.mConfiguration;
+            mLastUsedTime = pStats.mLastUsedTime;
+            mUsageCount = pStats.mUsageCount;
+            mUsageTime = pStats.mUsageTime;
+        }
+
+        public final Configuration getConfiguration() {
+            return mConfiguration;
+        }
+
+        public final long getLastUsedTime() {
+            return mLastUsedTime;
+        }
+
+        public final long getUsageTime(long elapsedRealtime) {
+            return mUsageTime + (mStartedTime > 0 ? (elapsedRealtime- mStartedTime) : 0);
+        }
+
+        public final int getUsageCount() {
+            return mUsageCount;
+        }
+
+        /** @hide */
+        public void start() {
+            mLastUsedTime = System.currentTimeMillis();
+            mUsageCount++;
+            mStartedTime = SystemClock.elapsedRealtime();
+        }
+
+        /** @hide */
+        public void stop() {
+            if (mStartedTime > 0) {
+                mUsageTime += SystemClock.elapsedRealtime() - mStartedTime;
+            }
+            mStartedTime = 0;
+        }
+
+        /** @hide */
+        public boolean clearUsageTimes() {
+            mUsageCount = 0;
+            mUsageTime = 0;
+            return mLastUsedTime == 0 && mStartedTime <= 0;
+        }
+
+        public final int describeContents() {
+            return 0;
+        }
+
+        public final void writeToParcel(Parcel dest, int parcelableFlags) {
+            writeToParcel(dest, parcelableFlags, 0);
+        }
+
+        final void writeToParcel(Parcel dest, int parcelableFlags, long elapsedRealtime) {
+            mConfiguration.writeToParcel(dest, parcelableFlags);
+            dest.writeLong(mLastUsedTime);
+            dest.writeInt(mUsageCount);
+            dest.writeLong(elapsedRealtime > 0 ? getUsageTime(elapsedRealtime) : mUsageTime);
+        }
+
+        /** @hide */
+        public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+        }
+    }
+
+    /** @hide */
+    public UsageStats() {
+    }
+
+    /** @hide */
+    public UsageStats(Parcel source, boolean extended) {
+        int N = source.readInt();
+        for (int i=0; i<N; i++) {
+            PackageStats pkg = extended ? onNewPackageStats(source) : new PackageStats(source);
+            mPackages.put(pkg.getPackageName(), pkg);
+        }
+        N = source.readInt();
+        for (int i=0; i<N; i++) {
+            ConfigurationStats config = extended ? onNewConfigurationStats(source)
+                    : new ConfigurationStats(source);
+            mConfigurations.put(config.getConfiguration(), config);
+        }
+    }
+
+    public int getPackageStatsCount() {
+        return mPackages.size();
+    }
+
+    public PackageStats getPackageStatsAt(int index) {
+        return mPackages.valueAt(index);
+    }
+
+    public PackageStats getPackageStats(String pkgName) {
+        return mPackages.get(pkgName);
+    }
+
+    /** @hide */
+    public PackageStats getOrCreatePackageStats(String pkgName) {
+        PackageStats ps = mPackages.get(pkgName);
+        if (ps == null) {
+            ps = onNewPackageStats(pkgName);
+            mPackages.put(pkgName, ps);
+        }
+        return ps;
+    }
+
+    public int getConfigurationStatsCount() {
+        return mConfigurations.size();
+    }
+
+    public ConfigurationStats getConfigurationStatsAt(int index) {
+        return mConfigurations.valueAt(index);
+    }
+
+    public ConfigurationStats getConfigurationStats(Configuration config) {
+        return mConfigurations.get(config);
+    }
+
+    /** @hide */
+    public ConfigurationStats getOrCreateConfigurationStats(Configuration config) {
+        ConfigurationStats cs = mConfigurations.get(config);
+        if (cs == null) {
+            cs = onNewConfigurationStats(config);
+            mConfigurations.put(config, cs);
+        }
+        return cs;
+    }
+
+    /** @hide */
+    public void clearUsageTimes() {
+        for (int i=mPackages.size()-1; i>=0; i--) {
+            if (mPackages.valueAt(i).clearUsageTimes()) {
+                mPackages.removeAt(i);
+            }
+        }
+        for (int i=mConfigurations.size()-1; i>=0; i--) {
+            if (mConfigurations.valueAt(i).clearUsageTimes()) {
+                mConfigurations.removeAt(i);
+            }
+        }
+    }
+
+    /** @hide */
+    public PackageStats onNewPackageStats(String pkgName) {
+        return new PackageStats(pkgName);
+    }
+
+    /** @hide */
+    public PackageStats onNewPackageStats(Parcel source) {
+        return new PackageStats(source);
+    }
+
+    /** @hide */
+    public ConfigurationStats onNewConfigurationStats(Configuration config) {
+        return new ConfigurationStats(config);
+    }
+
+    /** @hide */
+    public ConfigurationStats onNewConfigurationStats(Parcel source) {
+        return new ConfigurationStats(source);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
+        writeToParcelInner(dest, parcelableFlags, false);
+    }
+
+    /** @hide */
+    public void writeExtendedToParcel(Parcel dest, int parcelableFlags) {
+        writeToParcelInner(dest, parcelableFlags, true);
+    }
+
+    private void writeToParcelInner(Parcel dest, int parcelableFlags, boolean extended) {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+
+        int N = mPackages.size();
+        dest.writeInt(N);
+        for (int i=0; i<N; i++) {
+            PackageStats ps = mPackages.valueAt(i);
+            ps.writeToParcel(dest, parcelableFlags, elapsedRealtime);
+            if (extended) {
+                ps.writeExtendedToParcel(dest, parcelableFlags);
+            }
+        }
+        N = mConfigurations.size();
+        dest.writeInt(N);
+        for (int i=0; i<N; i++) {
+            ConfigurationStats cs = mConfigurations.valueAt(i);
+            cs.writeToParcel(dest, parcelableFlags, elapsedRealtime);
+            if (extended) {
+                cs.writeExtendedToParcel(dest, parcelableFlags);
+            }
+        }
+    }
+
+    public static final Parcelable.Creator<UsageStats> CREATOR
+            = new Parcelable.Creator<UsageStats>() {
+        public UsageStats createFromParcel(Parcel in) {
+            return new UsageStats(in, false);
+        }
+
+        public UsageStats[] newArray(int size) {
+            return new UsageStats[size];
+        }
+    };
+}
diff --git a/core/java/android/app/UsageStatsManager.java b/core/java/android/app/UsageStatsManager.java
new file mode 100644
index 0000000..fbf9c3b
--- /dev/null
+++ b/core/java/android/app/UsageStatsManager.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.os.ParcelableParcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import com.android.internal.app.IUsageStats;
+
+/**
+ * Access to usage stats data.
+ * @hide
+ */
+public class UsageStatsManager {
+    final Context mContext;
+    final IUsageStats mService;
+
+    /** @hide */
+    public UsageStatsManager(Context context) {
+        mContext = context;
+        mService = IUsageStats.Stub.asInterface(ServiceManager.getService(
+                Context.USAGE_STATS_SERVICE));
+    }
+
+    public UsageStats getCurrentStats() {
+        try {
+            ParcelableParcel in = mService.getCurrentStats(mContext.getOpPackageName());
+            if (in != null) {
+                return new UsageStats(in.getParcel(), false);
+            }
+        } catch (RemoteException e) {
+            // About to die.
+        }
+        return new UsageStats();
+    }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 61ff60a..58049fd 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16,8 +16,6 @@
 
 package android.app.admin;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
@@ -39,6 +37,8 @@
 
 import com.android.org.conscrypt.TrustedCertificateStore;
 
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -359,8 +359,8 @@
     }
 
     /**
-     * Retrieve the current minimum password quality for all admins
-     * or a particular one.
+     * Retrieve the current minimum password quality for all admins of this user
+     * and its profiles or a particular one.
      * @param admin The name of the admin component to check, or null to aggregate
      * all admins.
      */
@@ -412,8 +412,8 @@
     }
 
     /**
-     * Retrieve the current minimum password length for all admins
-     * or a particular one.
+     * Retrieve the current minimum password length for all admins of this
+     * user and its profiles or a particular one.
      * @param admin The name of the admin component to check, or null to aggregate
      * all admins.
      */
@@ -467,8 +467,9 @@
 
     /**
      * Retrieve the current number of upper case letters required in the
-     * password for all admins or a particular one. This is the same value as
-     * set by {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)}
+     * password for all admins of this user and its profiles or a particular one.
+     * This is the same value as set by
+     * {#link {@link #setPasswordMinimumUpperCase(ComponentName, int)}
      * and only applies when the password quality is
      * {@link #PASSWORD_QUALITY_COMPLEX}.
      *
@@ -527,8 +528,9 @@
 
     /**
      * Retrieve the current number of lower case letters required in the
-     * password for all admins or a particular one. This is the same value as
-     * set by {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)}
+     * password for all admins of this user and its profiles or a particular one.
+     * This is the same value as set by
+     * {#link {@link #setPasswordMinimumLowerCase(ComponentName, int)}
      * and only applies when the password quality is
      * {@link #PASSWORD_QUALITY_COMPLEX}.
      *
@@ -644,8 +646,9 @@
 
     /**
      * Retrieve the current number of numerical digits required in the password
-     * for all admins or a particular one. This is the same value as
-     * set by {#link {@link #setPasswordMinimumNumeric(ComponentName, int)}
+     * for all admins of this user and its profiles or a particular one.
+     * This is the same value as set by
+     * {#link {@link #setPasswordMinimumNumeric(ComponentName, int)}
      * and only applies when the password quality is
      * {@link #PASSWORD_QUALITY_COMPLEX}.
      *
@@ -760,8 +763,9 @@
 
     /**
      * Retrieve the current number of non-letter characters required in the
-     * password for all admins or a particular one. This is the same value as
-     * set by {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)}
+     * password for all admins of this user and its profiles or a particular one.
+     * This is the same value as set by
+     * {#link {@link #setPasswordMinimumNonLetter(ComponentName, int)}
      * and only applies when the password quality is
      * {@link #PASSWORD_QUALITY_COMPLEX}.
      *
@@ -868,9 +872,10 @@
 
     /**
      * Get the current password expiration time for the given admin or an aggregate of
-     * all admins if admin is null. If the password is expired, this will return the time since
-     * the password expired as a negative number.  If admin is null, then a composite of all
-     * expiration timeouts is returned - which will be the minimum of all timeouts.
+     * all admins of this user and its profiles if admin is null. If the password is
+     * expired, this will return the time since the password expired as a negative number.
+     * If admin is null, then a composite of all expiration timeouts is returned
+     * - which will be the minimum of all timeouts.
      *
      * @param admin The name of the admin component to check, or null to aggregate all admins.
      * @return The password expiration time, in ms.
@@ -887,8 +892,8 @@
     }
 
     /**
-     * Retrieve the current password history length for all admins
-     * or a particular one.
+     * Retrieve the current password history length for all admins of this
+     * user and its profiles or a particular one.
      * @param admin The name of the admin component to check, or null to aggregate
      * all admins.
      * @return The length of the password history
@@ -923,14 +928,13 @@
     /**
      * Determine whether the current password the user has set is sufficient
      * to meet the policy requirements (quality, minimum length) that have been
-     * requested.
+     * requested by the admins of this user and its profiles.
      *
      * <p>The calling device admin must have requested
      * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
      * this method; if it has not, a security exception will be thrown.
      *
-     * @return Returns true if the password meets the current requirements,
-     * else false.
+     * @return Returns true if the password meets the current requirements, else false.
      */
     public boolean isActivePasswordSufficient() {
         if (mService != null) {
@@ -993,7 +997,7 @@
 
     /**
      * Retrieve the current maximum number of login attempts that are allowed
-     * before the device wipes itself, for all admins
+     * before the device wipes itself, for all admins of this user and its profiles
      * or a particular one.
      * @param admin The name of the admin component to check, or null to aggregate
      * all admins.
@@ -1037,6 +1041,8 @@
      * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
      * this method; if it has not, a security exception will be thrown.
      *
+     * Can not be called from a managed profile.
+     *
      * @param password The new password for the user.
      * @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}.
      * @return Returns true if the password was applied, or false if it is
@@ -1077,8 +1083,8 @@
     }
 
     /**
-     * Retrieve the current maximum time to unlock for all admins
-     * or a particular one.
+     * Retrieve the current maximum time to unlock for all admins of this user
+     * and its profiles or a particular one.
      * @param admin The name of the admin component to check, or null to aggregate
      * all admins.
      */
@@ -2125,4 +2131,51 @@
 
         return null;
     }
+
+    /**
+     * Sets which components may enter lock task mode.
+     *
+     * This function can only be called by the device owner or the profile owner.
+     * @param components The list of components allowed to enter lock task mode
+     */
+    public void setLockTaskComponents(ComponentName[] components) throws SecurityException {
+        if (mService != null) {
+            try {
+                mService.setLockTaskComponents(components);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * This function returns the list of components allowed to start the lock task mode.
+     * @hide
+     */
+    public ComponentName[] getLockTaskComponents() {
+        if (mService != null) {
+            try {
+                return mService.getLockTaskComponents();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * This function lets the caller know whether the given component is allowed to start the
+     * lock task mode.
+     * @param component The component to check
+     */
+    public boolean isLockTaskPermitted(ComponentName component) {
+        if (mService != null) {
+            try {
+                return mService.isLockTaskPermitted(component);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 0096580..03ced0f 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -129,4 +129,8 @@
 
     void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
     String[] getAccountTypesWithManagementDisabled();
+
+    void setLockTaskComponents(in ComponentName[] components);
+    ComponentName[] getLockTaskComponents();
+    boolean isLockTaskPermitted(in ComponentName component);
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 042ee28..a059e48 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2683,6 +2683,16 @@
     public static final String NETWORK_SCORE_SERVICE = "network_score";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a {@link
+     * android.app.UsageStatsManager} for interacting with the status bar.
+     *
+     * @see #getSystemService
+     * @see android.app.UsageStatsManager
+     * @hide
+     */
+    public static final String USAGE_STATS_SERVICE = "usagestats";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 52a169b..eb2c11f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -936,13 +936,21 @@
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has at least one camera pointing in
-     * some direction.
+     * some direction, or can support an external camera being connected to it.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
 
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device can support having an external camera connected to it.
+     * The external camera may not always be connected or available to applications to use.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_CAMERA_EXTERNAL = "android.hardware.camera.external";
+
+    /**
+     * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device's camera supports flash.
      */
     @SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 8437228..ed223d1 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -36,6 +36,7 @@
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.InputMethodSession;
+import android.view.inputmethod.CursorAnchorInfo;
 
 class IInputMethodSessionWrapper extends IInputMethodSession.Stub
         implements HandlerCaller.Callback {
@@ -46,6 +47,7 @@
     private static final int DO_UPDATE_EXTRACTED_TEXT = 67;
     private static final int DO_UPDATE_SELECTION = 90;
     private static final int DO_UPDATE_CURSOR = 95;
+    private static final int DO_UPDATE_CURSOR_ANCHOR_INFO = 99;
     private static final int DO_APP_PRIVATE_COMMAND = 100;
     private static final int DO_TOGGLE_SOFT_INPUT = 105;
     private static final int DO_FINISH_SESSION = 110;
@@ -108,6 +110,10 @@
                 mInputMethodSession.updateCursor((Rect)msg.obj);
                 return;
             }
+            case DO_UPDATE_CURSOR_ANCHOR_INFO: {
+                mInputMethodSession.updateCursorAnchorInfo((CursorAnchorInfo)msg.obj);
+                return;
+            }
             case DO_APP_PRIVATE_COMMAND: {
                 SomeArgs args = (SomeArgs)msg.obj;
                 mInputMethodSession.appPrivateCommand((String)args.arg1,
@@ -181,6 +187,12 @@
     }
 
     @Override
+    public void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
+        mCaller.executeOrSendMessage(
+                mCaller.obtainMessageO(DO_UPDATE_CURSOR_ANCHOR_INFO, cursorAnchorInfo));
+    }
+
+    @Override
     public void appPrivateCommand(String action, Bundle data) {
         mCaller.executeOrSendMessage(
                 mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f6438b4..4bccaf1 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -51,6 +51,7 @@
 import android.view.WindowManager.BadTokenException;
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
@@ -545,6 +546,17 @@
         public void toggleSoftInput(int showFlags, int hideFlags) {
             InputMethodService.this.onToggleSoftInput(showFlags, hideFlags);
         }
+
+        /**
+         * Call {@link InputMethodService#onUpdateCursorAnchorInfo
+         * InputMethodService.onUpdateCursorAnchorInfo()}.
+         */
+        public void updateCursorAnchorInfo(CursorAnchorInfo info) {
+            if (!isEnabled()) {
+                return;
+            }
+            InputMethodService.this.onUpdateCursorAnchorInfo(info);
+        }
     }
     
     /**
@@ -1717,6 +1729,17 @@
     }
 
     /**
+     * Called when the application has reported a new location of its text insertion point and
+     * characters in the composition string.  This is only called if explicitly requested by the
+     * input method. The default implementation does nothing.
+     * @param cursorAnchorInfo The positional information of the text insertion point and the
+     * composition string.
+     */
+    public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
+        // Intentionally empty
+    }
+
+    /**
      * Update the cursor/anthor monitor mode.
      */
     public void setCursorAnchorMonitorMode(int monitorMode) {
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 8f41e85..daf0065 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -278,7 +278,9 @@
             host = p.getHost();
             port = Integer.toString(p.getPort());
             exclList = p.getExclusionListAsString();
-            pacFileUrl = p.getPacFileUrl().toString();
+            if (p.getPacFileUrl() != null) {
+                pacFileUrl = p.getPacFileUrl().toString();
+            }
         }
         setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
     }
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index ae9796b..521f4fd 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -34,4 +34,6 @@
     AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category);
     boolean removeAidGroupForService(int userHandle, in ComponentName service, String category);
     List<ApduServiceInfo> getServices(int userHandle, in String category);
+    boolean setPreferredService(in ComponentName service);
+    boolean unsetPreferredService();
 }
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
index 2820f40..b0449224 100644
--- a/core/java/android/nfc/cardemulation/AidGroup.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -12,10 +12,15 @@
 import android.util.Log;
 
 /**
- * The AidGroup class represents a group of ISO/IEC 7816-4
- * Application Identifiers (AIDs) for a specific application
- * category, along with a description resource describing
- * the group.
+ * The AidGroup class represents a group of Application Identifiers (AIDs).
+ *
+ * <p>An instance of this object can be used with
+ * {@link CardEmulation#registerAidGroupForService(android.content.ComponentName, AidGroup)}
+ * to tell the OS which AIDs are handled by your HCE- or SE-based service.
+ *
+ * <p>The format of AIDs is defined in the ISO/IEC 7816-4 specification. This class
+ * requires the AIDs to be input as a hexadecimal string, with an even amount of
+ * hexadecimal characters, e.g. "F014811481".
  */
 public final class AidGroup implements Parcelable {
     /**
@@ -33,7 +38,7 @@
      * Creates a new AidGroup object.
      *
      * @param aids The list of AIDs present in the group
-     * @param category The category of this group
+     * @param category The category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
      */
     public AidGroup(ArrayList<String> aids, String category) {
         if (aids == null || aids.size() == 0) {
@@ -42,11 +47,12 @@
         if (aids.size() > MAX_NUM_AIDS) {
             throw new IllegalArgumentException("Too many AIDs in AID group.");
         }
-        if (!isValidCategory(category)) {
-            throw new IllegalArgumentException("Category specified is not valid.");
+        if (isValidCategory(category)) {
+            this.category = category;
+        } else {
+            this.category = CardEmulation.CATEGORY_OTHER;
         }
         this.aids = aids;
-        this.category = category;
         this.description = null;
     }
 
@@ -158,7 +164,7 @@
         }
     }
 
-    boolean isValidCategory(String category) {
+    static boolean isValidCategory(String category) {
         return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
                 CardEmulation.CATEGORY_OTHER.equals(category);
     }
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 94f35ed..f379ee8 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -290,6 +290,20 @@
         return groups;
     }
 
+    /**
+     * Returns the category to which this service has attributed the AID that is passed in,
+     * or null if we don't know this AID.
+     */
+    public String getCategoryForAid(String aid) {
+        ArrayList<AidGroup> groups = getAidGroups();
+        for (AidGroup group : groups) {
+            if (group.aids.contains(aid)) {
+                return group.category;
+            }
+        }
+        return null;
+    }
+
     public boolean hasCategory(String category) {
         return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
     }
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 41f039c..e24a22a 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.app.Activity;
 import android.app.ActivityThread;
 import android.content.ComponentName;
 import android.content.Context;
@@ -28,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
 
 import java.util.HashMap;
@@ -248,6 +250,33 @@
     }
 
     /**
+     * Returns whether the user has allowed AIDs registered in the
+     * specified category to be handled by a service that is preferred
+     * by the foreground application, instead of by a pre-configured default.
+     *
+     * Foreground applications can set such preferences using the
+     * {@link #setPreferredService(Activity, ComponentName)} method.
+     *
+     * @param category The category, e.g. {@link #CATEGORY_PAYMENT}
+     * @return whether AIDs in the category can be handled by a service
+     *         specified by the foreground app.
+     */
+    public boolean categoryAllowsForegroundPreference(String category) {
+        if (CATEGORY_PAYMENT.equals(category)) {
+            boolean preferForeground = false;
+            try {
+                preferForeground = Settings.Secure.getInt(mContext.getContentResolver(),
+                        Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
+            } catch (SettingNotFoundException e) {
+            }
+            return preferForeground;
+        } else {
+            // Allowed for all other categories
+            return true;
+        }
+    }
+
+    /**
      * Returns the service selection mode for the passed in category.
      * Valid return values are:
      * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default
@@ -269,7 +298,6 @@
                 return SELECTION_MODE_ALWAYS_ASK;
             }
         } else {
-            // All other categories are in "only ask if conflict" mode
             return SELECTION_MODE_ASK_IF_CONFLICT;
         }
     }
@@ -283,7 +311,7 @@
      * that AID group will be replaced with this one.
      *
      * <p>Note that you can only register AIDs for a service that
-     * is running under the same UID as you are. Typically
+     * is running under the same UID as the caller of this API. Typically
      * this means you need to call this from the same
      * package as the service itself, though UIDs can also
      * be shared between packages using shared UIDs.
@@ -352,7 +380,7 @@
      * method. It will *not* remove AID groups that were statically registered in
      * the manifest. If a dynamically registered AID group is removed using
      * this method, and a statically registered AID group for the same category
-     * exists in the manifest, that AID group will become active again.
+     * exists in the manifest, the static AID group will become active again.
      *
      * @param service The component name of the service
      * @param category The category of the AID group to be removed, e.g. {@link #CATEGORY_PAYMENT}
@@ -378,6 +406,96 @@
     }
 
     /**
+     * Allows a foreground application to specify which card emulation service
+     * should be preferred while a specific Activity is in the foreground.
+     *
+     * <p>The specified Activity must currently be in resumed state. A good
+     * paradigm is to call this method in your {@link Activity#onResume}, and to call
+     * {@link #unsetPreferredService(Activity)} in your {@link Activity#onPause}.
+     *
+     * <p>This method call will fail in two specific scenarios:
+     * <ul>
+     * <li> If the service registers one or more AIDs in the {@link #CATEGORY_PAYMENT}
+     * category, but the user has indicated that foreground apps are not allowed
+     * to override the default payment service.
+     * <li> If the service registers one or more AIDs in the {@link #CATEGORY_OTHER}
+     * category that are also handled by the default payment service, and the
+     * user has indicated that foreground apps are not allowed to override the
+     * default payment service.
+     * </ul>
+     *
+     * <p> Use {@link #categoryAllowsForegroundPreference(String)} to determine
+     * whether foreground apps can override the default payment service.
+     *
+     * <p>Note that this preference is not persisted by the OS, and hence must be
+     * called every time the Activity is resumed.
+     *
+     * @param activity The activity which prefers this service to be invoked
+     * @param service The service to be preferred while this activity is in the foreground
+     * @return whether the registration was successful
+     */
+    public boolean setPreferredService(Activity activity, ComponentName service) {
+        // Verify the activity is in the foreground before calling into NfcService
+        if (activity == null || service == null) {
+            throw new NullPointerException("activity or service or category is null");
+        }
+        if (!activity.isResumed()) {
+            throw new IllegalArgumentException("Activity must be resumed.");
+        }
+        try {
+            return sService.setPreferredService(service);
+        } catch (RemoteException e) {
+            // Try one more time
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return false;
+            }
+            try {
+                return sService.setPreferredService(service);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to reach CardEmulationService.");
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Unsets the preferred service for the specified Activity.
+     *
+     * <p>Note that the specified Activity must still be in resumed
+     * state at the time of this call. A good place to call this method
+     * is in your {@link Activity#onPause} implementation.
+     *
+     * @param activity The activity which the service was registered for
+     * @return true when successful
+     */
+    public boolean unsetPreferredService(Activity activity) {
+        if (activity == null) {
+            throw new NullPointerException("activity is null");
+        }
+        if (!activity.isResumed()) {
+            throw new IllegalArgumentException("Activity must be resumed.");
+        }
+        try {
+            return sService.unsetPreferredService();
+        } catch (RemoteException e) {
+            // Try one more time
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return false;
+            }
+            try {
+                return sService.unsetPreferredService();
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to reach CardEmulationService.");
+                return false;
+            }
+        }
+    }
+
+    /**
      * @hide
      */
     public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e78ce33..8b7467f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -135,7 +135,7 @@
     /**
      * Bump the version on this if the checkin format changes.
      */
-    private static final int BATTERY_STATS_CHECKIN_VERSION = 7;
+    private static final int BATTERY_STATS_CHECKIN_VERSION = 8;
     
     private static final long BYTES_PER_KB = 1024;
     private static final long BYTES_PER_MB = 1048576; // 1024^2
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 899a958..cd47099 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -36,6 +36,7 @@
     Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers(boolean excludeDying);
     List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
+    UserInfo getProfileParent(int userHandle);
     UserInfo getUserInfo(int userHandle);
     boolean isRestricted();
     void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/ParcelableParcel.aidl b/core/java/android/os/ParcelableParcel.aidl
new file mode 100644
index 0000000..61f730c
--- /dev/null
+++ b/core/java/android/os/ParcelableParcel.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+parcelable ParcelableParcel;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 84639eb..312cdbe 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -234,6 +234,38 @@
      */
     public static final String DISALLOW_CONFIG_APPS = "no_config_apps";
 
+    /**
+     * Key for user restrictions. Specifies if a user is disallowed from mounting
+     * physical external media. The default value is <code>false</code>.
+     * <p/>
+     * Type: Boolean
+     * @see #setUserRestrictions(Bundle)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
+
+    /**
+     * Key for user restrictions. Specifies if a user is disallowed from adjusting microphone
+     * volume.
+     * The default value is <code>false</code>.
+     * <p/>
+     * Type: Boolean
+     * @see #setUserRestrictions(Bundle)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
+
+    /**
+     * Key for user restrictions. Specifies if a user is disallowed from adjusting the master
+     * volume.
+     * The default value is <code>false</code>.
+     * <p/>
+     * Type: Boolean
+     * @see #setUserRestrictions(Bundle)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
+
     /** @hide */
     public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
     /** @hide */
@@ -269,7 +301,8 @@
     }
 
     /**
-     * Returns the user handle for the user that this application is running for.
+     * Returns the user handle for the user that the calling process is running on.
+     *
      * @return the user handle of the user making this call.
      * @hide
      */
@@ -585,7 +618,8 @@
     }
 
     /**
-     * Returns a list of UserHandles for profiles associated with this user, including this user.
+     * Returns a list of UserHandles for profiles associated with the user that the calling process
+     * is running on, including the user itself.
      *
      * @return A non-empty list of UserHandles associated with the calling user.
      */
@@ -606,6 +640,21 @@
     }
 
     /**
+     * Returns the parent of the profile which this method is called from
+     * or null if called from a user that is not a profile.
+     *
+     * @hide
+     */
+    public UserInfo getProfileParent(int userHandle) {
+        try {
+            return mService.getProfileParent(userHandle);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get profile parent", re);
+            return null;
+        }
+    }
+
+    /**
      * If the target user is a managed profile of the calling user or the caller
      * is itself a managed profile, then this returns a badged copy of the given
      * icon to be able to distinguish it from the original icon.
@@ -632,7 +681,7 @@
 
     private int getBadgeResIdForUser(int userHandle) {
         // Return the framework-provided badge.
-        List<UserInfo> userProfiles = getProfiles(UserHandle.myUserId());
+        List<UserInfo> userProfiles = getProfiles(getUserHandle());
         for (UserInfo user : userProfiles) {
             if (user.id == userHandle
                     && user.isManagedProfile()) {
@@ -661,7 +710,7 @@
     /**
      * Returns information for all users on this device. Requires
      * {@link android.Manifest.permission#MANAGE_USERS} permission.
-     * 
+     *
      * @param excludeDying specify if the list should exclude users being
      *            removed.
      * @return the list of users that were created.
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index e4f73cb..811751d 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -167,7 +167,7 @@
 
         /**
          * Callback notifying that a print job state changed.
-         * 
+         *
          * @param printJobId The print job id.
          */
         public void onPrintJobStateChanged(PrintJobId printJobId);
@@ -175,7 +175,7 @@
 
     /**
      * Creates a new instance.
-     * 
+     *
      * @param context The current context in which to operate.
      * @param service The backing system service.
      * @hide
@@ -207,13 +207,17 @@
 
     /**
      * Creates an instance that can access all print jobs.
-     * 
+     *
      * @param userId The user id for which to get all print jobs.
      * @return An instance if the caller has the permission to access all print
      *         jobs, null otherwise.
      * @hide
      */
     public PrintManager getGlobalPrintManagerForUser(int userId) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return null;
+        }
         return new PrintManager(mContext, mService, userId, APP_ID_ANY);
     }
 
@@ -228,11 +232,15 @@
 
     /**
      * Adds a listener for observing the state of print jobs.
-     * 
+     *
      * @param listener The listener to add.
      * @hide
      */
     public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return;
+        }
         if (mPrintJobStateChangeListeners == null) {
             mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener,
                     PrintJobStateChangeListenerWrapper>();
@@ -249,11 +257,15 @@
 
     /**
      * Removes a listener for observing the state of print jobs.
-     * 
+     *
      * @param listener The listener to remove.
      * @hide
      */
     public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return;
+        }
         if (mPrintJobStateChangeListeners == null) {
             return;
         }
@@ -275,12 +287,16 @@
 
     /**
      * Gets a print job given its id.
-     * 
+     *
      * @return The print job list.
      * @see PrintJob
      * @hide
      */
     public PrintJob getPrintJob(PrintJobId printJobId) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return null;
+        }
         try {
             PrintJobInfo printJob = mService.getPrintJobInfo(printJobId, mAppId, mUserId);
             if (printJob != null) {
@@ -294,11 +310,15 @@
 
     /**
      * Gets the print jobs for this application.
-     * 
+     *
      * @return The print job list.
      * @see PrintJob
      */
     public List<PrintJob> getPrintJobs() {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return Collections.emptyList();
+        }
         try {
             List<PrintJobInfo> printJobInfos = mService.getPrintJobInfos(mAppId, mUserId);
             if (printJobInfos == null) {
@@ -317,6 +337,10 @@
     }
 
     void cancelPrintJob(PrintJobId printJobId) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return;
+        }
         try {
             mService.cancelPrintJob(printJobId, mAppId, mUserId);
         } catch (RemoteException re) {
@@ -325,6 +349,10 @@
     }
 
     void restartPrintJob(PrintJobId printJobId) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return;
+        }
         try {
             mService.restartPrintJob(printJobId, mAppId, mUserId);
         } catch (RemoteException re) {
@@ -383,6 +411,10 @@
      */
     public PrintJob print(String printJobName, PrintDocumentAdapter documentAdapter,
             PrintAttributes attributes) {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return null;
+        }
         if (!(mContext instanceof Activity)) {
             throw new IllegalStateException("Can print only from an activity");
         }
@@ -418,11 +450,15 @@
 
     /**
      * Gets the list of enabled print services.
-     * 
+     *
      * @return The enabled service list or an empty list.
      * @hide
      */
     public List<PrintServiceInfo> getEnabledPrintServices() {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return Collections.emptyList();
+        }
         try {
             List<PrintServiceInfo> enabledServices = mService.getEnabledPrintServices(mUserId);
             if (enabledServices != null) {
@@ -436,11 +472,15 @@
 
     /**
      * Gets the list of installed print services.
-     * 
+     *
      * @return The installed service list or an empty list.
      * @hide
      */
     public List<PrintServiceInfo> getInstalledPrintServices() {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return Collections.emptyList();
+        }
         try {
             List<PrintServiceInfo> installedServices = mService.getInstalledPrintServices(mUserId);
             if (installedServices != null) {
@@ -456,6 +496,10 @@
      * @hide
      */
     public PrinterDiscoverySession createPrinterDiscoverySession() {
+        if (mService == null) {
+            Log.w(LOG_TAG, "Feature android.software.print not available");
+            return null;
+        }
         return new PrinterDiscoverySession(mService, mContext, mUserId);
     }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e0ac60b..1847b55 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2823,7 +2823,6 @@
             MOVED_TO_GLOBAL.add(Settings.Global.TETHER_SUPPORTED);
             MOVED_TO_GLOBAL.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
             MOVED_TO_GLOBAL.add(Settings.Global.USE_GOOGLE_MAIL);
-            MOVED_TO_GLOBAL.add(Settings.Global.WEB_AUTOFILL_QUERY_URL);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_COUNTRY_CODE);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_FREQUENCY_BAND);
@@ -4530,6 +4529,12 @@
         public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
 
         /**
+         * Whether NFC payment is handled by the foreground application or a default.
+         * @hide
+         */
+        public static final String NFC_PAYMENT_FOREGROUND = "nfc_payment_foreground";
+
+        /**
          * Specifies the package name currently configured to be the primary sms application
          * @hide
          */
@@ -5355,11 +5360,6 @@
         */
        public static final String USE_GOOGLE_MAIL = "use_google_mail";
 
-       /** Autofill server address (Used in WebView/browser).
-        * {@hide} */
-       public static final String WEB_AUTOFILL_QUERY_URL =
-           "web_autofill_query_url";
-
        /**
         * Whether Wifi display is enabled/disabled
         * 0=disabled. 1=enabled.
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 05e202b..2d1016a 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1685,10 +1685,6 @@
             case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
             case KeyEvent.KEYCODE_BRIGHTNESS_UP:
             case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
-            case KeyEvent.KEYCODE_DPAD_UP:
-            case KeyEvent.KEYCODE_DPAD_RIGHT:
-            case KeyEvent.KEYCODE_DPAD_DOWN:
-            case KeyEvent.KEYCODE_DPAD_LEFT:
                 return true;
         }
 
diff --git a/core/java/android/view/inputmethod/CorrectionInfo.java b/core/java/android/view/inputmethod/CorrectionInfo.java
index 1b04e49..a43dfe8 100644
--- a/core/java/android/view/inputmethod/CorrectionInfo.java
+++ b/core/java/android/view/inputmethod/CorrectionInfo.java
@@ -88,16 +88,15 @@
     /**
      * Used to make this class parcelable.
      */
-    public static final Parcelable.Creator<CorrectionInfo> CREATOR
-            = new Parcelable.Creator<CorrectionInfo>() {
-        public CorrectionInfo createFromParcel(Parcel source) {
-            return new CorrectionInfo(source);
-        }
-
-        public CorrectionInfo[] newArray(int size) {
-            return new CorrectionInfo[size];
-        }
-    };
+    public static final Parcelable.Creator<CorrectionInfo> CREATOR =
+            new Parcelable.Creator<CorrectionInfo>() {
+                public CorrectionInfo createFromParcel(Parcel source) {
+                    return new CorrectionInfo(source);
+                }
+                public CorrectionInfo[] newArray(int size) {
+                    return new CorrectionInfo[size];
+                }
+            };
 
     public int describeContents() {
         return 0;
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.aidl b/core/java/android/view/inputmethod/CursorAnchorInfo.aidl
new file mode 100644
index 0000000..2ee9edb
--- /dev/null
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable CursorAnchorInfo;
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
new file mode 100644
index 0000000..92455df
--- /dev/null
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -0,0 +1,449 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.Layout;
+import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
+
+import java.util.Objects;
+
+/**
+ * Positional information about the text insertion point and characters in the composition string.
+ *
+ * <p>This class encapsulates locations of the text insertion point and the composition string in
+ * the screen coordinates so that IMEs can render their UI components near where the text is
+ * actually inserted.</p>
+ */
+public final class CursorAnchorInfo implements Parcelable {
+    private final int mSelectionStart;
+    private final int mSelectionEnd;
+    private final int mCandidatesStart;
+    private final int mCandidatesEnd;
+
+    /**
+     * Horizontal position of the insertion marker, in the local coordinates that will be
+     * transformed with the transformation matrix when rendered on the screen. This should be
+     * calculated or compatible with {@link Layout#getPrimaryHorizontal(int)}. This can be
+     * {@code java.lang.Float.NaN} when no value is specified.
+     */
+    private final float mInsertionMarkerHorizontal;
+    /**
+     * Vertical position of the insertion marker, in the local coordinates that will be
+     * transformed with the transformation matrix when rendered on the screen. This should be
+     * calculated or compatible with {@link Layout#getLineTop(int)}. This can be
+     * {@code java.lang.Float.NaN} when no value is specified.
+     */
+    private final float mInsertionMarkerTop;
+    /**
+     * Vertical position of the insertion marker, in the local coordinates that will be
+     * transformed with the transformation matrix when rendered on the screen. This should be
+     * calculated or compatible with {@link Layout#getLineBaseline(int)}. This can be
+     * {@code java.lang.Float.NaN} when no value is specified.
+     */
+    private final float mInsertionMarkerBaseline;
+    /**
+     * Vertical position of the insertion marker, in the local coordinates that will be
+     * transformed with the transformation matrix when rendered on the screen. This should be
+     * calculated or compatible with {@link Layout#getLineBottom(int)}. This can be
+     * {@code java.lang.Float.NaN} when no value is specified.
+     */
+    private final float mInsertionMarkerBottom;
+
+    /**
+     * Container of rectangular position of characters, keyed with character index in a unit of
+     * Java chars, in the local coordinates that will be transformed with the transformation matrix
+     * when rendered on the screen.
+     */
+    private final SparseRectFArray mCharacterRects;
+
+    /**
+     * Transformation matrix that is applied to any positional information of this class to
+     * transform local coordinates into screen coordinates.
+     */
+    private final Matrix mMatrix;
+
+    public CursorAnchorInfo(final Parcel source) {
+        mSelectionStart = source.readInt();
+        mSelectionEnd = source.readInt();
+        mCandidatesStart = source.readInt();
+        mCandidatesEnd = source.readInt();
+        mInsertionMarkerHorizontal = source.readFloat();
+        mInsertionMarkerTop = source.readFloat();
+        mInsertionMarkerBaseline = source.readFloat();
+        mInsertionMarkerBottom = source.readFloat();
+        mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader());
+        mMatrix = new Matrix();
+        mMatrix.setValues(source.createFloatArray());
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mSelectionStart);
+        dest.writeInt(mSelectionEnd);
+        dest.writeInt(mCandidatesStart);
+        dest.writeInt(mCandidatesEnd);
+        dest.writeFloat(mInsertionMarkerHorizontal);
+        dest.writeFloat(mInsertionMarkerTop);
+        dest.writeFloat(mInsertionMarkerBaseline);
+        dest.writeFloat(mInsertionMarkerBottom);
+        dest.writeParcelable(mCharacterRects, flags);
+        final float[] matrixArray = new float[9];
+        mMatrix.getValues(matrixArray);
+        dest.writeFloatArray(matrixArray);
+    }
+
+    @Override
+    public int hashCode(){
+        // TODO: Improve the hash function.
+        final float floatHash = mSelectionStart + mSelectionEnd + mCandidatesStart + mCandidatesEnd
+                + mInsertionMarkerHorizontal + mInsertionMarkerTop + mInsertionMarkerBaseline
+                + mInsertionMarkerBottom;
+        int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
+        if (mCharacterRects != null) {
+            hash += mCharacterRects.hashCode();
+        }
+        hash += mMatrix.hashCode();
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj){
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof CursorAnchorInfo)) {
+            return false;
+        }
+        final CursorAnchorInfo that = (CursorAnchorInfo) obj;
+        if (hashCode() != that.hashCode()) {
+            return false;
+        }
+        if (mSelectionStart != that.mSelectionStart
+                || mSelectionEnd != that.mSelectionEnd
+                || mCandidatesStart != that.mCandidatesStart
+                || mCandidatesEnd != that.mCandidatesEnd) {
+            return false;
+        }
+        if (!Objects.equals(mCharacterRects, that.mCharacterRects)) {
+            return false;
+        }
+        if (!Objects.equals(mMatrix, that.mMatrix)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
+                + " mCandiadtes=" + mCandidatesStart + "," + mCandidatesEnd
+                + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
+                + " mInsertionMarkerTop=" + mInsertionMarkerTop
+                + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+                + " mInsertionMarkerBottom=" + mInsertionMarkerBottom
+                + " mCharacterRects=" + (mCharacterRects != null ? mCharacterRects : "null")
+                + " mMatrix=" + mMatrix
+                + "}";
+    }
+
+    /**
+     * Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
+     */
+    public static final class CursorAnchorInfoBuilder {
+        /**
+         * Sets the text range of the selection. Calling this can be skipped if there is no
+         * selection.
+         */
+        public CursorAnchorInfoBuilder setSelectionRange(final int newStart, final int newEnd) {
+            mSelectionStart = newStart;
+            mSelectionEnd = newEnd;
+            return this;
+        }
+        private int mSelectionStart = -1;
+        private int mSelectionEnd = -1;
+
+        /**
+         * Sets the text range of the composition string. Calling this can be skipped if there is
+         * no composition.
+         */
+        public CursorAnchorInfoBuilder setCandidateRange(final int start, final int end) {
+            mCandidateStart = start;
+            mCandidateEnd = end;
+            return this;
+        }
+        private int mCandidateStart = -1;
+        private int mCandidateEnd = -1;
+
+        /**
+         * Sets the location of the text insertion point (zero width cursor) as a rectangle in
+         * local coordinates. Calling this can be skipped when there is no text insertion point;
+         * however if there is an insertion point, editors must call this method.
+         * @param horizontalPosition horizontal position of the insertion marker, in the local
+         * coordinates that will be transformed with the transformation matrix when rendered on the
+         * screen. This should be calculated or compatible with
+         * {@link Layout#getPrimaryHorizontal(int)}.
+         * @param lineTop vertical position of the insertion marker, in the local coordinates that
+         * will be transformed with the transformation matrix when rendered on the screen. This
+         * should be calculated or compatible with {@link Layout#getLineTop(int)}.
+         * @param lineBaseline vertical position of the insertion marker, in the local coordinates
+         * that will be transformed with the transformation matrix when rendered on the screen. This
+         * should be calculated or compatible with {@link Layout#getLineBaseline(int)}.
+         * @param lineBottom vertical position of the insertion marker, in the local coordinates
+         * that will be transformed with the transformation matrix when rendered on the screen. This
+         * should be calculated or compatible with {@link Layout#getLineBottom(int)}.
+         */
+        public CursorAnchorInfoBuilder setInsertionMarkerLocation(
+                final float horizontalPosition, final float lineTop, final float lineBaseline,
+                final float lineBottom){
+            mInsertionMarkerHorizontal = horizontalPosition;
+            mInsertionMarkerTop = lineTop;
+            mInsertionMarkerBaseline = lineBaseline;
+            mInsertionMarkerBottom = lineBottom;
+            return this;
+        }
+        private float mInsertionMarkerHorizontal = Float.NaN;
+        private float mInsertionMarkerTop = Float.NaN;
+        private float mInsertionMarkerBaseline = Float.NaN;
+        private float mInsertionMarkerBottom = Float.NaN;
+
+        /**
+         * Adds the bounding box of the character specified with the index.
+         * <p>
+         * Editor authors should not call this method for characters that are invisible.
+         * </p>
+         *
+         * @param index index of the character in Java chars units. Must be specified in
+         * ascending order across successive calls.
+         * @param leadingEdgeX x coordinate of the leading edge of the character in local
+         * coordinates, that is, left edge for LTR text and right edge for RTL text.
+         * @param leadingEdgeY y coordinate of the leading edge of the character in local
+         * coordinates.
+         * @param trailingEdgeX x coordinate of the trailing edge of the character in local
+         * coordinates, that is, right edge for LTR text and left edge for RTL text.
+         * @param trailingEdgeY y coordinate of the trailing edge of the character in local
+         * coordinates.
+         * @throws IllegalArgumentException If the index is a negative value, or not greater than
+         * all of the previously called indices.
+         */
+        public CursorAnchorInfoBuilder addCharacterRect(final int index,
+                final float leadingEdgeX, final float leadingEdgeY, final float trailingEdgeX,
+                final float trailingEdgeY) {
+            if (index < 0) {
+                throw new IllegalArgumentException("index must not be a negative integer.");
+            }
+            if (mCharacterRectBuilder == null) {
+                mCharacterRectBuilder = new SparseRectFArrayBuilder();
+            }
+            mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
+                    trailingEdgeY);
+            return this;
+        }
+        private SparseRectFArrayBuilder mCharacterRectBuilder = null;
+
+        /**
+         * Sets the matrix that transforms local coordinates into screen coordinates.
+         * @param matrix transformation matrix from local coordinates into screen coordinates. null
+         * is interpreted as an identity matrix.
+         */
+        public CursorAnchorInfoBuilder setMatrix(final Matrix matrix) {
+            if (matrix != null) {
+                mMatrix = matrix;
+            } else {
+                mMatrix = Matrix.IDENTITY_MATRIX;
+            }
+            return this;
+        }
+        private Matrix mMatrix = Matrix.IDENTITY_MATRIX;
+
+        /**
+         * @return {@link CursorAnchorInfo} using parameters in this
+         * {@link CursorAnchorInfoBuilder}.
+         */
+        public CursorAnchorInfo build() {
+            return new CursorAnchorInfo(this);
+        }
+
+        /**
+         * Resets the internal state so that this instance can be reused to build another
+         * instance of {@link CursorAnchorInfo}.
+         */
+        public void reset() {
+            mSelectionStart = -1;
+            mSelectionEnd = -1;
+            mCandidateStart = -1;
+            mCandidateEnd = -1;
+            mInsertionMarkerHorizontal = Float.NaN;
+            mInsertionMarkerTop = Float.NaN;
+            mInsertionMarkerBaseline = Float.NaN;
+            mInsertionMarkerBottom = Float.NaN;
+            mMatrix = Matrix.IDENTITY_MATRIX;
+            if (mCharacterRectBuilder != null) {
+                mCharacterRectBuilder.reset();
+            }
+        }
+    }
+
+    private CursorAnchorInfo(final CursorAnchorInfoBuilder builder) {
+        mSelectionStart = builder.mSelectionStart;
+        mSelectionEnd = builder.mSelectionEnd;
+        mCandidatesStart = builder.mCandidateStart;
+        mCandidatesEnd = builder.mCandidateEnd;
+        mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
+        mInsertionMarkerTop = builder.mInsertionMarkerTop;
+        mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
+        mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
+        mCharacterRects = builder.mCharacterRectBuilder != null ?
+                builder.mCharacterRectBuilder.build() : null;
+        mMatrix = builder.mMatrix;
+    }
+
+    /**
+     * Returns the index where the selection starts.
+     * @return -1 if there is no selection.
+     */
+    public int getSelectionStart() {
+        return mSelectionStart;
+    }
+
+    /**
+     * Returns the index where the selection ends.
+     * @return -1 if there is no selection.
+     */
+    public int getSelectionEnd() {
+        return mSelectionEnd;
+    }
+
+    /**
+     * Returns the index where the composition starts.
+     * @return -1 if there is no composition.
+     */
+    public int getCandidatesStart() {
+        return mCandidatesStart;
+    }
+
+    /**
+     * Returns the index where the composition ends.
+     * @return -1 if there is no composition.
+     */
+    public int getCandidatesEnd() {
+        return mCandidatesEnd;
+    }
+
+    /**
+     * Returns the horizontal start of the insertion marker, in the local coordinates that will
+     * be transformed with {@link #getMatrix()} when rendered on the screen.
+     * @return x coordinate that is compatible with {@link Layout#getPrimaryHorizontal(int)}.
+     * Pay special care to RTL/LTR handling.
+     * {@code java.lang.Float.NaN} if not specified.
+     * @see Layout#getPrimaryHorizontal(int)
+     */
+    public float getInsertionMarkerHorizontal() {
+        return mInsertionMarkerHorizontal;
+    }
+    /**
+     * Returns the vertical top position of the insertion marker, in the local coordinates that
+     * will be transformed with {@link #getMatrix()} when rendered on the screen.
+     * @return y coordinate that is compatible with {@link Layout#getLineTop(int)}.
+     * {@code java.lang.Float.NaN} if not specified.
+     */
+    public float getInsertionMarkerTop() {
+        return mInsertionMarkerTop;
+    }
+    /**
+     * Returns the vertical baseline position of the insertion marker, in the local coordinates
+     * that will be transformed with {@link #getMatrix()} when rendered on the screen.
+     * @return y coordinate that is compatible with {@link Layout#getLineBaseline(int)}.
+     * {@code java.lang.Float.NaN} if not specified.
+     */
+    public float getInsertionMarkerBaseline() {
+        return mInsertionMarkerBaseline;
+    }
+    /**
+     * Returns the vertical bottom position of the insertion marker, in the local coordinates
+     * that will be transformed with {@link #getMatrix()} when rendered on the screen.
+     * @return y coordinate that is compatible with {@link Layout#getLineBottom(int)}.
+     * {@code java.lang.Float.NaN} if not specified.
+     */
+    public float getInsertionMarkerBottom() {
+        return mInsertionMarkerBottom;
+    }
+
+    /**
+     * Returns a new instance of {@link RectF} that indicates the location of the character
+     * specified with the index.
+     * <p>
+     * Note that coordinates are not necessarily contiguous or even monotonous, especially when
+     * RTL text and LTR text are mixed.
+     * </p>
+     * @param index index of the character in a Java chars.
+     * @return a new instance of {@link RectF} that represents the location of the character in
+     * local coordinates. null if the character is invisible or the application did not provide
+     * the location. Note that the {@code left} field can be greater than the {@code right} field
+     * if the character is in RTL text.
+     */
+    // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
+    // characters, and non-graphical chars.
+    public RectF getCharacterRect(final int index) {
+        if (mCharacterRects == null) {
+            return null;
+        }
+        return mCharacterRects.get(index);
+    }
+
+    /**
+     * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation
+     * matrix that is to be applied other positional data in this class.
+     * @return a new instance (copy) of the transformation matrix.
+     */
+    public Matrix getMatrix() {
+        return new Matrix(mMatrix);
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<CursorAnchorInfo> CREATOR
+            = new Parcelable.Creator<CursorAnchorInfo>() {
+        @Override
+        public CursorAnchorInfo createFromParcel(Parcel source) {
+            return new CursorAnchorInfo(source);
+        }
+
+        @Override
+        public CursorAnchorInfo[] newArray(int size) {
+            return new CursorAnchorInfo[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 0227873..e1c6f52 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -49,6 +49,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewRootImpl;
+import android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -321,6 +322,7 @@
      * The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
      */
     private final int[] mViewTopLeft = new int[2];
+    private final CursorAnchorInfoBuilder mCursorAnchorInfoBuilder = new CursorAnchorInfoBuilder();
 
     // -----------------------------------------------------------
     
@@ -1435,7 +1437,7 @@
                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
                 return;
             }
-            
+
             if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
                     || mCursorCandStart != candidatesStart
                     || mCursorCandEnd != candidatesEnd) {
@@ -1556,6 +1558,31 @@
     }
 
     /**
+     * Report positional change of the text insertion point and/or characters in the composition
+     * string.
+     */
+    public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
+        if (view == null || cursorAnchorInfo == null) {
+            return;
+        }
+        checkFocus();
+        synchronized (mH) {
+            if ((mServedView != view &&
+                    (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
+                    || mCurrentTextBoxAttribute == null || mCurMethod == null) {
+                return;
+            }
+            if (DEBUG) Log.d(TAG, "updateCursorAnchorInfo");
+
+            try {
+                mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
+            } catch (RemoteException e) {
+                Log.w(TAG, "IME died: " + mCurId, e);
+            }
+        }
+    }
+
+    /**
      * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
      * InputMethodSession.appPrivateCommand()} on the current Input Method.
      * @param view Optional View that is sending the command, or null if
diff --git a/core/java/android/view/inputmethod/InputMethodSession.java b/core/java/android/view/inputmethod/InputMethodSession.java
index 6386299..74fbbc7 100644
--- a/core/java/android/view/inputmethod/InputMethodSession.java
+++ b/core/java/android/view/inputmethod/InputMethodSession.java
@@ -165,7 +165,7 @@
     public void appPrivateCommand(String action, Bundle data);
     
     /**
-     * Toggle the soft input window. 
+     * Toggle the soft input window.
      * Applications can toggle the state of the soft input window.
      * @param showFlags Provides additional operating flags.  May be
      * 0 or have the {@link InputMethodManager#SHOW_IMPLICIT},
@@ -175,4 +175,14 @@
      * {@link  InputMethodManager#HIDE_NOT_ALWAYS} bit set.
      */
     public void toggleSoftInput(int showFlags, int hideFlags);
+
+    /**
+     * This method is called when the cursor and/or the character position relevant to text input
+     * is changed on the screen.  This is not called by default.  It will only be reported if
+     * requested by the input method.
+     *
+     * @param cursorAnchorInfo Positional information relevant to text input, such as text
+     * insertion point and composition string.
+     */
+    public void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo);
 }
diff --git a/core/java/android/view/inputmethod/SparseRectFArray.java b/core/java/android/view/inputmethod/SparseRectFArray.java
new file mode 100644
index 0000000..40cade7
--- /dev/null
+++ b/core/java/android/view/inputmethod/SparseRectFArray.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.graphics.RectF;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * An implementation of SparseArray specialized for {@link android.graphics.RectF}.
+ * <p>
+ * As this is a sparse array, it represents an array of {@link RectF} most of which are null. This
+ * class could be in some other packages like android.graphics or android.util but currently
+ * belong to android.view.inputmethod because this class is hidden and used only in input method
+ * framework.
+ * </p>
+ * @hide
+ */
+public final class SparseRectFArray implements Parcelable {
+    /**
+     * The keys, in ascending order, of those {@link RectF} that are not null. For example,
+     * {@code [null, null, null, Rect1, null, Rect2]} would be represented by {@code [3,5]}.
+     * @see #mCoordinates
+     */
+    private final int[] mKeys;
+
+    /**
+     * Stores coordinates of the rectangles, in the order of
+     * {@code rects[mKeys[0]].left}, {@code rects[mKeys[0]].top},
+     * {@code rects[mKeys[0]].right}, {@code rects[mKeys[0]].bottom},
+     * {@code rects[mKeys[1]].left}, {@code rects[mKeys[1]].top},
+     * {@code rects[mKeys[1]].right}, {@code rects[mKeys[1]].bottom},
+     * {@code rects[mKeys[2]].left}, {@code rects[mKeys[2]].top}, ....
+     */
+    private final float[] mCoordinates;
+
+    public SparseRectFArray(final Parcel source) {
+        mKeys = source.createIntArray();
+        mCoordinates = source.createFloatArray();
+    }
+
+    /**
+     * Used to package this object into a {@link Parcel}.
+     *
+     * @param dest The {@link Parcel} to be written.
+     * @param flags The flags used for parceling.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeIntArray(mKeys);
+        dest.writeFloatArray(mCoordinates);
+    }
+
+    @Override
+    public int hashCode() {
+        // TODO: Improve the hash function.
+        if (mKeys == null || mKeys.length == 0) {
+            return 0;
+        }
+        int hash = mKeys.length;
+        // For performance reasons, only the first rectangle is used for the hash code now.
+        for (int i = 0; i < 4; i++) {
+            hash *= 31;
+            hash += mCoordinates[i];
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj){
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof SparseRectFArray)) {
+            return false;
+        }
+        final SparseRectFArray that = (SparseRectFArray) obj;
+
+        return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates);
+    }
+
+    @Override
+    public String toString() {
+        if (mKeys == null || mCoordinates == null) {
+            return "SparseRectFArray{}";
+        }
+        final StringBuilder sb = new StringBuilder();
+        sb.append("SparseRectFArray{");
+        for (int i = 0; i < mKeys.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            final int baseIndex = i * 4;
+            sb.append(mKeys[i]);
+            sb.append(":[");
+            sb.append(mCoordinates[baseIndex + 0]);
+            sb.append(",");
+            sb.append(mCoordinates[baseIndex + 1]);
+            sb.append("],[");
+            sb.append(mCoordinates[baseIndex + 2]);
+            sb.append(",");
+            sb.append(mCoordinates[baseIndex + 3]);
+            sb.append("]");
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /**
+     * Builder for {@link SparseRectFArray}. This class is not designed to be thread-safe.
+     * @hide
+     */
+    public static final class SparseRectFArrayBuilder {
+        /**
+         * Throws {@link IllegalArgumentException} to make sure that this class is correctly used.
+         * @param key key to be checked.
+         */
+        private void checkIndex(final int key) {
+            if (mCount == 0) {
+                return;
+            }
+            if (mKeys[mCount - 1] >= key) {
+                throw new IllegalArgumentException("key must be greater than all existing keys.");
+            }
+        }
+
+        /**
+         * Extends the internal array if necessary.
+         */
+        private void ensureBufferSize() {
+            if (mKeys == null) {
+                mKeys = new int[INITIAL_SIZE];
+            }
+            if (mCoordinates == null) {
+                mCoordinates = new float[INITIAL_SIZE * 4];
+            }
+            final int requiredIndexArraySize = mCount + 1;
+            if (mKeys.length <= requiredIndexArraySize) {
+                final int[] newArray = new int[requiredIndexArraySize * 2];
+                System.arraycopy(mKeys, 0, newArray, 0, mCount);
+                mKeys = newArray;
+            }
+            final int requiredCoordinatesArraySize = (mCount + 1) * 4;
+            if (mCoordinates.length <= requiredCoordinatesArraySize) {
+                final float[] newArray = new float[requiredCoordinatesArraySize * 2];
+                System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4);
+                mCoordinates = newArray;
+            }
+        }
+
+        /**
+         * Puts the rectangle with an integer key.
+         * @param key the key to be associated with the rectangle. It must be greater than all
+         * existing keys that have been previously specified.
+         * @param left left of the rectangle.
+         * @param top top of the rectangle.
+         * @param right right of the rectangle.
+         * @param bottom bottom of the rectangle.
+         * @return the receiver object itself for chaining method calls.
+         * @throws IllegalArgumentException If the index is not greater than all of existing keys.
+         */
+        public SparseRectFArrayBuilder append(final int key,
+                final float left, final float top, final float right, final float bottom) {
+            checkIndex(key);
+            ensureBufferSize();
+            final int baseCoordinatesIndex = mCount * 4;
+            mCoordinates[baseCoordinatesIndex + 0] = left;
+            mCoordinates[baseCoordinatesIndex + 1] = top;
+            mCoordinates[baseCoordinatesIndex + 2] = right;
+            mCoordinates[baseCoordinatesIndex + 3] = bottom;
+            mKeys[mCount] = key;
+            ++mCount;
+            return this;
+        }
+        private int mCount = 0;
+        private int[] mKeys = null;
+        private float[] mCoordinates = null;
+        private static int INITIAL_SIZE = 16;
+
+        /**
+         * @return {@link SparseRectFArray} using parameters in this {@link SparseRectFArray}.
+         */
+        public SparseRectFArray build() {
+            return new SparseRectFArray(this);
+        }
+
+        public void reset() {
+            if (mCount == 0) {
+                mKeys = null;
+                mCoordinates = null;
+            }
+            mCount = 0;
+        }
+    }
+
+    private SparseRectFArray(final SparseRectFArrayBuilder builder) {
+        if (builder.mCount == 0) {
+            mKeys = null;
+            mCoordinates = null;
+        } else {
+            mKeys = new int[builder.mCount];
+            mCoordinates = new float[builder.mCount * 4];
+            System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount);
+            System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4);
+        }
+    }
+
+    public RectF get(final int index) {
+        if (mKeys == null) {
+            return null;
+        }
+        if (index < 0) {
+            return null;
+        }
+        final int arrayIndex = Arrays.binarySearch(mKeys, index);
+        if (arrayIndex < 0) {
+            return null;
+        }
+        final int baseCoordIndex = arrayIndex * 4;
+        return new RectF(mCoordinates[baseCoordIndex],
+                mCoordinates[baseCoordIndex + 1],
+                mCoordinates[baseCoordIndex + 2],
+                mCoordinates[baseCoordIndex + 3]);
+    }
+
+    /**
+     * Used to make this class parcelable.
+     */
+    public static final Parcelable.Creator<SparseRectFArray> CREATOR =
+            new Parcelable.Creator<SparseRectFArray>() {
+                @Override
+                public SparseRectFArray createFromParcel(Parcel source) {
+                    return new SparseRectFArray(source);
+                }
+                @Override
+                public SparseRectFArray[] newArray(int size) {
+                    return new SparseRectFArray[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+}
+
diff --git a/core/java/android/webkit/EventLogTags.logtags b/core/java/android/webkit/EventLogTags.logtags
index b0b5493..a90aebd 100644
--- a/core/java/android/webkit/EventLogTags.logtags
+++ b/core/java/android/webkit/EventLogTags.logtags
@@ -8,3 +8,4 @@
 # 70103- used by the browser app itself
 
 70150 browser_snap_center
+70151 exp_det_attempt_to_call_object_getclass (app_signature|3)
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
index 3e33498..fa760b7 100644
--- a/core/java/android/webkit/PermissionRequest.java
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -28,6 +28,7 @@
 public interface PermissionRequest {
     /**
      * Resource belongs to geolocation service.
+     * @hide - see b/14668406
      */
     public final static long RESOURCE_GEOLOCATION = 1 << 0;
     /**
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index e4ad354..99a7886 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -276,8 +276,13 @@
      * @see Intent#ACTION_SEND_MULTIPLE
      */
     public void setShareIntent(Intent shareIntent) {
-        shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+        if (shareIntent != null) {
+            final String action = shareIntent.getAction();
+            if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+                shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
                         Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+            }
+        }
         ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
             mShareHistoryFileName);
         dataModel.setIntent(shareIntent);
@@ -294,8 +299,12 @@
             final int itemId = item.getItemId();
             Intent launchIntent = dataModel.chooseActivity(itemId);
             if (launchIntent != null) {
-                launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
-                        Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+                final String action = launchIntent.getAction();
+                if (Intent.ACTION_SEND.equals(action) ||
+                        Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+                    launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+                            Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+                }
                 mContext.startActivity(launchIntent);
             }
             return true;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 1eda373..106ac0b 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -33,6 +33,14 @@
             return;
         }
         Intent target = (Intent)targetParcelable;
+        if (target != null) {
+            final String action = target.getAction();
+            if (Intent.ACTION_SEND.equals(action) ||
+                    Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+                target.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+                        Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+            }
+        }
         CharSequence title = intent.getCharSequenceExtra(Intent.EXTRA_TITLE);
         if (title == null) {
             title = getResources().getText(com.android.internal.R.string.chooseActivity);
@@ -43,13 +51,19 @@
             initialIntents = new Intent[pa.length];
             for (int i=0; i<pa.length; i++) {
                 if (!(pa[i] instanceof Intent)) {
-                    Log.w("ChooserActivity", "Initial intent #" + i
-                            + " not an Intent: " + pa[i]);
+                    Log.w("ChooserActivity", "Initial intent #" + i + " not an Intent: " + pa[i]);
                     finish();
                     super.onCreate(null);
                     return;
                 }
-                initialIntents[i] = (Intent)pa[i];
+                final Intent in = (Intent) pa[i];
+                final String action = in.getAction();
+                if (Intent.ACTION_SEND.equals(action) ||
+                        Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+                    in.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+                            Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
+                }
+                initialIntents[i] = in;
             }
         }
         super.onCreate(savedInstanceState, target, title, initialIntents, null, false);
diff --git a/core/java/com/android/internal/app/IUsageStats.aidl b/core/java/com/android/internal/app/IUsageStats.aidl
index 1ea7409..7e7f0e1 100644
--- a/core/java/com/android/internal/app/IUsageStats.aidl
+++ b/core/java/com/android/internal/app/IUsageStats.aidl
@@ -16,13 +16,17 @@
 
 package com.android.internal.app;
 
+import android.app.UsageStats;
 import android.content.ComponentName;
-import com.android.internal.os.PkgUsageStats;
+import android.content.res.Configuration;
+import android.os.ParcelableParcel;
 
 interface IUsageStats {
     void noteResumeComponent(in ComponentName componentName);
     void notePauseComponent(in ComponentName componentName);
     void noteLaunchTime(in ComponentName componentName, int millis);
-    PkgUsageStats getPkgUsageStats(in ComponentName componentName);
-    PkgUsageStats[] getAllPkgUsageStats();
+    void noteStartConfig(in Configuration config);
+    UsageStats.PackageStats getPkgUsageStats(String callingPkg, in ComponentName componentName);
+    UsageStats.PackageStats[] getAllPkgUsageStats(String callingPkg);
+    ParcelableParcel getCurrentStats(String callingPkg);
 }
diff --git a/core/java/com/android/internal/os/PkgUsageStats.aidl b/core/java/com/android/internal/os/PkgUsageStats.aidl
deleted file mode 100644
index 8305271..0000000
--- a/core/java/com/android/internal/os/PkgUsageStats.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/content/Intent.aidl
-**
-** Copyright 2007, 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.internal.os;
-
-parcelable PkgUsageStats;
diff --git a/core/java/com/android/internal/os/PkgUsageStats.java b/core/java/com/android/internal/os/PkgUsageStats.java
deleted file mode 100644
index 8c2c405..0000000
--- a/core/java/com/android/internal/os/PkgUsageStats.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2009 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.internal.os;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * implementation of PkgUsageStats associated with an
- * application package.
- *  @hide
- */
-public class PkgUsageStats implements Parcelable {
-    public String packageName;
-    public int launchCount;
-    public long usageTime;
-    public Map<String, Long> componentResumeTimes;
-    
-    public static final Parcelable.Creator<PkgUsageStats> CREATOR
-    = new Parcelable.Creator<PkgUsageStats>() {
-        public PkgUsageStats createFromParcel(Parcel in) {
-            return new PkgUsageStats(in);
-        }
-
-        public PkgUsageStats[] newArray(int size) {
-            return new PkgUsageStats[size];
-        }
-    };
-    
-    public String toString() {
-        return "PkgUsageStats{"
-        + Integer.toHexString(System.identityHashCode(this))
-        + " " + packageName + "}";
-    }
-    
-    public PkgUsageStats(String pkgName, int count, long time, Map<String, Long> lastResumeTimes) {
-        packageName = pkgName;
-        launchCount = count;
-        usageTime = time;
-        componentResumeTimes = new HashMap<String, Long>(lastResumeTimes);
-    }
-    
-    public PkgUsageStats(Parcel source) {
-        packageName = source.readString();
-        launchCount = source.readInt();
-        usageTime = source.readLong();
-        final int N = source.readInt();
-        componentResumeTimes = new HashMap<String, Long>(N);
-        for (int i = 0; i < N; i++) {
-            String component = source.readString();
-            long lastResumeTime = source.readLong();
-            componentResumeTimes.put(component, lastResumeTime);
-        }
-    }
-    
-    public PkgUsageStats(PkgUsageStats pStats) {
-        packageName = pStats.packageName;
-        launchCount = pStats.launchCount;
-        usageTime = pStats.usageTime;
-        componentResumeTimes = new HashMap<String, Long>(pStats.componentResumeTimes);
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel dest, int parcelableFlags) {
-        dest.writeString(packageName);
-        dest.writeInt(launchCount);
-        dest.writeLong(usageTime);
-        dest.writeInt(componentResumeTimes.size());
-        for (Map.Entry<String, Long> ent : componentResumeTimes.entrySet()) {
-            dest.writeString(ent.getKey());
-            dest.writeLong(ent.getValue());
-        }
-    }
-}
diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl
index 90210ce..367b713 100644
--- a/core/java/com/android/internal/view/IInputMethodSession.aidl
+++ b/core/java/com/android/internal/view/IInputMethodSession.aidl
@@ -21,6 +21,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.ExtractedText;
 
 /**
@@ -47,4 +48,6 @@
     void toggleSoftInput(int showFlags, int hideFlags);
 
     void finishSession();
+
+    void updateCursorAnchorInfo(in CursorAnchorInfo cursorAnchorInfo);
 }
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 674d084..bcfa036 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -35,7 +35,7 @@
 public class SwipeDismissLayout extends FrameLayout {
     private static final String TAG = "SwipeDismissLayout";
 
-    private static final float DISMISS_MIN_PROGRESS = 0.6f;
+    private static final float DISMISS_MIN_DRAG_WIDTH_RATIO = .4f;
 
     public interface OnDismissedListener {
         void onDismissed(SwipeDismissLayout layout);
@@ -244,7 +244,11 @@
         if (!mSwiping) {
             float deltaX = ev.getRawX() - mDownX;
             float deltaY = ev.getRawY() - mDownY;
-            mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
+            if ((deltaX * deltaX) + (deltaY * deltaY) > mSlop * mSlop) {
+                mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
+            } else {
+                mSwiping = false;
+            }
         }
     }
 
@@ -254,12 +258,7 @@
             mVelocityTracker.addMovement(ev);
             mVelocityTracker.computeCurrentVelocity(1000);
 
-            float velocityX = mVelocityTracker.getXVelocity();
-            float absVelocityX = Math.abs(velocityX);
-            float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
-
-            if (deltaX > (getWidth() * DISMISS_MIN_PROGRESS) &&
-                    absVelocityX < mMinFlingVelocity && 
+            if (deltaX > (getWidth() * DISMISS_MIN_DRAG_WIDTH_RATIO) &&
                     ev.getRawX() >= mLastX) {
                 mDismissed = true;
             }
@@ -267,7 +266,7 @@
         // Check if the user tried to undo this.
         if (mDismissed && mSwiping) {
             // Check if the user's finger is actually back
-            if (deltaX < (getWidth() * DISMISS_MIN_PROGRESS)) {
+            if (deltaX < (getWidth() * DISMISS_MIN_DRAG_WIDTH_RATIO)) {
                 mDismissed = false;
             }
         }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 8bd2e4f..51e2871 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -241,8 +241,6 @@
 # <bionic_tls.h> in com_google_android_gles_jni_GLImpl.cpp
 LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private
 
-LOCAL_LDLIBS += -lpthread -ldl
-
 ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
 	LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
 endif
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index da752752..463a0a8 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -526,12 +526,15 @@
         switch (format) {
 
         default:
-            // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT
-            // and AUDIO_FORMAT_PCM_8_BIT, due to the limited set of values for audioFormat.
+            // TODO Currently the only possible values for format are AUDIO_FORMAT_PCM_16_BIT,
+            // AUDIO_FORMAT_PCM_8_BIT, and AUDIO_FORMAT_PCM_FLOAT,
+            // due to the limited set of values for audioFormat.
             // The next section of the switch will probably work for more formats, but it has only
-            // been tested for AUDIO_FORMAT_PCM_16_BIT, so that's why the "default" case fails.
+            // been tested for AUDIO_FORMAT_PCM_16_BIT and AUDIO_FORMAT_PCM_FLOAT,
+            // so that's why the "default" case fails.
             break;
 
+        case AUDIO_FORMAT_PCM_FLOAT:
         case AUDIO_FORMAT_PCM_16_BIT: {
             // writing to shared memory, check for capacity
             if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
@@ -679,6 +682,44 @@
 
 
 // ----------------------------------------------------------------------------
+static jint android_media_AudioTrack_write_float(JNIEnv *env,  jobject thiz,
+                                                  jfloatArray javaAudioData,
+                                                  jint offsetInFloats, jint sizeInFloats,
+                                                  jint javaAudioFormat,
+                                                  jboolean isWriteBlocking) {
+
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+    if (lpTrack == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioTrack pointer for write()");
+        return 0;
+    }
+
+    jfloat* cAudioData = NULL;
+    if (javaAudioData) {
+        cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL);
+        if (cAudioData == NULL) {
+            ALOGE("Error retrieving source of audio data to play, can't play");
+            return 0; // out of memory or no data to load
+        }
+    } else {
+        ALOGE("NULL java array of audio data to play, can't play");
+        return 0;
+    }
+    jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
+                                offsetInFloats * sizeof(float), sizeInFloats * sizeof(float),
+                                isWriteBlocking == JNI_TRUE /* blocking */);
+    env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0);
+
+    if (written > 0) {
+        written /= sizeof(float);
+    }
+
+    return written;
+}
+
+
+// ----------------------------------------------------------------------------
 static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env,  jobject thiz) {
     sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
     if (lpTrack == NULL) {
@@ -963,6 +1004,7 @@
                              "(Ljava/lang/Object;IIIZ)I",
                                          (void *)android_media_AudioTrack_write_native_bytes},
     {"native_write_short",   "([SIII)I", (void *)android_media_AudioTrack_write_short},
+    {"native_write_float",   "([FIIIZ)I",(void *)android_media_AudioTrack_write_float},
     {"native_setVolume",     "(FF)V",    (void *)android_media_AudioTrack_set_volume},
     {"native_get_native_frame_count",
                              "()I",      (void *)android_media_AudioTrack_get_native_frame_count},
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index 9029ba5..e0f4f6d 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -21,4 +21,4 @@
   $COMMAND
 fi
 
-adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest,android.os.CursorAnchorInfoTest,android.os.SparseRectFArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
new file mode 100644
index 0000000..59a6314
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.CursorAnchorInfo.CursorAnchorInfoBuilder;
+
+public class CursorAnchorInfoTest extends InstrumentationTestCase {
+    // null represents a character that is invisible, for example because it's overlapped by some
+    // other UI elements.
+    private static final RectF[] MANY_RECTS = new RectF[] {
+            null,
+            new RectF(102.0f, 202.0f, 302.0f, 402.0f),
+            new RectF(103.0f, 203.0f, 303.0f, 403.0f),
+            new RectF(104.0f, 204.0f, 304.0f, 404.0f),
+            new RectF(105.0f, 205.0f, 305.0f, 405.0f),
+            new RectF(106.0f, 206.0f, 306.0f, 406.0f),
+            null,
+            new RectF(108.0f, 208.0f, 308.0f, 408.0f),
+            new RectF(109.0f, 209.0f, 309.0f, 409.0f),
+            new RectF(110.0f, 210.0f, 310.0f, 410.0f),
+            new RectF(111.0f, 211.0f, 311.0f, 411.0f),
+            new RectF(112.0f, 212.0f, 312.0f, 412.0f),
+            new RectF(113.0f, 213.0f, 313.0f, 413.0f),
+            new RectF(114.0f, 214.0f, 314.0f, 414.0f),
+            new RectF(115.0f, 215.0f, 315.0f, 415.0f),
+            new RectF(116.0f, 216.0f, 316.0f, 416.0f),
+            new RectF(117.0f, 217.0f, 317.0f, 417.0f),
+            null,
+            null,
+    };
+
+    @SmallTest
+    public void testBuilder() throws Exception {
+        final int SELECTION_START = 30;
+        final int SELECTION_END = 40;
+        final int CANDIDATES_START = 32;
+        final int CANDIDATES_END = 33;
+        final float INSERTION_MARKER_HORIZONTAL = 10.5f;
+        final float INSERTION_MARKER_TOP = 100.1f;
+        final float INSERTION_MARKER_BASELINE = 110.4f;
+        final float INSERTION_MARKER_BOTOM = 111.0f;
+        Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
+        TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
+
+        final CursorAnchorInfoBuilder builder = new CursorAnchorInfoBuilder();
+        builder.setSelectionRange(SELECTION_START, SELECTION_END)
+                .setCandidateRange(CANDIDATES_START, CANDIDATES_END)
+                .setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
+                        INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM)
+                .setMatrix(TRANSFORM_MATRIX);
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            if (rect != null) {
+                builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom);
+            }
+        }
+
+        final CursorAnchorInfo info = builder.build();
+        assertEquals(SELECTION_START, info.getSelectionStart());
+        assertEquals(SELECTION_END, info.getSelectionEnd());
+        assertEquals(CANDIDATES_START, info.getCandidatesStart());
+        assertEquals(CANDIDATES_END, info.getCandidatesEnd());
+        assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal());
+        assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop());
+        assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline());
+        assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom());
+        assertEquals(TRANSFORM_MATRIX, info.getMatrix());
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            assertEquals(rect, info.getCharacterRect(i));
+        }
+
+        // Make sure that the builder can reproduce the same object.
+        final CursorAnchorInfo info2 = builder.build();
+        assertEquals(SELECTION_START, info2.getSelectionStart());
+        assertEquals(SELECTION_END, info2.getSelectionEnd());
+        assertEquals(CANDIDATES_START, info2.getCandidatesStart());
+        assertEquals(CANDIDATES_END, info2.getCandidatesEnd());
+        assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal());
+        assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop());
+        assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline());
+        assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom());
+        assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            assertEquals(rect, info2.getCharacterRect(i));
+        }
+        assertEquals(info, info2);
+        assertEquals(info.hashCode(), info2.hashCode());
+
+        // Make sure that object can be marshalled via {@link Parsel}.
+        final CursorAnchorInfo info3 = cloneViaParcel(info2);
+        assertEquals(SELECTION_START, info3.getSelectionStart());
+        assertEquals(SELECTION_END, info3.getSelectionEnd());
+        assertEquals(CANDIDATES_START, info3.getCandidatesStart());
+        assertEquals(CANDIDATES_END, info3.getCandidatesEnd());
+        assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal());
+        assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop());
+        assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline());
+        assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom());
+        assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            assertEquals(rect, info3.getCharacterRect(i));
+        }
+        assertEquals(info.hashCode(), info3.hashCode());
+
+        builder.reset();
+        final CursorAnchorInfo uninitializedInfo = builder.build();
+        assertEquals(-1, uninitializedInfo.getSelectionStart());
+        assertEquals(-1, uninitializedInfo.getSelectionEnd());
+        assertEquals(-1, uninitializedInfo.getCandidatesStart());
+        assertEquals(-1, uninitializedInfo.getCandidatesEnd());
+        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal());
+        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop());
+        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline());
+        assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBottom());
+        assertEquals(Matrix.IDENTITY_MATRIX, uninitializedInfo.getMatrix());
+    }
+
+    @SmallTest
+    public void testBuilderAdd() throws Exception {
+        // A negative index should be rejected.
+        try {
+            new CursorAnchorInfoBuilder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f);
+        } catch (IllegalArgumentException ex) {
+            assertTrue(true);
+        }
+    }
+
+    private static CursorAnchorInfo cloneViaParcel(final CursorAnchorInfo src) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            src.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            return new CursorAnchorInfo(parcel);
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+    }
+}
+
diff --git a/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java b/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java
new file mode 100644
index 0000000..fae7230
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/SparseRectFArrayTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.graphics.RectF;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.SparseRectFArray;
+import android.view.inputmethod.SparseRectFArray.SparseRectFArrayBuilder;
+
+import java.util.Objects;
+
+public class SparseRectFArrayTest extends InstrumentationTestCase {
+    // A test data for {@link SparseRectFArray}. null represents the gap of indices.
+    private static final RectF[] MANY_RECTS = new RectF[] {
+            null,
+            new RectF(102.0f, 202.0f, 302.0f, 402.0f),
+            new RectF(103.0f, 203.0f, 303.0f, 403.0f),
+            new RectF(104.0f, 204.0f, 304.0f, 404.0f),
+            new RectF(105.0f, 205.0f, 305.0f, 405.0f),
+            new RectF(106.0f, 206.0f, 306.0f, 406.0f),
+            null,
+            new RectF(108.0f, 208.0f, 308.0f, 408.0f),
+            new RectF(109.0f, 209.0f, 309.0f, 409.0f),
+            new RectF(110.0f, 210.0f, 310.0f, 410.0f),
+            new RectF(111.0f, 211.0f, 311.0f, 411.0f),
+            new RectF(112.0f, 212.0f, 312.0f, 412.0f),
+            new RectF(113.0f, 213.0f, 313.0f, 413.0f),
+            new RectF(114.0f, 214.0f, 314.0f, 414.0f),
+            new RectF(115.0f, 215.0f, 315.0f, 415.0f),
+            new RectF(116.0f, 216.0f, 316.0f, 416.0f),
+            new RectF(117.0f, 217.0f, 317.0f, 417.0f),
+            null,
+            null,
+            new RectF(118.0f, 218.0f, 318.0f, 418.0f),
+    };
+
+    @SmallTest
+    public void testBuilder() throws Exception {
+        final RectF TEMP_RECT = new RectF(10.0f, 20.0f, 30.0f, 40.0f);
+
+        final SparseRectFArrayBuilder builder = new SparseRectFArrayBuilder();
+        builder.append(100, TEMP_RECT.left, TEMP_RECT.top, TEMP_RECT.right, TEMP_RECT.bottom);
+        assertNull(builder.build().get(-1));
+        assertNull(builder.build().get(0));
+        assertNull(builder.build().get(99));
+        assertEquals(TEMP_RECT, builder.build().get(100));
+        assertNull(builder.build().get(101));
+
+        // Test if {@link SparseRectFArrayBuilder#reset} resets its internal state.
+        builder.reset();
+        assertNull(builder.build().get(100));
+
+        builder.reset();
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            if (rect != null) {
+                builder.append(i, rect.left, rect.top, rect.right, rect.bottom);
+            }
+        }
+        final SparseRectFArray array = builder.build();
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            assertEquals(rect, array.get(i));
+        }
+
+        // Make sure the builder reproduces an equivalent object.
+        final SparseRectFArray array2 = builder.build();
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            assertEquals(rect, array2.get(i));
+        }
+        assertEqualRects(array, array2);
+
+        // Make sure the instance can be marshaled via {@link Parcel}.
+        final SparseRectFArray array3 = cloneViaParcel(array);
+        for (int i = 0; i < MANY_RECTS.length; i++) {
+            final RectF rect = MANY_RECTS[i];
+            assertEquals(rect, array3.get(i));
+        }
+        assertEqualRects(array, array3);
+
+        // Make sure the builder can be reset.
+        builder.reset();
+        assertNull(builder.build().get(0));
+    }
+
+    @SmallTest
+    public void testEquality() throws Exception {
+        // Empty array should be equal.
+        assertEqualRects(new SparseRectFArrayBuilder().build(),
+                new SparseRectFArrayBuilder().build());
+
+        assertEqualRects(
+                new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+                new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+                new SparseRectFArrayBuilder().append(100, 2.0f, 2.0f, 3.0f, 4.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder().append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+                new SparseRectFArrayBuilder().append(101, 1.0f, 2.0f, 3.0f, 4.0f).build());
+
+        assertEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f).build(),
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 1.0f, 0.0f, 0.0f, 0.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 1.0f, 0.0f, 0.0f, 0.0f).build(),
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(101, 0.0f, 0.0f, 0.0f, 0.0f).build(),
+                new SparseRectFArrayBuilder()
+                        .append(100, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(102, 0.0f, 0.0f, 0.0f, 0.0f).build());
+
+        assertEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .build(),
+                new SparseRectFArrayBuilder()
+                        .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .build());
+
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .build(),
+                new SparseRectFArrayBuilder()
+                        .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .build());
+        assertNotEqualRects(
+                new SparseRectFArrayBuilder()
+                        .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(1000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .build(),
+                new SparseRectFArrayBuilder()
+                        .append(1, 1.0f, 2.0f, 3.0f, 4.0f)
+                        .append(1000, 1.0f, 0.0f, 0.0f, 0.0f)
+                        .append(100000000, 0.0f, 0.0f, 0.0f, 0.0f)
+                        .build());
+    }
+
+    @SmallTest
+    public void testBuilderAppend() throws Exception {
+        // Key should be appended in ascending order.
+        try {
+            new SparseRectFArrayBuilder().append(10, 0, 0, 0, 0).append(0, 1, 2, 3, 4);
+        } catch (IllegalArgumentException ex) {
+            assertTrue(true);
+        }
+
+        try {
+            new SparseRectFArrayBuilder().append(10, 0, 0, 0, 0).append(10, 1, 2, 3, 4);
+        } catch (IllegalArgumentException ex) {
+            assertTrue(true);
+        }
+    }
+
+    private static void assertEqualRects(SparseRectFArray a, SparseRectFArray b) {
+        assertEquals(a, b);
+        if (a != null && b != null) {
+            assertEquals(a.hashCode(), b.hashCode());
+        }
+    }
+
+    private static void assertNotEqualRects(SparseRectFArray a, SparseRectFArray b) {
+        assertFalse(Objects.equals(a, b));
+    }
+
+    private static SparseRectFArray cloneViaParcel(final SparseRectFArray src) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            src.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            return new SparseRectFArray(parcel);
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+    }
+}
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 4057736..6143b4b 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -584,9 +584,14 @@
 </tr>
 <tr>
   <td><code>android.hardware.camera.any</code></td>
-  <td>The application uses at least one camera facing in any direction. Use this
-in preference to <code>android.hardware.camera</code> if a back-facing camera is
-not required.</td>
+  <td>The application uses at least one camera facing in any direction, or an
+external camera device if one is connected. Use this in preference to
+<code>android.hardware.camera</code> if a back-facing camera is not required.
+  </td>
+</tr>
+<tr>
+  <td><code>android.hardware.camera.external</code></td>
+  <td>The application uses an external camera device if one is connected.</td>
 </tr>
 
 <tr>
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 3f8c45c..0862cdd 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -18,6 +18,7 @@
 
 import java.lang.ref.WeakReference;
 
+import android.annotation.Nullable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -132,14 +133,14 @@
      * Register a callback to be invoked when a new image frame becomes available to the
      * SurfaceTexture.
      * <p>
-     * This callback may be called on an arbitrary thread, so it is not
+     * The callback may be called on an arbitrary thread, so it is not
      * safe to call {@link #updateTexImage} without first binding the OpenGL ES context to the
      * thread invoking the callback.
      * </p>
      *
-     * @param listener The listener to set.
+     * @param listener The listener to use, or null to remove the listener.
      */
-    public void setOnFrameAvailableListener(OnFrameAvailableListener listener) {
+    public void setOnFrameAvailableListener(@Nullable OnFrameAvailableListener listener) {
         setOnFrameAvailableListener(listener, null);
     }
 
@@ -147,17 +148,18 @@
      * Register a callback to be invoked when a new image frame becomes available to the
      * SurfaceTexture.
      * <p>
-     * If no handler is specified, then this callback may be called on an arbitrary thread,
+     * If a handler is specified, the callback will be invoked on that handler's thread.
+     * If no handler is specified, then the callback may be called on an arbitrary thread,
      * so it is not safe to call {@link #updateTexImage} without first binding the OpenGL ES
      * context to the thread invoking the callback.
      * </p>
      *
-     * @param listener The listener to set.
+     * @param listener The listener to use, or null to remove the listener.
      * @param handler The handler on which the listener should be invoked, or null
      * to use an arbitrary thread.
      */
-    public void setOnFrameAvailableListener(final OnFrameAvailableListener listener,
-            Handler handler) {
+    public void setOnFrameAvailableListener(@Nullable final OnFrameAvailableListener listener,
+            @Nullable Handler handler) {
         if (listener != null) {
             // Although we claim the thread is arbitrary, earlier implementation would
             // prefer to send the callback on the creating looper or the main looper
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index eb0cac8..2cadf09 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -6,6 +6,7 @@
 ifeq ($(USE_OPENGL_RENDERER),true)
 	LOCAL_SRC_FILES := \
 		utils/Blur.cpp \
+		utils/GLUtils.cpp \
 		utils/SortedListImpl.cpp \
 		thread/TaskManager.cpp \
 		font/CacheTexture.cpp \
@@ -53,7 +54,7 @@
 		TextureCache.cpp \
 		TextDropShadowCache.cpp
 
-	# RenderThread stuff
+# RenderThread stuff
 	LOCAL_SRC_FILES += \
 		renderthread/CanvasContext.cpp \
 		renderthread/DrawFrameTask.cpp \
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index f06106b..2268386 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -482,8 +482,8 @@
     sy = copysignf(sqrtf(len), data[mat4::kScaleY]);
 }
 
-void Matrix4::dump() const {
-    ALOGD("Matrix4[simple=%d, type=0x%x", isSimple(), getType());
+void Matrix4::dump(const char* label) const {
+    ALOGD("%s[simple=%d, type=0x%x", label ? label : "Matrix4", isSimple(), getType());
     ALOGD("  %f %f %f %f", data[kScaleX], data[kSkewX], data[8], data[kTranslateX]);
     ALOGD("  %f %f %f %f", data[kSkewY], data[kScaleY], data[9], data[kTranslateY]);
     ALOGD("  %f %f %f %f", data[2], data[6], data[kScaleZ], data[kTranslateZ]);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 26cb05f..e33a001 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -209,7 +209,7 @@
 
     void decomposeScale(float& sx, float& sy) const;
 
-    void dump() const;
+    void dump(const char* label = NULL) const;
 
     static const Matrix4& identity();
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 77d2680..20b038d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -37,6 +37,7 @@
 #include "PathTessellator.h"
 #include "Properties.h"
 #include "ShadowTessellator.h"
+#include "utils/GLUtils.h"
 #include "Vector.h"
 #include "VertexBuffer.h"
 
@@ -296,24 +297,7 @@
 
     if (!suppressErrorChecks()) {
 #if DEBUG_OPENGL
-        GLenum status = GL_NO_ERROR;
-        while ((status = glGetError()) != GL_NO_ERROR) {
-            ALOGD("GL error from OpenGLRenderer: 0x%x", status);
-            switch (status) {
-                case GL_INVALID_ENUM:
-                    ALOGE("  GL_INVALID_ENUM");
-                    break;
-                case GL_INVALID_VALUE:
-                    ALOGE("  GL_INVALID_VALUE");
-                    break;
-                case GL_INVALID_OPERATION:
-                    ALOGE("  GL_INVALID_OPERATION");
-                    break;
-                case GL_OUT_OF_MEMORY:
-                    ALOGE("  Out of memory!");
-                    break;
-            }
-        }
+        GLUtils::dumpGLErrors();
 #endif
 
 #if DEBUG_MEMORY_USAGE
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 92964a8..f38d8b7 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -175,6 +175,10 @@
         bottom += dy;
     }
 
+    void inset(float delta) {
+        outset(-delta);
+    }
+
     void outset(float delta) {
         left -= delta;
         top -= delta;
@@ -230,8 +234,8 @@
         bottom = ceilf(bottom);
     }
 
-    void dump() const {
-        ALOGD("Rect[l=%f t=%f r=%f b=%f]", left, top, right, bottom);
+    void dump(const char* label) const {
+        ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
     }
 
 private:
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index d26ee38..6bfa203 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -27,9 +27,15 @@
 // Constructors
 ///////////////////////////////////////////////////////////////////////////////
 
-Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
-        invisible(false), empty(false), alpha(1.0f) {
-
+Snapshot::Snapshot()
+        : flags(0)
+        , previous(NULL)
+        , layer(NULL)
+        , fbo(0)
+        , invisible(false)
+        , empty(false)
+        , height(0)
+        , alpha(1.0f) {
     transform = &mTransformRoot;
     clipRect = &mClipRectRoot;
     region = NULL;
@@ -40,10 +46,16 @@
  * Copies the specified snapshot/ The specified snapshot is stored as
  * the previous snapshot.
  */
-Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
-        flags(0), previous(s), layer(s->layer), fbo(s->fbo),
-        invisible(s->invisible), empty(false),
-        viewport(s->viewport), height(s->height), alpha(s->alpha) {
+Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags)
+        : flags(0)
+        , previous(s)
+        , layer(s->layer)
+        , fbo(s->fbo)
+        , invisible(s->invisible)
+        , empty(false)
+        , viewport(s->viewport)
+        , height(s->height)
+        , alpha(s->alpha) {
 
     if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
         mTransformRoot.load(*s->transform);
diff --git a/libs/hwui/utils/GLUtils.cpp b/libs/hwui/utils/GLUtils.cpp
new file mode 100644
index 0000000..9b298ca
--- /dev/null
+++ b/libs/hwui/utils/GLUtils.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/Log.h>
+
+#include "GLUtils.h"
+
+namespace android {
+namespace uirenderer {
+
+void GLUtils::dumpGLErrors() {
+    GLenum status = GL_NO_ERROR;
+    while ((status = glGetError()) != GL_NO_ERROR) {
+        switch (status) {
+        case GL_INVALID_ENUM:
+            ALOGE("GL error:  GL_INVALID_ENUM");
+            break;
+        case GL_INVALID_VALUE:
+            ALOGE("GL error:  GL_INVALID_VALUE");
+            break;
+        case GL_INVALID_OPERATION:
+            ALOGE("GL error:  GL_INVALID_OPERATION");
+            break;
+        case GL_OUT_OF_MEMORY:
+            ALOGE("GL error:  Out of memory!");
+            break;
+        default:
+            ALOGE("GL error: 0x%x", status);
+        }
+    }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
new file mode 100644
index 0000000..890e374
--- /dev/null
+++ b/libs/hwui/utils/GLUtils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef GLUTILS_H
+#define GLUTILS_H
+
+namespace android {
+namespace uirenderer {
+
+class GLUtils {
+private:
+public:
+    /**
+     * Print out any GL errors with ALOGE
+     */
+    static void dumpGLErrors();
+
+}; // class GLUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* GLUTILS_H */
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 7deabe9..8ba44dc 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -38,4 +38,4 @@
 } /* namespace uirenderer */
 } /* namespace android */
 
-#endif /* RENDERNODE_H */
+#endif /* MATHUTILS_H */
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 6b2a247..57274ee 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -37,7 +37,7 @@
     public static final int ENCODING_PCM_16BIT = 2;
     /** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
     public static final int ENCODING_PCM_8BIT = 3;
-    /** @hide Candidate for public API */
+    /** Audio data format: single-precision floating-point per sample */
     public static final int ENCODING_PCM_FLOAT = 4;
 
     /** Invalid audio channel configuration */
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0c8a823..724022b 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -149,6 +149,7 @@
     private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
     private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
     private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
+    private static final int MSG_SYSTEM_READY = 21;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -370,7 +371,7 @@
     private int mScoConnectionState;
 
     // true if boot sequence has been completed
-    private boolean mBootCompleted;
+    private boolean mSystemReady;
     // listener for SoundPool sample load completion indication
     private SoundPoolCallback mSoundPoolCallBack;
     // thread for SoundPool listener
@@ -525,7 +526,6 @@
         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
         intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
         intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
-        intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -559,6 +559,43 @@
 
     }
 
+    public void systemReady() {
+        sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
+                0, 0, null, 0);
+    }
+
+    public void onSystemReady() {
+        mSystemReady = true;
+        sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
+                0, 0, null, 0);
+
+        mKeyguardManager =
+                (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
+        resetBluetoothSco();
+        getBluetoothHeadset();
+        //FIXME: this is to maintain compatibility with deprecated intent
+        // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
+        Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
+        newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
+                AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
+        sendStickyBroadcastToAll(newIntent);
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter != null) {
+            adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
+                                    BluetoothProfile.A2DP);
+        }
+
+        sendMsg(mAudioHandler,
+                MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
+                SENDMSG_REPLACE,
+                0,
+                0,
+                null,
+                SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
+    }
+
     private void createAudioSystemThread() {
         mAudioSystemThread = new AudioSystemThread();
         mAudioSystemThread.start();
@@ -1996,7 +2033,7 @@
     /** @see AudioManager#startBluetoothSco() */
     public void startBluetoothSco(IBinder cb, int targetSdkVersion){
         if (!checkAudioSettingsPermission("startBluetoothSco()") ||
-                !mBootCompleted) {
+                !mSystemReady) {
             return;
         }
         ScoClient client = getScoClient(cb, true);
@@ -2013,7 +2050,7 @@
     /** @see AudioManager#stopBluetoothSco() */
     public void stopBluetoothSco(IBinder cb){
         if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
-                !mBootCompleted) {
+                !mSystemReady) {
             return;
         }
         ScoClient client = getScoClient(cb, false);
@@ -3277,7 +3314,7 @@
             int status;
 
             synchronized (mSoundEffectsLock) {
-                if (!mBootCompleted) {
+                if (!mSystemReady) {
                     Log.w(TAG, "onLoadSoundEffects() called before boot complete");
                     return false;
                 }
@@ -3700,6 +3737,10 @@
                 case MSG_BROADCAST_BT_CONNECTION_STATE:
                     onBroadcastScoConnectionState(msg.arg1);
                     break;
+
+                case MSG_SYSTEM_READY:
+                    onSystemReady();
+                    break;
             }
         }
     }
@@ -4169,36 +4210,6 @@
                     newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
                     sendStickyBroadcastToAll(newIntent);
                 }
-            } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
-                mBootCompleted = true;
-                sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
-                        0, 0, null, 0);
-
-                mKeyguardManager =
-                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
-                mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
-                resetBluetoothSco();
-                getBluetoothHeadset();
-                //FIXME: this is to maintain compatibility with deprecated intent
-                // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
-                Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
-                newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
-                        AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
-                sendStickyBroadcastToAll(newIntent);
-
-                BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-                if (adapter != null) {
-                    adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
-                                            BluetoothProfile.A2DP);
-                }
-
-                sendMsg(mAudioHandler,
-                        MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
-                        SENDMSG_REPLACE,
-                        0,
-                        0,
-                        null,
-                        SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
                 AudioSystem.setParameters("screen_state=on");
             } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 007eb40..1a64cff 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -42,7 +42,8 @@
  * The AudioTrack class manages and plays a single audio resource for Java applications.
  * It allows streaming of PCM audio buffers to the audio sink for playback. This is
  * achieved by "pushing" the data to the AudioTrack object using one of the
- *  {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods.
+ *  {@link #write(byte[], int, int)}, {@link #write(short[], int, int)},
+ *  and {@link #write(float[], int, int, int)} methods.
  *
  * <p>An AudioTrack instance can operate under two modes: static or streaming.<br>
  * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using
@@ -244,6 +245,7 @@
      * The encoding of the audio samples.
      * @see AudioFormat#ENCODING_PCM_8BIT
      * @see AudioFormat#ENCODING_PCM_16BIT
+     * @see AudioFormat#ENCODING_PCM_FLOAT
      */
     private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
     /**
@@ -285,8 +287,9 @@
      *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
-     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
-     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT},
+     *   {@link AudioFormat#ENCODING_PCM_8BIT},
+     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is
      *   read from for playback.
      *   If track's creation mode is {@link #MODE_STREAM}, you can write data into
@@ -329,7 +332,8 @@
      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
-     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     *   {@link AudioFormat#ENCODING_PCM_8BIT},
+     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
      *   from for playback. If using the AudioTrack in streaming mode, you can write data into
      *   this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
@@ -459,11 +463,14 @@
             break;
         case AudioFormat.ENCODING_PCM_16BIT:
         case AudioFormat.ENCODING_PCM_8BIT:
+        case AudioFormat.ENCODING_PCM_FLOAT:
             mAudioFormat = audioFormat;
             break;
         default:
             throw new IllegalArgumentException("Unsupported sample encoding."
-                + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT.");
+                + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT"
+                + " or ENCODING_PCM_FLOAT"
+                + ".");
         }
 
         //--------------
@@ -723,7 +730,8 @@
      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
-     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     *   {@link AudioFormat#ENCODING_PCM_8BIT},
+     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
      *   or {@link #ERROR} if unable to query for output properties,
      *   or the minimum buffer size expressed in bytes.
@@ -750,7 +758,8 @@
         }
 
         if ((audioFormat != AudioFormat.ENCODING_PCM_16BIT)
-            && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)) {
+            && (audioFormat != AudioFormat.ENCODING_PCM_8BIT)
+            && (audioFormat != AudioFormat.ENCODING_PCM_FLOAT)) {
             loge("getMinBufferSize(): Invalid audio format.");
             return ERROR_BAD_VALUE;
         }
@@ -1150,7 +1159,7 @@
 
     public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) {
 
-        if (mState == STATE_UNINITIALIZED) {
+        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
             return ERROR_INVALID_OPERATION;
         }
 
@@ -1188,13 +1197,13 @@
      *     starts.
      * @param sizeInShorts the number of shorts to read in audioData after the offset.
      * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
-      *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-      *    the parameters don't resolve to valid data and indexes.
+     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     *    the parameters don't resolve to valid data and indexes.
      */
 
     public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
 
-        if (mState == STATE_UNINITIALIZED) {
+        if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
             return ERROR_INVALID_OPERATION;
         }
 
@@ -1220,6 +1229,79 @@
     /**
      * Writes the audio data to the audio sink for playback (streaming mode),
      * or copies audio data for later playback (static buffer mode).
+     * In static buffer mode, copies the data to the buffer starting at offset 0,
+     * and the write mode is ignored.
+     * In streaming mode, the blocking behavior will depend on the write mode.
+     * <p>
+     * Note that the actual playback of this data might occur after this function
+     * returns. This function is thread safe with respect to {@link #stop} calls,
+     * in which case all of the specified data might not be written to the audio sink.
+     * <p>
+     * @param audioData the array that holds the data to play.
+     *     The implementation does not clip for sample values within the nominal range
+     *     [-1.0f, 1.0f], provided that all gains in the audio pipeline are
+     *     less than or equal to unity (1.0f), and in the absence of post-processing effects
+     *     that could add energy, such as reverb.  For the convenience of applications
+     *     that compute samples using filters with non-unity gain,
+     *     sample values +3 dB beyond the nominal range are permitted.
+     *     However such values may eventually be limited or clipped, depending on various gains
+     *     and later processing in the audio path.  Therefore applications are encouraged
+     *     to provide samples values within the nominal range.
+     * @param offsetInFloats the offset, expressed as a number of floats,
+     *     in audioData where the data to play starts.
+     * @param sizeInFloats the number of floats to read in audioData after the offset.
+     * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
+     *     effect in static mode.
+     *     <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
+     *         to the audio sink.
+     *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
+     *     queuing as much audio data for playback as possible without blocking.
+     * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
+     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     *    the parameters don't resolve to valid data and indexes.
+     */
+    public int write(float[] audioData, int offsetInFloats, int sizeInFloats,
+            @WriteMode int writeMode) {
+
+        if (mState == STATE_UNINITIALIZED) {
+            Log.e(TAG, "AudioTrack.write() called in invalid state STATE_UNINITIALIZED");
+            return ERROR_INVALID_OPERATION;
+        }
+
+        if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
+            Log.e(TAG, "AudioTrack.write(float[] ...) requires format ENCODING_PCM_FLOAT");
+            return ERROR_INVALID_OPERATION;
+        }
+
+        if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
+            Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
+            return ERROR_BAD_VALUE;
+        }
+
+        if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0)
+                || (offsetInFloats + sizeInFloats < 0)  // detect integer overflow
+                || (offsetInFloats + sizeInFloats > audioData.length)) {
+            Log.e(TAG, "AudioTrack.write() called with invalid array, offset, or size");
+            return ERROR_BAD_VALUE;
+        }
+
+        int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
+                writeMode == WRITE_BLOCKING);
+
+        if ((mDataLoadMode == MODE_STATIC)
+                && (mState == STATE_NO_STATIC_DATA)
+                && (ret > 0)) {
+            // benign race with respect to other APIs that read mState
+            mState = STATE_INITIALIZED;
+        }
+
+        return ret;
+    }
+
+
+    /**
+     * Writes the audio data to the audio sink for playback (streaming mode),
+     * or copies audio data for later playback (static buffer mode).
      * In static buffer mode, copies the data to the buffer starting at its 0 offset, and the write
      * mode is ignored.
      * In streaming mode, the blocking behavior will depend on the write mode.
@@ -1247,6 +1329,11 @@
             return ERROR_INVALID_OPERATION;
         }
 
+        if (mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
+            Log.e(TAG, "AudioTrack.write(ByteBuffer ...) not yet supported for ENCODING_PCM_FLOAT");
+            return ERROR_INVALID_OPERATION;
+        }
+
         if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
             Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
             return ERROR_BAD_VALUE;
@@ -1487,6 +1574,10 @@
     private native final int native_write_short(short[] audioData,
                                                 int offsetInShorts, int sizeInShorts, int format);
 
+    private native final int native_write_float(float[] audioData,
+                                                int offsetInFloats, int sizeInFloats, int format,
+                                                boolean isBlocking);
+
     private native final int native_write_native_bytes(Object audioData,
             int positionInBytes, int sizeInBytes, int format, boolean blocking);
 
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index ed98b96..90fe695 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -66,8 +66,6 @@
 
 LOCAL_CFLAGS +=
 
-LOCAL_LDLIBS := -lpthread
-
 LOCAL_MODULE:= libmedia_jni
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
deleted file mode 100644
index 54dde82..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
deleted file mode 100644
index 3c0dc4e..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_clear_normal.png
deleted file mode 100644
index c526433..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_clear_normal.png
deleted file mode 100644
index d13bc69..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_clear_normal.png
deleted file mode 100644
index a137a80..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_clear_normal.png
deleted file mode 100644
index 8da7945..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
deleted file mode 100644
index 7cb52e3..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
deleted file mode 100644
index 8010ce7..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
deleted file mode 100644
index b9afa44..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
deleted file mode 100644
index 6d46fdd..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_clear_normal.png
deleted file mode 100644
index afdee8f..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_clear_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
deleted file mode 100644
index 7742207..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_notifications.xml b/packages/SystemUI/res/drawable/ic_notifications.xml
deleted file mode 100644
index 97a7623..0000000
--- a/packages/SystemUI/res/drawable/ic_notifications.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"
-         android:drawable="@drawable/ic_notify_open_normal" />
-    <item
-         android:drawable="@drawable/ic_notify_open_normal" />
-</selector>
-
diff --git a/packages/SystemUI/res/drawable/ic_notify_clear.xml b/packages/SystemUI/res/drawable/ic_notify_clear.xml
deleted file mode 100644
index 2163198..0000000
--- a/packages/SystemUI/res/drawable/ic_notify_clear.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"
-        android:drawable="@drawable/ic_notify_clear_normal" />
-    <item android:drawable="@drawable/ic_notify_clear_normal" />
-</selector>
diff --git a/packages/SystemUI/res/drawable/notification_header_bg.xml b/packages/SystemUI/res/drawable/notification_header_bg.xml
new file mode 100644
index 0000000..c5ba18b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_header_bg.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <shape>
+            <solid android:color="#ff54656e" />
+            <corners android:radius="@*android:dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <solid android:color="#ff374248" />
+            <corners android:radius="@*android:dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/heads_up.xml b/packages/SystemUI/res/layout/heads_up.xml
index e4954e7..7d9cfa1 100644
--- a/packages/SystemUI/res/layout/heads_up.xml
+++ b/packages/SystemUI/res/layout/heads_up.xml
@@ -20,7 +20,7 @@
 <com.android.systemui.statusbar.policy.HeadsUpNotificationView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_height="wrap_content"
-        android:layout_width="@dimen/notification_panel_width"
+        android:layout_width="match_parent"
         android:id="@+id/content_holder"
         android:background="@drawable/notification_panel_bg"
         />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3267c36..5b3f365 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -22,7 +22,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/notification_panel"
-    android:layout_width="0dp"
+    android:layout_width="match_parent"
     android:layout_height="match_parent"
     >
 
@@ -61,7 +61,7 @@
     <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
         android:id="@+id/notification_container_parent"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
         android:clipToPadding="false"
         android:clipChildren="false">
 
@@ -102,6 +102,8 @@
     <include layout="@layout/status_bar_expanded_header"
         android:layout_width="match_parent"
         android:layout_height="@dimen/status_bar_header_height"
+        android:layout_marginLeft="@dimen/notification_side_padding"
+        android:layout_marginRight="@dimen/notification_side_padding"
         />
 
     <include
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 460dd4b..adfa1e4 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -25,6 +25,7 @@
     android:orientation="horizontal"
     android:gravity="center_vertical"
     android:baselineAligned="false"
+    android:elevation="14dp"
     >
 
     <View
@@ -77,22 +78,4 @@
         android:padding="2dp"
         />
 
-    <include layout="@layout/status_bar_flip_button"
-        android:id="@+id/header_flipper"
-        android:layout_width="50dp"
-        android:layout_height="50dp"
-        android:layout_alignParentEnd="true"/>
-
-    <ImageView android:id="@+id/clear_all_button"
-        android:layout_width="50dp"
-        android:layout_height="50dp"
-        android:layout_toStartOf="@id/header_flipper"
-        android:scaleType="center"
-        android:src="@drawable/ic_notify_clear"
-        android:background="@drawable/ic_notify_button_bg"
-        android:contentDescription="@string/accessibility_clear_all"
-        />
-
-
-
 </com.android.systemui.statusbar.phone.StatusBarHeaderView>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index f9b022c..c29da18 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -35,9 +35,7 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" >
         <include layout="@layout/status_bar_expanded"
-            android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="match_parent"
-            android:layout_gravity="start|top" />
+            style="@style/StatusBarExpanded" />
     </com.android.systemui.statusbar.phone.PanelHolder>
 
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index b7becac..1ea9442 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -18,4 +18,10 @@
     <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
         <item name="android:layout_width">480dp</item>
     </style>
+
+    <style name="StatusBarExpanded">
+        <item name="android:layout_width">@dimen/notification_panel_width</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">start|top</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9281265..c78ff8e 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -30,7 +30,6 @@
     <drawable name="recents_callout_line">#99ffffff</drawable>
     <drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
     <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
-    <drawable name="notification_header_bg">#FF000000</drawable>
     <color name="notification_panel_scrim_color">#A0000000</color>
     <color name="notification_panel_scrim_color_keyguard">#80000000</color>
     <color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 93a75bc..c0376f0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -118,6 +118,8 @@
     <integer name="recents_animate_task_bar_exit_duration">150</integer>
     <!-- The animation duration for animating in the info pane. -->
     <integer name="recents_animate_task_view_info_pane_duration">150</integer>
+    <!-- The animation duration for animating the removal of a task view. -->
+    <integer name="recents_animate_task_view_remove_duration">150</integer>
     <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
     <integer name="recents_max_task_stack_view_dim">96</integer>
     <!-- Transposes the search bar layout in landscape -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8d3a565..b6e6ee2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -196,9 +196,6 @@
     <!-- Quick Settings CA Cert Warning tile geometry: gap between icon and text -->
     <dimen name="qs_cawarn_tile_margin_below_icon">3dp</dimen>
 
-    <!-- The width of the notification panel window: match_parent below sw600dp -->
-    <dimen name="notification_panel_width">-1dp</dimen>
-
     <!-- used by DessertCase -->
     <dimen name="dessert_case_cell_size">192dp</dimen>
 
@@ -223,6 +220,9 @@
     <!-- The translation in the Z index for each task above the last task. -->
     <dimen name="recents_task_view_z_increment">5dp</dimen>
 
+    <!-- The amount to translate when animating the removal of a task. -->
+    <dimen name="recents_task_view_remove_anim_translation_x">75dp</dimen>
+
     <!-- The amount of space a user has to scroll to dismiss any info panes. -->
     <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 8ab646d..6608c5d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -171,4 +171,10 @@
 
     <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
 
+    <style name="StatusBarExpanded">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">start|top</item>
+    </style>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 3be6932..b74f6ac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -22,6 +22,7 @@
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -37,6 +38,7 @@
 import com.android.systemui.recents.views.RecentsView;
 
 import java.util.ArrayList;
+import java.util.Set;
 
 /** Our special app widget host */
 class RecentsAppWidgetHost extends AppWidgetHost {
@@ -60,7 +62,7 @@
 
 /* Activity */
 public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
-        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks{
+        RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
     FrameLayout mContainerView;
     RecentsView mRecentsView;
     View mEmptyView;
@@ -308,6 +310,9 @@
         filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         registerReceiver(mScreenOffReceiver, filter);
+
+        // Register any broadcast receivers for the task loader
+        RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
     }
 
     @Override
@@ -320,6 +325,7 @@
         // Unregister any broadcast receivers we have registered
         unregisterReceiver(mServiceBroadcastReceiver);
         unregisterReceiver(mScreenOffReceiver);
+        RecentsTaskLoader.getInstance().unregisterReceivers();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index cb7e42a..463cf74 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -49,6 +49,8 @@
     public int taskStackScrollDismissInfoPaneDistance;
     public int taskStackMaxDim;
     public int taskViewInfoPaneAnimDuration;
+    public int taskViewRemoveAnimDuration;
+    public int taskViewRemoveAnimTranslationXPx;
     public int taskViewTranslationZMinPx;
     public int taskViewTranslationZIncrementPx;
     public int taskViewRoundedCornerRadiusPx;
@@ -108,6 +110,10 @@
         taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
         taskViewInfoPaneAnimDuration =
                 res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
+        taskViewRemoveAnimDuration =
+                res.getInteger(R.integer.recents_animate_task_view_remove_duration);
+        taskViewRemoveAnimTranslationXPx =
+                res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x);
         taskViewRoundedCornerRadiusPx =
                 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
new file mode 100644
index 0000000..4e620b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Looper;
+import com.android.internal.content.PackageMonitor;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * The package monitor listens for changes from PackageManager to update the contents of the Recents
+ * list.
+ */
+public class RecentsPackageMonitor extends PackageMonitor {
+    public interface PackageCallbacks {
+        public void onComponentRemoved(Set<ComponentName> cns);
+    }
+
+    PackageCallbacks mCb;
+    List<ActivityManager.RecentTaskInfo> mTasks;
+    SystemServicesProxy mSsp;
+
+    public RecentsPackageMonitor(Context context) {
+        mSsp = new SystemServicesProxy(context);
+    }
+
+    /** Registers the broadcast receivers with the specified callbacks. */
+    public void register(Context context, PackageCallbacks cb) {
+        mCb = cb;
+        register(context, Looper.getMainLooper(), false);
+    }
+
+    /** Unregisters the broadcast receivers. */
+    @Override
+    public void unregister() {
+        super.unregister();
+        mTasks.clear();
+    }
+
+    /** Sets the list of tasks to match against package broadcast changes. */
+    void setTasks(List<ActivityManager.RecentTaskInfo> tasks) {
+        mTasks = tasks;
+    }
+
+    @Override
+    public void onPackageRemoved(String packageName, int uid) {
+        if (mCb == null) return;
+
+        // Identify all the tasks that should be removed as a result of the package being removed.
+        // Using a set to ensure that we callback once per unique component.
+        HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
+        for (ActivityManager.RecentTaskInfo t : mTasks) {
+            ComponentName cn = t.baseIntent.getComponent();
+            if (cn.getPackageName().equals(packageName)) {
+                componentsToRemove.add(cn);
+            }
+        }
+        // Notify our callbacks that the components no longer exist
+        mCb.onComponentRemoved(componentsToRemove);
+    }
+
+    @Override
+    public boolean onPackageChanged(String packageName, int uid, String[] components) {
+        onPackageModified(packageName);
+        return true;
+    }
+
+    @Override
+    public void onPackageModified(String packageName) {
+        if (mCb == null) return;
+
+        // Identify all the tasks that should be removed as a result of the package being removed.
+        // Using a set to ensure that we callback once per unique component.
+        HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
+        HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
+        for (ActivityManager.RecentTaskInfo t : mTasks) {
+            ComponentName cn = t.baseIntent.getComponent();
+            if (cn.getPackageName().equals(packageName)) {
+                if (componentsKnownToExist.contains(cn)) {
+                    // If we know that the component still exists in the package, then skip
+                    continue;
+                }
+                if (mSsp.getActivityInfo(cn) != null) {
+                    componentsKnownToExist.add(cn);
+                } else {
+                    componentsToRemove.add(cn);
+                }
+            }
+        }
+        // Notify our callbacks that the components no longer exist
+        mCb.onComponentRemoved(componentsToRemove);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index c9038ee..c64ca54 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -300,6 +300,8 @@
     TaskResourceLoadQueue mLoadQueue;
     TaskResourceLoader mLoader;
 
+    RecentsPackageMonitor mPackageMonitor;
+
     int mMaxThumbnailCacheSize;
     int mMaxIconCacheSize;
 
@@ -325,6 +327,7 @@
 
         // Initialize the proxy, cache and loaders
         mSystemServicesProxy = new SystemServicesProxy(context);
+        mPackageMonitor = new RecentsPackageMonitor(context);
         mLoadQueue = new TaskResourceLoadQueue();
         mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -510,6 +513,9 @@
             mLoadQueue.addTask(t, true);
         }
 
+        // Update the package monitor with the list of packages to listen for
+        mPackageMonitor.setTasks(tasks);
+
         return root;
     }
 
@@ -548,14 +554,16 @@
     }
 
     /** Completely removes the resource data from the pool. */
-    public void deleteTaskData(Task t) {
+    public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
         Console.log(Constants.Log.App.TaskDataLoader,
                 "[RecentsTaskLoader|deleteTask]", t);
 
         mLoadQueue.removeTask(t);
         mThumbnailCache.remove(t.key);
         mApplicationIconCache.remove(t.key);
-        t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
+        if (notifyTaskDataUnloaded) {
+            t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
+        }
     }
 
     /** Stops the task loader and clears all pending tasks */
@@ -565,6 +573,21 @@
         mLoadQueue.clearTasks();
     }
 
+    /** Registers any broadcast receivers. */
+    public void registerReceivers(Context context, RecentsPackageMonitor.PackageCallbacks cb) {
+        // Register the broadcast receiver to handle messages related to packages being added/removed
+        mPackageMonitor.register(context, cb);
+    }
+
+    /** Unregisters any broadcast receivers. */
+    public void unregisterReceivers() {
+        mPackageMonitor.unregister();
+    }
+
+    /**
+     * Handles signals from the system, trimming memory when requested to prevent us from running
+     * out of memory.
+     */
     void onTrimMemory(int level) {
         Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
                 Console.trimMemoryLevelToString(level));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index b41555f..0d3ee38 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -165,11 +165,12 @@
     }
 
     /** Removes the task and kills the process */
-    public void removeTask(int taskId) {
+    public void removeTask(int taskId, boolean isDocument) {
         if (mAm == null) return;
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
 
-        mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+        // Remove the task, and only kill the process if it is not a document
+        mAm.removeTask(taskId, isDocument ? 0 : ActivityManager.REMOVE_TASK_KILL_PROCESS);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index eb7b5c6..a6d7e67 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -19,6 +19,7 @@
 import android.app.ActivityOptions;
 import android.app.TaskStackBuilder;
 import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -33,19 +34,22 @@
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsPackageMonitor;
 import com.android.systemui.recents.RecentsTaskLoader;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 
 import java.util.ArrayList;
+import java.util.Set;
 
 
 /**
  * This view is the the top level layout that contains TaskStacks (which are laid out according
  * to their SpaceNode bounds.
  */
-public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks {
+public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks,
+        RecentsPackageMonitor.PackageCallbacks {
 
     /** The RecentsView callbacks */
     public interface RecentsViewCallbacks {
@@ -342,7 +346,7 @@
                     RecentsTaskLoader.getInstance().getSystemServicesProxy()
                             .moveTaskToFront(task.key.id, opts);
                 } else {
-                    // Launch the activity with the desired animation
+                    // Launch the activity anew with the desired animation
                     Intent i = new Intent(task.key.baseIntent);
                     i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                             | Intent.FLAG_ACTIVITY_TASK_ON_HOME
@@ -357,6 +361,9 @@
                     } catch (ActivityNotFoundException anfe) {
                         Console.logError(getContext(), "Could not start Activity");
                     }
+
+                    // And clean up the old task
+                    onTaskRemoved(task);
                 }
 
                 Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
@@ -385,4 +392,35 @@
         TaskStackBuilder.create(getContext())
                 .addNextIntentWithParentStack(intent).startActivities();
     }
+
+    @Override
+    public void onTaskRemoved(Task t) {
+        // Remove any stored data from the loader.  We currently don't bother notifying the views
+        // that the data has been unloaded because at the point we call onTaskRemoved(), the views
+        // either don't need to be updated, or have already been removed.
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        loader.deleteTaskData(t, false);
+
+        // Remove the old task from activity manager
+        int flags = t.key.baseIntent.getFlags();
+        boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
+                Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
+                isDocument);
+    }
+
+    /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
+
+    @Override
+    public void onComponentRemoved(Set<ComponentName> cns) {
+        // Propagate this event down to each task stack view
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child instanceof TaskStackView) {
+                TaskStackView stackView = (TaskStackView) child;
+                stackView.onComponentRemoved(cns);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index cfacd18..55c38a9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -21,7 +21,9 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -39,6 +41,7 @@
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsPackageMonitor;
 import com.android.systemui.recents.RecentsTaskLoader;
 import com.android.systemui.recents.Utilities;
 import com.android.systemui.recents.model.Task;
@@ -46,17 +49,19 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Set;
 
 
 /* The visual representation of a task stack view */
 public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
         TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
-        View.OnClickListener, View.OnLongClickListener {
+        View.OnClickListener, View.OnLongClickListener, RecentsPackageMonitor.PackageCallbacks {
 
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
         public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
         public void onTaskAppInfoLaunched(Task t);
+        public void onTaskRemoved(Task t);
     }
 
     TaskStack mStack;
@@ -705,9 +710,24 @@
             }
         }
 
+        // Update the min/max scroll and animate other task views into their new positions
         updateMinMaxScroll(true);
         int movement = (int) (Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height());
         requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
+
+        // If there are no remaining tasks, then either unfilter the current stack, or just close
+        // the activity if there are no filtered stacks
+        if (mStack.getTaskCount() == 0) {
+            boolean shouldFinishActivity = true;
+            if (mStack.hasFilteredTasks()) {
+                mStack.unfilterTasks();
+                shouldFinishActivity = (mStack.getTaskCount() == 0);
+            }
+            if (shouldFinishActivity) {
+                Activity activity = (Activity) getContext();
+                activity.finish();
+            }
+        }
     }
 
     /**
@@ -1070,6 +1090,32 @@
         tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
         return true;
     }
+
+    /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
+
+    @Override
+    public void onComponentRemoved(Set<ComponentName> cns) {
+        // For other tasks, just remove them directly if they no longer exist
+        ArrayList<Task> tasks = mStack.getTasks();
+        for (int i = tasks.size() - 1; i >= 0; i--) {
+            final Task t = tasks.get(i);
+            if (cns.contains(t.key.baseIntent.getComponent())) {
+                TaskView tv = getChildViewForTask(t);
+                if (tv != null) {
+                    // For visible children, defer removing the task until after the animation
+                    tv.animateRemoval(new Runnable() {
+                        @Override
+                        public void run() {
+                            mStack.removeTask(t);
+                        }
+                    });
+                } else {
+                    // Otherwise, remove the task from the stack immediately
+                    mStack.removeTask(t);
+                }
+            }
+        }
+    }
 }
 
 /* Handles touch events */
@@ -1432,30 +1478,12 @@
     public void onChildDismissed(View v) {
         TaskView tv = (TaskView) v;
         Task task = tv.getTask();
-        Activity activity = (Activity) mSv.getContext();
 
         // Remove the task from the view
         mSv.mStack.removeTask(task);
 
-        // Remove any stored data from the loader
-        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
-        loader.deleteTaskData(task);
-
-        // Remove the task from activity manager
-        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
-
-        // If there are no remaining tasks, then either unfilter the current stack, or just close
-        // the activity if there are no filtered stacks
-        if (mSv.mStack.getTaskCount() == 0) {
-            boolean shouldFinishActivity = true;
-            if (mSv.mStack.hasFilteredTasks()) {
-                mSv.mStack.unfilterTasks();
-                shouldFinishActivity = (mSv.mStack.getTaskCount() == 0);
-            }
-            if (shouldFinishActivity) {
-                activity.finish();
-            }
-        }
+        // Notify the callback that we've removed the task and it can clean up after it
+        mSv.mCb.onTaskRemoved(task);
 
         // Disable HW layers
         mSv.decHwLayersRefCount("swipeComplete");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 45c2fae..b03f389 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -246,6 +246,24 @@
             .start();
     }
 
+    /** Animates the deletion of this task view */
+    public void animateRemoval(final Runnable r) {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        animate().translationX(config.taskViewRemoveAnimTranslationXPx)
+            .alpha(0f)
+            .setStartDelay(0)
+            .setInterpolator(BakedBezierInterpolator.INSTANCE)
+            .setDuration(config.taskViewRemoveAnimDuration)
+            .withLayer()
+            .withEndAction(new Runnable() {
+                @Override
+                public void run() {
+                    post(r);
+                }
+            })
+            .start();
+    }
+
     /** Returns the rect we want to clip (it may not be the full rect) */
     Rect getClippingRect(Rect outRect) {
         getHitRect(outRect);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ecefc39..898f06e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1029,6 +1029,9 @@
     }
 
     protected void addNotificationViews(NotificationData.Entry entry) {
+        if (entry == null) {
+            return;
+        }
         // Add the expanded view and icon.
         int pos = mNotificationData.add(entry);
         if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f63ba9c..377ef9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -144,7 +144,6 @@
 
     public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
         mQsExpansionEnabled = qsExpansionEnabled;
-        mHeader.setExpansionEnabled(qsExpansionEnabled);
     }
 
     public void closeQs() {
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 92eee4e..fa31b33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -240,8 +240,6 @@
     String mKeyguardHotwordPhrase = "";
     int mKeyguardMaxNotificationCount;
     View mDateTimeView;
-    View mClearButton;
-    ImageView mHeaderFlipper;
 
     // carrier/wifi label
     private TextView mCarrierLabel;
@@ -640,11 +638,6 @@
         mKeyguardBottomArea.setActivityStarter(this);
         mKeyguardIndicationTextView = (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
                 R.id.keyguard_indication_text);
-        mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
-        mClearButton.setOnClickListener(mClearButtonListener);
-        mClearButton.setAlpha(0f);
-        mClearButton.setVisibility(View.INVISIBLE);
-        mClearButton.setEnabled(false);
         mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
 
         mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
@@ -653,8 +646,6 @@
             mDateTimeView.setEnabled(true);
         }
 
-        mHeaderFlipper = (ImageView) mStatusBarWindow.findViewById(R.id.header_flipper);
-
         if (!mNotificationPanelIsFullScreenWidth) {
             mNotificationPanel.setSystemUiVisibility(
                     View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
@@ -1118,19 +1109,6 @@
         if (mNavigationBarView != null) {
             mNavigationBarView.setLayoutDirection(layoutDirection);
         }
-
-        if (mClearButton != null && mClearButton instanceof ImageView) {
-            // Force asset reloading
-            ((ImageView)mClearButton).setImageDrawable(null);
-            ((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear);
-        }
-
-        if (mHeaderFlipper != null) {
-            // Force asset reloading
-            mHeaderFlipper.setImageDrawable(null);
-            mHeaderFlipper.setImageResource(R.drawable.ic_notify_quicksettings);
-        }
-
         refreshAllStatusBarIcons();
     }
 
@@ -1301,38 +1279,6 @@
                     + " any=" + any + " clearable=" + clearable);
         }
 
-        if (mFlipSettingsView != null
-                && mFlipSettingsView.getVisibility() == View.VISIBLE
-                && mStackScroller.getVisibility() != View.VISIBLE) {
-            // the flip settings panel is unequivocally showing; we should not be shown
-            mClearButton.setVisibility(View.INVISIBLE);
-        } else if (mClearButton.isShown()) {
-            if (clearable != (mClearButton.getAlpha() == 1.0f)) {
-                ObjectAnimator clearAnimation = ObjectAnimator.ofFloat(
-                        mClearButton, "alpha", clearable ? 1.0f : 0.0f).setDuration(250);
-                clearAnimation.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        if (mClearButton.getAlpha() <= 0.0f) {
-                            mClearButton.setVisibility(View.INVISIBLE);
-                        }
-                    }
-
-                    @Override
-                    public void onAnimationStart(Animator animation) {
-                        if (mClearButton.getAlpha() <= 0.0f) {
-                            mClearButton.setVisibility(View.VISIBLE);
-                        }
-                    }
-                });
-                clearAnimation.start();
-            }
-        } else {
-            mClearButton.setAlpha(clearable ? 1.0f : 0.0f);
-            mClearButton.setVisibility(clearable ? View.VISIBLE : View.INVISIBLE);
-        }
-        mClearButton.setEnabled(clearable);
-
         final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
         final boolean showDot = (any&&!areLightsOn());
         if (showDot != (nlo.getAlpha() == 1.0f)) {
@@ -2449,10 +2395,6 @@
         final Context context = mContext;
         final Resources res = context.getResources();
 
-        if (mClearButton instanceof TextView) {
-            ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button));
-        }
-
         // Update the QuickSettings container
         if (mQS != null) mQS.updateResources();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 9d33930..fd53d15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -32,7 +32,6 @@
 
     private boolean mExpanded;
     private View mBackground;
-    private View mFlipper;
 
     private int mCollapsedHeight;
     private int mExpandedHeight;
@@ -45,7 +44,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mBackground = findViewById(R.id.background);
-        mFlipper = findViewById(R.id.header_flipper);
         loadDimens();
     }
 
@@ -73,10 +71,6 @@
         }
     }
 
-    public void setExpansionEnabled(boolean enabled) {
-        mFlipper.setVisibility(enabled ? View.VISIBLE : View.GONE);
-    }
-
     public void setExpansion(float height) {
         if (height < mCollapsedHeight) {
             height = mCollapsedHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index e24ddd9..48c54fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -73,8 +73,7 @@
     public void show(Bundle options) {
         mShowing = true;
         mStatusBarWindowManager.setKeyguardShowing(true);
-        showBouncerOrKeyguard();
-        updateStates();
+        reset();
     }
 
     /**
@@ -95,7 +94,9 @@
     }
 
     private void showBouncer() {
-        mBouncer.show();
+        if (!mOccluded) {
+            mBouncer.show();
+        }
         updateStates();
     }
 
@@ -103,8 +104,15 @@
      * Reset the state of the view.
      */
     public void reset() {
-        showBouncerOrKeyguard();
-        updateStates();
+        if (mShowing) {
+            if (mOccluded) {
+                mPhoneStatusBar.hideKeyguard();
+                mBouncer.hide();
+            } else {
+                showBouncerOrKeyguard();
+            }
+            updateStates();
+        }
     }
 
     public void onScreenTurnedOff() {
@@ -147,7 +155,7 @@
     public void setOccluded(boolean occluded) {
         mOccluded = occluded;
         mStatusBarWindowManager.setKeyguardOccluded(occluded);
-        updateStates();
+        reset();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index a4c9df5..c2061f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -79,8 +79,9 @@
                         | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                 PixelFormat.TRANSLUCENT);
 
+        mLp.width = ViewGroup.LayoutParams.MATCH_PARENT;
         mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-        mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+        mLp.gravity = Gravity.TOP;
         mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         mLp.setTitle("StatusBar");
         mLp.packageName = mContext.getPackageName();
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 07933b4..f1ddc07 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -27,7 +27,6 @@
 
 LOCAL_CFLAGS += -Wno-unused-parameter
 
-LOCAL_LDLIBS := -lpthread
 LOCAL_ADDITIONAL_DEPENDENCIES := $(addprefix $(rs_generated_include_dir)/,rsgApiFuncDecl.h)
 LOCAL_MODULE:= librs_jni
 LOCAL_ADDITIONAL_DEPENDENCIES += $(rs_generated_source)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 3619112..4a59a8f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -38,6 +38,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -197,6 +198,8 @@
 
     private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
 
+    private final UserManager mUserManager;
+
     private int mCurrentUserId = UserHandle.USER_OWNER;
 
     private final LongArray mTempLongArray = new LongArray();
@@ -210,15 +213,6 @@
         return getUserStateLocked(mCurrentUserId);
     }
 
-    private UserState getUserStateLocked(int userId) {
-        UserState state = mUserStates.get(userId);
-        if (state == null) {
-            state = new UserState(userId);
-            mUserStates.put(userId, state);
-        }
-        return state;
-    }
-
     /**
      * Creates a new instance.
      *
@@ -228,6 +222,7 @@
         mContext = context;
         mPackageManager = mContext.getPackageManager();
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mSecurityPolicy = new SecurityPolicy();
         mMainHandler = new MainHandler(mContext.getMainLooper());
         registerBroadcastReceivers();
@@ -235,11 +230,22 @@
                 context.getContentResolver());
     }
 
+    private UserState getUserStateLocked(int userId) {
+        UserState state = mUserStates.get(userId);
+        if (state == null) {
+            state = new UserState(userId);
+            mUserStates.put(userId, state);
+        }
+        return state;
+    }
+
     private void registerBroadcastReceivers() {
         PackageMonitor monitor = new PackageMonitor() {
             @Override
             public void onSomePackagesChanged() {
                 synchronized (mLock) {
+                    // Only the profile parent can install accessibility services.
+                    // Therefore we ignore packages from linked profiles.
                     if (getChangingUserId() != mCurrentUserId) {
                         return;
                     }
@@ -262,6 +268,8 @@
             public void onPackageRemoved(String packageName, int uid) {
                 synchronized (mLock) {
                     final int userId = getChangingUserId();
+                    // Only the profile parent can install accessibility services.
+                    // Therefore we ignore packages from linked profiles.
                     if (userId != mCurrentUserId) {
                         return;
                     }
@@ -297,6 +305,8 @@
                     int uid, boolean doit) {
                 synchronized (mLock) {
                     final int userId = getChangingUserId();
+                    // Only the profile parent can install accessibility services.
+                    // Therefore we ignore packages from linked profiles.
                     if (userId != mCurrentUserId) {
                         return false;
                     }
@@ -359,6 +369,9 @@
     @Override
     public int addClient(IAccessibilityManagerClient client, int userId) {
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
             // If the client is from a process that runs across users such as
@@ -388,6 +401,9 @@
     @Override
     public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution..
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
             // This method does nothing for a background user.
@@ -414,6 +430,9 @@
     @Override
     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
             // The automation service is a fake one and should not be reported
@@ -435,6 +454,9 @@
             int userId) {
         List<AccessibilityServiceInfo> result = null;
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
 
@@ -468,6 +490,9 @@
     public void interrupt(int userId) {
         CopyOnWriteArrayList<Service> services;
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
             // This method does nothing for a background user.
@@ -491,6 +516,9 @@
     public int addAccessibilityInteractionConnection(IWindow windowToken,
             IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(userId);
             final int windowId = sNextWindowId++;
@@ -527,6 +555,9 @@
     @Override
     public void removeAccessibilityInteractionConnection(IWindow window) {
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
                     UserHandle.getCallingUserId());
             IBinder token = window.asBinder();
@@ -675,6 +706,9 @@
                 Manifest.permission.RETRIEVE_WINDOW_TOKEN,
                 GET_WINDOW_TOKEN);
         synchronized (mLock) {
+            // We treat calls from a profile as if made by its parent as profiles
+            // share the accessibility state of the parent. The call below
+            // performs the current profile parent resolution.
             final int resolvedUserId = mSecurityPolicy
                     .resolveCallingUserIdEnforcingPermissionsLocked(
                             UserHandle.getCallingUserId());
@@ -770,7 +804,7 @@
             }
 
             // Disconnect from services for the old user.
-            UserState oldUserState = getUserStateLocked(mCurrentUserId);
+            UserState oldUserState = getCurrentUserStateLocked();
             oldUserState.onSwitchToAnotherUser();
 
             // Disable the local managers for the old user.
@@ -2034,6 +2068,9 @@
         @Override
         public List<AccessibilityWindowInfo> getWindows() {
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its perent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
                                 UserHandle.getCallingUserId());
@@ -2062,6 +2099,9 @@
         @Override
         public AccessibilityWindowInfo getWindow(int windowId) {
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
                                 UserHandle.getCallingUserId());
@@ -2092,6 +2132,9 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
                                 UserHandle.getCallingUserId());
@@ -2136,9 +2179,12 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
-                        UserHandle.getCallingUserId());
+                                UserHandle.getCallingUserId());
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
@@ -2180,9 +2226,12 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
-                        UserHandle.getCallingUserId());
+                                UserHandle.getCallingUserId());
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
@@ -2224,9 +2273,12 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
-                        UserHandle.getCallingUserId());
+                                UserHandle.getCallingUserId());
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
@@ -2268,9 +2320,12 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
-                        UserHandle.getCallingUserId());
+                                UserHandle.getCallingUserId());
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
@@ -2311,9 +2366,12 @@
             final int resolvedWindowId;
             IAccessibilityInteractionConnection connection = null;
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
-                        UserHandle.getCallingUserId());
+                                UserHandle.getCallingUserId());
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
@@ -2346,9 +2404,12 @@
 
         public boolean performGlobalAction(int action) {
             synchronized (mLock) {
+                // We treat calls from a profile as if made by its parent as profiles
+                // share the accessibility state of the parent. The call below
+                // performs the current profile parent resolution.
                 final int resolvedUserId = mSecurityPolicy
                         .resolveCallingUserIdEnforcingPermissionsLocked(
-                        UserHandle.getCallingUserId());
+                                UserHandle.getCallingUserId());
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
@@ -3407,16 +3468,35 @@
                     & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
         }
 
+        private int resolveProfileParentLocked(int userId) {
+            if (userId != mCurrentUserId) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    UserInfo parent = mUserManager.getProfileParent(userId);
+                    if (parent != null) {
+                        return parent.getUserHandle().getIdentifier();
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+            return userId;
+        }
+
         public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) {
             final int callingUid = Binder.getCallingUid();
             if (callingUid == 0
                     || callingUid == Process.SYSTEM_UID
                     || callingUid == Process.SHELL_UID) {
-                return mCurrentUserId;
+                if (userId == UserHandle.USER_CURRENT
+                        || userId == UserHandle.USER_CURRENT_OR_SELF) {
+                    return mCurrentUserId;
+                }
+                return resolveProfileParentLocked(userId);
             }
             final int callingUserId = UserHandle.getUserId(callingUid);
             if (callingUserId == userId) {
-                return userId;
+                return resolveProfileParentLocked(userId);
             }
             if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS)
                     && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
@@ -3673,8 +3753,10 @@
         public void onChange(boolean selfChange, Uri uri) {
             if (mAccessibilityEnabledUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readAccessibilityEnabledSettingLocked(userState)) {
                             onUserStateChangedLocked(userState);
@@ -3683,8 +3765,10 @@
                 }
             } else if (mTouchExplorationEnabledUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readTouchExplorationEnabledSettingLocked(userState)) {
                             onUserStateChangedLocked(userState);
@@ -3693,8 +3777,10 @@
                 }
             } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readDisplayMagnificationEnabledSettingLocked(userState)) {
                             onUserStateChangedLocked(userState);
@@ -3703,8 +3789,10 @@
                 }
             } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readEnabledAccessibilityServicesLocked(userState)) {
                             onUserStateChangedLocked(userState);
@@ -3713,8 +3801,10 @@
                 }
             } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
                             onUserStateChangedLocked(userState);
@@ -3723,8 +3813,10 @@
                 }
             } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
                             onUserStateChangedLocked(userState);
@@ -3739,8 +3831,10 @@
                     || mDisplayInversionUri.equals(uri)
                     || mDisplayDaltonizerUri.equals(uri)) {
                 synchronized (mLock) {
-                    // We will update when the automation service dies.
+                    // Profiles share the accessibility state of the parent. Therefore,
+                    // we are checking for changes only the parent settings.
                     UserState userState = getCurrentUserStateLocked();
+                    // We will update when the automation service dies.
                     if (userState.mUiAutomationService == null) {
                         if (readDisplayColorAdjustmentSettingsLocked(userState)) {
                             updateDisplayColorAdjustmentSettingsLocked(userState);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 132ca00..ea9de1e 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -41,6 +41,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Slog;
 import android.view.InputDevice;
+import android.media.AudioManager;
 
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.app.IBatteryStats;
@@ -73,6 +74,8 @@
     private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
 
     private int mCurVibUid = -1;
+    private boolean mLowPowerMode;
+    private SettingsObserver mSettingObserver;
 
     native static boolean vibratorExists();
     native static void vibratorOn(long milliseconds);
@@ -159,15 +162,15 @@
 
     public void systemReady() {
         mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
+        mSettingObserver = new SettingsObserver(mH);
 
         mContext.getContentResolver().registerContentObserver(
-                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true,
-                new ContentObserver(mH) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        updateInputDeviceVibrators();
-                    }
-                }, UserHandle.USER_ALL);
+                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
+                true, mSettingObserver, UserHandle.USER_ALL);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE), false,
+                mSettingObserver, UserHandle.USER_ALL);
 
         mContext.registerReceiver(new BroadcastReceiver() {
             @Override
@@ -179,6 +182,17 @@
         updateInputDeviceVibrators();
     }
 
+    private final class SettingsObserver extends ContentObserver {
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean SelfChange) {
+            updateInputDeviceVibrators();
+        }
+    }
+
     public boolean hasVibrator() {
         return doVibratorExists();
     }
@@ -346,6 +360,9 @@
     // Lock held on mVibrations
     private void startVibrationLocked(final Vibration vib) {
         try {
+            if (mLowPowerMode && vib.mStreamHint != AudioManager.STREAM_RING)
+                    return;
+
             int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
                     vib.mStreamHint, vib.mUid, vib.mOpPkg);
             if (mode == AppOpsManager.MODE_ALLOWED) {
@@ -425,6 +442,9 @@
                 } catch (SettingNotFoundException snfe) {
                 }
 
+                mLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
+                     Settings.Global.LOW_POWER_MODE, 0) != 0;
+
                 if (mVibrateInputDevicesSetting) {
                     if (!mInputDeviceListenerRegistered) {
                         mInputDeviceListenerRegistered = true;
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 50cfe48..c32beda 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -70,6 +70,7 @@
     private static final String NAME_HDMI = "hdmi";
 
     private static final int MSG_NEW_DEVICE_STATE = 1;
+    private static final int MSG_SYSTEM_READY = 2;
 
     private final Object mLock = new Object();
 
@@ -96,19 +97,9 @@
                 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
 
         mObserver = new WiredAccessoryObserver();
-
-        IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
-        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
-        context.registerReceiver(new BroadcastReceiver() {
-                    @Override
-                    public void onReceive(Context ctx, Intent intent) {
-                        bootCompleted();
-                    }
-                },
-                filter, null, null);
     }
 
-    private void bootCompleted() {
+    private void onSystemReady() {
         if (mUseDevInputEventForAudioJack) {
             int switchValues = 0;
             if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {
@@ -159,6 +150,16 @@
         }
     }
 
+    @Override
+    public void systemReady() {
+        synchronized (mLock) {
+            mWakeLock.acquire();
+
+            Message msg = mHandler.obtainMessage(MSG_SYSTEM_READY, 0, 0, null);
+            mHandler.sendMessage(msg);
+        }
+    }
+
     /**
      * Compare the existing headset state with the new state and pass along accordingly. Note
      * that this only supports a single headset at a time. Inserting both a usb and jacked headset
@@ -220,6 +221,11 @@
                 case MSG_NEW_DEVICE_STATE:
                     setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);
                     mWakeLock.release();
+                    break;
+                case MSG_SYSTEM_READY:
+                    onSystemReady();
+                    mWakeLock.release();
+                    break;
             }
         }
     };
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 29c781b..5358c1a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -35,6 +35,7 @@
 import android.appwidget.AppWidgetManager;
 import android.graphics.Rect;
 import android.os.BatteryStats;
+import android.os.PersistableBundle;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArrayMap;
 
@@ -1327,12 +1328,14 @@
                 String host = "";
                 String port = "";
                 String exclList = "";
-                String pacFileUrl = null;
+                String pacFileUrl = "";
                 if (proxy != null) {
                     host = proxy.getHost();
                     port = Integer.toString(proxy.getPort());
                     exclList = proxy.getExclusionListAsString();
-                    pacFileUrl = proxy.getPacFileUrl().toString();
+                    if (proxy.getPacFileUrl() != null) {
+                        pacFileUrl = proxy.getPacFileUrl().toString();
+                    }
                 }
                 synchronized (ActivityManagerService.this) {
                     for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
@@ -1850,6 +1853,12 @@
 
         @Override
         public boolean onPackageChanged(String packageName, int uid, String[] components) {
+            onPackageModified(packageName);
+            return true;
+        }
+
+        @Override
+        public void onPackageModified(String packageName) {
             final PackageManager pm = mContext.getPackageManager();
             final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
                     new ArrayList<Pair<Intent, Integer>>();
@@ -1885,7 +1894,6 @@
                     removeTaskByIdLocked(tasksToRemove.get(i), 0);
                 }
             }
-            return true;
         }
 
         @Override
@@ -5422,22 +5430,21 @@
     }
 
     @Override
-    public final void activityPaused(IBinder token) {
+    public final void activityPaused(IBinder token, PersistableBundle persistentState) {
         final long origId = Binder.clearCallingIdentity();
         synchronized(this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
-                stack.activityPausedLocked(token, false);
+                stack.activityPausedLocked(token, false, persistentState);
             }
         }
         Binder.restoreCallingIdentity(origId);
     }
 
     @Override
-    public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
-            CharSequence description) {
-        if (localLOGV) Slog.v(
-            TAG, "Activity stopped: token=" + token);
+    public final void activityStopped(IBinder token, Bundle icicle,
+            PersistableBundle persistentState, CharSequence description) {
+        if (localLOGV) Slog.v(TAG, "Activity stopped: token=" + token);
 
         // Refuse possible leaked file descriptors
         if (icicle != null && icicle.hasFileDescriptors()) {
@@ -5449,7 +5456,7 @@
         synchronized (this) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.task.stack.activityStoppedLocked(r, icicle, thumbnail, description);
+                r.task.stack.activityStoppedLocked(r, icicle, persistentState, description);
             }
         }
 
@@ -9565,6 +9572,7 @@
             }
 
             mAppOpsService.systemReady();
+            mUsageStatsService.systemReady();
             mSystemReady = true;
         }
 
@@ -14386,6 +14394,7 @@
                 newConfig.seq = mConfigurationSeq;
                 mConfiguration = newConfig;
                 Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
+                mUsageStatsService.noteStartConfig(newConfig);
 
                 final Configuration configCopy = new Configuration(mConfiguration);
                 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index efd2b57..8391f79 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.os.PersistableBundle;
 import android.os.Trace;
 import com.android.internal.app.ResolverActivity;
 import com.android.server.AttributeCache;
@@ -117,6 +118,7 @@
     ProcessRecord app;      // if non-null, hosting application
     ActivityState state;    // current state we are in
     Bundle  icicle;         // last saved activity state
+    PersistableBundle persistentState; // last persistently saved activity state
     boolean frontOfTask;    // is this the root activity of its task?
     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
     boolean haveState;      // have we gotten the last activity state?
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a95710b..7c29d85 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -68,6 +68,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -276,7 +277,7 @@
                         if (r.app != null) {
                             mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
                         }
-                        activityPausedLocked(r.appToken, true);
+                        activityPausedLocked(r.appToken, true, r.persistentState);
                     }
                 } break;
                 case LAUNCH_TICK_MSG: {
@@ -860,13 +861,15 @@
         }
     }
 
-    final void activityPausedLocked(IBinder token, boolean timeout) {
+    final void activityPausedLocked(IBinder token, boolean timeout,
+            PersistableBundle persistentState) {
         if (DEBUG_PAUSE) Slog.v(
             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
 
         final ActivityRecord r = isInStackLocked(token);
         if (r != null) {
             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
+            r.persistentState = persistentState;
             if (mPausingActivity == r) {
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
                         + (timeout ? " (due to timeout)" : " (pause complete)"));
@@ -881,13 +884,14 @@
         }
     }
 
-    final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
-            CharSequence description) {
+    final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
+            PersistableBundle persistentState, CharSequence description) {
         if (r.state != ActivityState.STOPPING) {
             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
             return;
         }
+        r.persistentState = persistentState;
         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
         if (icicle != null) {
             // If icicle is null, this is happening due to a timeout, so we
@@ -895,7 +899,7 @@
             r.icicle = icicle;
             r.haveState = true;
             r.launchCount = 0;
-            r.updateThumbnail(thumbnail, description);
+            r.updateThumbnail(null, description);
         }
         if (!r.stopped) {
             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
@@ -1080,20 +1084,6 @@
         }
     }
 
-    /**
-     * Version of ensureActivitiesVisible that can easily be called anywhere.
-     */
-    final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
-        return ensureActivitiesVisibleLocked(starting, configChanges, false);
-    }
-
-    final boolean ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
-            boolean forceHomeShown) {
-        ActivityRecord r = topRunningActivityLocked(null);
-        return r != null &&
-                ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown);
-    }
-
     // Checks if any of the stacks above this one has a fullscreen activity behind it.
     // If so, this stack is hidden, otherwise it is visible.
     private boolean isStackVisible() {
@@ -1105,16 +1095,26 @@
             return true;
         }
 
-        // Start at the task above this one and go up, looking for a visible
-        // fullscreen activity, or a translucent activity that requested the
-        // wallpaper to be shown behind it.
+        /**
+         * Start at the task above this one and go up, looking for a visible
+         * fullscreen activity, or a translucent activity that requested the
+         * wallpaper to be shown behind it.
+         */
         for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
             final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
             for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
                 final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities;
                 for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
                     final ActivityRecord r = activities.get(activityNdx);
-                    if (!r.finishing && r.visible && r.fullscreen) {
+
+                    // Conditions for an activity to obscure the stack we're
+                    // examining:
+                    // 1. Not Finishing AND Visible AND:
+                    // 2. Either:
+                    // - Full Screen Activity OR
+                    // - On top of Home and our stack is NOT home
+                    if (!r.finishing && r.visible && (r.fullscreen ||
+                            (!isHomeStack() && r.frontOfTask && tasks.get(taskNdx).mOnTopOfHome))) {
                         return false;
                     }
                 }
@@ -1124,12 +1124,19 @@
         return true;
     }
 
+    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+        ActivityRecord r = topRunningActivityLocked(null);
+        if (r != null) {
+            ensureActivitiesVisibleLocked(r, starting, null, configChanges);
+        }
+    }
+
     /**
      * Make sure that all activities that need to be visible (that is, they
      * currently can be seen by the user) actually are.
      */
-    final boolean ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
-            String onlyThisProcess, int configChanges, boolean forceHomeShown) {
+    final void ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
+            String onlyThisProcess, int configChanges) {
         if (DEBUG_VISBILITY) Slog.v(
                 TAG, "ensureActivitiesVisible behind " + top
                 + " configChanges=0x" + Integer.toHexString(configChanges));
@@ -1147,7 +1154,6 @@
         // If the top activity is not fullscreen, then we need to
         // make sure any activities under it are now visible.
         boolean aboveTop = true;
-        boolean showHomeBehindStack = false;
         boolean behindFullscreen = !isStackVisible();
 
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -1235,11 +1241,9 @@
                         // At this point, nothing else needs to be shown
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
                         behindFullscreen = true;
-                        showHomeBehindStack = false;
-                    } else if (isActivityOverHome(r)) {
+                    } else if (!isHomeStack() && r.frontOfTask && task.mOnTopOfHome) {
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
-                        showHomeBehindStack = true;
-                        behindFullscreen = !isHomeStack() && r.frontOfTask && task.mOnTopOfHome;
+                        behindFullscreen = true;
                     }
                 } else {
                     if (DEBUG_VISBILITY) Slog.v(
@@ -1289,7 +1293,6 @@
                 }
             }
         }
-        return showHomeBehindStack;
     }
 
     void convertToTranslucent(ActivityRecord r) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 00327ac..6f62a03 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1026,10 +1026,10 @@
             r.clearOptionsLocked();
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info,
-                    new Configuration(mService.mConfiguration), r.compat,
-                    r.task.voiceInteractor, app.repProcState, r.icicle, results, newIntents,
-                    !andResume, mService.isNextTransitionForward(), profileFile, profileFd,
-                    profileAutoStop, options);
+                    new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor,
+                    app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume,
+                    mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop,
+                    options);
 
             if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
                 // This may be a heavy-weight process!  Note that the package
@@ -2455,21 +2455,12 @@
 
     void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
         // First the front stacks. In case any are not fullscreen and are in front of home.
-        boolean showHomeBehindStack = false;
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             final int topStackNdx = stacks.size() - 1;
             for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
-                if (stackNdx == topStackNdx) {
-                    // Top stack.
-                    showHomeBehindStack =
-                            stack.ensureActivitiesVisibleLocked(starting, configChanges);
-                } else {
-                    // Back stack.
-                    stack.ensureActivitiesVisibleLocked(starting, configChanges,
-                            showHomeBehindStack);
-                }
+                stack.ensureActivitiesVisibleLocked(starting, configChanges);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java
index 42cf900..4a5a554 100644
--- a/services/core/java/com/android/server/am/UsageStatsService.java
+++ b/services/core/java/com/android/server/am/UsageStatsService.java
@@ -17,26 +17,31 @@
 package com.android.server.am;
 
 import android.app.AppGlobals;
+import android.app.AppOpsManager;
+import android.app.UsageStats;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.FileUtils;
 import android.os.Parcel;
+import android.os.ParcelableParcel;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.text.format.DateFormat;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Slog;
+import android.util.TimeUtils;
 import android.util.Xml;
 
 import com.android.internal.app.IUsageStats;
 import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.PkgUsageStats;
 import com.android.internal.util.FastXmlSerializer;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -46,7 +51,6 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -55,8 +59,6 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
 import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -75,7 +77,7 @@
     private static final String TAG = "UsageStats";
 
     // Current on-disk Parcel version
-    private static final int VERSION = 1008;
+    private static final int VERSION = 1010;
 
     private static final int CHECKIN_VERSION = 4;
 
@@ -94,13 +96,10 @@
 
     static IUsageStats sService;
     private Context mContext;
-    // structure used to maintain statistics since the last checkin.
-    final private ArrayMap<String, PkgUsageStatsExtended> mStats
-            = new ArrayMap<String, PkgUsageStatsExtended>();
+    private AppOpsManager mAppOps;
 
-    // Maintains the last time any component was resumed, for all time.
-    final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes
-            = new ArrayMap<String, ArrayMap<String, Long>>();
+    // structure used to maintain statistics since the last checkin.
+    private LocalUsageStats mStats = new LocalUsageStats();
 
     // To remove last-resume time stats when a pacakge is removed.
     private PackageMonitor mPackageMonitor;
@@ -115,6 +114,7 @@
     private String mLastResumedPkg;
     private String mLastResumedComp;
     private boolean mIsResumed;
+    private ConfigUsageStatsExtended mCurrentConfigStats;
     private File mFile;
     private AtomicFile mHistoryFile;
     private String mFileLeaf;
@@ -127,6 +127,30 @@
     private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0);
     private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false);
 
+    static class LocalUsageStats extends UsageStats {
+        public LocalUsageStats() {
+        }
+        public LocalUsageStats(Parcel in, boolean extended) {
+            super(in, extended);
+        }
+        @Override
+        public PackageStats onNewPackageStats(String pkgName) {
+            return new PkgUsageStatsExtended(pkgName);
+        }
+        @Override
+        public PackageStats onNewPackageStats(Parcel in) {
+            return new PkgUsageStatsExtended(in);
+        }
+        @Override
+        public ConfigurationStats onNewConfigurationStats(Configuration config) {
+            return new ConfigUsageStatsExtended(config);
+        }
+        @Override
+        public ConfigurationStats onNewConfigurationStats(Parcel source) {
+            return new ConfigUsageStatsExtended(source);
+        }
+    }
+
     static class TimeStats {
         int mCount;
         final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS];
@@ -166,27 +190,18 @@
         }
     }
 
-    static class PkgUsageStatsExtended {
+    static class PkgUsageStatsExtended extends UsageStats.PackageStats {
         final ArrayMap<String, TimeStats> mLaunchTimes
                 = new ArrayMap<String, TimeStats>();
         final ArrayMap<String, TimeStats> mFullyDrawnTimes
                 = new ArrayMap<String, TimeStats>();
-        int mLaunchCount;
-        long mUsageTime;
-        long mPausedTime;
-        long mResumedTime;
 
-        PkgUsageStatsExtended() {
-            mLaunchCount = 0;
-            mUsageTime = 0;
+        PkgUsageStatsExtended(String pkgName) {
+            super(pkgName);
         }
 
         PkgUsageStatsExtended(Parcel in) {
-            mLaunchCount = in.readInt();
-            mUsageTime = in.readLong();
-            if (localLOGV) Slog.v(TAG, "Launch count: " + mLaunchCount
-                    + ", Usage time:" + mUsageTime);
-
+            super(in);
             final int numLaunchTimeStats = in.readInt();
             if (localLOGV) Slog.v(TAG, "Reading launch times: " + numLaunchTimeStats);
             mLaunchTimes.ensureCapacity(numLaunchTimeStats);
@@ -208,18 +223,6 @@
             }
         }
 
-        void updateResume(String comp, boolean launched) {
-            if (launched) {
-                mLaunchCount++;
-            }
-            mResumedTime = SystemClock.elapsedRealtime();
-        }
-
-        void updatePause() {
-            mPausedTime =  SystemClock.elapsedRealtime();
-            mUsageTime += (mPausedTime - mResumedTime);
-        }
-
         void addLaunchCount(String comp) {
             TimeStats times = mLaunchTimes.get(comp);
             if (times == null) {
@@ -247,9 +250,7 @@
             times.add(millis);
         }
 
-        void writeToParcel(Parcel out) {
-            out.writeInt(mLaunchCount);
-            out.writeLong(mUsageTime);
+        public void writeExtendedToParcel(Parcel out, int parcelableFlags) {
             final int numLaunchTimeStats = mLaunchTimes.size();
             out.writeInt(numLaunchTimeStats);
             for (int i=0; i<numLaunchTimeStats; i++) {
@@ -264,11 +265,21 @@
             }
         }
 
-        void clear() {
+        @Override
+        public boolean clearUsageTimes() {
             mLaunchTimes.clear();
             mFullyDrawnTimes.clear();
-            mLaunchCount = 0;
-            mUsageTime = 0;
+            return super.clearUsageTimes();
+        }
+    }
+
+    static class ConfigUsageStatsExtended extends UsageStats.ConfigurationStats {
+        ConfigUsageStatsExtended(Configuration config) {
+            super(config);
+        }
+
+        ConfigUsageStatsExtended(Parcel in) {
+            super(in);
         }
     }
 
@@ -364,18 +375,9 @@
                    + VERSION + "; dropping");
             return;
         }
-        int N = in.readInt();
-        while (N > 0) {
-            N--;
-            String pkgName = in.readString();
-            if (pkgName == null) {
-                break;
-            }
-            if (localLOGV) Slog.v(TAG, "Reading package #" + N + ": " + pkgName);
-            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
-            synchronized (mStatsLock) {
-                mStats.put(pkgName, pus);
-            }
+        LocalUsageStats stats = new LocalUsageStats(in, true);
+        synchronized (mStatsLock) {
+            mStats = stats;
         }
     }
 
@@ -419,12 +421,9 @@
                                 try {
                                     long lastResumeTime = Long.parseLong(lastResumeTimeStr);
                                     synchronized (mStatsLock) {
-                                        ArrayMap<String, Long> lrt = mLastResumeTimes.get(pkg);
-                                        if (lrt == null) {
-                                            lrt = new ArrayMap<String, Long>();
-                                            mLastResumeTimes.put(pkg, lrt);
-                                        }
-                                        lrt.put(comp, lastResumeTime);
+                                        PkgUsageStatsExtended pus = (PkgUsageStatsExtended)
+                                                mStats.getOrCreatePackageStats(pkg);
+                                        pus.componentResumeTimes.put(comp, lastResumeTime);
                                     }
                                 } catch (NumberFormatException e) {
                                 }
@@ -543,6 +542,15 @@
             return;
         }
 
+        Parcel out = Parcel.obtain();
+        synchronized (mStatsLock) {
+            out.writeInt(VERSION);
+            mStats.writeExtendedToParcel(out, 0);
+            if (dayChanged) {
+                mStats.clearUsageTimes();
+            }
+        }
+
         synchronized (mFileLock) {
             // Get the most recent file
             mFileLeaf = getCurrentDateStr(FILE_PREFIX);
@@ -553,6 +561,7 @@
                 if (!backupFile.exists()) {
                     if (!mFile.renameTo(backupFile)) {
                         Slog.w(TAG, "Failed to persist new stats");
+                        out.recycle();
                         return;
                     }
                 } else {
@@ -562,14 +571,10 @@
 
             try {
                 // Write mStats to file
-                writeStatsFLOCK(mFile);
+                writeStatsFLOCK(mFile, out);
                 mLastWriteElapsedTime.set(currElapsedTime);
                 if (dayChanged) {
                     mLastWriteDay.set(curDay);
-                    // clear stats
-                    synchronized (mStats) {
-                        mStats.clear();
-                    }
                     mFile = new File(mDir, mFileLeaf);
                     checkFileLimitFLOCK();
                 }
@@ -590,17 +595,15 @@
                     backupFile.renameTo(mFile);
                 }
             }
+            out.recycle();
         }
         if (localLOGV) Slog.d(TAG, "Dumped usage stats.");
     }
 
-    private void writeStatsFLOCK(File file) throws IOException {
+    private void writeStatsFLOCK(File file, Parcel parcel) throws IOException {
         FileOutputStream stream = new FileOutputStream(file);
         try {
-            Parcel out = Parcel.obtain();
-            writeStatsToParcelFLOCK(out);
-            stream.write(out.marshall());
-            out.recycle();
+            stream.write(parcel.marshall());
             stream.flush();
         } finally {
             FileUtils.sync(stream);
@@ -608,29 +611,14 @@
         }
     }
 
-    private void writeStatsToParcelFLOCK(Parcel out) {
-        synchronized (mStatsLock) {
-            out.writeInt(VERSION);
-            Set<String> keys = mStats.keySet();
-            out.writeInt(keys.size());
-            for (String key : keys) {
-                PkgUsageStatsExtended pus = mStats.get(key);
-                out.writeString(key);
-                pus.writeToParcel(out);
-            }
-        }
-    }
-
     /** Filter out stats for any packages which aren't present anymore. */
     private void filterHistoryStats() {
         synchronized (mStatsLock) {
             IPackageManager pm = AppGlobals.getPackageManager();
-            for (int i=0; i<mLastResumeTimes.size(); i++) {
-                String pkg = mLastResumeTimes.keyAt(i);
+            for (int i=mStats.mPackages.size()-1; i>=0; i--) {
                 try {
-                    if (pm.getPackageUid(pkg, 0) < 0) {
-                        mLastResumeTimes.removeAt(i);
-                        i--;
+                    if (pm.getPackageUid(mStats.mPackages.valueAt(i).getPackageName(), 0) < 0) {
+                        mStats.mPackages.removeAt(i);
                     }
                 } catch (RemoteException e) {
                 }
@@ -648,10 +636,12 @@
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             out.startTag(null, "usage-history");
             synchronized (mStatsLock) {
-                for (int i=0; i<mLastResumeTimes.size(); i++) {
+                int NP = mStats.mPackages.size();
+                for (int i=0; i<NP; i++) {
+                    UsageStats.PackageStats ps = mStats.mPackages.valueAt(i);
                     out.startTag(null, "pkg");
-                    out.attribute(null, "name", mLastResumeTimes.keyAt(i));
-                    ArrayMap<String, Long> comp = mLastResumeTimes.valueAt(i);
+                    out.attribute(null, "name", ps.getPackageName());
+                    ArrayMap<String, Long> comp = ps.componentResumeTimes;
                     for (int j=0; j<comp.size(); j++) {
                         out.startTag(null, "comp");
                         out.attribute(null, "name", comp.keyAt(j));
@@ -678,6 +668,10 @@
         ServiceManager.addService(SERVICE_NAME, asBinder());
     }
 
+    public void systemReady() {
+        mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
+    }
+
     /**
      * Start watching packages to remove stats when a package is uninstalled.
      * May only be called when the package manager is ready.
@@ -687,7 +681,7 @@
             @Override
             public void onPackageRemovedAllUsers(String packageName, int uid) {
                 synchronized (mStatsLock) {
-                    mLastResumeTimes.remove(packageName);
+                    mStats.mPackages.remove(packageName);
                 }
             }
         };
@@ -729,9 +723,10 @@
                     // to recover.
                     if (REPORT_UNEXPECTED) Slog.i(TAG, "Unexpected resume of " + pkgName
                             + " while already resumed in " + mLastResumedPkg);
-                    PkgUsageStatsExtended pus = mStats.get(mLastResumedPkg);
+                    PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(
+                            mLastResumedPkg);
                     if (pus != null) {
-                        pus.updatePause();
+                        pus.pause();
                     }
                 }
             }
@@ -744,22 +739,13 @@
             mLastResumedComp = componentName.getClassName();
 
             if (localLOGV) Slog.i(TAG, "started component:" + pkgName);
-            PkgUsageStatsExtended pus = mStats.get(pkgName);
-            if (pus == null) {
-                pus = new PkgUsageStatsExtended();
-                mStats.put(pkgName, pus);
-            }
-            pus.updateResume(mLastResumedComp, !samePackage);
+            PkgUsageStatsExtended pus = (PkgUsageStatsExtended)
+                    mStats.getOrCreatePackageStats(pkgName);
+            pus.resume(!samePackage);
             if (!sameComp) {
                 pus.addLaunchCount(mLastResumedComp);
             }
-
-            ArrayMap<String, Long> componentResumeTimes = mLastResumeTimes.get(pkgName);
-            if (componentResumeTimes == null) {
-                componentResumeTimes = new ArrayMap<String, Long>();
-                mLastResumeTimes.put(pkgName, componentResumeTimes);
-            }
-            componentResumeTimes.put(mLastResumedComp, System.currentTimeMillis());
+            pus.componentResumeTimes.put(mLastResumedComp, System.currentTimeMillis());
         }
     }
 
@@ -782,13 +768,13 @@
 
             if (localLOGV) Slog.i(TAG, "paused component:"+pkgName);
 
-            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
             if (pus == null) {
                 // Weird some error here
                 Slog.i(TAG, "No package stats for pkg:"+pkgName);
                 return;
             }
-            pus.updatePause();
+            pus.pause();
         }
 
         // Persist current data to file if needed.
@@ -808,7 +794,7 @@
         writeStatsToFile(false, false);
 
         synchronized (mStatsLock) {
-            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
             if (pus != null) {
                 pus.addLaunchTime(componentName.getClassName(), millis);
             }
@@ -827,13 +813,29 @@
         writeStatsToFile(false, false);
 
         synchronized (mStatsLock) {
-            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
             if (pus != null) {
                 pus.addFullyDrawnTime(componentName.getClassName(), millis);
             }
         }
     }
 
+    public void noteStartConfig(Configuration config) {
+        enforceCallingPermission();
+        synchronized (mStatsLock) {
+            config = new Configuration(config);
+            ConfigUsageStatsExtended cus = (ConfigUsageStatsExtended)
+                    mStats.getOrCreateConfigurationStats(config);
+            if (cus != mCurrentConfigStats) {
+                if (mCurrentConfigStats != null) {
+                    mCurrentConfigStats.stop();
+                }
+                cus.start();
+                mCurrentConfigStats = cus;
+            }
+        }
+    }
+
     public void enforceCallingPermission() {
         if (Binder.getCallingPid() == Process.myPid()) {
             return;
@@ -843,53 +845,71 @@
     }
 
     @Override
-    public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+    public UsageStats.PackageStats getPkgUsageStats(String callingPkg,
+            ComponentName componentName) {
+        checkCallerPermission(callingPkg, "getPkgUsageStats");
         String pkgName;
         if ((componentName == null) ||
                 ((pkgName = componentName.getPackageName()) == null)) {
             return null;
         }
         synchronized (mStatsLock) {
-            PkgUsageStatsExtended pus = mStats.get(pkgName);
-            Map<String, Long> lastResumeTimes = mLastResumeTimes.get(pkgName);
-            if (pus == null && lastResumeTimes == null) {
+            PkgUsageStatsExtended pus = (PkgUsageStatsExtended)mStats.getPackageStats(pkgName);
+            if (pus == null) {
                 return null;
             }
-            int launchCount = pus != null ? pus.mLaunchCount : 0;
-            long usageTime = pus != null ? pus.mUsageTime : 0;
-            return new PkgUsageStats(pkgName, launchCount, usageTime, lastResumeTimes);
+            return new UsageStats.PackageStats(pus);
         }
     }
 
     @Override
-    public PkgUsageStats[] getAllPkgUsageStats() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+    public UsageStats.PackageStats[] getAllPkgUsageStats(String callingPkg) {
+        checkCallerPermission(callingPkg, "getAllPkgUsageStats");
         synchronized (mStatsLock) {
-            int size = mLastResumeTimes.size();
-            if (size <= 0) {
+            int NP = mStats.mPackages.size();
+            if (NP <= 0) {
                 return null;
             }
-            PkgUsageStats retArr[] = new PkgUsageStats[size];
-            for (int i=0; i<size; i++) {
-                String pkg = mLastResumeTimes.keyAt(i);
-                long usageTime = 0;
-                int launchCount = 0;
-
-                PkgUsageStatsExtended pus = mStats.get(pkg);
-                if (pus != null) {
-                    usageTime = pus.mUsageTime;
-                    launchCount = pus.mLaunchCount;
-                }
-                retArr[i] = new PkgUsageStats(pkg, launchCount, usageTime,
-                        mLastResumeTimes.valueAt(i));
+            UsageStats.PackageStats retArr[] = new UsageStats.PackageStats[NP];
+            for (int p=0; p<NP; p++) {
+                UsageStats.PackageStats ps = mStats.mPackages.valueAt(p);
+                retArr[p] = new UsageStats.PackageStats(ps);
             }
             return retArr;
         }
     }
 
+    @Override
+    public ParcelableParcel getCurrentStats(String callingPkg) {
+        checkCallerPermission(callingPkg, "getCurrentStats");
+        synchronized (mStatsLock) {
+            ParcelableParcel out = new ParcelableParcel(null);
+            mStats.writeToParcel(out.getParcel(), 0);
+            return out;
+        }
+    }
+
+    private void checkCallerPermission(String callingPkg, String callingOp) {
+        // Because the permission for this is system-only, its use with
+        // app ops is a little different: the op is disabled by default,
+        // and enabling it allows apps to get access even if they don't
+        // hold the permission.
+        int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_GET_USAGE_STATS, Binder.getCallingUid(),
+                callingPkg);
+        if (mode == AppOpsManager.MODE_ALLOWED) {
+            return;
+        } else if (mode != AppOpsManager.MODE_IGNORED) {
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.PACKAGE_USAGE_STATS)
+                    == PackageManager.PERMISSION_GRANTED) {
+                return;
+            }
+        }
+
+        String msg = "Package " + callingPkg + " not allowed to call " + callingOp;
+        throw new SecurityException(msg);
+    }
+
     static byte[] readFully(FileInputStream stream) throws IOException {
         int pos = 0;
         int avail = stream.available();
@@ -963,31 +983,28 @@
             return;
         }
 
-        pw.println(sb.toString());
-        int N = in.readInt();
+        final LocalUsageStats stats = new LocalUsageStats(in, true);
+        final long time = SystemClock.elapsedRealtime();
 
-        while (N > 0) {
-            N--;
-            String pkgName = in.readString();
-            if (pkgName == null) {
-                break;
-            }
+        pw.println(sb.toString());
+        int NP = stats.mPackages.size();
+        for (int p=0; p<NP; p++) {
+            PkgUsageStatsExtended pus = (PkgUsageStatsExtended)stats.mPackages.valueAt(p);
             sb.setLength(0);
-            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
-            if (packages != null && !packages.contains(pkgName)) {
+            if (packages != null && !packages.contains(pus.getPackageName())) {
                 // This package has not been requested -- don't print
                 // anything for it.
             } else if (isCompactOutput) {
                 sb.append("P:");
-                sb.append(pkgName);
+                sb.append(pus.getPackageName());
                 sb.append(',');
-                sb.append(pus.mLaunchCount);
+                sb.append(pus.getLaunchCount());
                 sb.append(',');
-                sb.append(pus.mUsageTime);
+                sb.append(pus.getUsageTime(time));
                 sb.append('\n');
                 final int NLT = pus.mLaunchTimes.size();
                 for (int i=0; i<NLT; i++) {
-                    sb.append("A:");
+                    sb.append("L:");
                     String activity = pus.mLaunchTimes.keyAt(i);
                     sb.append(activity);
                     TimeStats times = pus.mLaunchTimes.valueAt(i);
@@ -1001,7 +1018,7 @@
                 }
                 final int NFDT = pus.mFullyDrawnTimes.size();
                 for (int i=0; i<NFDT; i++) {
-                    sb.append("A:");
+                    sb.append("D:");
                     String activity = pus.mFullyDrawnTimes.keyAt(i);
                     sb.append(activity);
                     TimeStats times = pus.mFullyDrawnTimes.valueAt(i);
@@ -1011,15 +1028,23 @@
                     }
                     sb.append('\n');
                 }
+                final int NC = pus.componentResumeTimes.size();
+                for (int c=0; c<NC; c++) {
+                    pw.print("R:"); pw.print(pus.componentResumeTimes.keyAt(c)); pw.print(",");
+                    pw.println(pus.componentResumeTimes.valueAt(c));
+                }
 
             } else {
                 sb.append("  ");
-                sb.append(pkgName);
-                sb.append(": ");
-                sb.append(pus.mLaunchCount);
-                sb.append(" times, ");
-                sb.append(pus.mUsageTime);
-                sb.append(" ms");
+                sb.append(pus.getPackageName());
+                if (pus.getLaunchCount() != 0 || pus.getUsageTime(time) != 0) {
+                    sb.append(": ");
+                    sb.append(pus.getLaunchCount());
+                    sb.append(" times, ");
+                    TimeUtils.formatDuration(pus.getUsageTime(time), sb);
+                } else {
+                    sb.append(":");
+                }
                 sb.append('\n');
                 final int NLT = pus.mLaunchTimes.size();
                 for (int i=0; i<NLT; i++) {
@@ -1084,10 +1109,50 @@
                     }
                     sb.append('\n');
                 }
+                final int NC = pus.componentResumeTimes.size();
+                for (int c=0; c<NC; c++) {
+                    sb.append("    ");
+                    sb.append(pus.componentResumeTimes.keyAt(c));
+                    sb.append(" last resumed ");
+                    sb.append(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+                            pus.componentResumeTimes.valueAt(c)).toString());
+                    sb.append('\n');
+                }
             }
 
             pw.write(sb.toString());
         }
+        if (packages == null) {
+            int NC = stats.mConfigurations.size();
+            for (int c=0; c<NC; c++) {
+                ConfigUsageStatsExtended cus
+                        = (ConfigUsageStatsExtended)stats.mConfigurations.valueAt(c);
+                sb.setLength(0);
+                if (isCompactOutput) {
+                    sb.append("C:"); sb.append(cus.getConfiguration().toString());
+                    sb.append(","); sb.append(cus.getUsageCount()); sb.append(",");
+                    sb.append(cus.getUsageTime(time));
+                } else {
+                    sb.append("  ");
+                    sb.append(cus.getConfiguration().toString());
+                    sb.append(":\n");
+                    if (cus.getUsageCount() != 0 || cus.getUsageTime(time) != 0) {
+                        sb.append("    Used ");
+                        sb.append(cus.getUsageCount());
+                        sb.append(" times, ");
+                        TimeUtils.formatDuration(cus.getUsageTime(time), sb);
+                        sb.append("\n");
+                    }
+                    if (cus.getLastUsedTime() > 0) {
+                        sb.append("    Last used: ");
+                        sb.append(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+                                cus.getLastUsedTime()).toString());
+                        sb.append("\n");
+                    }
+                }
+                pw.write(sb.toString());
+            }
+        }
     }
 
     /**
@@ -1174,5 +1239,4 @@
             collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages);
         }
     }
-
 }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 54cb035..0f5805c 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -323,6 +323,10 @@
 
         mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
         mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
+
+        if (mWiredAccessoryCallbacks != null) {
+            mWiredAccessoryCallbacks.systemReady();
+        }
     }
 
     private void reloadKeyboardLayouts() {
@@ -1588,6 +1592,7 @@
      */
     public interface WiredAccessoryCallbacks {
         public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
+        public void systemReady();
     }
 
     /**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index fce86e8..4698587 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -444,7 +444,7 @@
     public static final class NotificationRecord
     {
         final StatusBarNotification sbn;
-        final SingleNotificationStats stats = new SingleNotificationStats();
+        SingleNotificationStats stats;
         IBinder statusBarKey;
 
         NotificationRecord(StatusBarNotification sbn)
@@ -1639,7 +1639,7 @@
                     } else {
                         old = mNotificationList.get(index);
                         mNotificationList.set(index, r);
-                        mUsageStats.registerUpdatedByApp(r);
+                        mUsageStats.registerUpdatedByApp(r, old);
                         // Make sure we don't lose the foreground service state.
                         if (old != null) {
                             notification.flags |=
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 45ab3d3..a60e95b 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -58,6 +58,7 @@
      * Called when a notification has been posted.
      */
     public synchronized void registerPostedByApp(NotificationRecord notification) {
+        notification.stats = new SingleNotificationStats();
         notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
         for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
             stats.numPostedByApp++;
@@ -68,7 +69,8 @@
     /**
      * Called when a notification has been updated.
      */
-    public void registerUpdatedByApp(NotificationRecord notification) {
+    public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) {
+        notification.stats = old.stats;
         for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
             stats.numUpdatedByApp++;
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c8b61f1..a7f4b28 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -613,6 +613,12 @@
         private final AtomicLong mLastWritten = new AtomicLong(0);
         private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
 
+        private boolean mIsFirstBoot = false;
+
+        boolean isFirstBoot() {
+            return mIsFirstBoot;
+        }
+
         void write(boolean force) {
             if (force) {
                 write();
@@ -701,6 +707,7 @@
                         pkg.mLastPackageUsageTimeInMills = timeInMillis;
                     }
                 } catch (FileNotFoundException expected) {
+                    mIsFirstBoot = true;
                 } catch (IOException e) {
                     Log.w(TAG, "Failed to read package usage times", e);
                 } finally {
@@ -1745,7 +1752,7 @@
 
     @Override
     public boolean isFirstBoot() {
-        return !mRestoredSettings;
+        return !mRestoredSettings || mPackageUsage.isFirstBoot();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4f5326f..60212bf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -288,6 +288,20 @@
         return users;
     }
 
+    @Override
+    public UserInfo getProfileParent(int userHandle) {
+        checkManageUsersPermission("get the profile parent");
+        synchronized (mPackagesLock) {
+            UserInfo profile = getUserInfoLocked(userHandle);
+            int parentUserId = profile.profileGroupId;
+            if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
+                return null;
+            } else {
+                return getUserInfoLocked(parentUserId);
+            }
+        }
+    }
+
     private boolean isProfileOf(UserInfo user, UserInfo profile) {
         return user.id == profile.id ||
                 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
@@ -743,6 +757,9 @@
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
                 writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_APPS);
+                writeBoolean(serializer, restrictions, UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+                writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+                writeBoolean(serializer, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
                 serializer.endTag(null, TAG_RESTRICTIONS);
             }
             serializer.endTag(null, TAG_USER);
@@ -891,6 +908,10 @@
                         readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
                         readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_APPS);
+                        readBoolean(parser, restrictions,
+                                UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
+                        readBoolean(parser, restrictions, UserManager.DISALLOW_UNMUTE_MICROPHONE);
+                        readBoolean(parser, restrictions, UserManager.DISALLOW_ADJUST_VOLUME);
                     }
                 }
             }
@@ -1015,17 +1036,6 @@
         }
     }
 
-    private int getNextProfileGroupIdLocked() {
-        int maxGroupId = UserInfo.NO_PROFILE_GROUP_ID;
-        for (int i = 0; i < mUsers.size(); i++) {
-            UserInfo ui = mUsers.valueAt(i);
-            if (maxGroupId < ui.profileGroupId) {
-                maxGroupId = ui.profileGroupId;
-            }
-        }
-        return maxGroupId + 1;
-    }
-
     @Override
     public UserInfo createProfileForUser(String name, int flags, int userId) {
         checkManageUsersPermission("Only the system can create users");
@@ -1042,16 +1052,16 @@
         return createUserInternal(name, flags, UserHandle.USER_NULL);
     }
 
-    private UserInfo createUserInternal(String name, int flags, int profileId) {
+    private UserInfo createUserInternal(String name, int flags, int parentId) {
         final long ident = Binder.clearCallingIdentity();
         UserInfo userInfo = null;
         try {
             synchronized (mInstallLock) {
                 synchronized (mPackagesLock) {
-                    UserInfo profile = null;
-                    if (profileId != UserHandle.USER_NULL) {
-                        profile = getUserInfoLocked(profileId);
-                        if (profile == null) return null;
+                    UserInfo parent = null;
+                    if (parentId != UserHandle.USER_NULL) {
+                        parent = getUserInfoLocked(parentId);
+                        if (parent == null) return null;
                     }
                     if (isUserLimitReachedLocked()) return null;
                     int userId = getNextAvailableIdLocked();
@@ -1064,12 +1074,12 @@
                     Environment.getUserSystemDirectory(userInfo.id).mkdirs();
                     mUsers.put(userId, userInfo);
                     writeUserListLocked();
-                    if (profile != null) {
-                        if (profile.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
-                            profile.profileGroupId = getNextProfileGroupIdLocked();
-                            writeUserLocked(profile);
+                    if (parent != null) {
+                        if (parent.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+                            parent.profileGroupId = parent.id;
+                            writeUserLocked(parent);
                         }
-                        userInfo.profileGroupId = profile.profileGroupId;
+                        userInfo.profileGroupId = parent.profileGroupId;
                     }
                     writeUserLocked(userInfo);
                     mPm.createNewUserLILPw(userId, userPath);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9039236..99ec242 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -116,7 +116,8 @@
     /** Fraction of animation at which the recents thumbnail becomes completely transparent */
     private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
 
-    private static final long DEFAULT_APP_TRANSITION_DURATION = 250;
+    private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
+    private static final int THUMBNAIL_APP_TRANSITION_DURATION = 225;
 
     private final Context mContext;
     private final Handler mH;
@@ -160,6 +161,7 @@
     private final int mConfigShortAnimTime;
     private final Interpolator mDecelerateInterpolator;
     private final Interpolator mThumbnailFadeoutInterpolator;
+    private final Interpolator mThumbnailCubicInterpolator;
 
     private int mCurrentUserId = 0;
 
@@ -170,6 +172,8 @@
                 com.android.internal.R.integer.config_shortAnimTime);
         mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.decelerate_cubic);
+        mThumbnailCubicInterpolator = AnimationUtils.loadInterpolator(context,
+                com.android.internal.R.interpolator.fast_out_slow_in);
         mThumbnailFadeoutInterpolator = new Interpolator() {
             @Override
             public float getInterpolation(float input) {
@@ -401,11 +405,23 @@
     /**
      * Prepares the specified animation with a standard duration, interpolator, etc.
      */
+    Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
+            int duration, Interpolator interpolator) {
+        a.setDuration(duration);
+        a.setFillAfter(true);
+        a.setInterpolator(interpolator);
+        a.initialize(appWidth, appHeight, appWidth, appHeight);
+        return a;
+    }
+
+    /**
+     * Prepares the specified animation with a standard duration, interpolator, etc.
+     */
     Animation prepareThumbnailAnimation(Animation a, int appWidth, int appHeight, int transit) {
         // Pick the desired duration.  If this is an inter-activity transition,
         // it  is the standard duration for that.  Otherwise we use the longer
         // task transition duration.
-        final long duration;
+        final int duration;
         switch (transit) {
             case TRANSIT_ACTIVITY_OPEN:
             case TRANSIT_ACTIVITY_CLOSE:
@@ -415,11 +431,8 @@
                 duration = DEFAULT_APP_TRANSITION_DURATION;
                 break;
         }
-        a.setDuration(duration);
-        a.setFillAfter(true);
-        a.setInterpolator(mDecelerateInterpolator);
-        a.initialize(appWidth, appHeight, appWidth, appHeight);
-        return a;
+        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
+                mDecelerateInterpolator);
     }
 
     /**
@@ -594,7 +607,8 @@
                 throw new RuntimeException("Invalid thumbnail transition state");
         }
 
-        return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
+                THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailCubicInterpolator);
     }
 
     /**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a9f1c8..1980d1e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -97,6 +97,7 @@
 import java.security.cert.X509Certificate;
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -113,6 +114,8 @@
 
     private static final String DEVICE_POLICIES_XML = "device_policies.xml";
 
+    private static final String LOCK_TASK_COMPONENTS_XML = "lock-task-component";
+
     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
 
     private static final long MS_PER_DAY = 86400 * 1000;
@@ -127,6 +130,7 @@
     private static final boolean DBG = false;
 
     final Context mContext;
+    final UserManager mUserManager;
     final PowerManager.WakeLock mWakeLock;
 
     IPowerManager mIPowerManager;
@@ -182,6 +186,9 @@
         final ArrayList<ActiveAdmin> mAdminList
                 = new ArrayList<ActiveAdmin>();
 
+        // This is the list of component allowed to start lock task mode.
+        final List<ComponentName> mLockTaskComponents = new ArrayList<ComponentName>();
+
         public DevicePolicyData(int userHandle) {
             mUserHandle = userHandle;
         }
@@ -203,7 +210,7 @@
                         + action + " for user " + userHandle);
                 mHandler.post(new Runnable() {
                     public void run() {
-                        handlePasswordExpirationNotification(getUserData(userHandle));
+                        handlePasswordExpirationNotification(userHandle);
                     }
                 });
             }
@@ -605,6 +612,7 @@
      */
     public DevicePolicyManagerService(Context context) {
         mContext = context;
+        mUserManager = UserManager.get(mContext);
         mHasFeature = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_DEVICE_ADMIN);
         mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
@@ -812,6 +820,9 @@
         sendAdminCommandLocked(admin, action, null);
     }
 
+    /**
+     * Send an update to one specific admin, get notified when that admin returns a result.
+     */
     void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
         Intent intent = new Intent(action);
         intent.setComponent(admin.info.getComponent());
@@ -826,12 +837,15 @@
         }
     }
 
+    /**
+     * Send an update to all admins of a user that enforce a specified policy.
+     */
     void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) {
         final DevicePolicyData policy = getUserData(userHandle);
         final int count = policy.mAdminList.size();
         if (count > 0) {
             for (int i = 0; i < count; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
+                final ActiveAdmin admin = policy.mAdminList.get(i);
                 if (admin.info.usesPolicy(reqPolicy)) {
                     sendAdminCommandLocked(admin, action);
                 }
@@ -839,6 +853,19 @@
         }
     }
 
+    /**
+     * Send an update intent to all admins of a user and its profiles. Only send to admins that
+     * enforce a specified policy.
+     */
+    private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy,
+            int userHandle) {
+        List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+        for (UserInfo ui : profiles) {
+            int id = ui.getUserHandle().getIdentifier();
+            sendAdminCommandLocked(action, reqPolicy, id);
+        }
+    }
+
     void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
         final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
         if (admin != null) {
@@ -955,6 +982,13 @@
                 out.endTag(null, "active-password");
             }
 
+            for (int i=0; i<policy.mLockTaskComponents.size(); i++) {
+                ComponentName component = policy.mLockTaskComponents.get(i);
+                out.startTag(null, LOCK_TASK_COMPONENTS_XML);
+                out.attribute(null, "name", component.flattenToString());
+                out.endTag(null, LOCK_TASK_COMPONENTS_XML);
+            }
+
             out.endTag(null, "policies");
 
             out.endDocument();
@@ -1004,6 +1038,7 @@
             }
             type = parser.next();
             int outerDepth = parser.getDepth();
+            policy.mLockTaskComponents.clear();
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -1056,6 +1091,11 @@
                     policy.mActivePasswordNonLetter = Integer.parseInt(
                             parser.getAttributeValue(null, "nonletter"));
                     XmlUtils.skipCurrentTag(parser);
+                } else if (LOCK_TASK_COMPONENTS_XML.equals(tag)) {
+                    policy.mLockTaskComponents.add
+                        (ComponentName.unflattenFromString
+                         (parser.getAttributeValue(null, "name")));
+                    XmlUtils.skipCurrentTag(parser);
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -1171,23 +1211,29 @@
         }
     }
 
-    private void handlePasswordExpirationNotification(DevicePolicyData policy) {
+    private void handlePasswordExpirationNotification(int userHandle) {
         synchronized (this) {
             final long now = System.currentTimeMillis();
-            final int N = policy.mAdminList.size();
-            if (N <= 0) {
-                return;
-            }
-            for (int i=0; i < N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
-                        && admin.passwordExpirationTimeout > 0L
-                        && admin.passwordExpirationDate > 0L
-                        && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) {
-                    sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
+
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo ui : profiles) {
+                int profileUserHandle = ui.getUserHandle().getIdentifier();
+                final DevicePolicyData policy = getUserData(profileUserHandle);
+                final int count = policy.mAdminList.size();
+                if (count > 0) {
+                    for (int i = 0; i < count; i++) {
+                        final ActiveAdmin admin = policy.mAdminList.get(i);
+                        if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
+                                && admin.passwordExpirationTimeout > 0L
+                                && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS
+                                && admin.passwordExpirationDate > 0L) {
+                            sendAdminCommandLocked(admin,
+                                    DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
+                        }
+                    }
                 }
             }
-            setExpirationAlarmCheckLocked(mContext, policy);
+            setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
         }
     }
 
@@ -1197,8 +1243,7 @@
         final boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
         if (! hasCert) {
             if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
-                UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-                for (UserInfo user : um.getUsers()) {
+                for (UserInfo user : mUserManager.getUsers()) {
                     notificationManager.cancelAsUser(
                             null, MONITORING_CERT_NOTIFICATION_ID, user.getUserHandle());
                 }
@@ -1237,8 +1282,7 @@
         // If this is a boot intent, this will fire for each user. But if this is a storage changed
         // intent, it will fire once, so we need to notify all users.
         if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
-            UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            for (UserInfo user : um.getUsers()) {
+            for (UserInfo user : mUserManager.getUsers()) {
                 notificationManager.notifyAsUser(
                         null, MONITORING_CERT_NOTIFICATION_ID, noti, user.getUserHandle());
             }
@@ -1415,18 +1459,22 @@
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
             int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-            DevicePolicyData policy = getUserData(userHandle);
 
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
                 return admin != null ? admin.passwordQuality : mode;
             }
 
-            final int N = policy.mAdminList.size();
-            for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (mode < admin.passwordQuality) {
-                    mode = admin.passwordQuality;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (mode < admin.passwordQuality) {
+                        mode = admin.passwordQuality;
+                    }
                 }
             }
             return mode;
@@ -1457,7 +1505,6 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
             int length = 0;
 
             if (who != null) {
@@ -1465,11 +1512,16 @@
                 return admin != null ? admin.minimumPasswordLength : length;
             }
 
-            final int N = policy.mAdminList.size();
-            for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordLength) {
-                    length = admin.minimumPasswordLength;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordLength) {
+                        length = admin.minimumPasswordLength;
+                    }
                 }
             }
             return length;
@@ -1500,7 +1552,6 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
             int length = 0;
 
             if (who != null) {
@@ -1508,11 +1559,16 @@
                 return admin != null ? admin.passwordHistoryLength : length;
             }
 
-            final int N = policy.mAdminList.size();
-            for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.passwordHistoryLength) {
-                    length = admin.passwordHistoryLength;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i = 0; i < N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.passwordHistoryLength) {
+                        length = admin.passwordHistoryLength;
+                    }
                 }
             }
             return length;
@@ -1558,19 +1614,23 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
+            long timeout = 0L;
+
             if (who != null) {
                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
-                return admin != null ? admin.passwordExpirationTimeout : 0L;
+                return admin != null ? admin.passwordExpirationTimeout : timeout;
             }
 
-            long timeout = 0L;
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
-                        && timeout > admin.passwordExpirationTimeout)) {
-                    timeout = admin.passwordExpirationTimeout;
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i = 0; i < N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
+                            && timeout > admin.passwordExpirationTimeout)) {
+                        timeout = admin.passwordExpirationTimeout;
+                    }
                 }
             }
             return timeout;
@@ -1582,19 +1642,23 @@
      * Returns 0 if not configured.
      */
     private long getPasswordExpirationLocked(ComponentName who, int userHandle) {
+        long timeout = 0L;
+
         if (who != null) {
             ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
-            return admin != null ? admin.passwordExpirationDate : 0L;
+            return admin != null ? admin.passwordExpirationDate : timeout;
         }
 
-        long timeout = 0L;
-        DevicePolicyData policy = getUserData(userHandle);
-        final int N = policy.mAdminList.size();
-        for (int i = 0; i < N; i++) {
-            ActiveAdmin admin = policy.mAdminList.get(i);
-            if (timeout == 0L || (admin.passwordExpirationDate != 0
-                    && timeout > admin.passwordExpirationDate)) {
-                timeout = admin.passwordExpirationDate;
+        List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+        for (UserInfo userInfo : profiles) {
+            DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+            final int N = policy.mAdminList.size();
+            for (int i = 0; i < N; i++) {
+                ActiveAdmin admin = policy.mAdminList.get(i);
+                if (timeout == 0L || (admin.passwordExpirationDate != 0
+                        && timeout > admin.passwordExpirationDate)) {
+                    timeout = admin.passwordExpirationDate;
+                }
             }
         }
         return timeout;
@@ -1641,12 +1705,16 @@
                 return admin != null ? admin.minimumPasswordUpperCase : length;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordUpperCase) {
-                    length = admin.minimumPasswordUpperCase;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordUpperCase) {
+                        length = admin.minimumPasswordUpperCase;
+                    }
                 }
             }
             return length;
@@ -1681,12 +1749,16 @@
                 return admin != null ? admin.minimumPasswordLowerCase : length;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordLowerCase) {
-                    length = admin.minimumPasswordLowerCase;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordLowerCase) {
+                        length = admin.minimumPasswordLowerCase;
+                    }
                 }
             }
             return length;
@@ -1724,12 +1796,16 @@
                 return admin != null ? admin.minimumPasswordLetters : length;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordLetters) {
-                    length = admin.minimumPasswordLetters;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordLetters) {
+                        length = admin.minimumPasswordLetters;
+                    }
                 }
             }
             return length;
@@ -1767,12 +1843,16 @@
                 return admin != null ? admin.minimumPasswordNumeric : length;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for (int i = 0; i < N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordNumeric) {
-                    length = admin.minimumPasswordNumeric;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i = 0; i < N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordNumeric) {
+                        length = admin.minimumPasswordNumeric;
+                    }
                 }
             }
             return length;
@@ -1810,12 +1890,16 @@
                 return admin != null ? admin.minimumPasswordSymbols : length;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordSymbols) {
-                    length = admin.minimumPasswordSymbols;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordSymbols) {
+                        length = admin.minimumPasswordSymbols;
+                    }
                 }
             }
             return length;
@@ -1853,12 +1937,16 @@
                 return admin != null ? admin.minimumPasswordNonLetter : length;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (length < admin.minimumPasswordNonLetter) {
-                    length = admin.minimumPasswordNonLetter;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (length < admin.minimumPasswordNonLetter) {
+                        length = admin.minimumPasswordNonLetter;
+                    }
                 }
             }
             return length;
@@ -1870,8 +1958,16 @@
             return true;
         }
         enforceCrossUserPermission(userHandle);
+
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
+
+            // The active password is stored in the user that runs the launcher
+            // If the user this is called from is part of a profile group, that is the parent
+            // of the group.
+            UserInfo parent = getProfileParent(userHandle);
+            int id = parent == null ? userHandle : parent.id;
+            DevicePolicyData policy = getUserData(id);
+
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
@@ -1893,13 +1989,16 @@
     }
 
     public int getCurrentFailedPasswordAttempts(int userHandle) {
-        enforceCrossUserPermission(userHandle);
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
-            return getUserData(userHandle).mFailedPasswordAttempts;
+
+            // The active password is stored in the parent.
+            DevicePolicyData policy = getUserData(getProfileParent(userHandle).id);
+
+            return policy.mFailedPasswordAttempts;
         }
     }
 
@@ -1909,6 +2008,9 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(who,
@@ -1928,7 +2030,6 @@
         }
         enforceCrossUserPermission(userHandle);
         synchronized (this) {
-            DevicePolicyData policy = getUserData(userHandle);
             int count = 0;
 
             if (who != null) {
@@ -1936,14 +2037,19 @@
                 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
             }
 
-            final int N = policy.mAdminList.size();
-            for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (count == 0) {
-                    count = admin.maximumFailedPasswordsForWipe;
-                } else if (admin.maximumFailedPasswordsForWipe != 0
-                        && count > admin.maximumFailedPasswordsForWipe) {
-                    count = admin.maximumFailedPasswordsForWipe;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (count == 0) {
+                        count = admin.maximumFailedPasswordsForWipe;
+                    } else if (admin.maximumFailedPasswordsForWipe != 0
+                            && count > admin.maximumFailedPasswordsForWipe) {
+                        count = admin.maximumFailedPasswordsForWipe;
+                    }
                 }
             }
             return count;
@@ -1955,9 +2061,11 @@
             return false;
         }
         enforceCrossUserPermission(userHandle);
+        enforceNotManagedProfile(userHandle, "reset the password");
+
         int quality;
         synchronized (this) {
-            // This API can only be called by an active device admin,
+            // This api can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null,
                     DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
@@ -2135,15 +2243,19 @@
                 return admin != null ? admin.maximumTimeToUnlock : time;
             }
 
-            DevicePolicyData policy = getUserData(userHandle);
-            final int N = policy.mAdminList.size();
-            for  (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (time == 0) {
-                    time = admin.maximumTimeToUnlock;
-                } else if (admin.maximumTimeToUnlock != 0
-                        && time > admin.maximumTimeToUnlock) {
-                    time = admin.maximumTimeToUnlock;
+            // Return strictest policy for this user and profiles that are visible from this user.
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                DevicePolicyData policy = getUserData(userInfo.getUserHandle().getIdentifier());
+                final int N = policy.mAdminList.size();
+                for (int i=0; i<N; i++) {
+                    ActiveAdmin admin = policy.mAdminList.get(i);
+                    if (time == 0) {
+                        time = admin.maximumTimeToUnlock;
+                    } else if (admin.maximumTimeToUnlock != 0
+                            && time > admin.maximumTimeToUnlock) {
+                        time = admin.maximumTimeToUnlock;
+                    }
                 }
             }
             return time;
@@ -2301,7 +2413,7 @@
                 public void run() {
                     try {
                         ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
-                        ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
+                        (mUserManager)
                                 .removeUser(userHandle);
                     } catch (RemoteException re) {
                         // Shouldn't happen
@@ -2349,6 +2461,8 @@
             return;
         }
         enforceCrossUserPermission(userHandle);
+        enforceNotManagedProfile(userHandle, "set the active password");
+
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
         DevicePolicyData p = getUserData(userHandle);
@@ -2377,7 +2491,8 @@
                     saveSettingsLocked(userHandle);
                     updatePasswordExpirationsLocked(userHandle);
                     setExpirationAlarmCheckLocked(mContext, p);
-                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
+                    sendAdminCommandToSelfAndProfilesLocked(
+                            DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
                             DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
                 } finally {
                     Binder.restoreCallingIdentity(ident);
@@ -2387,26 +2502,31 @@
     }
 
     /**
-     * Called any time the device password is updated.  Resets all password expiration clocks.
+     * Called any time the device password is updated. Resets all password expiration clocks.
      */
     private void updatePasswordExpirationsLocked(int userHandle) {
-        DevicePolicyData policy = getUserData(userHandle);
-        final int N = policy.mAdminList.size();
-        if (N > 0) {
-            for (int i=0; i<N; i++) {
-                ActiveAdmin admin = policy.mAdminList.get(i);
-                if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
-                    long timeout = admin.passwordExpirationTimeout;
-                    long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
-                    admin.passwordExpirationDate = expiration;
+            List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
+            for (UserInfo userInfo : profiles) {
+                int profileId = userInfo.getUserHandle().getIdentifier();
+                DevicePolicyData policy = getUserData(profileId);
+                final int N = policy.mAdminList.size();
+                if (N > 0) {
+                    for (int i=0; i<N; i++) {
+                        ActiveAdmin admin = policy.mAdminList.get(i);
+                        if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
+                            long timeout = admin.passwordExpirationTimeout;
+                            long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
+                            admin.passwordExpirationDate = expiration;
+                        }
+                    }
                 }
+                saveSettingsLocked(profileId);
             }
-            saveSettingsLocked(userHandle);
-        }
     }
 
     public void reportFailedPasswordAttempt(int userHandle) {
         enforceCrossUserPermission(userHandle);
+        enforceNotManagedProfile(userHandle, "report failed password attempt");
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
 
@@ -2421,7 +2541,8 @@
                     if (max > 0 && policy.mFailedPasswordAttempts >= max) {
                         wipeDeviceOrUserLocked(0, userHandle);
                     }
-                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
+                    sendAdminCommandToSelfAndProfilesLocked(
+                            DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
                             DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
                 }
             } finally {
@@ -2444,7 +2565,8 @@
                     policy.mPasswordOwner = -1;
                     saveSettingsLocked(userHandle);
                     if (mHasFeature) {
-                        sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
+                        sendAdminCommandToSelfAndProfilesLocked(
+                                DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
                                 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
                     }
                 } finally {
@@ -2473,7 +2595,7 @@
             // Scan through active admins and find if anyone has already
             // set the global proxy.
             Set<ComponentName> compSet = policy.mAdminMap.keySet();
-            for  (ComponentName component : compSet) {
+            for (ComponentName component : compSet) {
                 ActiveAdmin ap = policy.mAdminMap.get(component);
                 if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
                     // Another admin already sets the global proxy
@@ -2502,8 +2624,11 @@
             // Reset the global proxy accordingly
             // Do this using system permissions, as apps cannot write to secure settings
             long origId = Binder.clearCallingIdentity();
-            resetGlobalProxyLocked(policy);
-            Binder.restoreCallingIdentity(origId);
+            try {
+                resetGlobalProxyLocked(policy);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
             return null;
         }
     }
@@ -2888,8 +3013,7 @@
         }
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
 
-        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        if (um.getUserInfo(userHandle) == null) {
+        if (mUserManager.getUserInfo(userHandle) == null) {
             // User doesn't exist.
             throw new IllegalArgumentException(
                     "Attempted to set profile owner for invalid userId: " + userHandle);
@@ -2935,10 +3059,9 @@
             int userId = UserHandle.getCallingUserId();
             Slog.d(LOG_TAG, "Enabling the profile for: " + userId);
 
-            UserManager um = UserManager.get(mContext);
             long id = Binder.clearCallingIdentity();
             try {
-                um.setUserEnabled(userId);
+                mUserManager.setUserEnabled(userId);
                 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
                 intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
@@ -3002,6 +3125,30 @@
         }
     }
 
+    private void enforceNotManagedProfile(int userHandle, String message) {
+        if(isManagedProfile(userHandle)) {
+            throw new SecurityException("You can not " + message + " from a managed profile. ");
+        }
+    }
+
+    private UserInfo getProfileParent(int userHandle) {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            return mUserManager.getProfileParent(userHandle);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private boolean isManagedProfile(int userHandle) {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            return mUserManager.getUserInfo(userHandle).isManagedProfile();
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     private void enableIfNecessary(String packageName, int userId) {
         try {
             IPackageManager ipm = AppGlobals.getPackageManager();
@@ -3105,10 +3252,9 @@
             }
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            UserManager um = UserManager.get(mContext);
             long id = Binder.clearCallingIdentity();
             try {
-                um.setApplicationRestrictions(packageName, settings, userHandle);
+                mUserManager.setApplicationRestrictions(packageName, settings, userHandle);
             } finally {
                 restoreCallingIdentity(id);
             }
@@ -3172,10 +3318,9 @@
             }
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            UserManager um = UserManager.get(mContext);
             long id = Binder.clearCallingIdentity();
             try {
-                return um.getApplicationRestrictions(packageName, userHandle);
+                return mUserManager.getApplicationRestrictions(packageName, userHandle);
             } finally {
                 restoreCallingIdentity(id);
             }
@@ -3192,10 +3337,9 @@
             }
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            UserManager um = UserManager.get(mContext);
             long id = Binder.clearCallingIdentity();
             try {
-                um.setUserRestriction(key, enabled, userHandle);
+                mUserManager.setUserRestriction(key, enabled, userHandle);
             } finally {
                 restoreCallingIdentity(id);
             }
@@ -3344,4 +3488,74 @@
             return resultSet.toArray(new String[resultSet.size()]);
         }
     }
+
+    /**
+     * Sets which componets may enter lock task mode.
+     *
+     * This function can only be called by the device owner or the profile owner.
+     * @param components The list of components allowed to enter lock task mode.
+     */
+    public void setLockTaskComponents(ComponentName[] components) throws SecurityException {
+        // Get the package names of the caller.
+        int uid = Binder.getCallingUid();
+        String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+
+        // Check whether any of the package name is the device owner or the profile owner.
+        for (int i=0; i<packageNames.length; i++) {
+            String packageName = packageNames[i];
+            int userHandle = UserHandle.getUserId(uid);
+            String profileOwnerPackage = getProfileOwner(userHandle);
+            if (isDeviceOwner(packageName) ||
+                (profileOwnerPackage != null && profileOwnerPackage.equals(packageName))) {
+
+                // If a package name is the device owner or the profile owner,
+                // we update the component list.
+                DevicePolicyData policy = getUserData(userHandle);
+                policy.mLockTaskComponents.clear();
+                if (components != null) {
+                    for (int j=0; j<components.length; j++) {
+                        ComponentName component = components[j];
+                        policy.mLockTaskComponents.add(component);
+                    }
+                }
+
+                // Store the settings persistently.
+                saveSettingsLocked(userHandle);
+                return;
+            }
+        }
+        throw new SecurityException();
+    }
+
+    /**
+     * This function returns the list of components allowed to start the task lock mode.
+     */
+    public ComponentName[] getLockTaskComponents() {
+        int userHandle = UserHandle.USER_OWNER;
+        DevicePolicyData policy = getUserData(userHandle);
+        ComponentName[] tempArray = policy.mLockTaskComponents.toArray(new ComponentName[0]);
+        return tempArray;
+    }
+
+    /**
+     * This function lets the caller know whether the given component is allowed to start the
+     * lock task mode.
+     * @param component The component to check
+     */
+    public boolean isLockTaskPermitted(ComponentName component) {
+        // Get current user's devicepolicy
+        int uid = Binder.getCallingUid();
+        int userHandle = UserHandle.getUserId(uid);
+        DevicePolicyData policy = getUserData(userHandle);
+        for (int i=0; i<policy.mLockTaskComponents.size(); i++) {
+            ComponentName lockTaskComponent = policy.mLockTaskComponents.get(i);
+
+            // If the given component equals one of the component stored our device-owner-set
+            // list, we allow this component to start the lock task mode.
+            if (lockTaskComponent.getPackageName().equals(component.getPackageName())) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 716823c..22e2a6e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -334,6 +334,7 @@
         InputManagerService inputManager = null;
         TelephonyRegistry telephonyRegistry = null;
         ConsumerIrService consumerIr = null;
+        AudioService audioService = null;
 
         boolean onlyCore = false;
         boolean firstBoot = false;
@@ -769,7 +770,8 @@
             if (!disableMedia && !"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
                 try {
                     Slog.i(TAG, "Audio Service");
-                    ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context));
+                    audioService = new AudioService(context);
+                    ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
                 } catch (Throwable e) {
                     reportWtf("starting Audio Service", e);
                 }
@@ -1084,6 +1086,7 @@
         final InputManagerService inputManagerF = inputManager;
         final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
         final MediaRouterService mediaRouterF = mediaRouter;
+        final AudioService audioServiceF = audioService;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -1152,6 +1155,11 @@
                 } catch (Throwable e) {
                     reportWtf("making Recognition Service ready", e);
                 }
+                try {
+                    if (audioServiceF != null) audioServiceF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("Notifying AudioService running", e);
+                }
                 Watchdog.getInstance().start();
 
                 // It is now okay to let the various system services start their
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ce8c8b8..85b81d9 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -506,6 +506,12 @@
      * @hide
      */
     public boolean isValid() {
+        if (SSID == null)
+            return false;
+
+        if (allowedKeyManagement == null)
+            return false;
+
         if (allowedKeyManagement.cardinality() > 1) {
             if (allowedKeyManagement.cardinality() != 2) {
                 return false;