Merge "Correctly use ByteBuffer in UsbRequest"
diff --git a/Android.mk b/Android.mk
index 561d220..b549dde 100644
--- a/Android.mk
+++ b/Android.mk
@@ -241,6 +241,10 @@
 	core/java/android/os/IUpdateLock.aidl \
 	core/java/android/os/IUserManager.aidl \
 	core/java/android/os/IVibratorService.aidl \
+	core/java/android/os/storage/IMountService.aidl \
+	core/java/android/os/storage/IMountServiceListener.aidl \
+	core/java/android/os/storage/IMountShutdownObserver.aidl \
+	core/java/android/os/storage/IObbActionListener.aidl \
 	core/java/android/security/IKeystoreService.aidl \
 	core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
 	core/java/android/service/carrier/ICarrierService.aidl \
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 5d1cd3b..8124232 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -2849,6 +2849,17 @@
         return mAnimationInfo.mEnterTransitionPostponed;
     }
 
+    boolean isHideReplaced() {
+        if (mAnimationInfo == null) {
+            return false;
+        }
+        return mAnimationInfo.mIsHideReplaced;
+    }
+
+    void setHideReplaced(boolean replaced) {
+        ensureAnimationInfo().mIsHideReplaced = replaced;
+    }
+
     /**
      * Used internally to be notified when {@link #startPostponedEnterTransition()} has
      * been called. This listener will only be called once and then be removed from the
@@ -2902,7 +2913,7 @@
         // be set to null
         OnStartEnterTransitionListener mStartEnterTransitionListener;
 
-        // True if the View was added, and its animation has yet to be run.
-        boolean mIsNewlyAdded;
+        // True if the View was hidden, but the transition is handling the hide
+        boolean mIsHideReplaced;
     }
 }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 9345a03..233fee7 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1185,23 +1185,32 @@
             if (anim != null) {
                 anim.setTarget(fragment.mView);
                 if (fragment.mHidden) {
-                    // Delay the actual hide operation until the animation finishes, otherwise
-                    // the fragment will just immediately disappear
-                    anim.addListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            animation.removeListener(this);
-                            if (fragment.mView != null) {
-                                fragment.mView.setVisibility(View.GONE);
+                    if (fragment.isHideReplaced()) {
+                        fragment.setHideReplaced(false);
+                    } else {
+                        // Delay the actual hide operation until the animation finishes, otherwise
+                        // the fragment will just immediately disappear
+                        anim.addListener(new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                animation.removeListener(this);
+                                if (fragment.mView != null) {
+                                    fragment.mView.setVisibility(View.GONE);
+                                }
                             }
-                        }
-                    });
+                        });
+                    }
                 }
                 setHWLayerAnimListenerIfAlpha(fragment.mView, anim);
                 anim.start();
             } else {
-                final int visibility = fragment.mHidden ? View.GONE : View.VISIBLE;
+                final int visibility = fragment.mHidden && !fragment.isHideReplaced()
+                        ? View.GONE
+                        : View.VISIBLE;
                 fragment.mView.setVisibility(visibility);
+                if (fragment.isHideReplaced()) {
+                    fragment.setHideReplaced(false);
+                }
             }
         }
         if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) {
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index 6f52114..d27dff5 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -222,6 +222,7 @@
                 sharedElementTransition, inFragment, inIsPop);
 
         if (transition != null) {
+            replaceHide(exitTransition, outFragment, exitingViews);
             transition.setNameOverrides(nameOverrides);
             scheduleRemoveTargets(transition,
                     enterTransition, enteringViews, exitTransition, exitingViews,
@@ -309,6 +310,38 @@
     }
 
     /**
+     * Replace hide operations with visibility changes on the exiting views. Instead of making
+     * the entire fragment's view GONE, make each exiting view INVISIBLE. At the end of the
+     * transition, make the fragment's view GONE.
+     */
+    private static void replaceHide(Transition exitTransition, Fragment exitingFragment,
+            final ArrayList<View> exitingViews) {
+        if (exitingFragment != null && exitTransition != null && exitingFragment.mAdded
+                && exitingFragment.mHidden && exitingFragment.mHiddenChanged) {
+            exitingFragment.setHideReplaced(true);
+            final View fragmentView = exitingFragment.getView();
+            final ViewGroup container = exitingFragment.mContainer;
+            container.getViewTreeObserver().addOnPreDrawListener(
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            container.getViewTreeObserver().removeOnPreDrawListener(this);
+                            setViewVisibility(exitingViews, View.INVISIBLE);
+                            return true;
+                        }
+                    });
+            exitTransition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    transition.removeListener(this);
+                    fragmentView.setVisibility(View.GONE);
+                    setViewVisibility(exitingViews, View.VISIBLE);
+                }
+            });
+        }
+    }
+
+    /**
      * This method is used for fragment transitions for unoptimized transactions to change the
      * enter and exit transition targets after the call to
      * {@link TransitionManager#beginDelayedTransition(ViewGroup, Transition)}. The exit transition
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index bb5f7a1..4c8360f 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -377,13 +377,13 @@
      * AppWidget provider. Will animate into these new views as needed
      */
     public void updateAppWidget(RemoteViews remoteViews) {
-        applyRemoteViews(remoteViews);
+        applyRemoteViews(remoteViews, true);
     }
 
     /**
      * @hide
      */
-    protected void applyRemoteViews(RemoteViews remoteViews) {
+    protected void applyRemoteViews(RemoteViews remoteViews, boolean useAsyncIfPossible) {
         if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
 
         boolean recycled = false;
@@ -423,7 +423,7 @@
             mLayoutId = -1;
             mViewMode = VIEW_MODE_DEFAULT;
         } else {
-            if (mAsyncExecutor != null) {
+            if (mAsyncExecutor != null && useAsyncIfPossible) {
                 inflateAsync(remoteViews);
                 return;
             }
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index bc5af81..15dd282 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -726,7 +726,7 @@
     /** @hide */
     public UserManager(Context context, IUserManager service) {
         mService = service;
-        mContext = context;
+        mContext = context.getApplicationContext();
     }
 
     /**
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
new file mode 100644
index 0000000..af0d7b7
--- /dev/null
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -0,0 +1,291 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+import android.content.pm.IPackageMoveObserver;
+import android.os.ParcelFileDescriptor;
+import android.os.storage.DiskInfo;
+import android.os.storage.IMountServiceListener;
+import android.os.storage.IMountShutdownObserver;
+import android.os.storage.IObbActionListener;
+import android.os.storage.StorageVolume;
+import android.os.storage.VolumeInfo;
+import android.os.storage.VolumeRecord;
+
+/**
+ * WARNING! Update IMountService.h and IMountService.cpp if you change this
+ * file. In particular, the transaction ids below must match the
+ * _TRANSACTION enum in IMountService.cpp
+ *
+ * @hide - Applications should use android.os.storage.StorageManager to access
+ *       storage functions.
+ */
+interface IMountService {
+    /**
+     * Registers an IMountServiceListener for receiving async notifications.
+     */
+    void registerListener(IMountServiceListener listener) = 1;
+    /**
+     * Unregisters an IMountServiceListener
+     */
+    void unregisterListener(IMountServiceListener listener) = 2;
+    /**
+     * Returns true if a USB mass storage host is connected
+     */
+    boolean isUsbMassStorageConnected() = 3;
+    /**
+     * Enables / disables USB mass storage. The caller should check actual
+     * status of enabling/disabling USB mass storage via StorageEventListener.
+     */
+    void setUsbMassStorageEnabled(boolean enable) = 4;
+    /**
+     * Returns true if a USB mass storage host is enabled (media is shared)
+     */
+    boolean isUsbMassStorageEnabled() = 5;
+    /**
+     * Mount external storage at given mount point. Returns an int consistent
+     * with MountServiceResultCode
+     */
+    int mountVolume(in String mountPoint) = 6;
+    /**
+     * Safely unmount external storage at given mount point. The unmount is an
+     * asynchronous operation. Applications should register StorageEventListener
+     * for storage related status changes.
+     * @param mountPoint the mount point
+     * @param force whether or not to forcefully unmount it (e.g. even if programs are using this
+     *     data currently)
+     * @param removeEncryption whether or not encryption mapping should be removed from the volume.
+     *     This value implies {@code force}.
+     */
+    void unmountVolume(in String mountPoint, boolean force, boolean removeEncryption) = 7;
+    /**
+     * Format external storage given a mount point. Returns an int consistent
+     * with MountServiceResultCode
+     */
+    int formatVolume(in String mountPoint) = 8;
+    /**
+     * Returns an array of pids with open files on the specified path.
+     */
+    int[] getStorageUsers(in String path) = 9;
+    /**
+     * Gets the state of a volume via its mountpoint.
+     */
+    String getVolumeState(in String mountPoint) = 10;
+    /*
+     * Creates a secure container with the specified parameters. Returns an int
+     * consistent with MountServiceResultCode
+     */
+    int createSecureContainer(in String id, int sizeMb, in String fstype, in String key,
+            int ownerUid, boolean external) = 11;
+    /*
+     * Finalize a container which has just been created and populated. After
+     * finalization, the container is immutable. Returns an int consistent with
+     * MountServiceResultCode
+     */
+    int finalizeSecureContainer(in String id) = 12;
+    /*
+     * Destroy a secure container, and free up all resources associated with it.
+     * NOTE: Ensure all references are released prior to deleting. Returns an
+     * int consistent with MountServiceResultCode
+     */
+    int destroySecureContainer(in String id, boolean force) = 13;
+    /*
+     * Mount a secure container with the specified key and owner UID. Returns an
+     * int consistent with MountServiceResultCode
+     */
+    int mountSecureContainer(in String id, in String key, int ownerUid, boolean readOnly) = 14;
+    /*
+     * Unount a secure container. Returns an int consistent with
+     * MountServiceResultCode
+     */
+    int unmountSecureContainer(in String id, boolean force) = 15;
+    /*
+     * Returns true if the specified container is mounted
+     */
+    boolean isSecureContainerMounted(in String id) = 16;
+    /*
+     * Rename an unmounted secure container. Returns an int consistent with
+     * MountServiceResultCode
+     */
+    int renameSecureContainer(in String oldId, in String newId) = 17;
+    /*
+     * Returns the filesystem path of a mounted secure container.
+     */
+    String getSecureContainerPath(in String id) = 18;
+    /**
+     * Gets an Array of currently known secure container IDs
+     */
+    String[] getSecureContainerList() = 19;
+    /**
+     * Shuts down the MountService and gracefully unmounts all external media.
+     * Invokes call back once the shutdown is complete.
+     */
+    void shutdown(IMountShutdownObserver observer) = 20;
+    /**
+     * Call into MountService by PackageManager to notify that its done
+     * processing the media status update request.
+     */
+    void finishMediaUpdate() = 21;
+    /**
+     * Mounts an Opaque Binary Blob (OBB) with the specified decryption key and
+     * only allows the calling process's UID access to the contents.
+     * MountService will call back to the supplied IObbActionListener to inform
+     * it of the terminal state of the call.
+     */
+    void mountObb(in String rawPath, in String canonicalPath, in String key,
+            IObbActionListener token, int nonce) = 22;
+    /**
+     * Unmounts an Opaque Binary Blob (OBB). When the force flag is specified,
+     * any program using it will be forcibly killed to unmount the image.
+     * MountService will call back to the supplied IObbActionListener to inform
+     * it of the terminal state of the call.
+     */
+    void unmountObb(in String rawPath, boolean force, IObbActionListener token, int nonce) = 23;
+    /**
+     * Checks whether the specified Opaque Binary Blob (OBB) is mounted
+     * somewhere.
+     */
+    boolean isObbMounted(in String rawPath) = 24;
+    /**
+     * Gets the path to the mounted Opaque Binary Blob (OBB).
+     */
+    String getMountedObbPath(in String rawPath) = 25;
+    /**
+     * Returns whether or not the external storage is emulated.
+     */
+    boolean isExternalStorageEmulated() = 26;
+    /**
+     * Decrypts any encrypted volumes.
+     */
+    int decryptStorage(in String password) = 27;
+    /**
+     * Encrypts storage.
+     */
+    int encryptStorage(int type, in String password) = 28;
+    /**
+     * Changes the encryption password.
+     */
+    int changeEncryptionPassword(int type, in String password) = 29;
+    /**
+     * Returns list of all mountable volumes.
+     */
+    StorageVolume[] getVolumeList(int uid, in String packageName, int flags) = 30;
+    /**
+     * Gets the path on the filesystem for the ASEC container itself.
+     *
+     * @param cid ASEC container ID
+     * @return path to filesystem or {@code null} if it's not found
+     * @throws RemoteException
+     */
+    String getSecureContainerFilesystemPath(in String cid) = 31;
+    /**
+     * Determines the encryption state of the volume.
+     * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
+     * values.
+     * Note that this has been replaced in most cases by the APIs in
+     * StorageManager (see isEncryptable and below)
+     * This is still useful to get the error state when encryption has failed
+     * and CryptKeeper needs to throw up a screen advising the user what to do
+     */
+    int getEncryptionState() = 32;
+    /**
+     * Verify the encryption password against the stored volume.  This method
+     * may only be called by the system process.
+     */
+    int verifyEncryptionPassword(in String password) = 33;
+    /*
+     * Fix permissions in a container which has just been created and populated.
+     * Returns an int consistent with MountServiceResultCode
+     */
+    int fixPermissionsSecureContainer(in String id, int gid, in String filename) = 34;
+    /**
+     * Ensure that all directories along given path exist, creating parent
+     * directories as needed. Validates that given path is absolute and that it
+     * contains no relative "." or ".." paths or symlinks. Also ensures that
+     * path belongs to a volume managed by vold, and that path is either
+     * external storage data or OBB directory belonging to calling app.
+     */
+    int mkdirs(in String callingPkg, in String path) = 35;
+    /**
+     * Determines the type of the encryption password
+     * @return PasswordType
+     */
+    int getPasswordType() = 36;
+    /**
+     * Get password from vold
+     * @return password or empty string
+     */
+    String getPassword() = 37;
+    /**
+     * Securely clear password from vold
+     */
+    oneway void clearPassword() = 38;
+    /**
+     * Set a field in the crypto header.
+     * @param field field to set
+     * @param contents contents to set in field
+     */
+    oneway void setField(in String field, in String contents) = 39;
+    /**
+     * Gets a field from the crypto header.
+     * @param field field to get
+     * @return contents of field
+     */
+    String getField(in String field) = 40;
+    int resizeSecureContainer(in String id, int sizeMb, in String key) = 41;
+    /**
+     * Report the time of the last maintenance operation such as fstrim.
+     * @return Timestamp of the last maintenance operation, in the
+     *     System.currentTimeMillis() time base
+     * @throws RemoteException
+     */
+    long lastMaintenance() = 42;
+    /**
+     * Kick off an immediate maintenance operation
+     * @throws RemoteException
+     */
+    void runMaintenance() = 43;
+    void waitForAsecScan() = 44;
+    DiskInfo[] getDisks() = 45;
+    VolumeInfo[] getVolumes(int flags) = 46;
+    VolumeRecord[] getVolumeRecords(int flags) = 47;
+    void mount(in String volId) = 48;
+    void unmount(in String volId) = 49;
+    void format(in String volId) = 50;
+    void partitionPublic(in String diskId) = 51;
+    void partitionPrivate(in String diskId) = 52;
+    void partitionMixed(in String diskId, int ratio) = 53;
+    void setVolumeNickname(in String fsUuid, in String nickname) = 54;
+    void setVolumeUserFlags(in String fsUuid, int flags, int mask) = 55;
+    void forgetVolume(in String fsUuid) = 56;
+    void forgetAllVolumes() = 57;
+    String getPrimaryStorageUuid() = 58;
+    void setPrimaryStorageUuid(in String volumeUuid, IPackageMoveObserver callback) = 59;
+    long benchmark(in String volId) = 60;
+    void setDebugFlags(int flags, int mask) = 61;
+    void createUserKey(int userId, int serialNumber, boolean ephemeral) = 62;
+    void destroyUserKey(int userId) = 63;
+    void unlockUserKey(int userId, int serialNumber, in byte[] token, in byte[] secret) = 64;
+    void lockUserKey(int userId) = 65;
+    boolean isUserKeyUnlocked(int userId) = 66;
+    void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 67;
+    void destroyUserStorage(in String volumeUuid, int userId, int flags) = 68;
+    boolean isConvertibleToFBE() = 69;
+    ParcelFileDescriptor mountAppFuse(in String name) = 70;
+    void addUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 71;
+    void fixateNewestUserKeyAuth(int userId) = 72;
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
deleted file mode 100644
index b9bcd1c..0000000
--- a/core/java/android/os/storage/IMountService.java
+++ /dev/null
@@ -1,2491 +0,0 @@
-/*
- * Copyright (C) 2010 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.storage;
-
-import android.content.pm.IPackageMoveObserver;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-import android.os.RemoteException;
-
-/**
- * WARNING! Update IMountService.h and IMountService.cpp if you change this
- * file. In particular, the ordering of the methods below must match the
- * _TRANSACTION enum in IMountService.cpp
- *
- * @hide - Applications should use android.os.storage.StorageManager to access
- *       storage functions.
- */
-public interface IMountService extends IInterface {
-    /** Local-side IPC implementation stub class. */
-    public static abstract class Stub extends Binder implements IMountService {
-        private static class Proxy implements IMountService {
-            private final IBinder mRemote;
-
-            Proxy(IBinder remote) {
-                mRemote = remote;
-            }
-
-            public IBinder asBinder() {
-                return mRemote;
-            }
-
-            public String getInterfaceDescriptor() {
-                return DESCRIPTOR;
-            }
-
-            /**
-             * Registers an IMountServiceListener for receiving async
-             * notifications.
-             */
-            public void registerListener(IMountServiceListener listener) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeStrongBinder((listener != null ? listener.asBinder() : null));
-                    mRemote.transact(Stub.TRANSACTION_registerListener, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Unregisters an IMountServiceListener
-             */
-            public void unregisterListener(IMountServiceListener listener) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeStrongBinder((listener != null ? listener.asBinder() : null));
-                    mRemote.transact(Stub.TRANSACTION_unregisterListener, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Returns true if a USB mass storage host is connected
-             */
-            public boolean isUsbMassStorageConnected() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_isUsbMassStorageConnected, _data, _reply, 0);
-                    _reply.readException();
-                    _result = 0 != _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Enables / disables USB mass storage. The caller should check
-             * actual status of enabling/disabling USB mass storage via
-             * StorageEventListener.
-             */
-            public void setUsbMassStorageEnabled(boolean enable) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt((enable ? 1 : 0));
-                    mRemote.transact(Stub.TRANSACTION_setUsbMassStorageEnabled, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Returns true if a USB mass storage host is enabled (media is
-             * shared)
-             */
-            public boolean isUsbMassStorageEnabled() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_isUsbMassStorageEnabled, _data, _reply, 0);
-                    _reply.readException();
-                    _result = 0 != _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Mount external storage at given mount point. Returns an int
-             * consistent with MountServiceResultCode
-             */
-            public int mountVolume(String mountPoint) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(mountPoint);
-                    mRemote.transact(Stub.TRANSACTION_mountVolume, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Safely unmount external storage at given mount point. The unmount
-             * is an asynchronous operation. Applications should register
-             * StorageEventListener for storage related status changes.
-             */
-            public void unmountVolume(String mountPoint, boolean force, boolean removeEncryption)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(mountPoint);
-                    _data.writeInt((force ? 1 : 0));
-                    _data.writeInt((removeEncryption ? 1 : 0));
-                    mRemote.transact(Stub.TRANSACTION_unmountVolume, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Format external storage given a mount point. Returns an int
-             * consistent with MountServiceResultCode
-             */
-            public int formatVolume(String mountPoint) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(mountPoint);
-                    mRemote.transact(Stub.TRANSACTION_formatVolume, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Returns an array of pids with open files on the specified path.
-             */
-            public int[] getStorageUsers(String path) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(path);
-                    mRemote.transact(Stub.TRANSACTION_getStorageUsers, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createIntArray();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Gets the state of a volume via its mountpoint.
-             */
-            public String getVolumeState(String mountPoint) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(mountPoint);
-                    mRemote.transact(Stub.TRANSACTION_getVolumeState, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Creates a secure container with the specified parameters. Returns
-             * an int consistent with MountServiceResultCode
-             */
-            public int createSecureContainer(String id, int sizeMb, String fstype, String key,
-                    int ownerUid, boolean external) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    _data.writeInt(sizeMb);
-                    _data.writeString(fstype);
-                    _data.writeString(key);
-                    _data.writeInt(ownerUid);
-                    _data.writeInt(external ? 1 : 0);
-                    mRemote.transact(Stub.TRANSACTION_createSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Destroy a secure container, and free up all resources associated
-             * with it. NOTE: Ensure all references are released prior to
-             * deleting. Returns an int consistent with MountServiceResultCode
-             */
-            public int destroySecureContainer(String id, boolean force) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    _data.writeInt((force ? 1 : 0));
-                    mRemote.transact(Stub.TRANSACTION_destroySecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Finalize a container which has just been created and populated.
-             * After finalization, the container is immutable. Returns an int
-             * consistent with MountServiceResultCode
-             */
-            public int finalizeSecureContainer(String id) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    mRemote.transact(Stub.TRANSACTION_finalizeSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Mount a secure container with the specified key and owner UID.
-             * Returns an int consistent with MountServiceResultCode
-             */
-            public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    _data.writeString(key);
-                    _data.writeInt(ownerUid);
-                    _data.writeInt(readOnly ? 1 : 0);
-                    mRemote.transact(Stub.TRANSACTION_mountSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Unount a secure container. Returns an int consistent with
-             * MountServiceResultCode
-             */
-            public int unmountSecureContainer(String id, boolean force) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    _data.writeInt((force ? 1 : 0));
-                    mRemote.transact(Stub.TRANSACTION_unmountSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Returns true if the specified container is mounted
-             */
-            public boolean isSecureContainerMounted(String id) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    mRemote.transact(Stub.TRANSACTION_isSecureContainerMounted, _data, _reply, 0);
-                    _reply.readException();
-                    _result = 0 != _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Rename an unmounted secure container. Returns an int consistent
-             * with MountServiceResultCode
-             */
-            public int renameSecureContainer(String oldId, String newId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(oldId);
-                    _data.writeString(newId);
-                    mRemote.transact(Stub.TRANSACTION_renameSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Returns the filesystem path of a mounted secure container.
-             */
-            public String getSecureContainerPath(String id) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    mRemote.transact(Stub.TRANSACTION_getSecureContainerPath, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Gets an Array of currently known secure container IDs
-             */
-            public String[] getSecureContainerList() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_getSecureContainerList, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createStringArray();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Shuts down the MountService and gracefully unmounts all external
-             * media. Invokes call back once the shutdown is complete.
-             */
-            public void shutdown(IMountShutdownObserver observer)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeStrongBinder((observer != null ? observer.asBinder() : null));
-                    mRemote.transact(Stub.TRANSACTION_shutdown, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Call into MountService by PackageManager to notify that its done
-             * processing the media status update request.
-             */
-            public void finishMediaUpdate() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_finishMediaUpdate, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Mounts an Opaque Binary Blob (OBB) with the specified decryption
-             * key and only allows the calling process's UID access to the
-             * contents. MountService will call back to the supplied
-             * IObbActionListener to inform it of the terminal state of the
-             * call.
-             */
-            public void mountObb(String rawPath, String canonicalPath, String key,
-                    IObbActionListener token, int nonce) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(rawPath);
-                    _data.writeString(canonicalPath);
-                    _data.writeString(key);
-                    _data.writeStrongBinder((token != null ? token.asBinder() : null));
-                    _data.writeInt(nonce);
-                    mRemote.transact(Stub.TRANSACTION_mountObb, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Unmounts an Opaque Binary Blob (OBB). When the force flag is
-             * specified, any program using it will be forcibly killed to
-             * unmount the image. MountService will call back to the supplied
-             * IObbActionListener to inform it of the terminal state of the
-             * call.
-             */
-            public void unmountObb(
-                    String rawPath, boolean force, IObbActionListener token, int nonce)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(rawPath);
-                    _data.writeInt((force ? 1 : 0));
-                    _data.writeStrongBinder((token != null ? token.asBinder() : null));
-                    _data.writeInt(nonce);
-                    mRemote.transact(Stub.TRANSACTION_unmountObb, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Checks whether the specified Opaque Binary Blob (OBB) is mounted
-             * somewhere.
-             */
-            public boolean isObbMounted(String rawPath) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(rawPath);
-                    mRemote.transact(Stub.TRANSACTION_isObbMounted, _data, _reply, 0);
-                    _reply.readException();
-                    _result = 0 != _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Gets the path to the mounted Opaque Binary Blob (OBB).
-             */
-            public String getMountedObbPath(String rawPath) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(rawPath);
-                    mRemote.transact(Stub.TRANSACTION_getMountedObbPath, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Returns whether the external storage is emulated.
-             */
-            public boolean isExternalStorageEmulated() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_isExternalStorageEmulated, _data, _reply, 0);
-                    _reply.readException();
-                    _result = 0 != _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int getEncryptionState() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_getEncryptionState, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int decryptStorage(String password) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(password);
-                    mRemote.transact(Stub.TRANSACTION_decryptStorage, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int encryptStorage(int type, String password) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(type);
-                    _data.writeString(password);
-                    mRemote.transact(Stub.TRANSACTION_encryptStorage, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int changeEncryptionPassword(int type, String password) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(type);
-                    _data.writeString(password);
-                    mRemote.transact(Stub.TRANSACTION_changeEncryptionPassword, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int verifyEncryptionPassword(String password) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(password);
-                    mRemote.transact(Stub.TRANSACTION_verifyEncryptionPassword, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public int getPasswordType() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_getPasswordType, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public String getPassword() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_getPassword, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public void clearPassword() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_clearPassword, _data, _reply, IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            public void setField(String field, String data) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(field);
-                    _data.writeString(data);
-                    mRemote.transact(Stub.TRANSACTION_setField, _data, _reply, IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            public String getField(String field) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(field);
-                    mRemote.transact(Stub.TRANSACTION_getField, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public boolean isConvertibleToFBE() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_isConvertibleToFBE, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt() != 0;
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            public StorageVolume[] getVolumeList(int uid, String packageName, int flags)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                StorageVolume[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(uid);
-                    _data.writeString(packageName);
-                    _data.writeInt(flags);
-                    mRemote.transact(Stub.TRANSACTION_getVolumeList, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createTypedArray(StorageVolume.CREATOR);
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /*
-             * Returns the filesystem path of a mounted secure container.
-             */
-            public String getSecureContainerFilesystemPath(String id) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    mRemote.transact(Stub.TRANSACTION_getSecureContainerFilesystemPath, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            /**
-             * Fix permissions in a container which has just been created and
-             * populated. Returns an int consistent with MountServiceResultCode
-             */
-            public int fixPermissionsSecureContainer(String id, int gid, String filename)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    _data.writeInt(gid);
-                    _data.writeString(filename);
-                    mRemote.transact(Stub.TRANSACTION_fixPermissionsSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int mkdirs(String callingPkg, String path) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(callingPkg);
-                    _data.writeString(path);
-                    mRemote.transact(Stub.TRANSACTION_mkdirs, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public int resizeSecureContainer(String id, int sizeMb, String key)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                int _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(id);
-                    _data.writeInt(sizeMb);
-                    _data.writeString(key);
-                    mRemote.transact(Stub.TRANSACTION_resizeSecureContainer, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public long lastMaintenance() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                long _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_lastMaintenance, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readLong();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public void runMaintenance() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_runMaintenance, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return;
-            }
-
-            @Override
-            public void waitForAsecScan() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_waitForAsecScan, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return;
-            }
-
-            @Override
-            public DiskInfo[] getDisks() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                DiskInfo[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_getDisks, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createTypedArray(DiskInfo.CREATOR);
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public VolumeInfo[] getVolumes(int _flags) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                VolumeInfo[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(_flags);
-                    mRemote.transact(Stub.TRANSACTION_getVolumes, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createTypedArray(VolumeInfo.CREATOR);
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public VolumeRecord[] getVolumeRecords(int _flags) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                VolumeRecord[] _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(_flags);
-                    mRemote.transact(Stub.TRANSACTION_getVolumeRecords, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.createTypedArray(VolumeRecord.CREATOR);
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public void mount(String volId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volId);
-                    mRemote.transact(Stub.TRANSACTION_mount, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void unmount(String volId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volId);
-                    mRemote.transact(Stub.TRANSACTION_unmount, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void format(String volId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volId);
-                    mRemote.transact(Stub.TRANSACTION_format, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public long benchmark(String volId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volId);
-                    mRemote.transact(Stub.TRANSACTION_benchmark, _data, _reply, 0);
-                    _reply.readException();
-                    return _reply.readLong();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void partitionPublic(String diskId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(diskId);
-                    mRemote.transact(Stub.TRANSACTION_partitionPublic, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void partitionPrivate(String diskId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(diskId);
-                    mRemote.transact(Stub.TRANSACTION_partitionPrivate, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void partitionMixed(String diskId, int ratio) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(diskId);
-                    _data.writeInt(ratio);
-                    mRemote.transact(Stub.TRANSACTION_partitionMixed, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(fsUuid);
-                    _data.writeString(nickname);
-                    mRemote.transact(Stub.TRANSACTION_setVolumeNickname, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(fsUuid);
-                    _data.writeInt(flags);
-                    _data.writeInt(mask);
-                    mRemote.transact(Stub.TRANSACTION_setVolumeUserFlags, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void forgetVolume(String fsUuid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(fsUuid);
-                    mRemote.transact(Stub.TRANSACTION_forgetVolume, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void forgetAllVolumes() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_forgetAllVolumes, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void setDebugFlags(int _flags, int _mask) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(_flags);
-                    _data.writeInt(_mask);
-                    mRemote.transact(Stub.TRANSACTION_setDebugFlags, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public String getPrimaryStorageUuid() throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                String _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    mRemote.transact(Stub.TRANSACTION_getPrimaryStorageUuid, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.readString();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volumeUuid);
-                    _data.writeStrongBinder((callback != null ? callback.asBinder() : null));
-                    mRemote.transact(Stub.TRANSACTION_setPrimaryStorageUuid, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void createUserKey(int userId, int serialNumber, boolean ephemeral)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    _data.writeInt(serialNumber);
-                    _data.writeInt(ephemeral ? 1 : 0);
-                    mRemote.transact(Stub.TRANSACTION_createUserKey, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void destroyUserKey(int userId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    mRemote.transact(Stub.TRANSACTION_destroyUserKey, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void addUserKeyAuth(int userId, int serialNumber,
-                    byte[] token, byte[] secret) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    _data.writeInt(serialNumber);
-                    _data.writeByteArray(token);
-                    _data.writeByteArray(secret);
-                    mRemote.transact(Stub.TRANSACTION_addUserKeyAuth, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void fixateNewestUserKeyAuth(int userId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    mRemote.transact(Stub.TRANSACTION_fixateNewestUserKeyAuth, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void unlockUserKey(int userId, int serialNumber,
-                    byte[] token, byte[] secret) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    _data.writeInt(serialNumber);
-                    _data.writeByteArray(token);
-                    _data.writeByteArray(secret);
-                    mRemote.transact(Stub.TRANSACTION_unlockUserKey, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void lockUserKey(int userId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    mRemote.transact(Stub.TRANSACTION_lockUserKey, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public boolean isUserKeyUnlocked(int userId) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                boolean _result;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(userId);
-                    mRemote.transact(Stub.TRANSACTION_isUserKeyUnlocked, _data, _reply, 0);
-                    _reply.readException();
-                    _result = 0 != _reply.readInt();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-
-            @Override
-            public void prepareUserStorage(
-                    String volumeUuid, int userId, int serialNumber, int flags)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volumeUuid);
-                    _data.writeInt(userId);
-                    _data.writeInt(serialNumber);
-                    _data.writeInt(flags);
-                    mRemote.transact(Stub.TRANSACTION_prepareUserStorage, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void destroyUserStorage(String volumeUuid, int userId, int flags)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(volumeUuid);
-                    _data.writeInt(userId);
-                    _data.writeInt(flags);
-                    mRemote.transact(Stub.TRANSACTION_destroyUserStorage, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public ParcelFileDescriptor mountAppFuse(String name) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                ParcelFileDescriptor _result = null;
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(name);
-                    mRemote.transact(Stub.TRANSACTION_mountAppFuse, _data, _reply, 0);
-                    _reply.readException();
-                    _result = _reply.<ParcelFileDescriptor>readParcelable(
-                            ClassLoader.getSystemClassLoader());
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-                return _result;
-            }
-        }
-
-        private static final String DESCRIPTOR = "IMountService";
-
-        static final int TRANSACTION_registerListener = IBinder.FIRST_CALL_TRANSACTION + 0;
-
-        static final int TRANSACTION_unregisterListener = IBinder.FIRST_CALL_TRANSACTION + 1;
-
-        static final int TRANSACTION_isUsbMassStorageConnected = IBinder.FIRST_CALL_TRANSACTION + 2;
-
-        static final int TRANSACTION_setUsbMassStorageEnabled = IBinder.FIRST_CALL_TRANSACTION + 3;
-
-        static final int TRANSACTION_isUsbMassStorageEnabled = IBinder.FIRST_CALL_TRANSACTION + 4;
-
-        static final int TRANSACTION_mountVolume = IBinder.FIRST_CALL_TRANSACTION + 5;
-
-        static final int TRANSACTION_unmountVolume = IBinder.FIRST_CALL_TRANSACTION + 6;
-
-        static final int TRANSACTION_formatVolume = IBinder.FIRST_CALL_TRANSACTION + 7;
-
-        static final int TRANSACTION_getStorageUsers = IBinder.FIRST_CALL_TRANSACTION + 8;
-
-        static final int TRANSACTION_getVolumeState = IBinder.FIRST_CALL_TRANSACTION + 9;
-
-        static final int TRANSACTION_createSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 10;
-
-        static final int TRANSACTION_finalizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 11;
-
-        static final int TRANSACTION_destroySecureContainer = IBinder.FIRST_CALL_TRANSACTION + 12;
-
-        static final int TRANSACTION_mountSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 13;
-
-        static final int TRANSACTION_unmountSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 14;
-
-        static final int TRANSACTION_isSecureContainerMounted = IBinder.FIRST_CALL_TRANSACTION + 15;
-
-        static final int TRANSACTION_renameSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 16;
-
-        static final int TRANSACTION_getSecureContainerPath = IBinder.FIRST_CALL_TRANSACTION + 17;
-
-        static final int TRANSACTION_getSecureContainerList = IBinder.FIRST_CALL_TRANSACTION + 18;
-
-        static final int TRANSACTION_shutdown = IBinder.FIRST_CALL_TRANSACTION + 19;
-
-        static final int TRANSACTION_finishMediaUpdate = IBinder.FIRST_CALL_TRANSACTION + 20;
-
-        static final int TRANSACTION_mountObb = IBinder.FIRST_CALL_TRANSACTION + 21;
-
-        static final int TRANSACTION_unmountObb = IBinder.FIRST_CALL_TRANSACTION + 22;
-
-        static final int TRANSACTION_isObbMounted = IBinder.FIRST_CALL_TRANSACTION + 23;
-
-        static final int TRANSACTION_getMountedObbPath = IBinder.FIRST_CALL_TRANSACTION + 24;
-
-        static final int TRANSACTION_isExternalStorageEmulated = IBinder.FIRST_CALL_TRANSACTION + 25;
-
-        static final int TRANSACTION_decryptStorage = IBinder.FIRST_CALL_TRANSACTION + 26;
-
-        static final int TRANSACTION_encryptStorage = IBinder.FIRST_CALL_TRANSACTION + 27;
-
-        static final int TRANSACTION_changeEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 28;
-
-        static final int TRANSACTION_getVolumeList = IBinder.FIRST_CALL_TRANSACTION + 29;
-
-        static final int TRANSACTION_getSecureContainerFilesystemPath = IBinder.FIRST_CALL_TRANSACTION + 30;
-
-        static final int TRANSACTION_getEncryptionState = IBinder.FIRST_CALL_TRANSACTION + 31;
-
-        static final int TRANSACTION_verifyEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 32;
-
-        static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33;
-
-        static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
-
-        static final int TRANSACTION_getPasswordType = IBinder.FIRST_CALL_TRANSACTION + 35;
-
-        static final int TRANSACTION_getPassword = IBinder.FIRST_CALL_TRANSACTION + 36;
-
-        static final int TRANSACTION_clearPassword = IBinder.FIRST_CALL_TRANSACTION + 37;
-
-        static final int TRANSACTION_setField = IBinder.FIRST_CALL_TRANSACTION + 38;
-
-        static final int TRANSACTION_getField = IBinder.FIRST_CALL_TRANSACTION + 39;
-
-        static final int TRANSACTION_resizeSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 40;
-
-        static final int TRANSACTION_lastMaintenance = IBinder.FIRST_CALL_TRANSACTION + 41;
-
-        static final int TRANSACTION_runMaintenance = IBinder.FIRST_CALL_TRANSACTION + 42;
-
-        static final int TRANSACTION_waitForAsecScan = IBinder.FIRST_CALL_TRANSACTION + 43;
-
-        static final int TRANSACTION_getDisks = IBinder.FIRST_CALL_TRANSACTION + 44;
-        static final int TRANSACTION_getVolumes = IBinder.FIRST_CALL_TRANSACTION + 45;
-        static final int TRANSACTION_getVolumeRecords = IBinder.FIRST_CALL_TRANSACTION + 46;
-
-        static final int TRANSACTION_mount = IBinder.FIRST_CALL_TRANSACTION + 47;
-        static final int TRANSACTION_unmount = IBinder.FIRST_CALL_TRANSACTION + 48;
-        static final int TRANSACTION_format = IBinder.FIRST_CALL_TRANSACTION + 49;
-
-        static final int TRANSACTION_partitionPublic = IBinder.FIRST_CALL_TRANSACTION + 50;
-        static final int TRANSACTION_partitionPrivate = IBinder.FIRST_CALL_TRANSACTION + 51;
-        static final int TRANSACTION_partitionMixed = IBinder.FIRST_CALL_TRANSACTION + 52;
-
-        static final int TRANSACTION_setVolumeNickname = IBinder.FIRST_CALL_TRANSACTION + 53;
-        static final int TRANSACTION_setVolumeUserFlags = IBinder.FIRST_CALL_TRANSACTION + 54;
-        static final int TRANSACTION_forgetVolume = IBinder.FIRST_CALL_TRANSACTION + 55;
-        static final int TRANSACTION_forgetAllVolumes = IBinder.FIRST_CALL_TRANSACTION + 56;
-
-        static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 57;
-        static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 58;
-
-        static final int TRANSACTION_benchmark = IBinder.FIRST_CALL_TRANSACTION + 59;
-        static final int TRANSACTION_setDebugFlags = IBinder.FIRST_CALL_TRANSACTION + 60;
-
-        static final int TRANSACTION_createUserKey = IBinder.FIRST_CALL_TRANSACTION + 61;
-        static final int TRANSACTION_destroyUserKey = IBinder.FIRST_CALL_TRANSACTION + 62;
-
-        static final int TRANSACTION_unlockUserKey = IBinder.FIRST_CALL_TRANSACTION + 63;
-        static final int TRANSACTION_lockUserKey = IBinder.FIRST_CALL_TRANSACTION + 64;
-        static final int TRANSACTION_isUserKeyUnlocked = IBinder.FIRST_CALL_TRANSACTION + 65;
-
-        static final int TRANSACTION_prepareUserStorage = IBinder.FIRST_CALL_TRANSACTION + 66;
-        static final int TRANSACTION_destroyUserStorage = IBinder.FIRST_CALL_TRANSACTION + 67;
-
-        static final int TRANSACTION_isConvertibleToFBE = IBinder.FIRST_CALL_TRANSACTION + 68;
-
-        static final int TRANSACTION_mountAppFuse = IBinder.FIRST_CALL_TRANSACTION + 69;
-
-        static final int TRANSACTION_addUserKeyAuth = IBinder.FIRST_CALL_TRANSACTION + 70;
-
-        static final int TRANSACTION_fixateNewestUserKeyAuth = IBinder.FIRST_CALL_TRANSACTION + 71;
-
-        /**
-         * Cast an IBinder object into an IMountService interface, generating a
-         * proxy if needed.
-         */
-        public static IMountService asInterface(IBinder obj) {
-            if (obj == null) {
-                return null;
-            }
-            IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
-            if (iin != null && iin instanceof IMountService) {
-                return (IMountService) iin;
-            }
-            return new IMountService.Stub.Proxy(obj);
-        }
-
-        /** Construct the stub at attach it to the interface. */
-        public Stub() {
-            attachInterface(this, DESCRIPTOR);
-        }
-
-        public IBinder asBinder() {
-            return this;
-        }
-
-        @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply,
-                int flags) throws RemoteException {
-            switch (code) {
-                case INTERFACE_TRANSACTION: {
-                    reply.writeString(DESCRIPTOR);
-                    return true;
-                }
-                case TRANSACTION_registerListener: {
-                    data.enforceInterface(DESCRIPTOR);
-                    IMountServiceListener listener;
-                    listener = IMountServiceListener.Stub.asInterface(data.readStrongBinder());
-                    registerListener(listener);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_unregisterListener: {
-                    data.enforceInterface(DESCRIPTOR);
-                    IMountServiceListener listener;
-                    listener = IMountServiceListener.Stub.asInterface(data.readStrongBinder());
-                    unregisterListener(listener);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_isUsbMassStorageConnected: {
-                    data.enforceInterface(DESCRIPTOR);
-                    boolean result = isUsbMassStorageConnected();
-                    reply.writeNoException();
-                    reply.writeInt((result ? 1 : 0));
-                    return true;
-                }
-                case TRANSACTION_setUsbMassStorageEnabled: {
-                    data.enforceInterface(DESCRIPTOR);
-                    boolean enable;
-                    enable = 0 != data.readInt();
-                    setUsbMassStorageEnabled(enable);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_isUsbMassStorageEnabled: {
-                    data.enforceInterface(DESCRIPTOR);
-                    boolean result = isUsbMassStorageEnabled();
-                    reply.writeNoException();
-                    reply.writeInt((result ? 1 : 0));
-                    return true;
-                }
-                case TRANSACTION_mountVolume: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String mountPoint;
-                    mountPoint = data.readString();
-                    int resultCode = mountVolume(mountPoint);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_unmountVolume: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String mountPoint;
-                    mountPoint = data.readString();
-                    boolean force = 0 != data.readInt();
-                    boolean removeEncrypt = 0 != data.readInt();
-                    unmountVolume(mountPoint, force, removeEncrypt);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_formatVolume: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String mountPoint;
-                    mountPoint = data.readString();
-                    int result = formatVolume(mountPoint);
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_getStorageUsers: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String path;
-                    path = data.readString();
-                    int[] pids = getStorageUsers(path);
-                    reply.writeNoException();
-                    reply.writeIntArray(pids);
-                    return true;
-                }
-                case TRANSACTION_getVolumeState: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String mountPoint;
-                    mountPoint = data.readString();
-                    String state = getVolumeState(mountPoint);
-                    reply.writeNoException();
-                    reply.writeString(state);
-                    return true;
-                }
-                case TRANSACTION_createSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    int sizeMb;
-                    sizeMb = data.readInt();
-                    String fstype;
-                    fstype = data.readString();
-                    String key;
-                    key = data.readString();
-                    int ownerUid;
-                    ownerUid = data.readInt();
-                    boolean external;
-                    external = 0 != data.readInt();
-                    int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid,
-                            external);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_finalizeSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    int resultCode = finalizeSecureContainer(id);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_destroySecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    boolean force;
-                    force = 0 != data.readInt();
-                    int resultCode = destroySecureContainer(id, force);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_mountSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    String key;
-                    key = data.readString();
-                    int ownerUid;
-                    ownerUid = data.readInt();
-                    boolean readOnly;
-                    readOnly = data.readInt() != 0;
-                    int resultCode = mountSecureContainer(id, key, ownerUid, readOnly);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_unmountSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    boolean force;
-                    force = 0 != data.readInt();
-                    int resultCode = unmountSecureContainer(id, force);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_isSecureContainerMounted: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    boolean status = isSecureContainerMounted(id);
-                    reply.writeNoException();
-                    reply.writeInt((status ? 1 : 0));
-                    return true;
-                }
-                case TRANSACTION_renameSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String oldId;
-                    oldId = data.readString();
-                    String newId;
-                    newId = data.readString();
-                    int resultCode = renameSecureContainer(oldId, newId);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_getSecureContainerPath: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    String path = getSecureContainerPath(id);
-                    reply.writeNoException();
-                    reply.writeString(path);
-                    return true;
-                }
-                case TRANSACTION_getSecureContainerList: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String[] ids = getSecureContainerList();
-                    reply.writeNoException();
-                    reply.writeStringArray(ids);
-                    return true;
-                }
-                case TRANSACTION_shutdown: {
-                    data.enforceInterface(DESCRIPTOR);
-                    IMountShutdownObserver observer;
-                    observer = IMountShutdownObserver.Stub.asInterface(data
-                            .readStrongBinder());
-                    shutdown(observer);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_finishMediaUpdate: {
-                    data.enforceInterface(DESCRIPTOR);
-                    finishMediaUpdate();
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_mountObb: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final String rawPath = data.readString();
-                    final String canonicalPath = data.readString();
-                    final String key = data.readString();
-                    IObbActionListener observer;
-                    observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
-                    int nonce;
-                    nonce = data.readInt();
-                    mountObb(rawPath, canonicalPath, key, observer, nonce);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_unmountObb: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String filename;
-                    filename = data.readString();
-                    boolean force;
-                    force = 0 != data.readInt();
-                    IObbActionListener observer;
-                    observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
-                    int nonce;
-                    nonce = data.readInt();
-                    unmountObb(filename, force, observer, nonce);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_isObbMounted: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String filename;
-                    filename = data.readString();
-                    boolean status = isObbMounted(filename);
-                    reply.writeNoException();
-                    reply.writeInt((status ? 1 : 0));
-                    return true;
-                }
-                case TRANSACTION_getMountedObbPath: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String filename;
-                    filename = data.readString();
-                    String mountedPath = getMountedObbPath(filename);
-                    reply.writeNoException();
-                    reply.writeString(mountedPath);
-                    return true;
-                }
-                case TRANSACTION_isExternalStorageEmulated: {
-                    data.enforceInterface(DESCRIPTOR);
-                    boolean emulated = isExternalStorageEmulated();
-                    reply.writeNoException();
-                    reply.writeInt(emulated ? 1 : 0);
-                    return true;
-                }
-                case TRANSACTION_decryptStorage: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String password = data.readString();
-                    int result = decryptStorage(password);
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_encryptStorage: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int type = data.readInt();
-                    String password = data.readString();
-                    int result = encryptStorage(type, password);
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_changeEncryptionPassword: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int type = data.readInt();
-                    String password = data.readString();
-                    int result = changeEncryptionPassword(type, password);
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_getVolumeList: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int uid = data.readInt();
-                    String packageName = data.readString();
-                    int _flags = data.readInt();
-                    StorageVolume[] result = getVolumeList(uid, packageName, _flags);
-                    reply.writeNoException();
-                    reply.writeTypedArray(result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-                    return true;
-                }
-                case TRANSACTION_getSecureContainerFilesystemPath: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    String path = getSecureContainerFilesystemPath(id);
-                    reply.writeNoException();
-                    reply.writeString(path);
-                    return true;
-                }
-                case TRANSACTION_getEncryptionState: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int result = getEncryptionState();
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_fixPermissionsSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    int gid;
-                    gid = data.readInt();
-                    String filename;
-                    filename = data.readString();
-                    int resultCode = fixPermissionsSecureContainer(id, gid, filename);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_mkdirs: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String callingPkg = data.readString();
-                    String path = data.readString();
-                    int result = mkdirs(callingPkg, path);
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_getPasswordType: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int result = getPasswordType();
-                    reply.writeNoException();
-                    reply.writeInt(result);
-                    return true;
-                }
-                case TRANSACTION_getPassword: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String result = getPassword();
-                    reply.writeNoException();
-                    reply.writeString(result);
-                    return true;
-                }
-                case TRANSACTION_clearPassword: {
-                    data.enforceInterface(DESCRIPTOR);
-                    clearPassword();
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_setField: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String field = data.readString();
-                    String contents = data.readString();
-                    setField(field, contents);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_getField: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String field = data.readString();
-                    String contents = getField(field);
-                    reply.writeNoException();
-                    reply.writeString(contents);
-                    return true;
-                }
-                case TRANSACTION_isConvertibleToFBE: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int resultCode = isConvertibleToFBE() ? 1 : 0;
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_resizeSecureContainer: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String id;
-                    id = data.readString();
-                    int sizeMb;
-                    sizeMb = data.readInt();
-                    String key;
-                    key = data.readString();
-                    int resultCode = resizeSecureContainer(id, sizeMb, key);
-                    reply.writeNoException();
-                    reply.writeInt(resultCode);
-                    return true;
-                }
-                case TRANSACTION_lastMaintenance: {
-                    data.enforceInterface(DESCRIPTOR);
-                    long lastMaintenance = lastMaintenance();
-                    reply.writeNoException();
-                    reply.writeLong(lastMaintenance);
-                    return true;
-                }
-                case TRANSACTION_runMaintenance: {
-                    data.enforceInterface(DESCRIPTOR);
-                    runMaintenance();
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_waitForAsecScan: {
-                    data.enforceInterface(DESCRIPTOR);
-                    waitForAsecScan();
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_getDisks: {
-                    data.enforceInterface(DESCRIPTOR);
-                    DiskInfo[] disks = getDisks();
-                    reply.writeNoException();
-                    reply.writeTypedArray(disks, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-                    return true;
-                }
-                case TRANSACTION_getVolumes: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int _flags = data.readInt();
-                    VolumeInfo[] volumes = getVolumes(_flags);
-                    reply.writeNoException();
-                    reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-                    return true;
-                }
-                case TRANSACTION_getVolumeRecords: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int _flags = data.readInt();
-                    VolumeRecord[] volumes = getVolumeRecords(_flags);
-                    reply.writeNoException();
-                    reply.writeTypedArray(volumes, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-                    return true;
-                }
-                case TRANSACTION_mount: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volId = data.readString();
-                    mount(volId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_unmount: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volId = data.readString();
-                    unmount(volId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_format: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volId = data.readString();
-                    format(volId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_benchmark: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volId = data.readString();
-                    long res = benchmark(volId);
-                    reply.writeNoException();
-                    reply.writeLong(res);
-                    return true;
-                }
-                case TRANSACTION_partitionPublic: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String diskId = data.readString();
-                    partitionPublic(diskId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_partitionPrivate: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String diskId = data.readString();
-                    partitionPrivate(diskId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_partitionMixed: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String diskId = data.readString();
-                    int ratio = data.readInt();
-                    partitionMixed(diskId, ratio);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_setVolumeNickname: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volId = data.readString();
-                    String nickname = data.readString();
-                    setVolumeNickname(volId, nickname);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_setVolumeUserFlags: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volId = data.readString();
-                    int _flags = data.readInt();
-                    int _mask = data.readInt();
-                    setVolumeUserFlags(volId, _flags, _mask);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_forgetVolume: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String fsUuid = data.readString();
-                    forgetVolume(fsUuid);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_forgetAllVolumes: {
-                    data.enforceInterface(DESCRIPTOR);
-                    forgetAllVolumes();
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_setDebugFlags: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int _flags = data.readInt();
-                    int _mask = data.readInt();
-                    setDebugFlags(_flags, _mask);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_getPrimaryStorageUuid: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volumeUuid = getPrimaryStorageUuid();
-                    reply.writeNoException();
-                    reply.writeString(volumeUuid);
-                    return true;
-                }
-                case TRANSACTION_setPrimaryStorageUuid: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volumeUuid = data.readString();
-                    IPackageMoveObserver listener = IPackageMoveObserver.Stub.asInterface(
-                            data.readStrongBinder());
-                    setPrimaryStorageUuid(volumeUuid, listener);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_createUserKey: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    int serialNumber = data.readInt();
-                    boolean ephemeral = data.readInt() != 0;
-                    createUserKey(userId, serialNumber, ephemeral);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_destroyUserKey: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    destroyUserKey(userId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_addUserKeyAuth: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    int serialNumber = data.readInt();
-                    byte[] token = data.createByteArray();
-                    byte[] secret = data.createByteArray();
-                    addUserKeyAuth(userId, serialNumber, token, secret);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_fixateNewestUserKeyAuth: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    fixateNewestUserKeyAuth(userId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_unlockUserKey: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    int serialNumber = data.readInt();
-                    byte[] token = data.createByteArray();
-                    byte[] secret = data.createByteArray();
-                    unlockUserKey(userId, serialNumber, token, secret);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_lockUserKey: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    lockUserKey(userId);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_isUserKeyUnlocked: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int userId = data.readInt();
-                    boolean result = isUserKeyUnlocked(userId);
-                    reply.writeNoException();
-                    reply.writeInt(result ? 1 : 0);
-                    return true;
-                }
-                case TRANSACTION_prepareUserStorage: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volumeUuid = data.readString();
-                    int userId = data.readInt();
-                    int serialNumber = data.readInt();
-                    int _flags = data.readInt();
-                    prepareUserStorage(volumeUuid, userId, serialNumber, _flags);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_destroyUserStorage: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String volumeUuid = data.readString();
-                    int userId = data.readInt();
-                    int _flags = data.readInt();
-                    destroyUserStorage(volumeUuid, userId, _flags);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_mountAppFuse: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String name = data.readString();
-                    ParcelFileDescriptor fd = mountAppFuse(name);
-                    reply.writeNoException();
-                    reply.writeParcelable(fd, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-                    return true;
-                }
-            }
-            return super.onTransact(code, data, reply, flags);
-        }
-    }
-
-    /*
-     * Creates a secure container with the specified parameters. Returns an int
-     * consistent with MountServiceResultCode
-     */
-    public int createSecureContainer(String id, int sizeMb, String fstype, String key,
-            int ownerUid, boolean external) throws RemoteException;
-
-    /*
-     * Destroy a secure container, and free up all resources associated with it.
-     * NOTE: Ensure all references are released prior to deleting. Returns an
-     * int consistent with MountServiceResultCode
-     */
-    public int destroySecureContainer(String id, boolean force) throws RemoteException;
-
-    /*
-     * Finalize a container which has just been created and populated. After
-     * finalization, the container is immutable. Returns an int consistent with
-     * MountServiceResultCode
-     */
-    public int finalizeSecureContainer(String id) throws RemoteException;
-
-    /**
-     * Call into MountService by PackageManager to notify that its done
-     * processing the media status update request.
-     */
-    public void finishMediaUpdate() throws RemoteException;
-
-    /**
-     * Format external storage given a mount point. Returns an int consistent
-     * with MountServiceResultCode
-     */
-    public int formatVolume(String mountPoint) throws RemoteException;
-
-    /**
-     * Gets the path to the mounted Opaque Binary Blob (OBB).
-     */
-    public String getMountedObbPath(String rawPath) throws RemoteException;
-
-    /**
-     * Gets an Array of currently known secure container IDs
-     */
-    public String[] getSecureContainerList() throws RemoteException;
-
-    /*
-     * Returns the filesystem path of a mounted secure container.
-     */
-    public String getSecureContainerPath(String id) throws RemoteException;
-
-    /**
-     * Returns an array of pids with open files on the specified path.
-     */
-    public int[] getStorageUsers(String path) throws RemoteException;
-
-    /**
-     * Gets the state of a volume via its mountpoint.
-     */
-    public String getVolumeState(String mountPoint) throws RemoteException;
-
-    /**
-     * Checks whether the specified Opaque Binary Blob (OBB) is mounted
-     * somewhere.
-     */
-    public boolean isObbMounted(String rawPath) throws RemoteException;
-
-    /*
-     * Returns true if the specified container is mounted
-     */
-    public boolean isSecureContainerMounted(String id) throws RemoteException;
-
-    /**
-     * Returns true if a USB mass storage host is connected
-     */
-    public boolean isUsbMassStorageConnected() throws RemoteException;
-
-    /**
-     * Returns true if a USB mass storage host is enabled (media is shared)
-     */
-    public boolean isUsbMassStorageEnabled() throws RemoteException;
-
-    /**
-     * Mounts an Opaque Binary Blob (OBB) with the specified decryption key and
-     * only allows the calling process's UID access to the contents.
-     * MountService will call back to the supplied IObbActionListener to inform
-     * it of the terminal state of the call.
-     */
-    public void mountObb(String rawPath, String canonicalPath, String key,
-            IObbActionListener token, int nonce) throws RemoteException;
-
-    /*
-     * Mount a secure container with the specified key and owner UID. Returns an
-     * int consistent with MountServiceResultCode
-     */
-    public int mountSecureContainer(String id, String key, int ownerUid, boolean readOnly)
-            throws RemoteException;
-
-    /**
-     * Mount external storage at given mount point. Returns an int consistent
-     * with MountServiceResultCode
-     */
-    public int mountVolume(String mountPoint) throws RemoteException;
-
-    /**
-     * Registers an IMountServiceListener for receiving async notifications.
-     */
-    public void registerListener(IMountServiceListener listener) throws RemoteException;
-
-    /*
-     * Rename an unmounted secure container. Returns an int consistent with
-     * MountServiceResultCode
-     */
-    public int renameSecureContainer(String oldId, String newId) throws RemoteException;
-
-    /**
-     * Enables / disables USB mass storage. The caller should check actual
-     * status of enabling/disabling USB mass storage via StorageEventListener.
-     */
-    public void setUsbMassStorageEnabled(boolean enable) throws RemoteException;
-
-    /**
-     * Shuts down the MountService and gracefully unmounts all external media.
-     * Invokes call back once the shutdown is complete.
-     */
-    public void shutdown(IMountShutdownObserver observer) throws RemoteException;
-
-    /**
-     * Unmounts an Opaque Binary Blob (OBB). When the force flag is specified,
-     * any program using it will be forcibly killed to unmount the image.
-     * MountService will call back to the supplied IObbActionListener to inform
-     * it of the terminal state of the call.
-     */
-    public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce)
-            throws RemoteException;
-
-    /*
-     * Unount a secure container. Returns an int consistent with
-     * MountServiceResultCode
-     */
-    public int unmountSecureContainer(String id, boolean force) throws RemoteException;
-
-    /**
-     * Safely unmount external storage at given mount point. The unmount is an
-     * asynchronous operation. Applications should register StorageEventListener
-     * for storage related status changes.
-     * @param mountPoint the mount point
-     * @param force whether or not to forcefully unmount it (e.g. even if programs are using this
-     *     data currently)
-     * @param removeEncryption whether or not encryption mapping should be removed from the volume.
-     *     This value implies {@code force}.
-     */
-    public void unmountVolume(String mountPoint, boolean force, boolean removeEncryption)
-            throws RemoteException;
-
-    /**
-     * Unregisters an IMountServiceListener
-     */
-    public void unregisterListener(IMountServiceListener listener) throws RemoteException;
-
-    /**
-     * Returns whether or not the external storage is emulated.
-     */
-    public boolean isExternalStorageEmulated() throws RemoteException;
-
-    /** The volume is not encrypted. */
-    static final int ENCRYPTION_STATE_NONE = 1;
-    /** The volume has been encrypted succesfully. */
-    static final int ENCRYPTION_STATE_OK = 0;
-    /** The volume is in a bad state.*/
-    static final int ENCRYPTION_STATE_ERROR_UNKNOWN = -1;
-    /** Encryption is incomplete */
-    static final int ENCRYPTION_STATE_ERROR_INCOMPLETE = -2;
-    /** Encryption is incomplete and irrecoverable */
-    static final int ENCRYPTION_STATE_ERROR_INCONSISTENT = -3;
-    /** Underlying data is corrupt */
-    static final int ENCRYPTION_STATE_ERROR_CORRUPT = -4;
-
-    /**
-     * Determines the encryption state of the volume.
-     * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
-     * values.
-     * Note that this has been replaced in most cases by the APIs in
-     * StorageManager (see isEncryptable and below)
-     * This is still useful to get the error state when encryption has failed
-     * and CryptKeeper needs to throw up a screen advising the user what to do
-     */
-    public int getEncryptionState() throws RemoteException;
-
-    /**
-     * Decrypts any encrypted volumes.
-     */
-    public int decryptStorage(String password) throws RemoteException;
-
-    /**
-     * Encrypts storage.
-     */
-    public int encryptStorage(int type, String password) throws RemoteException;
-
-    /**
-     * Changes the encryption password.
-     */
-    public int changeEncryptionPassword(int type, String password)
-        throws RemoteException;
-
-    /**
-     * Verify the encryption password against the stored volume.  This method
-     * may only be called by the system process.
-     */
-    public int verifyEncryptionPassword(String password) throws RemoteException;
-
-    /**
-     * Returns list of all mountable volumes.
-     */
-    public StorageVolume[] getVolumeList(int uid, String packageName, int flags) throws RemoteException;
-
-    /**
-     * Gets the path on the filesystem for the ASEC container itself.
-     *
-     * @param cid ASEC container ID
-     * @return path to filesystem or {@code null} if it's not found
-     * @throws RemoteException
-     */
-    public String getSecureContainerFilesystemPath(String cid) throws RemoteException;
-
-    /*
-     * Fix permissions in a container which has just been created and populated.
-     * Returns an int consistent with MountServiceResultCode
-     */
-    public int fixPermissionsSecureContainer(String id, int gid, String filename)
-            throws RemoteException;
-
-    /**
-     * Ensure that all directories along given path exist, creating parent
-     * directories as needed. Validates that given path is absolute and that it
-     * contains no relative "." or ".." paths or symlinks. Also ensures that
-     * path belongs to a volume managed by vold, and that path is either
-     * external storage data or OBB directory belonging to calling app.
-     */
-    public int mkdirs(String callingPkg, String path) throws RemoteException;
-
-    /**
-     * Determines the type of the encryption password
-     * @return PasswordType
-     */
-    public int getPasswordType() throws RemoteException;
-
-    /**
-     * Get password from vold
-     * @return password or empty string
-     */
-    public String getPassword() throws RemoteException;
-
-    /**
-     * Securely clear password from vold
-     */
-    public void clearPassword() throws RemoteException;
-
-    /**
-     * Set a field in the crypto header.
-     * @param field field to set
-     * @param contents contents to set in field
-     */
-    public void setField(String field, String contents) throws RemoteException;
-
-    /**
-     * Gets a field from the crypto header.
-     * @param field field to get
-     * @return contents of field
-     */
-    public String getField(String field) throws RemoteException;
-
-    public boolean isConvertibleToFBE() throws RemoteException;
-
-    public int resizeSecureContainer(String id, int sizeMb, String key) throws RemoteException;
-
-    /**
-     * Report the time of the last maintenance operation such as fstrim.
-     * @return Timestamp of the last maintenance operation, in the
-     *     System.currentTimeMillis() time base
-     * @throws RemoteException
-     */
-    public long lastMaintenance() throws RemoteException;
-
-    /**
-     * Kick off an immediate maintenance operation
-     * @throws RemoteException
-     */
-    public void runMaintenance() throws RemoteException;
-
-    public void waitForAsecScan() throws RemoteException;
-
-    public DiskInfo[] getDisks() throws RemoteException;
-    public VolumeInfo[] getVolumes(int flags) throws RemoteException;
-    public VolumeRecord[] getVolumeRecords(int flags) throws RemoteException;
-
-    public void mount(String volId) throws RemoteException;
-    public void unmount(String volId) throws RemoteException;
-    public void format(String volId) throws RemoteException;
-    public long benchmark(String volId) throws RemoteException;
-
-    public void partitionPublic(String diskId) throws RemoteException;
-    public void partitionPrivate(String diskId) throws RemoteException;
-    public void partitionMixed(String diskId, int ratio) throws RemoteException;
-
-    public void setVolumeNickname(String fsUuid, String nickname) throws RemoteException;
-    public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException;
-    public void forgetVolume(String fsUuid) throws RemoteException;
-    public void forgetAllVolumes() throws RemoteException;
-    public void setDebugFlags(int flags, int mask) throws RemoteException;
-
-    public String getPrimaryStorageUuid() throws RemoteException;
-    public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)
-            throws RemoteException;
-
-    public void createUserKey(int userId, int serialNumber, boolean ephemeral)
-            throws RemoteException;
-    public void destroyUserKey(int userId) throws RemoteException;
-    public void addUserKeyAuth(int userId, int serialNumber,
-            byte[] token, byte[] secret) throws RemoteException;
-    public void fixateNewestUserKeyAuth(int userId) throws RemoteException;
-
-    public void unlockUserKey(int userId, int serialNumber,
-            byte[] token, byte[] secret) throws RemoteException;
-    public void lockUserKey(int userId) throws RemoteException;
-    public boolean isUserKeyUnlocked(int userId) throws RemoteException;
-
-    public void prepareUserStorage(String volumeUuid, int userId, int serialNumber,
-            int flags) throws RemoteException;
-    public void destroyUserStorage(String volumeUuid, int userId, int flags) throws RemoteException;
-
-    public ParcelFileDescriptor mountAppFuse(String name) throws RemoteException;
-}
diff --git a/core/java/android/os/storage/IMountServiceListener.aidl b/core/java/android/os/storage/IMountServiceListener.aidl
new file mode 100644
index 0000000..e149978
--- /dev/null
+++ b/core/java/android/os/storage/IMountServiceListener.aidl
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+import android.os.storage.DiskInfo;
+import android.os.storage.VolumeInfo;
+import android.os.storage.VolumeRecord;
+
+/**
+ * Callback class for receiving events from MountService.
+ *
+ * Don't change the existing transaction Ids as they could be used in the native code.
+ * When adding a new method, assign the next available transaction id.
+ *
+ * @hide - Applications should use IStorageEventListener for storage event
+ *       callbacks.
+ */
+oneway interface IMountServiceListener {
+    /**
+     * Detection state of USB Mass Storage has changed
+     *
+     * @param available true if a UMS host is connected.
+     */
+    void onUsbMassStorageConnectionChanged(boolean connected) = 1;
+
+    /**
+     * Storage state has changed.
+     *
+     * @param path The volume mount path.
+     * @param oldState The old state of the volume.
+     * @param newState The new state of the volume. Note: State is one of the
+     *            values returned by Environment.getExternalStorageState()
+     */
+    void onStorageStateChanged(in String path, in String oldState, in String newState) = 2;
+
+    void onVolumeStateChanged(in VolumeInfo vol, int oldState, int newState) = 3;
+
+    void onVolumeRecordChanged(in VolumeRecord rec) = 4;
+
+    void onVolumeForgotten(in String fsUuid) = 5;
+
+    void onDiskScanned(in DiskInfo disk, int volumeCount) = 6;
+
+    void onDiskDestroyed(in DiskInfo disk) = 7;
+
+    /**
+     * Don't change the existing transaction Ids as they could be used in the native code.
+     * When adding a new method, assign the next available transaction id.
+     */
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/IMountServiceListener.java b/core/java/android/os/storage/IMountServiceListener.java
deleted file mode 100644
index cade9d7..0000000
--- a/core/java/android/os/storage/IMountServiceListener.java
+++ /dev/null
@@ -1,309 +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 android.os.storage;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.RemoteException;
-
-/**
- * Callback class for receiving events from MountService.
- * 
- * @hide - Applications should use IStorageEventListener for storage event
- *       callbacks.
- */
-public interface IMountServiceListener extends IInterface {
-    /** Local-side IPC implementation stub class. */
-    public static abstract class Stub extends Binder implements IMountServiceListener {
-        private static final String DESCRIPTOR = "IMountServiceListener";
-
-        /** Construct the stub at attach it to the interface. */
-        public Stub() {
-            this.attachInterface(this, DESCRIPTOR);
-        }
-
-        /**
-         * Cast an IBinder object into an IMountServiceListener interface,
-         * generating a proxy if needed.
-         */
-        public static IMountServiceListener asInterface(IBinder obj) {
-            if ((obj == null)) {
-                return null;
-            }
-            IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR);
-            if (((iin != null) && (iin instanceof IMountServiceListener))) {
-                return ((IMountServiceListener) iin);
-            }
-            return new IMountServiceListener.Stub.Proxy(obj);
-        }
-
-        public IBinder asBinder() {
-            return this;
-        }
-
-        @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                throws RemoteException {
-            switch (code) {
-                case INTERFACE_TRANSACTION: {
-                    reply.writeString(DESCRIPTOR);
-                    return true;
-                }
-                case TRANSACTION_onUsbMassStorageConnectionChanged: {
-                    data.enforceInterface(DESCRIPTOR);
-                    boolean connected;
-                    connected = (0 != data.readInt());
-                    this.onUsbMassStorageConnectionChanged(connected);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_onStorageStateChanged: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final String path = data.readString();
-                    final String oldState = data.readString();
-                    final String newState = data.readString();
-                    this.onStorageStateChanged(path, oldState, newState);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_onVolumeStateChanged: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final VolumeInfo vol = (VolumeInfo) data.readParcelable(null);
-                    final int oldState = data.readInt();
-                    final int newState = data.readInt();
-                    onVolumeStateChanged(vol, oldState, newState);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_onVolumeRecordChanged: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final VolumeRecord rec = (VolumeRecord) data.readParcelable(null);
-                    onVolumeRecordChanged(rec);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_onVolumeForgotten: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final String fsUuid = data.readString();
-                    onVolumeForgotten(fsUuid);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_onDiskScanned: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final DiskInfo disk = (DiskInfo) data.readParcelable(null);
-                    final int volumeCount = data.readInt();
-                    onDiskScanned(disk, volumeCount);
-                    reply.writeNoException();
-                    return true;
-                }
-                case TRANSACTION_onDiskDestroyed: {
-                    data.enforceInterface(DESCRIPTOR);
-                    final DiskInfo disk = (DiskInfo) data.readParcelable(null);
-                    onDiskDestroyed(disk);
-                    reply.writeNoException();
-                    return true;
-                }
-            }
-            return super.onTransact(code, data, reply, flags);
-        }
-
-        private static class Proxy implements IMountServiceListener {
-            private IBinder mRemote;
-
-            Proxy(IBinder remote) {
-                mRemote = remote;
-            }
-
-            public IBinder asBinder() {
-                return mRemote;
-            }
-
-            public String getInterfaceDescriptor() {
-                return DESCRIPTOR;
-            }
-
-            /**
-             * Detection state of USB Mass Storage has changed
-             * 
-             * @param available true if a UMS host is connected.
-             */
-            public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(((connected) ? (1) : (0)));
-                    mRemote.transact(Stub.TRANSACTION_onUsbMassStorageConnectionChanged, _data,
-                            _reply, android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            /**
-             * Storage state has changed.
-             * 
-             * @param path The volume mount path.
-             * @param oldState The old state of the volume.
-             * @param newState The new state of the volume. Note: State is one
-             *            of the values returned by
-             *            Environment.getExternalStorageState()
-             */
-            public void onStorageStateChanged(String path, String oldState, String newState)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(path);
-                    _data.writeString(oldState);
-                    _data.writeString(newState);
-                    mRemote.transact(Stub.TRANSACTION_onStorageStateChanged, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeParcelable(vol, 0);
-                    _data.writeInt(oldState);
-                    _data.writeInt(newState);
-                    mRemote.transact(Stub.TRANSACTION_onVolumeStateChanged, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void onVolumeRecordChanged(VolumeRecord rec) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeParcelable(rec, 0);
-                    mRemote.transact(Stub.TRANSACTION_onVolumeRecordChanged, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void onVolumeForgotten(String fsUuid) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(fsUuid);
-                    mRemote.transact(Stub.TRANSACTION_onVolumeForgotten, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeParcelable(disk, 0);
-                    _data.writeInt(volumeCount);
-                    mRemote.transact(Stub.TRANSACTION_onDiskScanned, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-
-            @Override
-            public void onDiskDestroyed(DiskInfo disk) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeParcelable(disk, 0);
-                    mRemote.transact(Stub.TRANSACTION_onDiskDestroyed, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-        }
-
-        static final int TRANSACTION_onUsbMassStorageConnectionChanged = (IBinder.FIRST_CALL_TRANSACTION + 0);
-        static final int TRANSACTION_onStorageStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 1);
-        static final int TRANSACTION_onVolumeStateChanged = (IBinder.FIRST_CALL_TRANSACTION + 2);
-        static final int TRANSACTION_onVolumeRecordChanged = (IBinder.FIRST_CALL_TRANSACTION + 3);
-        static final int TRANSACTION_onVolumeForgotten = (IBinder.FIRST_CALL_TRANSACTION + 4);
-        static final int TRANSACTION_onDiskScanned = (IBinder.FIRST_CALL_TRANSACTION + 5);
-        static final int TRANSACTION_onDiskDestroyed = (IBinder.FIRST_CALL_TRANSACTION + 6);
-    }
-
-    /**
-     * Detection state of USB Mass Storage has changed
-     * 
-     * @param available true if a UMS host is connected.
-     */
-    public void onUsbMassStorageConnectionChanged(boolean connected) throws RemoteException;
-
-    /**
-     * Storage state has changed.
-     * 
-     * @param path The volume mount path.
-     * @param oldState The old state of the volume.
-     * @param newState The new state of the volume. Note: State is one of the
-     *            values returned by Environment.getExternalStorageState()
-     */
-    public void onStorageStateChanged(String path, String oldState, String newState)
-            throws RemoteException;
-
-    public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState)
-            throws RemoteException;
-    public void onVolumeRecordChanged(VolumeRecord rec) throws RemoteException;
-    public void onVolumeForgotten(String fsUuid) throws RemoteException;
-
-    public void onDiskScanned(DiskInfo disk, int volumeCount) throws RemoteException;
-
-    public void onDiskDestroyed(DiskInfo disk) throws RemoteException;
-}
diff --git a/core/java/android/os/storage/IMountShutdownObserver.aidl b/core/java/android/os/storage/IMountShutdownObserver.aidl
new file mode 100644
index 0000000..3353bc5
--- /dev/null
+++ b/core/java/android/os/storage/IMountShutdownObserver.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Callback class for receiving events related to shutdown.
+ *
+ * Don't change the existing transaction Ids as they could be used in the native code.
+ * When adding a new method, assign the next available transaction id.
+ *
+ * @hide - For internal consumption only.
+ */
+interface IMountShutdownObserver {
+    /**
+     * This method is called when the shutdown of MountService completed.
+     *
+     * @param statusCode indicates success or failure of the shutdown.
+     */
+    void onShutDownComplete(int statusCode) = 1;
+
+    /**
+     * Don't change the existing transaction Ids as they could be used in the native code.
+     * When adding a new method, assign the next available transaction id.
+     */
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/IMountShutdownObserver.java b/core/java/android/os/storage/IMountShutdownObserver.java
deleted file mode 100644
index d946e1a..0000000
--- a/core/java/android/os/storage/IMountShutdownObserver.java
+++ /dev/null
@@ -1,124 +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 android.os.storage;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.RemoteException;
-
-/**
- * Callback class for receiving events related to shutdown.
- * 
- * @hide - For internal consumption only.
- */
-public interface IMountShutdownObserver extends IInterface {
-    /** Local-side IPC implementation stub class. */
-    public static abstract class Stub extends Binder implements IMountShutdownObserver {
-        private static final java.lang.String DESCRIPTOR = "IMountShutdownObserver";
-
-        /** Construct the stub at attach it to the interface. */
-        public Stub() {
-            this.attachInterface(this, DESCRIPTOR);
-        }
-
-        /**
-         * Cast an IBinder object into an IMountShutdownObserver interface,
-         * generating a proxy if needed.
-         */
-        public static IMountShutdownObserver asInterface(IBinder obj) {
-            if ((obj == null)) {
-                return null;
-            }
-            IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR);
-            if (((iin != null) && (iin instanceof IMountShutdownObserver))) {
-                return ((IMountShutdownObserver) iin);
-            }
-            return new IMountShutdownObserver.Stub.Proxy(obj);
-        }
-
-        public IBinder asBinder() {
-            return this;
-        }
-
-        @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                throws RemoteException {
-            switch (code) {
-                case INTERFACE_TRANSACTION: {
-                    reply.writeString(DESCRIPTOR);
-                    return true;
-                }
-                case TRANSACTION_onShutDownComplete: {
-                    data.enforceInterface(DESCRIPTOR);
-                    int statusCode;
-                    statusCode = data.readInt();
-                    this.onShutDownComplete(statusCode);
-                    reply.writeNoException();
-                    return true;
-                }
-            }
-            return super.onTransact(code, data, reply, flags);
-        }
-
-        private static class Proxy implements IMountShutdownObserver {
-            private IBinder mRemote;
-
-            Proxy(IBinder remote) {
-                mRemote = remote;
-            }
-
-            public IBinder asBinder() {
-                return mRemote;
-            }
-
-            public java.lang.String getInterfaceDescriptor() {
-                return DESCRIPTOR;
-            }
-
-            /**
-             * This method is called when the shutdown of MountService
-             * completed.
-             * 
-             * @param statusCode indicates success or failure of the shutdown.
-             */
-            public void onShutDownComplete(int statusCode) throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeInt(statusCode);
-                    mRemote.transact(Stub.TRANSACTION_onShutDownComplete, _data, _reply, 0);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-        }
-
-        static final int TRANSACTION_onShutDownComplete = (IBinder.FIRST_CALL_TRANSACTION + 0);
-    }
-
-    /**
-     * This method is called when the shutdown of MountService completed.
-     * 
-     * @param statusCode indicates success or failure of the shutdown.
-     */
-    public void onShutDownComplete(int statusCode) throws RemoteException;
-}
diff --git a/core/java/android/os/storage/IObbActionListener.aidl b/core/java/android/os/storage/IObbActionListener.aidl
new file mode 100644
index 0000000..71e6aaf
--- /dev/null
+++ b/core/java/android/os/storage/IObbActionListener.aidl
@@ -0,0 +1,42 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Callback class for receiving events from MountService about Opaque Binary
+ * Blobs (OBBs).
+ *
+ * Don't change the existing transaction Ids as they could be used in the native code.
+ * When adding a new method, assign the next available transaction id.
+ *
+ * @hide - Applications should use StorageManager to interact with OBBs.
+ */
+oneway interface IObbActionListener {
+    /**
+     * Return from an OBB action result.
+     *
+     * @param filename the path to the OBB the operation was performed on
+     * @param nonce identifier that is meaningful to the receiver
+     * @param status status code as defined in {@link OnObbStateChangeListener}
+     */
+    void onObbResult(in String filename, int nonce, int status) = 1;
+
+    /**
+     * Don't change the existing transaction Ids as they could be used in the native code.
+     * When adding a new method, assign the next available transaction id.
+     */
+}
\ No newline at end of file
diff --git a/core/java/android/os/storage/IObbActionListener.java b/core/java/android/os/storage/IObbActionListener.java
deleted file mode 100644
index 35da4b0..0000000
--- a/core/java/android/os/storage/IObbActionListener.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2010 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.storage;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Parcel;
-import android.os.RemoteException;
-
-/**
- * Callback class for receiving events from MountService about Opaque Binary
- * Blobs (OBBs).
- * 
- * @hide - Applications should use StorageManager to interact with OBBs.
- */
-public interface IObbActionListener extends IInterface {
-    /** Local-side IPC implementation stub class. */
-    public static abstract class Stub extends Binder implements IObbActionListener {
-        private static final String DESCRIPTOR = "IObbActionListener";
-
-        /** Construct the stub at attach it to the interface. */
-        public Stub() {
-            this.attachInterface(this, DESCRIPTOR);
-        }
-
-        /**
-         * Cast an IBinder object into an IObbActionListener interface,
-         * generating a proxy if needed.
-         */
-        public static IObbActionListener asInterface(IBinder obj) {
-            if ((obj == null)) {
-                return null;
-            }
-            IInterface iin = (IInterface) obj.queryLocalInterface(DESCRIPTOR);
-            if (((iin != null) && (iin instanceof IObbActionListener))) {
-                return ((IObbActionListener) iin);
-            }
-            return new IObbActionListener.Stub.Proxy(obj);
-        }
-
-        public IBinder asBinder() {
-            return this;
-        }
-
-        @Override
-        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
-                throws RemoteException {
-            switch (code) {
-                case INTERFACE_TRANSACTION: {
-                    reply.writeString(DESCRIPTOR);
-                    return true;
-                }
-                case TRANSACTION_onObbResult: {
-                    data.enforceInterface(DESCRIPTOR);
-                    String filename;
-                    filename = data.readString();
-                    int nonce;
-                    nonce = data.readInt();
-                    int status;
-                    status = data.readInt();
-                    this.onObbResult(filename, nonce, status);
-                    reply.writeNoException();
-                    return true;
-                }
-            }
-            return super.onTransact(code, data, reply, flags);
-        }
-
-        private static class Proxy implements IObbActionListener {
-            private IBinder mRemote;
-
-            Proxy(IBinder remote) {
-                mRemote = remote;
-            }
-
-            public IBinder asBinder() {
-                return mRemote;
-            }
-
-            public String getInterfaceDescriptor() {
-                return DESCRIPTOR;
-            }
-
-            /**
-             * Return from an OBB action result.
-             * 
-             * @param filename the path to the OBB the operation was performed
-             *            on
-             * @param returnCode status of the operation
-             */
-            public void onObbResult(String filename, int nonce, int status)
-                    throws RemoteException {
-                Parcel _data = Parcel.obtain();
-                Parcel _reply = Parcel.obtain();
-                try {
-                    _data.writeInterfaceToken(DESCRIPTOR);
-                    _data.writeString(filename);
-                    _data.writeInt(nonce);
-                    _data.writeInt(status);
-                    mRemote.transact(Stub.TRANSACTION_onObbResult, _data, _reply,
-                            android.os.IBinder.FLAG_ONEWAY);
-                    _reply.readException();
-                } finally {
-                    _reply.recycle();
-                    _data.recycle();
-                }
-            }
-        }
-
-        static final int TRANSACTION_onObbResult = (IBinder.FIRST_CALL_TRANSACTION + 0);
-    }
-
-    /**
-     * Return from an OBB action result.
-     * 
-     * @param filename the path to the OBB the operation was performed on
-     * @param nonce identifier that is meaningful to the receiver
-     * @param status status code as defined in {@link OnObbStateChangeListener}
-     */
-    public void onObbResult(String filename, int nonce, int status) throws RemoteException;
-}
diff --git a/core/java/android/os/storage/MountServiceListener.java b/core/java/android/os/storage/MountServiceListener.java
deleted file mode 100644
index bebb3f6..0000000
--- a/core/java/android/os/storage/MountServiceListener.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 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.storage;
-
-/**
- * Callback class for receiving progress reports during a restore operation.  These
- * methods will all be called on your application's main thread.
- * @hide
- */
-public abstract class MountServiceListener {
-    /**
-     * USB Mass storage connection state has changed.
-     *
-     * @param connected True if UMS is connected.
-     */
-    void onUsbMassStorageConnectionChanged(boolean connected) {
-    }
-
-    /**
-     *  Storage state has changed.
-     *
-     * @param path The volume mount path.
-     * @param oldState The old state of the volume.
-     * @param newState The new state of the volume.
-     *
-     * @Note: State is one of the values returned by Environment.getExternalStorageState()
-     */
-    void onStorageStateChange(String path, String oldState, String newState) {
-    }
-}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 1a78fe7..1942fde 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -41,6 +41,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -133,6 +134,24 @@
     /** {@hide} */
     public static final int FLAG_INCLUDE_INVISIBLE = 1 << 10;
 
+    /** @hide The volume is not encrypted. */
+    public static final int ENCRYPTION_STATE_NONE = 1;
+
+    /** @hide The volume has been encrypted succesfully. */
+    public static final int ENCRYPTION_STATE_OK = 0;
+
+    /** @hide The volume is in a bad state.*/
+    public static final int ENCRYPTION_STATE_ERROR_UNKNOWN = -1;
+
+    /** @hide Encryption is incomplete */
+    public static final int ENCRYPTION_STATE_ERROR_INCOMPLETE = -2;
+
+    /** @hide Encryption is incomplete and irrecoverable */
+    public static final int ENCRYPTION_STATE_ERROR_INCONSISTENT = -3;
+
+    /** @hide Underlying data is corrupt */
+    public static final int ENCRYPTION_STATE_ERROR_CORRUPT = -4;
+
     private static volatile IMountService sMountService = null;
 
     // TODO: the location of the primary storage block varies from device to device, so we need to
@@ -929,22 +948,29 @@
     }
 
     /** {@hide} */
-    public long getPrimaryStorageSize() {
+    public static Pair<String, Long> getPrimaryStoragePathAndSize() {
         for (String path : INTERNAL_STORAGE_SIZE_PATHS) {
             final long numberBlocks = readLong(path);
             if (numberBlocks > 0) {
-                return numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE;
+                return new Pair<>(path, Long.valueOf(numberBlocks * INTERNAL_STORAGE_SECTOR_SIZE));
             }
         }
-        return 0;
+        return null;
     }
 
-    private long readLong(String path) {
+
+    /** {@hide} */
+    public long getPrimaryStorageSize() {
+        final Pair<String, Long> pair = getPrimaryStoragePathAndSize();
+        return pair == null ? 0 : pair.second.longValue();
+    }
+
+    private static long readLong(String path) {
         try (final FileInputStream fis = new FileInputStream(path);
                 final BufferedReader reader = new BufferedReader(new InputStreamReader(fis));) {
             return Long.parseLong(reader.readLine());
         } catch (Exception e) {
-            Slog.w(TAG, "Could not read " + path, e);
+            Slog.w(TAG, "readLong(): could not read " + path + ": " + e);
             return 0;
         }
     }
diff --git a/core/java/android/os/storage/VolumeRecord.aidl b/core/java/android/os/storage/VolumeRecord.aidl
new file mode 100644
index 0000000..27c4010
--- /dev/null
+++ b/core/java/android/os/storage/VolumeRecord.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2016, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/** @hide */
+parcelable VolumeRecord;
\ No newline at end of file
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 184453b..d5a933c 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -6284,6 +6284,17 @@
      * @param intent the intent used to identify the RemoteViewsService for the adapter to connect to.
      */
     public void setRemoteViewsAdapter(Intent intent) {
+        setRemoteViewsAdapter(intent, false);
+    }
+
+    /** @hide **/
+    public Runnable setRemoteViewsAdapterAsync(final Intent intent) {
+        return new RemoteViewsAdapter.AsyncRemoteAdapterAction(this, intent);
+    }
+
+    /** @hide **/
+    @Override
+    public void setRemoteViewsAdapter(Intent intent, boolean isAsync) {
         // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
         // service handling the specified intent.
         if (mRemoteAdapter != null) {
@@ -6296,7 +6307,7 @@
         }
         mDeferNotifyDataSetChanged = false;
         // Otherwise, create a new RemoteViewsAdapter for binding
-        mRemoteAdapter = new RemoteViewsAdapter(getContext(), intent, this);
+        mRemoteAdapter = new RemoteViewsAdapter(getContext(), intent, this, isAsync);
         if (mRemoteAdapter.isDataReady()) {
             setAdapter(mRemoteAdapter);
         }
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 0e3a69f..6f29368 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -975,8 +975,19 @@
      * @param intent the intent used to identify the RemoteViewsService for the adapter to
      *        connect to.
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl="setRemoteViewsAdapterAsync")
     public void setRemoteViewsAdapter(Intent intent) {
+        setRemoteViewsAdapter(intent, false);
+    }
+
+    /** @hide **/
+    public Runnable setRemoteViewsAdapterAsync(final Intent intent) {
+        return new RemoteViewsAdapter.AsyncRemoteAdapterAction(this, intent);
+    }
+
+    /** @hide **/
+    @Override
+    public void setRemoteViewsAdapter(Intent intent, boolean isAsync) {
         // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
         // service handling the specified intent.
         if (mRemoteViewsAdapter != null) {
@@ -989,7 +1000,7 @@
         }
         mDeferNotifyDataSetChanged = false;
         // Otherwise, create a new RemoteViewsAdapter for binding
-        mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this);
+        mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this, isAsync);
         if (mRemoteViewsAdapter.isDataReady()) {
             setAdapter(mRemoteViewsAdapter);
         }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 20543fb..82071d7 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -175,7 +175,7 @@
      * through the specified intent.
      * @param intent the intent used to identify the RemoteViewsService for the adapter to connect to.
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl="setRemoteViewsAdapterAsync")
     public void setRemoteViewsAdapter(Intent intent) {
         super.setRemoteViewsAdapter(intent);
     }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 4d405c5..cd80651 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -455,7 +455,16 @@
 
     /** @hide **/
     public Runnable setImageResourceAsync(@DrawableRes int resId) {
-        return new ImageDrawableCallback(getContext().getDrawable(resId), null, resId);
+        Drawable d = null;
+        if (resId != 0) {
+            try {
+                d = getContext().getDrawable(resId);
+            } catch (Exception e) {
+                Log.w(LOG_TAG, "Unable to find resource: " + resId, e);
+                resId = 0;
+            }
+        }
+        return new ImageDrawableCallback(d, null, resId);
     }
 
     /**
@@ -865,7 +874,7 @@
             } catch (Exception e) {
                 Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
                 // Don't try again.
-                mUri = null;
+                mResource = 0;
             }
         } else if (mUri != null) {
             d = getDrawableFromUri(mUri);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index e88c7ef..e52c13b 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -448,7 +448,7 @@
      * through the specified intent.
      * @param intent the intent used to identify the RemoteViewsService for the adapter to connect to.
      */
-    @android.view.RemotableViewMethod
+    @android.view.RemotableViewMethod(asyncImpl="setRemoteViewsAdapterAsync")
     public void setRemoteViewsAdapter(Intent intent) {
         super.setRemoteViewsAdapter(intent);
     }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 6543d0c..316dab5 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -320,6 +320,10 @@
             return this;
         }
 
+        public boolean prefersAsyncApply() {
+            return false;
+        }
+
         int viewId;
     }
 
@@ -715,20 +719,29 @@
             intent.putExtra(EXTRA_REMOTEADAPTER_APPWIDGET_ID, host.getAppWidgetId());
             if (target instanceof AbsListView) {
                 AbsListView v = (AbsListView) target;
-                v.setRemoteViewsAdapter(intent);
+                v.setRemoteViewsAdapter(intent, isAsync);
                 v.setRemoteViewsOnClickHandler(handler);
             } else if (target instanceof AdapterViewAnimator) {
                 AdapterViewAnimator v = (AdapterViewAnimator) target;
-                v.setRemoteViewsAdapter(intent);
+                v.setRemoteViewsAdapter(intent, isAsync);
                 v.setRemoteViewsOnClickHandler(handler);
             }
         }
 
+        @Override
+        public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+                OnClickHandler handler) {
+            SetRemoteViewsAdapterIntent copy = new SetRemoteViewsAdapterIntent(viewId, intent);
+            copy.isAsync = true;
+            return copy;
+        }
+
         public String getActionName() {
             return "SetRemoteViewsAdapterIntent";
         }
 
         Intent intent;
+        boolean isAsync = false;
 
         public final static int TAG = 10;
     }
@@ -1461,6 +1474,11 @@
             // unique from the standpoint of merging.
             return "ReflectionAction" + this.methodName + this.type;
         }
+
+        @Override
+        public boolean prefersAsyncApply() {
+            return this.type == URI || this.type == ICON;
+        }
     }
 
     /**
@@ -1598,6 +1616,11 @@
             return MERGE_APPEND;
         }
 
+        @Override
+        public boolean prefersAsyncApply() {
+            return nestedViews != null && nestedViews.prefersAsyncApply();
+        }
+
         RemoteViews nestedViews;
 
         public final static int TAG = 4;
@@ -1749,6 +1772,11 @@
             return copy;
         }
 
+        @Override
+        public boolean prefersAsyncApply() {
+            return useIcons;
+        }
+
         public String getActionName() {
             return "TextViewDrawableAction";
         }
@@ -3443,6 +3471,24 @@
         }
     }
 
+    /**
+     * Returns true if the RemoteViews contains potentially costly operations and should be
+     * applied asynchronously.
+     *
+     * @hide
+     */
+    public boolean prefersAsyncApply() {
+        if (mActions != null) {
+            final int count = mActions.size();
+            for (int i = 0; i < count; i++) {
+                if (mActions.get(i).prefersAsyncApply()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     private Context getContextForResources(Context context) {
         if (mApplication != null) {
             if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index e0f94fd..11e0a3f 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -45,6 +45,12 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.concurrent.Executor;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
 
 /**
  * An adapter to a RemoteViewsService which fetches and caches RemoteViews
@@ -73,7 +79,8 @@
     private final Context mContext;
     private final Intent mIntent;
     private final int mAppWidgetId;
-    private LayoutInflater mLayoutInflater;
+    private final Executor mAsyncViewLoadExecutor;
+
     private RemoteViewsAdapterServiceConnection mServiceConnection;
     private WeakReference<RemoteAdapterConnectionCallback> mCallback;
     private OnClickHandler mRemoteViewsOnClickHandler;
@@ -120,15 +127,33 @@
         /**
          * @return whether the adapter was set or not.
          */
-        public boolean onRemoteAdapterConnected();
+        boolean onRemoteAdapterConnected();
 
-        public void onRemoteAdapterDisconnected();
+        void onRemoteAdapterDisconnected();
 
         /**
          * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
          * connected yet.
          */
-        public void deferNotifyDataSetChanged();
+        void deferNotifyDataSetChanged();
+
+        void setRemoteViewsAdapter(Intent intent, boolean isAsync);
+    }
+
+    public static class AsyncRemoteAdapterAction implements Runnable {
+
+        private final RemoteAdapterConnectionCallback mCallback;
+        private final Intent mIntent;
+
+        public AsyncRemoteAdapterAction(RemoteAdapterConnectionCallback callback, Intent intent) {
+            mCallback = callback;
+            mIntent = intent;
+        }
+
+        @Override
+        public void run() {
+            mCallback.setRemoteViewsAdapter(mIntent, true);
+        }
     }
 
     /**
@@ -162,7 +187,7 @@
                     }
                     mIsConnecting = true;
                 } catch (Exception e) {
-                    Log.e("RemoteViewsAdapterServiceConnection", "bind(): " + e.getMessage());
+                    Log.e("RVAServiceConnection", "bind(): " + e.getMessage());
                     mIsConnecting = false;
                     mIsConnected = false;
                 }
@@ -180,7 +205,7 @@
                 }
                 mIsConnecting = false;
             } catch (Exception e) {
-                Log.e("RemoteViewsAdapterServiceConnection", "unbind(): " + e.getMessage());
+                Log.e("RVAServiceConnection", "unbind(): " + e.getMessage());
                 mIsConnecting = false;
                 mIsConnected = false;
             }
@@ -298,15 +323,29 @@
          * Updates this RemoteViewsFrameLayout depending on the view that was loaded.
          * @param view the RemoteViews that was loaded. If null, the RemoteViews was not loaded
          *             successfully.
+         * @param forceApplyAsync when true, the host will always try to inflate the view
+         *                        asynchronously (for eg, when we are already showing the loading
+         *                        view)
          */
-        public void onRemoteViewsLoaded(RemoteViews view, OnClickHandler handler) {
+        public void onRemoteViewsLoaded(RemoteViews view, OnClickHandler handler,
+                boolean forceApplyAsync) {
             setOnClickHandler(handler);
-            applyRemoteViews(view);
+            applyRemoteViews(view, forceApplyAsync || ((view != null) && view.prefersAsyncApply()));
         }
 
+        /**
+         * Creates a default loading view. Uses the size of the first row as a guide for the
+         * size of the loading view.
+         */
         @Override
         protected View getDefaultView() {
-            return mCache.getMetaData().createDefaultLoadingView(this);
+            int viewHeight = mCache.getMetaData().getLoadingTemplate(getContext()).defaultHeight;
+            // Compose the loading view text
+            TextView loadingTextView = (TextView) LayoutInflater.from(getContext()).inflate(
+                    com.android.internal.R.layout.remote_views_adapter_default_loading_view,
+                    this, false);
+            loadingTextView.setHeight(viewHeight);
+            return loadingTextView;
         }
 
         @Override
@@ -359,7 +398,7 @@
             if (refs != null) {
                 // Notify all the references for that position of the newly loaded RemoteViews
                 for (final RemoteViewsFrameLayout ref : refs) {
-                    ref.onRemoteViewsLoaded(view, mRemoteViewsOnClickHandler);
+                    ref.onRemoteViewsLoaded(view, mRemoteViewsOnClickHandler, true);
                     if (mViewToLinkedList.containsKey(ref)) {
                         mViewToLinkedList.remove(ref);
                     }
@@ -402,9 +441,7 @@
         // Used to determine how to construct loading views.  If a loading view is not specified
         // by the user, then we try and load the first view, and use its height as the height for
         // the default loading view.
-        RemoteViews mUserLoadingView;
-        RemoteViews mFirstView;
-        int mFirstViewHeight;
+        LoadingViewTemplate loadingTemplate;
 
         // A mapping from type id to a set of unique type ids
         private final SparseIntArray mTypeIdIndexMap = new SparseIntArray();
@@ -418,7 +455,7 @@
                 count = d.count;
                 viewTypeCount = d.viewTypeCount;
                 hasStableIds = d.hasStableIds;
-                setLoadingViewTemplates(d.mUserLoadingView, d.mFirstView);
+                loadingTemplate = d.loadingTemplate;
             }
         }
 
@@ -428,20 +465,10 @@
             // by default there is at least one dummy view type
             viewTypeCount = 1;
             hasStableIds = true;
-            mUserLoadingView = null;
-            mFirstView = null;
-            mFirstViewHeight = 0;
+            loadingTemplate = null;
             mTypeIdIndexMap.clear();
         }
 
-        public void setLoadingViewTemplates(RemoteViews loadingView, RemoteViews firstView) {
-            mUserLoadingView = loadingView;
-            if (firstView != null) {
-                mFirstView = firstView;
-                mFirstViewHeight = -1;
-            }
-        }
-
         public int getMappedViewType(int typeId) {
             int mappedTypeId = mTypeIdIndexMap.get(typeId, -1);
             if (mappedTypeId == -1) {
@@ -457,33 +484,11 @@
             return (mappedType < viewTypeCount);
         }
 
-        /**
-         * Creates a default loading view. Uses the size of the first row as a guide for the
-         * size of the loading view.
-         */
-        private synchronized View createDefaultLoadingView(ViewGroup parent) {
-            final Context context = parent.getContext();
-            if (mFirstViewHeight < 0) {
-                try {
-                    View firstView = mFirstView.apply(parent.getContext(), parent);
-                    firstView.measure(
-                            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
-                            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-                    mFirstViewHeight = firstView.getMeasuredHeight();
-                } catch (Exception e) {
-                    float density = context.getResources().getDisplayMetrics().density;
-                    mFirstViewHeight = Math.round(sDefaultLoadingViewHeight * density);
-                    Log.w(TAG, "Error inflating first RemoteViews" + e);
-                }
-                mFirstView = null;
+        public synchronized LoadingViewTemplate getLoadingTemplate(Context context) {
+            if (loadingTemplate == null) {
+                loadingTemplate = new LoadingViewTemplate(null, context);
             }
-
-            // Compose the loading view text
-            TextView loadingTextView = (TextView) LayoutInflater.from(context).inflate(
-                    com.android.internal.R.layout.remote_views_adapter_default_loading_view,
-                    parent, false);
-            loadingTextView.setHeight(mFirstViewHeight);
-            return loadingTextView;
+            return loadingTemplate;
         }
     }
 
@@ -772,7 +777,7 @@
     }
 
     public RemoteViewsAdapter(Context context, Intent intent,
-            RemoteAdapterConnectionCallback callback) {
+            RemoteAdapterConnectionCallback callback, boolean useAsyncLoader) {
         mContext = context;
         mIntent = intent;
 
@@ -781,7 +786,6 @@
         }
 
         mAppWidgetId = intent.getIntExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID, -1);
-        mLayoutInflater = LayoutInflater.from(context);
         mRequestedViews = new RemoteViewsFrameLayoutRefSet();
 
         // Strip the previously injected app widget id from service intent
@@ -794,6 +798,7 @@
         mWorkerThread.start();
         mWorkerQueue = new Handler(mWorkerThread.getLooper());
         mMainQueue = new Handler(Looper.myLooper(), this);
+        mAsyncViewLoadExecutor = useAsyncLoader ? new HandlerThreadExecutor(mWorkerThread) : null;
 
         if (sCacheRemovalThread == null) {
             sCacheRemovalThread = new HandlerThread("RemoteViewsAdapter-cachePruner");
@@ -941,10 +946,14 @@
             boolean hasStableIds = factory.hasStableIds();
             int viewTypeCount = factory.getViewTypeCount();
             int count = factory.getCount();
-            RemoteViews loadingView = factory.getLoadingView();
-            RemoteViews firstView = null;
-            if ((count > 0) && (loadingView == null)) {
-                firstView = factory.getViewAt(0);
+            LoadingViewTemplate loadingTemplate =
+                    new LoadingViewTemplate(factory.getLoadingView(), mContext);
+            if ((count > 0) && (loadingTemplate.remoteViews == null)) {
+                RemoteViews firstView = factory.getViewAt(0);
+                if (firstView != null) {
+                    loadingTemplate.loadFirstViewHeight(firstView, mContext,
+                            new HandlerThreadExecutor(mWorkerThread));
+                }
             }
             final RemoteViewsMetaData tmpMetaData = mCache.getTemporaryMetaData();
             synchronized (tmpMetaData) {
@@ -952,7 +961,7 @@
                 // We +1 because the base view type is the loading view
                 tmpMetaData.viewTypeCount = viewTypeCount + 1;
                 tmpMetaData.count = count;
-                tmpMetaData.setLoadingViewTemplates(loadingView, firstView);
+                tmpMetaData.loadingTemplate = loadingTemplate;
             }
         } catch(RemoteException e) {
             processException("updateMetaData", e);
@@ -1100,18 +1109,25 @@
                 hasNewItems = mCache.queuePositionsToBePreloadedFromRequestedPosition(position);
             }
 
-            final RemoteViewsFrameLayout layout =
-                    (convertView instanceof RemoteViewsFrameLayout)
-                            ? (RemoteViewsFrameLayout) convertView
-                            : new RemoteViewsFrameLayout(parent.getContext(), mCache);
+            final RemoteViewsFrameLayout layout;
+            if (convertView instanceof RemoteViewsFrameLayout) {
+                layout = (RemoteViewsFrameLayout) convertView;
+            } else {
+                layout = new RemoteViewsFrameLayout(parent.getContext(), mCache);
+                layout.setAsyncExecutor(mAsyncViewLoadExecutor);
+            }
+
             if (isInCache) {
-                layout.onRemoteViewsLoaded(rv, mRemoteViewsOnClickHandler);
+                // Apply the view synchronously if possible, to avoid flickering
+                layout.onRemoteViewsLoaded(rv, mRemoteViewsOnClickHandler, false);
                 if (hasNewItems) loadNextIndexInBackground();
             } else {
                 // If the views is not loaded, apply the loading view. If the loading view doesn't
                 // exist, the layout will create a default view based on the firstView height.
-                layout.onRemoteViewsLoaded(mCache.getMetaData().mUserLoadingView,
-                        mRemoteViewsOnClickHandler);
+                layout.onRemoteViewsLoaded(
+                        mCache.getMetaData().getLoadingTemplate(mContext).remoteViews,
+                        mRemoteViewsOnClickHandler,
+                        false);
                 mRequestedViews.add(position, layout);
                 mCache.queueRequestedPositionToLoad(position);
                 loadNextIndexInBackground();
@@ -1285,4 +1301,58 @@
         mMainQueue.removeMessages(sUnbindServiceMessageType);
         return mServiceConnection.isConnected();
     }
+
+    private static class HandlerThreadExecutor implements Executor {
+        private final HandlerThread mThread;
+
+        HandlerThreadExecutor(HandlerThread thread) {
+            mThread = thread;
+        }
+
+        @Override
+        public void execute(Runnable runnable) {
+            if (Thread.currentThread().getId() == mThread.getId()) {
+                runnable.run();
+            } else {
+                new Handler(mThread.getLooper()).post(runnable);
+            }
+        }
+    }
+
+    private static class LoadingViewTemplate {
+        public final RemoteViews remoteViews;
+        public int defaultHeight;
+
+        LoadingViewTemplate(RemoteViews views, Context context) {
+            remoteViews = views;
+
+            float density = context.getResources().getDisplayMetrics().density;
+            defaultHeight = Math.round(sDefaultLoadingViewHeight * density);
+        }
+
+        public void loadFirstViewHeight(
+                RemoteViews firstView, Context context, Executor executor) {
+            // Inflate the first view on the worker thread
+            firstView.applyAsync(context, new RemoteViewsFrameLayout(context, null), executor,
+                    new RemoteViews.OnViewAppliedListener() {
+                        @Override
+                        public void onViewApplied(View v) {
+                            try {
+                                v.measure(
+                                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+                                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+                                defaultHeight = v.getMeasuredHeight();
+                            } catch (Exception e) {
+                                onError(e);
+                            }
+                        }
+
+                        @Override
+                        public void onError(Exception e) {
+                            // Do nothing. The default height will stay the same.
+                            Log.w(TAG, "Error inflating first RemoteViews", e);
+                        }
+                    });
+        }
+    }
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 7950685..506a284 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -119,12 +119,15 @@
     android/graphics/DrawFilter.cpp \
     android/graphics/FontFamily.cpp \
     android/graphics/CreateJavaOutputStreamAdaptor.cpp \
+    android/graphics/GIFMovie.cpp \
     android/graphics/Graphics.cpp \
     android/graphics/HarfBuzzNGFaceSkia.cpp \
     android/graphics/Interpolator.cpp \
     android/graphics/MaskFilter.cpp \
     android/graphics/Matrix.cpp \
     android/graphics/Movie.cpp \
+    android/graphics/MovieImpl.cpp \
+    android/graphics/Movie_FactoryDefault.cpp \
     android/graphics/NinePatch.cpp \
     android/graphics/NinePatchPeeker.cpp \
     android/graphics/Paint.cpp \
@@ -200,6 +203,7 @@
     $(TOP)/system/core/include \
     $(TOP)/system/media/camera/include \
     $(TOP)/system/netd/include \
+    external/giflib \
     external/pdfium/core/include/fpdfapi \
     external/pdfium/fpdfsdk/include \
     external/pdfium/public \
@@ -219,6 +223,9 @@
     external/freetype/include
 # TODO: clean up Minikin so it doesn't need the freetype include
 
+LOCAL_STATIC_LIBRARIES := \
+    libgif \
+
 LOCAL_SHARED_LIBRARIES := \
     libmemtrack \
     libandroidfw \
diff --git a/core/jni/android/graphics/GIFMovie.cpp b/core/jni/android/graphics/GIFMovie.cpp
new file mode 100644
index 0000000..035417e
--- /dev/null
+++ b/core/jni/android/graphics/GIFMovie.cpp
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "Movie.h"
+#include "SkColor.h"
+#include "SkColorPriv.h"
+#include "SkStream.h"
+#include "SkTemplates.h"
+#include "SkUtils.h"
+
+#include "gif_lib.h"
+
+#if GIFLIB_MAJOR < 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR == 0)
+#define DGifCloseFile(a, b) DGifCloseFile(a)
+#endif
+
+class GIFMovie : public Movie {
+public:
+    GIFMovie(SkStream* stream);
+    virtual ~GIFMovie();
+
+protected:
+    virtual bool onGetInfo(Info*);
+    virtual bool onSetTime(SkMSec);
+    virtual bool onGetBitmap(SkBitmap*);
+
+private:
+    GifFileType* fGIF;
+    int fCurrIndex;
+    int fLastDrawIndex;
+    SkBitmap fBackup;
+    SkColor fPaintingColor;
+};
+
+static int Decode(GifFileType* fileType, GifByteType* out, int size) {
+    SkStream* stream = (SkStream*) fileType->UserData;
+    return (int) stream->read(out, size);
+}
+
+GIFMovie::GIFMovie(SkStream* stream)
+{
+#if GIFLIB_MAJOR < 5
+    fGIF = DGifOpen( stream, Decode );
+#else
+    fGIF = DGifOpen( stream, Decode, nullptr );
+#endif
+    if (nullptr == fGIF)
+        return;
+
+    if (DGifSlurp(fGIF) != GIF_OK)
+    {
+        DGifCloseFile(fGIF, nullptr);
+        fGIF = nullptr;
+    }
+    fCurrIndex = -1;
+    fLastDrawIndex = -1;
+    fPaintingColor = SkPackARGB32(0, 0, 0, 0);
+}
+
+GIFMovie::~GIFMovie()
+{
+    if (fGIF)
+        DGifCloseFile(fGIF, nullptr);
+}
+
+static SkMSec savedimage_duration(const SavedImage* image)
+{
+    for (int j = 0; j < image->ExtensionBlockCount; j++)
+    {
+        if (image->ExtensionBlocks[j].Function == GRAPHICS_EXT_FUNC_CODE)
+        {
+            SkASSERT(image->ExtensionBlocks[j].ByteCount >= 4);
+            const uint8_t* b = (const uint8_t*)image->ExtensionBlocks[j].Bytes;
+            return ((b[2] << 8) | b[1]) * 10;
+        }
+    }
+    return 0;
+}
+
+bool GIFMovie::onGetInfo(Info* info)
+{
+    if (nullptr == fGIF)
+        return false;
+
+    SkMSec dur = 0;
+    for (int i = 0; i < fGIF->ImageCount; i++)
+        dur += savedimage_duration(&fGIF->SavedImages[i]);
+
+    info->fDuration = dur;
+    info->fWidth = fGIF->SWidth;
+    info->fHeight = fGIF->SHeight;
+    info->fIsOpaque = false;    // how to compute?
+    return true;
+}
+
+bool GIFMovie::onSetTime(SkMSec time)
+{
+    if (nullptr == fGIF)
+        return false;
+
+    SkMSec dur = 0;
+    for (int i = 0; i < fGIF->ImageCount; i++)
+    {
+        dur += savedimage_duration(&fGIF->SavedImages[i]);
+        if (dur >= time)
+        {
+            fCurrIndex = i;
+            return fLastDrawIndex != fCurrIndex;
+        }
+    }
+    fCurrIndex = fGIF->ImageCount - 1;
+    return true;
+}
+
+static void copyLine(uint32_t* dst, const unsigned char* src, const ColorMapObject* cmap,
+                     int transparent, int width)
+{
+    for (; width > 0; width--, src++, dst++) {
+        if (*src != transparent) {
+            const GifColorType& col = cmap->Colors[*src];
+            *dst = SkPackARGB32(0xFF, col.Red, col.Green, col.Blue);
+        }
+    }
+}
+
+#if GIFLIB_MAJOR < 5
+static void copyInterlaceGroup(SkBitmap* bm, const unsigned char*& src,
+                               const ColorMapObject* cmap, int transparent, int copyWidth,
+                               int copyHeight, const GifImageDesc& imageDesc, int rowStep,
+                               int startRow)
+{
+    int row;
+    // every 'rowStep'th row, starting with row 'startRow'
+    for (row = startRow; row < copyHeight; row += rowStep) {
+        uint32_t* dst = bm->getAddr32(imageDesc.Left, imageDesc.Top + row);
+        copyLine(dst, src, cmap, transparent, copyWidth);
+        src += imageDesc.Width;
+    }
+
+    // pad for rest height
+    src += imageDesc.Width * ((imageDesc.Height - row + rowStep - 1) / rowStep);
+}
+
+static void blitInterlace(SkBitmap* bm, const SavedImage* frame, const ColorMapObject* cmap,
+                          int transparent)
+{
+    int width = bm->width();
+    int height = bm->height();
+    GifWord copyWidth = frame->ImageDesc.Width;
+    if (frame->ImageDesc.Left + copyWidth > width) {
+        copyWidth = width - frame->ImageDesc.Left;
+    }
+
+    GifWord copyHeight = frame->ImageDesc.Height;
+    if (frame->ImageDesc.Top + copyHeight > height) {
+        copyHeight = height - frame->ImageDesc.Top;
+    }
+
+    // deinterlace
+    const unsigned char* src = (unsigned char*)frame->RasterBits;
+
+    // group 1 - every 8th row, starting with row 0
+    copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 8, 0);
+
+    // group 2 - every 8th row, starting with row 4
+    copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 8, 4);
+
+    // group 3 - every 4th row, starting with row 2
+    copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 4, 2);
+
+    copyInterlaceGroup(bm, src, cmap, transparent, copyWidth, copyHeight, frame->ImageDesc, 2, 1);
+}
+#endif
+
+static void blitNormal(SkBitmap* bm, const SavedImage* frame, const ColorMapObject* cmap,
+                       int transparent)
+{
+    int width = bm->width();
+    int height = bm->height();
+    const unsigned char* src = (unsigned char*)frame->RasterBits;
+    uint32_t* dst = bm->getAddr32(frame->ImageDesc.Left, frame->ImageDesc.Top);
+    GifWord copyWidth = frame->ImageDesc.Width;
+    if (frame->ImageDesc.Left + copyWidth > width) {
+        copyWidth = width - frame->ImageDesc.Left;
+    }
+
+    GifWord copyHeight = frame->ImageDesc.Height;
+    if (frame->ImageDesc.Top + copyHeight > height) {
+        copyHeight = height - frame->ImageDesc.Top;
+    }
+
+    for (; copyHeight > 0; copyHeight--) {
+        copyLine(dst, src, cmap, transparent, copyWidth);
+        src += frame->ImageDesc.Width;
+        dst += width;
+    }
+}
+
+static void fillRect(SkBitmap* bm, GifWord left, GifWord top, GifWord width, GifWord height,
+                     uint32_t col)
+{
+    int bmWidth = bm->width();
+    int bmHeight = bm->height();
+    uint32_t* dst = bm->getAddr32(left, top);
+    GifWord copyWidth = width;
+    if (left + copyWidth > bmWidth) {
+        copyWidth = bmWidth - left;
+    }
+
+    GifWord copyHeight = height;
+    if (top + copyHeight > bmHeight) {
+        copyHeight = bmHeight - top;
+    }
+
+    for (; copyHeight > 0; copyHeight--) {
+        sk_memset32(dst, col, copyWidth);
+        dst += bmWidth;
+    }
+}
+
+static void drawFrame(SkBitmap* bm, const SavedImage* frame, const ColorMapObject* cmap)
+{
+    int transparent = -1;
+
+    for (int i = 0; i < frame->ExtensionBlockCount; ++i) {
+        ExtensionBlock* eb = frame->ExtensionBlocks + i;
+        if (eb->Function == GRAPHICS_EXT_FUNC_CODE &&
+            eb->ByteCount == 4) {
+            bool has_transparency = ((eb->Bytes[0] & 1) == 1);
+            if (has_transparency) {
+                transparent = (unsigned char)eb->Bytes[3];
+            }
+        }
+    }
+
+    if (frame->ImageDesc.ColorMap != nullptr) {
+        // use local color table
+        cmap = frame->ImageDesc.ColorMap;
+    }
+
+    if (cmap == nullptr || cmap->ColorCount != (1 << cmap->BitsPerPixel)) {
+        SkDEBUGFAIL("bad colortable setup");
+        return;
+    }
+
+#if GIFLIB_MAJOR < 5
+    // before GIFLIB 5, de-interlacing wasn't done by library at load time
+    if (frame->ImageDesc.Interlace) {
+        blitInterlace(bm, frame, cmap, transparent);
+        return;
+    }
+#endif
+
+    blitNormal(bm, frame, cmap, transparent);
+}
+
+static bool checkIfWillBeCleared(const SavedImage* frame)
+{
+    for (int i = 0; i < frame->ExtensionBlockCount; ++i) {
+        ExtensionBlock* eb = frame->ExtensionBlocks + i;
+        if (eb->Function == GRAPHICS_EXT_FUNC_CODE &&
+            eb->ByteCount == 4) {
+            // check disposal method
+            int disposal = ((eb->Bytes[0] >> 2) & 7);
+            if (disposal == 2 || disposal == 3) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+static void getTransparencyAndDisposalMethod(const SavedImage* frame, bool* trans, int* disposal)
+{
+    *trans = false;
+    *disposal = 0;
+    for (int i = 0; i < frame->ExtensionBlockCount; ++i) {
+        ExtensionBlock* eb = frame->ExtensionBlocks + i;
+        if (eb->Function == GRAPHICS_EXT_FUNC_CODE &&
+            eb->ByteCount == 4) {
+            *trans = ((eb->Bytes[0] & 1) == 1);
+            *disposal = ((eb->Bytes[0] >> 2) & 7);
+        }
+    }
+}
+
+// return true if area of 'target' is completely covers area of 'covered'
+static bool checkIfCover(const SavedImage* target, const SavedImage* covered)
+{
+    if (target->ImageDesc.Left <= covered->ImageDesc.Left
+        && covered->ImageDesc.Left + covered->ImageDesc.Width <=
+               target->ImageDesc.Left + target->ImageDesc.Width
+        && target->ImageDesc.Top <= covered->ImageDesc.Top
+        && covered->ImageDesc.Top + covered->ImageDesc.Height <=
+               target->ImageDesc.Top + target->ImageDesc.Height) {
+        return true;
+    }
+    return false;
+}
+
+static void disposeFrameIfNeeded(SkBitmap* bm, const SavedImage* cur, const SavedImage* next,
+                                 SkBitmap* backup, SkColor color)
+{
+    // We can skip disposal process if next frame is not transparent
+    // and completely covers current area
+    bool curTrans;
+    int curDisposal;
+    getTransparencyAndDisposalMethod(cur, &curTrans, &curDisposal);
+    bool nextTrans;
+    int nextDisposal;
+    getTransparencyAndDisposalMethod(next, &nextTrans, &nextDisposal);
+    if ((curDisposal == 2 || curDisposal == 3)
+        && (nextTrans || !checkIfCover(next, cur))) {
+        switch (curDisposal) {
+        // restore to background color
+        // -> 'background' means background under this image.
+        case 2:
+            fillRect(bm, cur->ImageDesc.Left, cur->ImageDesc.Top,
+                     cur->ImageDesc.Width, cur->ImageDesc.Height,
+                     color);
+            break;
+
+        // restore to previous
+        case 3:
+            bm->swap(*backup);
+            break;
+        }
+    }
+
+    // Save current image if next frame's disposal method == 3
+    if (nextDisposal == 3) {
+        const uint32_t* src = bm->getAddr32(0, 0);
+        uint32_t* dst = backup->getAddr32(0, 0);
+        int cnt = bm->width() * bm->height();
+        memcpy(dst, src, cnt*sizeof(uint32_t));
+    }
+}
+
+bool GIFMovie::onGetBitmap(SkBitmap* bm)
+{
+    const GifFileType* gif = fGIF;
+    if (nullptr == gif)
+        return false;
+
+    if (gif->ImageCount < 1) {
+        return false;
+    }
+
+    const int width = gif->SWidth;
+    const int height = gif->SHeight;
+    if (width <= 0 || height <= 0) {
+        return false;
+    }
+
+    // no need to draw
+    if (fLastDrawIndex >= 0 && fLastDrawIndex == fCurrIndex) {
+        return true;
+    }
+
+    int startIndex = fLastDrawIndex + 1;
+    if (fLastDrawIndex < 0 || !bm->readyToDraw()) {
+        // first time
+
+        startIndex = 0;
+
+        // create bitmap
+        if (!bm->tryAllocN32Pixels(width, height)) {
+            return false;
+        }
+        // create bitmap for backup
+        if (!fBackup.tryAllocN32Pixels(width, height)) {
+            return false;
+        }
+    } else if (startIndex > fCurrIndex) {
+        // rewind to 1st frame for repeat
+        startIndex = 0;
+    }
+
+    int lastIndex = fCurrIndex;
+    if (lastIndex < 0) {
+        // first time
+        lastIndex = 0;
+    } else if (lastIndex > fGIF->ImageCount - 1) {
+        // this block must not be reached.
+        lastIndex = fGIF->ImageCount - 1;
+    }
+
+    SkColor bgColor = SkPackARGB32(0, 0, 0, 0);
+    if (gif->SColorMap != nullptr) {
+        const GifColorType& col = gif->SColorMap->Colors[fGIF->SBackGroundColor];
+        bgColor = SkColorSetARGB(0xFF, col.Red, col.Green, col.Blue);
+    }
+
+    // draw each frames - not intelligent way
+    for (int i = startIndex; i <= lastIndex; i++) {
+        const SavedImage* cur = &fGIF->SavedImages[i];
+        if (i == 0) {
+            bool trans;
+            int disposal;
+            getTransparencyAndDisposalMethod(cur, &trans, &disposal);
+            if (!trans && gif->SColorMap != nullptr) {
+                fPaintingColor = bgColor;
+            } else {
+                fPaintingColor = SkColorSetARGB(0, 0, 0, 0);
+            }
+
+            bm->eraseColor(fPaintingColor);
+            fBackup.eraseColor(fPaintingColor);
+        } else {
+            // Dispose previous frame before move to next frame.
+            const SavedImage* prev = &fGIF->SavedImages[i-1];
+            disposeFrameIfNeeded(bm, prev, cur, &fBackup, fPaintingColor);
+        }
+
+        // Draw frame
+        // We can skip this process if this index is not last and disposal
+        // method == 2 or method == 3
+        if (i == lastIndex || !checkIfWillBeCleared(cur)) {
+            drawFrame(bm, cur, gif->SColorMap);
+        }
+    }
+
+    // save index
+    fLastDrawIndex = lastIndex;
+    return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SkTRegistry.h"
+
+Movie* Factory(SkStreamRewindable* stream) {
+    char buf[GIF_STAMP_LEN];
+    if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) {
+        if (memcmp(GIF_STAMP,   buf, GIF_STAMP_LEN) == 0 ||
+                memcmp(GIF87_STAMP, buf, GIF_STAMP_LEN) == 0 ||
+                memcmp(GIF89_STAMP, buf, GIF_STAMP_LEN) == 0) {
+            // must rewind here, since our construct wants to re-read the data
+            stream->rewind();
+            return new GIFMovie(stream);
+        }
+    }
+    return nullptr;
+}
+
+static SkTRegistry<Movie*(*)(SkStreamRewindable*)> gReg(Factory);
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index ad1b0c3..776ed66 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -2,7 +2,7 @@
 #include "GraphicsJNI.h"
 #include "ScopedLocalRef.h"
 #include "SkFrontBufferedStream.h"
-#include "SkMovie.h"
+#include "Movie.h"
 #include "SkStream.h"
 #include "SkUtils.h"
 #include "Utils.h"
@@ -19,7 +19,7 @@
 static jmethodID    gMovie_constructorMethodID;
 static jfieldID     gMovie_nativeInstanceID;
 
-jobject create_jmovie(JNIEnv* env, SkMovie* moov) {
+jobject create_jmovie(JNIEnv* env, Movie* moov) {
     if (NULL == moov) {
         return NULL;
     }
@@ -27,11 +27,11 @@
             static_cast<jlong>(reinterpret_cast<uintptr_t>(moov)));
 }
 
-static SkMovie* J2Movie(JNIEnv* env, jobject movie) {
+static Movie* J2Movie(JNIEnv* env, jobject movie) {
     SkASSERT(env);
     SkASSERT(movie);
     SkASSERT(env->IsInstanceOf(movie, gMovie_class));
-    SkMovie* m = (SkMovie*)env->GetLongField(movie, gMovie_nativeInstanceID);
+    Movie* m = (Movie*)env->GetLongField(movie, gMovie_nativeInstanceID);
     SkASSERT(m);
     return m;
 }
@@ -74,7 +74,7 @@
     // therefore may be NULL.
     SkASSERT(c != NULL);
 
-    SkMovie* m = J2Movie(env, movie);
+    Movie* m = J2Movie(env, movie);
     const SkBitmap& b = m->bitmap();
     sk_sp<android::Bitmap> wrapper = android::Bitmap::createFrom(b.info(), *b.pixelRef());
     c->drawBitmap(*wrapper, fx, fy, p);
@@ -84,7 +84,7 @@
     android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
     if (asset == NULL) return NULL;
     android::AssetStreamAdaptor stream(asset);
-    SkMovie* moov = SkMovie::DecodeStream(&stream);
+    Movie* moov = Movie::DecodeStream(&stream);
     return create_jmovie(env, moov);
 }
 
@@ -107,7 +107,7 @@
     std::unique_ptr<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(strm, 6));
     SkASSERT(bufferedStream.get() != NULL);
 
-    SkMovie* moov = SkMovie::DecodeStream(bufferedStream.get());
+    Movie* moov = Movie::DecodeStream(bufferedStream.get());
     return create_jmovie(env, moov);
 }
 
@@ -124,12 +124,12 @@
     }
 
     AutoJavaByteArray   ar(env, byteArray);
-    SkMovie* moov = SkMovie::DecodeMemory(ar.ptr() + offset, length);
+    Movie* moov = Movie::DecodeMemory(ar.ptr() + offset, length);
     return create_jmovie(env, moov);
 }
 
 static void movie_destructor(JNIEnv* env, jobject, jlong movieHandle) {
-    SkMovie* movie = (SkMovie*) movieHandle;
+    Movie* movie = (Movie*) movieHandle;
     delete movie;
 }
 
diff --git a/core/jni/android/graphics/Movie.h b/core/jni/android/graphics/Movie.h
new file mode 100644
index 0000000..c0fbe4f
--- /dev/null
+++ b/core/jni/android/graphics/Movie.h
@@ -0,0 +1,78 @@
+
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef Movie_DEFINED
+#define Movie_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkCanvas.h"
+
+class SkStreamRewindable;
+
+class Movie : public SkRefCnt {
+public:
+    /** Try to create a movie from the stream. If the stream format is not
+        supported, return NULL.
+    */
+    static Movie* DecodeStream(SkStreamRewindable*);
+    /** Try to create a movie from the specified file path. If the file is not
+        found, or the format is not supported, return NULL. If a movie is
+        returned, the stream may be retained by the movie (via ref()) until
+        the movie is finished with it (by calling unref()).
+    */
+    static Movie* DecodeFile(const char path[]);
+    /** Try to create a movie from the specified memory.
+        If the format is not supported, return NULL. If a movie is returned,
+        the data will have been read or copied, and so the caller may free
+        it.
+    */
+    static Movie* DecodeMemory(const void* data, size_t length);
+
+    SkMSec  duration();
+    int     width();
+    int     height();
+    int     isOpaque();
+
+    /** Specify the time code (between 0...duration) to sample a bitmap
+        from the movie. Returns true if this time code generated a different
+        bitmap/frame from the previous state (i.e. true means you need to
+        redraw).
+    */
+    bool setTime(SkMSec);
+
+    // return the right bitmap for the current time code
+    const SkBitmap& bitmap();
+
+protected:
+    struct Info {
+        SkMSec  fDuration;
+        int     fWidth;
+        int     fHeight;
+        bool    fIsOpaque;
+    };
+
+    virtual bool onGetInfo(Info*) = 0;
+    virtual bool onSetTime(SkMSec) = 0;
+    virtual bool onGetBitmap(SkBitmap*) = 0;
+
+    // visible for subclasses
+    Movie();
+
+private:
+    Info        fInfo;
+    SkMSec      fCurrTime;
+    SkBitmap    fBitmap;
+    bool        fNeedBitmap;
+
+    void ensureInfo();
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif
diff --git a/core/jni/android/graphics/MovieImpl.cpp b/core/jni/android/graphics/MovieImpl.cpp
new file mode 100644
index 0000000..ae9e04e
--- /dev/null
+++ b/core/jni/android/graphics/MovieImpl.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "Movie.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+
+// We should never see this in normal operation since our time values are
+// 0-based. So we use it as a sentinal.
+#define UNINITIALIZED_MSEC ((SkMSec)-1)
+
+Movie::Movie()
+{
+    fInfo.fDuration = UNINITIALIZED_MSEC;  // uninitialized
+    fCurrTime = UNINITIALIZED_MSEC; // uninitialized
+    fNeedBitmap = true;
+}
+
+void Movie::ensureInfo()
+{
+    if (fInfo.fDuration == UNINITIALIZED_MSEC && !this->onGetInfo(&fInfo))
+        memset(&fInfo, 0, sizeof(fInfo));   // failure
+}
+
+SkMSec Movie::duration()
+{
+    this->ensureInfo();
+    return fInfo.fDuration;
+}
+
+int Movie::width()
+{
+    this->ensureInfo();
+    return fInfo.fWidth;
+}
+
+int Movie::height()
+{
+    this->ensureInfo();
+    return fInfo.fHeight;
+}
+
+int Movie::isOpaque()
+{
+    this->ensureInfo();
+    return fInfo.fIsOpaque;
+}
+
+bool Movie::setTime(SkMSec time)
+{
+    SkMSec dur = this->duration();
+    if (time > dur)
+        time = dur;
+
+    bool changed = false;
+    if (time != fCurrTime)
+    {
+        fCurrTime = time;
+        changed = this->onSetTime(time);
+        fNeedBitmap |= changed;
+    }
+    return changed;
+}
+
+const SkBitmap& Movie::bitmap()
+{
+    if (fCurrTime == UNINITIALIZED_MSEC)    // uninitialized
+        this->setTime(0);
+
+    if (fNeedBitmap)
+    {
+        if (!this->onGetBitmap(&fBitmap))   // failure
+            fBitmap.reset();
+        fNeedBitmap = false;
+    }
+    return fBitmap;
+}
+
+////////////////////////////////////////////////////////////////////
+
+#include "SkStream.h"
+
+Movie* Movie::DecodeMemory(const void* data, size_t length) {
+    SkMemoryStream stream(data, length, false);
+    return Movie::DecodeStream(&stream);
+}
+
+Movie* Movie::DecodeFile(const char path[]) {
+    std::unique_ptr<SkStreamRewindable> stream = SkStream::MakeFromFile(path);
+    return stream ? Movie::DecodeStream(stream.get()) : nullptr;
+}
diff --git a/core/jni/android/graphics/Movie_FactoryDefault.cpp b/core/jni/android/graphics/Movie_FactoryDefault.cpp
new file mode 100644
index 0000000..175e0a6
--- /dev/null
+++ b/core/jni/android/graphics/Movie_FactoryDefault.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Movie.h"
+#include "SkStream.h"
+
+typedef SkTRegistry<Movie*(*)(SkStreamRewindable*)> MovieReg;
+
+Movie* Movie::DecodeStream(SkStreamRewindable* stream) {
+    const MovieReg* curr = MovieReg::Head();
+    while (curr) {
+        Movie* movie = curr->factory()(stream);
+        if (movie) {
+            return movie;
+        }
+        // we must rewind only if we got nullptr, since we gave the stream to the
+        // movie, who may have already started reading from it
+        stream->rewind();
+        curr = curr->next();
+    }
+    return nullptr;
+}
diff --git a/core/res/res/layout-watch/progress_dialog_material.xml b/core/res/res/layout-watch/progress_dialog_material.xml
index 228f724..96bda1d 100644
--- a/core/res/res/layout-watch/progress_dialog_material.xml
+++ b/core/res/res/layout-watch/progress_dialog_material.xml
@@ -32,14 +32,15 @@
 
         <ProgressBar
             android:id="@id/progress"
-            style="?android:attr/progressBarStyleSmall"
+            style="?android:attr/progressBarStyle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:max="10000"
-            android:layout_marginEnd="?attr/dialogPreferredPadding" />
+            android:layout_marginEnd="8dp" />
 
         <TextView
             android:id="@+id/message"
+            android:textAppearance="?attr/textAppearanceListItem"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical" />
diff --git a/core/res/res/values-watch/dimens_material.xml b/core/res/res/values-watch/dimens_material.xml
index b48cde6..3c4904c 100644
--- a/core/res/res/values-watch/dimens_material.xml
+++ b/core/res/res/values-watch/dimens_material.xml
@@ -39,4 +39,9 @@
     <!-- Date and time picker legacy dimens -->
     <dimen name="picker_top_margin">1dip</dimen>
     <dimen name="picker_bottom_margin">1dip</dimen>
+
+    <!-- Progress bar dimens -->
+    <dimen name="progress_bar_size_small">16dip</dimen>
+    <dimen name="progress_bar_size_medium">32dip</dimen>
+    <dimen name="progress_bar_size_large">64dip</dimen>
 </resources>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index ae31165..30e7b31 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -193,4 +193,9 @@
     <!-- Date and time picker legacy dimens -->
     <dimen name="picker_top_margin">16dip</dimen>
     <dimen name="picker_bottom_margin">16dip</dimen>
+
+    <!-- Progress bar dimens -->
+    <dimen name="progress_bar_size_small">16dip</dimen>
+    <dimen name="progress_bar_size_medium">48dp</dimen>
+    <dimen name="progress_bar_size_large">76dp</dimen>
 </resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 22bdf7e..a1e12d2 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -739,6 +739,10 @@
 
     <style name="Widget.Material.ProgressBar" parent="Widget.ProgressBar">
         <item name="indeterminateDrawable">@drawable/progress_medium_material</item>
+        <item name="minWidth">@dimen/progress_bar_size_medium</item>
+        <item name="maxWidth">@dimen/progress_bar_size_medium</item>
+        <item name="minHeight">@dimen/progress_bar_size_medium</item>
+        <item name="maxHeight">@dimen/progress_bar_size_medium</item>
     </style>
 
     <style name="Widget.Material.ProgressBar.Inverse"/>
@@ -752,6 +756,10 @@
 
     <style name="Widget.Material.ProgressBar.Small" parent="Widget.ProgressBar.Small">
         <item name="indeterminateDrawable">@drawable/progress_small_material</item>
+        <item name="minWidth">@dimen/progress_bar_size_small</item>
+        <item name="maxWidth">@dimen/progress_bar_size_small</item>
+        <item name="minHeight">@dimen/progress_bar_size_small</item>
+        <item name="maxHeight">@dimen/progress_bar_size_small</item>
     </style>
 
     <style name="Widget.Material.ProgressBar.Small.Inverse"/>
@@ -759,6 +767,10 @@
 
     <style name="Widget.Material.ProgressBar.Large" parent="Widget.ProgressBar.Large">
         <item name="indeterminateDrawable">@drawable/progress_large_material</item>
+        <item name="minWidth">@dimen/progress_bar_size_large</item>
+        <item name="maxWidth">@dimen/progress_bar_size_large</item>
+        <item name="minHeight">@dimen/progress_bar_size_large</item>
+        <item name="maxHeight">@dimen/progress_bar_size_large</item>
     </style>
 
     <style name="Widget.Material.ProgressBar.Large.Inverse"/>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 0b7b99f..bfc9ff3 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -272,7 +272,7 @@
     boolean deviceIsEncrypted() {
         try {
             return mMountService.getEncryptionState()
-                     != IMountService.ENCRYPTION_STATE_NONE
+                     != StorageManager.ENCRYPTION_STATE_NONE
                 && mMountService.getPasswordType()
                      != StorageManager.CRYPT_TYPE_DEFAULT;
         } catch (Exception e) {
diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
index f8ce1d3..eba1d0f 100644
--- a/packages/SystemUI/src/com/android/systemui/DejankUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
@@ -16,8 +16,9 @@
 
 package com.android.systemui;
 
+import com.android.systemui.util.Assert;
+
 import android.os.Handler;
-import android.os.Looper;
 import android.view.Choreographer;
 
 import java.util.ArrayList;
@@ -50,7 +51,7 @@
      * <p>Needs to be called from the main thread.
      */
     public static void postAfterTraversal(Runnable r) {
-        throwIfNotCalledOnMainThread();
+        Assert.isMainThread();
         sPendingRunnables.add(r);
         postAnimationCallback();
     }
@@ -61,7 +62,7 @@
      * <p>Needs to be called from the main thread.
      */
     public static void removeCallbacks(Runnable r) {
-        throwIfNotCalledOnMainThread();
+        Assert.isMainThread();
         sPendingRunnables.remove(r);
         sHandler.removeCallbacks(r);
     }
@@ -70,10 +71,4 @@
         sChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, sAnimationCallbackRunnable,
                 null);
     }
-
-    private static void throwIfNotCalledOnMainThread() {
-        if (!Looper.getMainLooper().isCurrentThread()) {
-            throw new IllegalStateException("should be called from the main thread.");
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
new file mode 100644
index 0000000..fd1ac8e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.doze;
+
+import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto;
+import com.android.systemui.statusbar.phone.DozeParameters;
+
+import android.annotation.AnyThread;
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
+import android.media.AudioAttributes;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.List;
+
+public class DozeSensors {
+
+    private static final boolean DEBUG = DozeService.DEBUG;
+
+    private static final String TAG = "DozeSensors";
+
+    private final Context mContext;
+    private final SensorManager mSensorManager;
+    private final TriggerSensor[] mSensors;
+    private final ContentResolver mResolver;
+    private final TriggerSensor mPickupSensor;
+    private final DozeParameters mDozeParameters;
+    private final AmbientDisplayConfiguration mConfig;
+    private final PowerManager.WakeLock mWakeLock;
+    private final Callback mCallback;
+
+    private final Handler mHandler = new Handler();
+
+
+    public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
+            AmbientDisplayConfiguration config, PowerManager.WakeLock wakeLock, Callback callback) {
+        mContext = context;
+        mSensorManager = sensorManager;
+        mDozeParameters = dozeParameters;
+        mConfig = config;
+        mWakeLock = wakeLock;
+        mResolver = mContext.getContentResolver();
+
+        mSensors = new TriggerSensor[] {
+                new TriggerSensor(
+                        mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
+                        null /* setting */,
+                        dozeParameters.getPulseOnSigMotion(),
+                        DozeLog.PULSE_REASON_SENSOR_SIGMOTION),
+                mPickupSensor = new TriggerSensor(
+                        mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
+                        Settings.Secure.DOZE_PULSE_ON_PICK_UP,
+                        config.pulseOnPickupAvailable(),
+                        DozeLog.PULSE_REASON_SENSOR_PICKUP),
+                new TriggerSensor(
+                        findSensorWithType(config.doubleTapSensorType()),
+                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP,
+                        true /* configured */,
+                        DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
+        };
+        mCallback = callback;
+    }
+
+    private Sensor findSensorWithType(String type) {
+        if (TextUtils.isEmpty(type)) {
+            return null;
+        }
+        List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+        for (Sensor s : sensorList) {
+            if (type.equals(s.getStringType())) {
+                return s;
+            }
+        }
+        return null;
+    }
+
+    public void setListen(boolean listen) {
+        for (TriggerSensor s : mSensors) {
+            s.setListening(listen);
+            if (listen) {
+                s.registerSettingsObserver(mSettingsObserver);
+            }
+        }
+        if (!listen) {
+            mResolver.unregisterContentObserver(mSettingsObserver);
+        }
+    }
+
+    public void reregisterAllSensors() {
+        for (TriggerSensor s : mSensors) {
+            s.setListening(false);
+        }
+        for (TriggerSensor s : mSensors) {
+            s.setListening(true);
+        }
+    }
+
+    public void onUserSwitched() {
+        for (TriggerSensor s : mSensors) {
+            s.updateListener();
+        }
+    }
+
+    private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            if (userId != ActivityManager.getCurrentUser()) {
+                return;
+            }
+            for (TriggerSensor s : mSensors) {
+                s.updateListener();
+            }
+        }
+    };
+
+    public void setDisableSensorsInterferingWithProximity(boolean disable) {
+        mPickupSensor.setDisabled(disable);
+    }
+
+    private class TriggerSensor extends TriggerEventListener {
+        final Sensor mSensor;
+        final boolean mConfigured;
+        final int mPulseReason;
+        final String mSetting;
+
+        private boolean mRequested;
+        private boolean mRegistered;
+        private boolean mDisabled;
+
+        public TriggerSensor(Sensor sensor, String setting, boolean configured, int pulseReason) {
+            mSensor = sensor;
+            mSetting = setting;
+            mConfigured = configured;
+            mPulseReason = pulseReason;
+        }
+
+        public void setListening(boolean listen) {
+            if (mRequested == listen) return;
+            mRequested = listen;
+            updateListener();
+        }
+
+        public void setDisabled(boolean disabled) {
+            if (mDisabled == disabled) return;
+            mDisabled = disabled;
+            updateListener();
+        }
+
+        public void updateListener() {
+            if (!mConfigured || mSensor == null) return;
+            if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
+                mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
+                if (DEBUG) Log.d(TAG, "requestTriggerSensor " + mRegistered);
+            } else if (mRegistered) {
+                final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
+                if (DEBUG) Log.d(TAG, "cancelTriggerSensor " + rt);
+                mRegistered = false;
+            }
+        }
+
+        private boolean enabledBySetting() {
+            if (TextUtils.isEmpty(mSetting)) {
+                return true;
+            }
+            return Settings.Secure.getIntForUser(mResolver, mSetting, 1,
+                    UserHandle.USER_CURRENT) != 0;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder("{mRegistered=").append(mRegistered)
+                    .append(", mRequested=").append(mRequested)
+                    .append(", mDisabled=").append(mDisabled)
+                    .append(", mConfigured=").append(mConfigured)
+                    .append(", mSensor=").append(mSensor).append("}").toString();
+        }
+
+        @Override
+        @AnyThread
+        public void onTrigger(TriggerEvent event) {
+            mHandler.post(mWakeLock.wrap(() -> {
+                if (DEBUG)
+                    Log.d(TAG, "onTrigger: " + triggerEventToString(event));
+                boolean sensorPerformsProxCheck = false;
+                if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
+                    int subType = (int) event.values[0];
+                    MetricsLogger.action(
+                            mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
+                            subType);
+                    sensorPerformsProxCheck =
+                            mDozeParameters.getPickupSubtypePerformsProxCheck(subType);
+                }
+
+                mRegistered = false;
+                mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck);
+                updateListener();  // reregister, this sensor only fires once
+            }));
+        }
+
+        public void registerSettingsObserver(ContentObserver settingsObserver) {
+            if (mConfigured && !TextUtils.isEmpty(mSetting)) {
+                mResolver.registerContentObserver(
+                        Settings.Secure.getUriFor(mSetting), false /* descendants */,
+                        mSettingsObserver, UserHandle.USER_ALL);
+            }
+        }
+
+        private String triggerEventToString(TriggerEvent event) {
+            if (event == null) return null;
+            final StringBuilder sb = new StringBuilder("TriggerEvent[")
+                    .append(event.timestamp).append(',')
+                    .append(event.sensor.getName());
+            if (event.values != null) {
+                for (int i = 0; i < event.values.length; i++) {
+                    sb.append(',').append(event.values[i]);
+                }
+            }
+            return sb.append(']').toString();
+        }
+    }
+
+    public interface Callback {
+        void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 6c35243..8789845c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -16,47 +16,38 @@
 
 package com.android.systemui.doze;
 
-import android.app.ActivityManager;
 import android.app.UiModeManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
-import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
-import android.hardware.TriggerEvent;
-import android.hardware.TriggerEventListener;
-import android.media.AudioAttributes;
-import android.net.Uri;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
 import android.service.dreams.DreamService;
-import android.text.TextUtils;
 import android.util.Log;
 import android.view.Display;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.internal.util.Preconditions;
+import com.android.systemui.DejankUtils;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.Assert;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Date;
-import java.util.List;
 
-public class DozeService extends DreamService {
+public class DozeService extends DreamService implements DozeSensors.Callback {
     private static final String TAG = "DozeService";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String ACTION_BASE = "com.android.systemui.doze";
     private static final String PULSE_ACTION = ACTION_BASE + ".pulse";
@@ -72,9 +63,8 @@
     private final Handler mHandler = new Handler();
 
     private DozeHost mHost;
+    private DozeSensors mDozeSensors;
     private SensorManager mSensorManager;
-    private TriggerSensor[] mSensors;
-    private TriggerSensor mPickupSensor;
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
     private UiModeManager mUiModeManager;
@@ -101,10 +91,6 @@
         pw.print("  mWakeLock: held="); pw.println(mWakeLock.isHeld());
         pw.print("  mHost: "); pw.println(mHost);
         pw.print("  mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered);
-        for (TriggerSensor s : mSensors) {
-            pw.print("  sensor: ");
-            pw.println(s);
-        }
         pw.print("  mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
         pw.print("  mPowerSaveActive: "); pw.println(mPowerSaveActive);
         pw.print("  mCarMode: "); pw.println(mCarMode);
@@ -129,30 +115,14 @@
 
         mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
         mConfig = new AmbientDisplayConfiguration(mContext);
-        mSensors = new TriggerSensor[] {
-                new TriggerSensor(
-                        mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
-                        null /* setting */,
-                        mDozeParameters.getPulseOnSigMotion(),
-                        mDozeParameters.getVibrateOnSigMotion(),
-                        DozeLog.PULSE_REASON_SENSOR_SIGMOTION),
-                mPickupSensor = new TriggerSensor(
-                        mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
-                        Settings.Secure.DOZE_PULSE_ON_PICK_UP,
-                        mConfig.pulseOnPickupAvailable(), mDozeParameters.getVibrateOnPickup(),
-                        DozeLog.PULSE_REASON_SENSOR_PICKUP),
-                new TriggerSensor(
-                        findSensorWithType(mConfig.doubleTapSensorType()),
-                        Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, true,
-                        mDozeParameters.getVibrateOnPickup(),
-                        DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP)
-        };
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(true);
         mDisplayStateSupported = mDozeParameters.getDisplayStateSupported();
         mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
         turnDisplayOff();
+        mDozeSensors = new DozeSensors(mContext, mSensorManager, mDozeParameters,
+                mConfig, mWakeLock, this);
     }
 
     @Override
@@ -221,6 +191,7 @@
     }
 
     private void requestPulse(final int reason, boolean performedProxCheck) {
+        Assert.isMainThread();
         if (mHost != null && mDreaming && !mPulsing) {
             // Let the host know we want to pulse.  Wait for it to be ready, then
             // turn the screen on.  When finished, turn the screen off again.
@@ -282,7 +253,7 @@
                 if (mPulsing && mDreaming) {
                     mPulsing = false;
                     if (REREGISTER_ALL_SENSORS_ON_SCREEN_OFF) {
-                        reregisterAllSensors();
+                        mDozeSensors.reregisterAllSensors();
                     }
                     turnDisplayOff();
                 }
@@ -313,22 +284,11 @@
 
     private void listenForPulseSignals(boolean listen) {
         if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
-        for (TriggerSensor s : mSensors) {
-            s.setListening(listen);
-        }
+        mDozeSensors.setListen(listen);
         listenForBroadcasts(listen);
         listenForNotifications(listen);
     }
 
-    private void reregisterAllSensors() {
-        for (TriggerSensor s : mSensors) {
-            s.setListening(false);
-        }
-        for (TriggerSensor s : mSensors) {
-            s.setListening(true);
-        }
-    }
-
     private void listenForBroadcasts(boolean listen) {
         if (listen) {
             final IntentFilter filter = new IntentFilter(PULSE_ACTION);
@@ -336,18 +296,10 @@
             filter.addAction(Intent.ACTION_USER_SWITCHED);
             mContext.registerReceiver(mBroadcastReceiver, filter);
 
-            for (TriggerSensor s : mSensors) {
-                if (s.mConfigured && !TextUtils.isEmpty(s.mSetting)) {
-                    mContext.getContentResolver().registerContentObserver(
-                            Settings.Secure.getUriFor(s.mSetting), false /* descendants */,
-                            mSettingsObserver, UserHandle.USER_ALL);
-                }
-            }
             mBroadcastReceiverRegistered = true;
         } else {
             if (mBroadcastReceiverRegistered) {
                 mContext.unregisterReceiver(mBroadcastReceiver);
-                mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
             }
             mBroadcastReceiverRegistered = false;
         }
@@ -368,17 +320,18 @@
         requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
     }
 
-    private static String triggerEventToString(TriggerEvent event) {
-        if (event == null) return null;
-        final StringBuilder sb = new StringBuilder("TriggerEvent[")
-                .append(event.timestamp).append(',')
-                .append(event.sensor.getName());
-        if (event.values != null) {
-            for (int i = 0; i < event.values.length; i++) {
-                sb.append(',').append(event.values[i]);
-            }
+    @Override
+    public void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck) {
+        requestPulse(pulseReason, sensorPerformedProxCheck);
+
+        if (pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP) {
+            final long timeSinceNotification =
+                    SystemClock.elapsedRealtime() - mNotificationPulseTime;
+            final boolean withinVibrationThreshold =
+                    timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
+            DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
         }
-        return sb.append(']').toString();
+
     }
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -395,21 +348,7 @@
                 }
             }
             if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
-                for (TriggerSensor s : mSensors) {
-                    s.updateListener();
-                }
-            }
-        }
-    };
-
-    private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
-        @Override
-        public void onChange(boolean selfChange, Uri uri, int userId) {
-            if (userId != ActivityManager.getCurrentUser()) {
-                return;
-            }
-            for (TriggerSensor s : mSensors) {
-                s.updateListener();
+                mDozeSensors.onUserSwitched();
             }
         }
     };
@@ -442,122 +381,6 @@
         }
     };
 
-    private Sensor findSensorWithType(String type) {
-        if (TextUtils.isEmpty(type)) {
-            return null;
-        }
-        List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
-        for (Sensor s : sensorList) {
-            if (type.equals(s.getStringType())) {
-                return s;
-            }
-        }
-        return null;
-    }
-
-    private class TriggerSensor extends TriggerEventListener {
-        final Sensor mSensor;
-        final boolean mConfigured;
-        final boolean mDebugVibrate;
-        final int mPulseReason;
-        final String mSetting;
-
-        private boolean mRequested;
-        private boolean mRegistered;
-        private boolean mDisabled;
-
-        public TriggerSensor(Sensor sensor, String setting, boolean configured,
-                boolean debugVibrate, int pulseReason) {
-            mSensor = sensor;
-            mSetting = setting;
-            mConfigured = configured;
-            mDebugVibrate = debugVibrate;
-            mPulseReason = pulseReason;
-        }
-
-        public void setListening(boolean listen) {
-            if (mRequested == listen) return;
-            mRequested = listen;
-            updateListener();
-        }
-
-        public void setDisabled(boolean disabled) {
-            if (mDisabled == disabled) return;
-            mDisabled = disabled;
-            updateListener();
-        }
-
-        public void updateListener() {
-            if (!mConfigured || mSensor == null) return;
-            if (mRequested && !mDisabled && enabledBySetting() && !mRegistered) {
-                mRegistered = mSensorManager.requestTriggerSensor(this, mSensor);
-                if (DEBUG) Log.d(mTag, "requestTriggerSensor " + mRegistered);
-            } else if (mRegistered) {
-                final boolean rt = mSensorManager.cancelTriggerSensor(this, mSensor);
-                if (DEBUG) Log.d(mTag, "cancelTriggerSensor " + rt);
-                mRegistered = false;
-            }
-        }
-
-        private boolean enabledBySetting() {
-            if (TextUtils.isEmpty(mSetting)) {
-                return true;
-            }
-            return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSetting, 1,
-                    UserHandle.USER_CURRENT) != 0;
-        }
-
-        @Override
-        public String toString() {
-            return new StringBuilder("{mRegistered=").append(mRegistered)
-                    .append(", mRequested=").append(mRequested)
-                    .append(", mDisabled=").append(mDisabled)
-                    .append(", mConfigured=").append(mConfigured)
-                    .append(", mDebugVibrate=").append(mDebugVibrate)
-                    .append(", mSensor=").append(mSensor).append("}").toString();
-        }
-
-        @Override
-        public void onTrigger(TriggerEvent event) {
-            mWakeLock.acquire();
-            try {
-                if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event));
-                boolean sensorPerformsProxCheck = false;
-                if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
-                    int subType = (int) event.values[0];
-                    MetricsLogger.action(mContext, MetricsEvent.ACTION_AMBIENT_GESTURE, subType);
-                    sensorPerformsProxCheck = mDozeParameters.getPickupSubtypePerformsProxCheck(
-                            subType);
-                }
-                if (mDebugVibrate) {
-                    final Vibrator v = (Vibrator) mContext.getSystemService(
-                            Context.VIBRATOR_SERVICE);
-                    if (v != null) {
-                        v.vibrate(1000, new AudioAttributes.Builder()
-                                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                                .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build());
-                    }
-                }
-
-                mRegistered = false;
-                requestPulse(mPulseReason, sensorPerformsProxCheck);
-                updateListener();  // reregister, this sensor only fires once
-
-                // record pickup gesture, also keep track of whether we might have been triggered
-                // by recent vibration.
-                final long timeSinceNotification = SystemClock.elapsedRealtime()
-                        - mNotificationPulseTime;
-                final boolean withinVibrationThreshold =
-                        timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
-                if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
-                    DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
-                }
-            } finally {
-                mWakeLock.release();
-            }
-        }
-    }
-
     private abstract class ProximityCheck implements SensorEventListener, Runnable {
         private static final int TIMEOUT_DELAY_MS = 500;
 
@@ -581,8 +404,7 @@
                 finishWithResult(RESULT_UNKNOWN);
                 return;
             }
-            // the pickup sensor interferes with the prox event, disable it until we have a result
-            mPickupSensor.setDisabled(true);
+            mDozeSensors.setDisableSensorsInterferingWithProximity(true);
 
             mMaxRange = sensor.getMaximumRange();
             mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
@@ -614,8 +436,7 @@
             if (mRegistered) {
                 mHandler.removeCallbacks(this);
                 mSensorManager.unregisterListener(this);
-                // we're done - reenable the pickup sensor
-                mPickupSensor.setDisabled(false);
+                mDozeSensors.setDisableSensorsInterferingWithProximity(false);
                 mRegistered = false;
             }
             onProximityResult(result);
diff --git a/packages/SystemUI/src/com/android/systemui/util/Assert.java b/packages/SystemUI/src/com/android/systemui/util/Assert.java
new file mode 100644
index 0000000..af447f3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/Assert.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.util;
+
+import android.os.Looper;
+
+/**
+ * Helper providing common assertions.
+ */
+public class Assert {
+
+    public static void isMainThread() {
+        if (!Looper.getMainLooper().isCurrentThread()) {
+            throw new IllegalStateException("should be called from the main thread.");
+        }
+    }
+}
diff --git a/services/core/proto/ipconnectivity.proto b/proto/src/ipconnectivity.proto
similarity index 100%
rename from services/core/proto/ipconnectivity.proto
rename to proto/src/ipconnectivity.proto
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
new file mode 100644
index 0000000..9416ac1
--- /dev/null
+++ b/proto/src/wifi.proto
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package clearcut.connectivity;
+
+option java_package = "com.android.server.wifi";
+option java_outer_classname = "WifiMetricsProto";
+
+// The information about the Wifi events.
+message WifiLog {
+
+  // Session information that gets logged for every Wifi connection.
+  repeated ConnectionEvent connection_event = 1;
+
+  // Number of saved networks in the user profile.
+  optional int32 num_saved_networks = 2;
+
+  // Number of open networks in the saved networks.
+  optional int32 num_open_networks = 3;
+
+  // Number of personal networks.
+  optional int32 num_personal_networks = 4;
+
+  // Number of enterprise networks.
+  optional int32 num_enterprise_networks = 5;
+
+  // Does the user have location setting enabled.
+  optional bool is_location_enabled = 6;
+
+  // Does the user have scanning enabled.
+  optional bool is_scanning_always_enabled = 7;
+
+  // Number of times user toggled wifi using the settings menu.
+  optional int32 num_wifi_toggled_via_settings = 8;
+
+  // Number of times user toggled wifi using the airplane menu.
+  optional int32 num_wifi_toggled_via_airplane = 9;
+
+  // Number of networks added by the user.
+  optional int32 num_networks_added_by_user = 10;
+
+  // Number of networks added by applications.
+  optional int32 num_networks_added_by_apps = 11;
+
+  // Number scans that returned empty results.
+  optional int32 num_empty_scan_results = 12;
+
+  // Number scans that returned at least one result.
+  optional int32 num_non_empty_scan_results = 13;
+
+  // Number of scans that were one time.
+  optional int32 num_oneshot_scans = 14;
+
+  // Number of repeated background scans that were scheduled to the chip.
+  optional int32 num_background_scans = 15;
+
+  // Error codes that a scan can result in.
+  enum ScanReturnCode {
+
+    // Return Code is unknown.
+    SCAN_UNKNOWN = 0;
+
+    // Scan was successful.
+    SCAN_SUCCESS = 1;
+
+    // Scan was successfully started, but was interrupted.
+    SCAN_FAILURE_INTERRUPTED = 2;
+
+    //  Scan failed to start because of invalid configuration
+    //  (bad channel, etc).
+    SCAN_FAILURE_INVALID_CONFIGURATION = 3;
+
+    // Could not start a scan because wifi is disabled.
+    FAILURE_WIFI_DISABLED = 4;
+
+  }
+
+  // Mapping of error codes to the number of times that scans resulted
+  // in that error.
+  repeated ScanReturnEntry scan_return_entries = 16;
+
+  message ScanReturnEntry {
+
+     // Return code of the scan.
+     optional ScanReturnCode scan_return_code = 1;
+
+     // Number of entries that were found in the scan.
+     optional int32 scan_results_count = 2;
+  }
+
+  // State of the Wifi.
+  enum WifiState {
+
+    // State is unknown.
+    WIFI_UNKNOWN = 0;
+
+    // Wifi is disabled.
+    WIFI_DISABLED = 1;
+
+    // Wifi is enabled.
+    WIFI_DISCONNECTED = 2;
+
+    // Wifi is enabled and associated with an AP.
+    WIFI_ASSOCIATED = 3;
+  }
+
+  // Mapping of system state to the number of times that scans were requested in
+  // that state
+  repeated WifiSystemStateEntry wifi_system_state_entries = 17;
+
+  message WifiSystemStateEntry {
+
+     // Current WiFi state.
+     optional WifiState wifi_state = 1;
+
+     // Count of scans in state.
+     optional int32 wifi_state_count = 2;
+
+     // Is screen on.
+     optional bool is_screen_on = 3;
+  }
+
+  // Mapping of Error/Success codes to the number of background scans that resulted in it
+  repeated ScanReturnEntry background_scan_return_entries = 18;
+
+  // Mapping of system state to the number of times that Background scans were requested in that
+  // state
+  repeated WifiSystemStateEntry background_scan_request_state = 19;
+
+  // Total number of times the Watchdog of Last Resort triggered, resetting the wifi stack
+  optional int32 num_last_resort_watchdog_triggers = 20;
+
+  // Total number of networks over bad association threshold when watchdog triggered
+  optional int32 num_last_resort_watchdog_bad_association_networks_total = 21;
+
+  // Total number of networks over bad authentication threshold when watchdog triggered
+  optional int32 num_last_resort_watchdog_bad_authentication_networks_total = 22;
+
+  // Total number of networks over bad dhcp threshold when watchdog triggered
+  optional int32 num_last_resort_watchdog_bad_dhcp_networks_total = 23;
+
+  // Total number of networks over bad other threshold when watchdog triggered
+  optional int32 num_last_resort_watchdog_bad_other_networks_total = 24;
+
+  // Total count of networks seen when watchdog triggered
+  optional int32 num_last_resort_watchdog_available_networks_total = 25;
+
+  // Total count of triggers with atleast one bad association network
+  optional int32 num_last_resort_watchdog_triggers_with_bad_association = 26;
+
+  // Total count of triggers with atleast one bad authentication network
+  optional int32 num_last_resort_watchdog_triggers_with_bad_authentication = 27;
+
+  // Total count of triggers with atleast one bad dhcp network
+  optional int32 num_last_resort_watchdog_triggers_with_bad_dhcp = 28;
+
+  // Total count of triggers with atleast one bad other network
+  optional int32 num_last_resort_watchdog_triggers_with_bad_other = 29;
+
+  // Count of times connectivity watchdog confirmed pno is working
+  optional int32 num_connectivity_watchdog_pno_good = 30;
+
+  // Count of times connectivity watchdog found pno not working
+  optional int32 num_connectivity_watchdog_pno_bad = 31;
+
+  // Count of times connectivity watchdog confirmed background scan is working
+  optional int32 num_connectivity_watchdog_background_good = 32;
+
+  // Count of times connectivity watchdog found background scan not working
+  optional int32 num_connectivity_watchdog_background_bad = 33;
+
+  // The time duration represented by this wifi log, from start to end of capture
+  optional int32 record_duration_sec = 34;
+
+  // Counts the occurrences of each individual RSSI poll level
+  repeated RssiPollCount rssi_poll_rssi_count = 35;
+
+  // Total number of times WiFi connected immediately after a Last Resort Watchdog trigger,
+  // without new networks becoming available.
+  optional int32 num_last_resort_watchdog_successes = 36;
+
+  // Total number of saved hidden networks
+  optional int32 num_hidden_networks = 37;
+
+  // Total number of saved passpoint / hotspot 2.0 networks
+  optional int32 num_passpoint_networks = 38;
+
+  // Total number of scan results
+  optional int32 num_total_scan_results = 39;
+
+  // Total number of scan results for open networks
+  optional int32 num_open_network_scan_results = 40;
+
+  // Total number of scan results for personal networks
+  optional int32 num_personal_network_scan_results = 41;
+
+  // Total number of scan results for enterprise networks
+  optional int32 num_enterprise_network_scan_results = 42;
+
+  // Total number of scan results for hidden networks
+  optional int32 num_hidden_network_scan_results = 43;
+
+  // Total number of scan results for hotspot 2.0 r1 networks
+  optional int32 num_hotspot2_r1_network_scan_results = 44;
+
+  // Total number of scan results for hotspot 2.0 r2 networks
+  optional int32 num_hotspot2_r2_network_scan_results = 45;
+
+  // Total number of scans handled by framework (oneshot or otherwise)
+  optional int32 num_scans = 46;
+
+  // Counts the occurrences of each alert reason.
+  repeated AlertReasonCount alert_reason_count = 47;
+
+  // Counts the occurrences of each Wifi score
+  repeated WifiScoreCount wifi_score_count = 48;
+
+  // Histogram of Soft AP Durations
+  repeated SoftApDurationBucket soft_ap_duration = 49;
+
+  // Histogram of Soft AP ReturnCode
+  repeated SoftApReturnCodeCount soft_ap_return_code = 50;
+
+  // Histogram of the delta between scan result RSSI and RSSI polls
+  repeated RssiPollCount rssi_poll_delta_count = 51;
+}
+
+// Information that gets logged for every WiFi connection.
+message RouterFingerPrint {
+
+  enum RoamType {
+
+    // Type is unknown.
+    ROAM_TYPE_UNKNOWN = 0;
+
+    // No roaming - usually happens on a single band (2.4 GHz) router.
+    ROAM_TYPE_NONE = 1;
+
+    // Enterprise router.
+    ROAM_TYPE_ENTERPRISE = 2;
+
+    // DBDC => Dual Band Dual Concurrent essentially a router that
+    // supports both 2.4 GHz and 5 GHz bands.
+    ROAM_TYPE_DBDC = 3;
+  }
+
+  enum Auth {
+
+    // Auth is unknown.
+    AUTH_UNKNOWN = 0;
+
+    // No authentication.
+    AUTH_OPEN = 1;
+
+    // If the router uses a personal authentication.
+    AUTH_PERSONAL = 2;
+
+    // If the router is setup for enterprise authentication.
+    AUTH_ENTERPRISE = 3;
+  }
+
+  enum RouterTechnology {
+
+    // Router is unknown.
+    ROUTER_TECH_UNKNOWN = 0;
+
+    // Router Channel A.
+    ROUTER_TECH_A = 1;
+
+    // Router Channel B.
+    ROUTER_TECH_B = 2;
+
+    // Router Channel G.
+    ROUTER_TECH_G = 3;
+
+    // Router Channel N.
+    ROUTER_TECH_N = 4;
+
+    // Router Channel AC.
+    ROUTER_TECH_AC = 5;
+
+    // When the channel is not one of the above.
+    ROUTER_TECH_OTHER = 6;
+  }
+
+  optional RoamType roam_type = 1;
+
+  // Channel on which the connection takes place.
+  optional int32 channel_info = 2;
+
+  // DTIM setting of the router.
+  optional int32 dtim = 3;
+
+  // Authentication scheme of the router.
+  optional Auth authentication = 4;
+
+  // If the router is hidden.
+  optional bool hidden = 5;
+
+  // Channel information.
+  optional RouterTechnology router_technology = 6;
+
+  // whether ipv6 is supported.
+  optional bool supports_ipv6 = 7;
+
+  // If the router is a passpoint / hotspot 2.0 network
+  optional bool passpoint = 8;
+}
+
+message ConnectionEvent {
+
+  // Roam Type.
+  enum RoamType {
+
+    // Type is unknown.
+    ROAM_UNKNOWN = 0;
+
+    // No roaming.
+    ROAM_NONE  = 1;
+
+    // DBDC roaming.
+    ROAM_DBDC = 2;
+
+    // Enterprise roaming.
+    ROAM_ENTERPRISE = 3;
+
+    // User selected roaming.
+    ROAM_USER_SELECTED = 4;
+
+    // Unrelated.
+    ROAM_UNRELATED = 5;
+  }
+
+  // Connectivity Level Failure.
+  enum ConnectivityLevelFailure {
+
+    // Failure is unknown.
+    HLF_UNKNOWN = 0;
+
+    // No failure.
+    HLF_NONE = 1;
+
+    // DHCP failure.
+    HLF_DHCP = 2;
+
+    // No internet connection.
+    HLF_NO_INTERNET = 3;
+
+    // No internet connection.
+    HLF_UNWANTED = 4;
+  }
+
+  // Start time of the connection.
+  optional int64 start_time_millis = 1;// [(datapol.semantic_type) = ST_TIMESTAMP];
+
+  // Duration to connect.
+  optional int32 duration_taken_to_connect_millis = 2;
+
+  // Router information.
+  optional RouterFingerPrint router_fingerprint = 3;
+
+  // RSSI at the start of the connection.
+  optional int32 signal_strength = 4;
+
+  // Roam Type.
+  optional RoamType roam_type = 5;
+
+  // Result of the connection.
+  optional int32 connection_result = 6;
+
+  // Reasons for level 2 failure (needs to be coordinated with wpa-supplicant).
+  optional int32 level_2_failure_code = 7;
+
+  // Failures that happen at the connectivity layer.
+  optional ConnectivityLevelFailure connectivity_level_failure_code = 8;
+
+  // Has bug report been taken.
+  optional bool automatic_bug_report_taken = 9;
+}
+
+// Number of occurrences of a specific RSSI poll rssi value
+message RssiPollCount {
+  // RSSI
+  optional int32 rssi = 1;
+
+  // Number of RSSI polls with 'rssi'
+  optional int32 count = 2;
+}
+
+// Number of occurrences of a specific alert reason value
+message AlertReasonCount {
+  // Alert reason
+  optional int32 reason = 1;
+
+  // Number of alerts with |reason|.
+  optional int32 count = 2;
+}
+
+// Counts the number of instances of a specific Wifi Score calculated by WifiScoreReport
+message WifiScoreCount {
+  // Wifi Score
+  optional int32 score = 1;
+
+  // Number of Wifi score reports with this score
+  optional int32 count = 2;
+}
+
+// Number of occurrences of Soft AP session durations
+message SoftApDurationBucket {
+  // Bucket covers duration : [duration_sec, duration_sec + bucket_size_sec)
+  // The (inclusive) lower bound of Soft AP session duration represented by this bucket
+  optional int32 duration_sec = 1;
+
+  // The size of this bucket
+  optional int32 bucket_size_sec = 2;
+
+  // Number of soft AP session durations that fit into this bucket
+  optional int32 count = 3;
+}
+
+// Number of occurrences of a soft AP session return code
+message SoftApReturnCodeCount {
+  // Return code of the soft AP session
+  optional int32 return_code = 1;
+
+  // Occurrences of this soft AP return code
+  optional int32 count = 2;
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 9d3035a..6375e9a 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -3983,7 +3983,7 @@
     boolean deviceIsEncrypted() {
         try {
             return mMountService.getEncryptionState()
-                     != IMountService.ENCRYPTION_STATE_NONE
+                     != StorageManager.ENCRYPTION_STATE_NONE
                 && mMountService.getPasswordType()
                      != StorageManager.CRYPT_TYPE_DEFAULT;
         } catch (Exception e) {
diff --git a/services/core/Android.mk b/services/core/Android.mk
index 9efafb7..11586ee 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -8,7 +8,6 @@
 
 LOCAL_SRC_FILES += \
     $(call all-java-files-under,java) \
-    $(call all-proto-files-under, proto) \
     java/com/android/server/EventLogTags.logtags \
     java/com/android/server/am/EventLogTags.logtags \
     ../../../../system/netd/server/binder/android/net/INetd.aidl \
@@ -24,7 +23,6 @@
     android.hardware.light@2.0-java
 
 LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 
 ifneq ($(INCREMENTAL_BUILDS),)
     LOCAL_PROGUARD_ENABLED := disabled
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b9a4831..8bb9326 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -46,6 +46,7 @@
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.ObbInfo;
+import android.net.TrafficStats;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.DropBoxManager;
@@ -86,6 +87,7 @@
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.util.Xml;
@@ -2535,11 +2537,11 @@
         } catch (NumberFormatException e) {
             // Bad result - unexpected.
             Slog.w(TAG, "Unable to parse result from cryptfs cryptocomplete");
-            return ENCRYPTION_STATE_ERROR_UNKNOWN;
+            return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
         } catch (NativeDaemonConnectorException e) {
             // Something bad happened.
             Slog.w(TAG, "Error in communicating with cryptfs in validating");
-            return ENCRYPTION_STATE_ERROR_UNKNOWN;
+            return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
         }
     }
 
@@ -3738,6 +3740,18 @@
 
             pw.println();
             pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
+            final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
+            if (pair == null) {
+                pw.println("Internal storage total size: N/A");
+            } else {
+                pw.print("Internal storage (");
+                pw.print(pair.first);
+                pw.print(") total size: ");
+                pw.print(pair.second);
+                pw.print(" (");
+                pw.print((float) pair.second / TrafficStats.GB_IN_BYTES);
+                pw.println(" GB)");
+            }
             pw.println("Force adoptable: " + mForceAdoptable);
             pw.println();
             pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index 68b465a..a6a3774 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -56,6 +56,7 @@
     /** Intent used to bind to the service */
     private final Intent mIntent;
 
+    private volatile boolean mBindRequested;
     private IEphemeralResolver mRemoteInstance;
 
     public EphemeralResolverConnection(Context context, ComponentName componentName) {
@@ -111,8 +112,11 @@
             return;
         }
 
-        mContext.bindServiceAsUser(mIntent, mServiceConnection,
-                Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, UserHandle.SYSTEM);
+        if (!mBindRequested) {
+            mBindRequested = true;
+            mContext.bindServiceAsUser(mIntent, mServiceConnection,
+                    Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, UserHandle.SYSTEM);
+        }
 
         final long startMillis = SystemClock.uptimeMillis();
         while (true) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index efd6f46..d0baaf0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2483,6 +2483,7 @@
      */
     @Override
     public boolean removeUser(int userHandle) {
+        Slog.i(LOG_TAG, "removeUser u" + userHandle);
         checkManageOrCreateUsersPermission("Only the system can remove users");
         if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
                 UserManager.DISALLOW_REMOVE_USER, false)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6e5c025..40dfcda 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -7922,6 +7922,12 @@
         if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
             return false;
         }
+        // If the navigation bar can't change sides, then it will
+        // jump when we change orientations and we don't rotate
+        // seamlessly.
+        if (!mNavigationBarCanMove) {
+            return false;
+        }
         int delta = newRotation - oldRotation;
         if (delta < 0) delta += 4;
         // Likewise we don't rotate seamlessly for 180 degree rotations
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 84f0f90..6ff0c5a 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -16,6 +16,17 @@
 
 package com.android.server.connectivity;
 
+import static com.android.server.connectivity.MetricsTestUtil.aBool;
+import static com.android.server.connectivity.MetricsTestUtil.aByteArray;
+import static com.android.server.connectivity.MetricsTestUtil.aLong;
+import static com.android.server.connectivity.MetricsTestUtil.aString;
+import static com.android.server.connectivity.MetricsTestUtil.aType;
+import static com.android.server.connectivity.MetricsTestUtil.anInt;
+import static com.android.server.connectivity.MetricsTestUtil.anIntArray;
+import static com.android.server.connectivity.MetricsTestUtil.b;
+import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent;
+import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog;
+
 import android.net.ConnectivityMetricsEvent;
 import android.net.metrics.ApfProgramEvent;
 import android.net.metrics.ApfStats;
@@ -28,21 +39,10 @@
 import android.net.metrics.NetworkEvent;
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
-import com.google.protobuf.nano.MessageNano;
-import java.util.Arrays;
+
 import junit.framework.TestCase;
 
-import static com.android.server.connectivity.metrics.IpConnectivityLogClass.IpConnectivityLog;
-import static com.android.server.connectivity.MetricsTestUtil.aBool;
-import static com.android.server.connectivity.MetricsTestUtil.aByteArray;
-import static com.android.server.connectivity.MetricsTestUtil.aLong;
-import static com.android.server.connectivity.MetricsTestUtil.aString;
-import static com.android.server.connectivity.MetricsTestUtil.aType;
-import static com.android.server.connectivity.MetricsTestUtil.anInt;
-import static com.android.server.connectivity.MetricsTestUtil.anIntArray;
-import static com.android.server.connectivity.MetricsTestUtil.b;
-import static com.android.server.connectivity.MetricsTestUtil.describeIpEvent;
-import static com.android.server.connectivity.MetricsTestUtil.ipEv;
+import java.util.Arrays;
 
 public class IpConnectivityEventBuilderTest extends TestCase {
 
@@ -351,8 +351,7 @@
     static void verifySerialization(String want, ConnectivityMetricsEvent... input) {
         try {
             byte[] got = IpConnectivityEventBuilder.serialize(0, Arrays.asList(input));
-            IpConnectivityLog log = new IpConnectivityLog();
-            MessageNano.mergeFrom(log, got);
+            IpConnectivityLog log = IpConnectivityLog.parseFrom(got);
             assertEquals(want, log.toString());
         } catch (Exception e) {
             fail(e.toString());
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java
index aa491bb..c7982b1 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.connectivity;
 
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
 import android.content.Context;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
@@ -30,22 +33,21 @@
 import android.net.metrics.ValidationProbeEvent;
 import android.os.Parcelable;
 import android.util.Base64;
+
 import com.android.server.connectivity.metrics.IpConnectivityLogClass;
-import com.google.protobuf.nano.MessageNano;
+
+import junit.framework.TestCase;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
-import junit.framework.TestCase;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import static org.mockito.Mockito.timeout;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 
 public class IpConnectivityMetricsTest extends TestCase {
     static final IpReachabilityEvent FAKE_EV =
@@ -254,8 +256,7 @@
         try {
             byte[] got = Base64.decode(output, Base64.DEFAULT);
             IpConnectivityLogClass.IpConnectivityLog log =
-                    new IpConnectivityLogClass.IpConnectivityLog();
-            MessageNano.mergeFrom(log, got);
+                    IpConnectivityLogClass.IpConnectivityLog.parseFrom(got);
             assertEquals(want, log.toString());
         } catch (Exception e) {
             fail(e.toString());