Merge "Remove screenshot APIs." into mnc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 3209169..afd82e3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -111,6 +111,7 @@
     field public static final java.lang.String INVOKE_CARRIER_SETUP = "android.permission.INVOKE_CARRIER_SETUP";
     field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
     field public static final java.lang.String KILL_UID = "android.permission.KILL_UID";
+    field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
     field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1e9bc54..15cfbcd 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2466,13 +2466,6 @@
             return true;
         }
 
-        case SYSTEM_BACKUP_RESTORED: {
-            data.enforceInterface(IActivityManager.descriptor);
-            systemBackupRestored();
-            reply.writeNoException();
-            return true;
-        }
-
         case NOTIFY_CLEARTEXT_NETWORK_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             final int uid = data.readInt();
@@ -5759,17 +5752,6 @@
     }
 
     @Override
-    public void systemBackupRestored() throws RemoteException {
-        Parcel data = Parcel.obtain();
-        Parcel reply = Parcel.obtain();
-        data.writeInterfaceToken(IActivityManager.descriptor);
-        mRemote.transact(SYSTEM_BACKUP_RESTORED, data, reply, 0);
-        reply.readException();
-        data.recycle();
-        reply.recycle();
-    }
-
-    @Override
     public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 05a936c..4ba1055 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -488,7 +488,6 @@
     public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
     public void notifyEnterAnimationComplete(IBinder token) throws RemoteException;
 
-    public void systemBackupRestored() throws RemoteException;
     public void notifyCleartextNetwork(int uid, byte[] firstPacket) throws RemoteException;
 
     public void setDumpHeapDebugLimit(String processName, int uid, long maxMemSize,
@@ -825,7 +824,6 @@
     int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240;
     int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241;
     int REGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+242;
-    int SYSTEM_BACKUP_RESTORED = IBinder.FIRST_CALL_TRANSACTION+243;
 
     // Start of M transactions
     int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
diff --git a/core/java/android/app/backup/RecentsBackupHelper.java b/core/java/android/app/backup/RecentsBackupHelper.java
deleted file mode 100644
index 1a64da6..0000000
--- a/core/java/android/app/backup/RecentsBackupHelper.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.backup;
-
-import android.content.Context;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.util.Slog;
-
-import java.io.File;
-
-/**
- * Helper for saving/restoring 'recent tasks' infrastructure.
- * @hide
- */
-public class RecentsBackupHelper implements BackupHelper {
-    private static final String TAG = "RecentsBackup";
-    private static final boolean DEBUG = false;
-
-    // This must match TaskPersister.TASKS_DIRNAME, but that class is not accessible from here
-    private static final String RECENTS_TASK_DIR = "recent_tasks";
-
-    // Must match TaskPersister.IMAGES_DIRNAME, as above
-    private static final String RECENTS_IMAGE_DIR = "recent_images";
-
-    // At restore time, tasks/thumbnails are placed in these directories alongside
-    // the "live" recents dirs named above.
-    private static final String RECENTS_TASK_RESTORE_DIR = "restored_" + RECENTS_TASK_DIR;
-    private static final String RECENTS_IMAGE_RESTORE_DIR = "restored_" + RECENTS_IMAGE_DIR;
-
-    // Prefixes for tagging the two kinds of recents backup records that we might generate
-    private static final String RECENTS_TASK_KEY = "task:";
-    private static final String RECENTS_IMAGE_KEY = "image:";
-
-    FileBackupHelperBase mTaskFileHelper;
-
-    final File mSystemDir;
-    final File mTasksDir;
-    final File mRestoredTasksDir;
-    final File mRestoredImagesDir;
-    final String[] mRecentFiles;
-    final String[] mRecentKeys;
-
-    /**
-     * @param context The agent context in which this helper instance will run
-     */
-    public RecentsBackupHelper(Context context) {
-        mTaskFileHelper = new FileBackupHelperBase(context);
-
-        mSystemDir = new File(Environment.getDataDirectory(), "system");
-        mTasksDir = new File(mSystemDir, RECENTS_TASK_DIR);
-        mRestoredTasksDir = new File(mSystemDir, RECENTS_TASK_RESTORE_DIR);
-        mRestoredImagesDir = new File(mSystemDir, RECENTS_IMAGE_RESTORE_DIR);
-
-        // Currently we back up only the recent-task descriptions, not the thumbnails
-        File[] recentFiles = mTasksDir.listFiles();
-        if (recentFiles != null) {
-            // We explicitly proceed even if this is a zero-size array
-            final int N = recentFiles.length;
-            mRecentKeys = new String[N];
-            mRecentFiles = new String[N];
-            if (DEBUG) {
-                Slog.i(TAG, "Identifying recents for backup: " + N);
-            }
-            for (int i = 0; i < N; i++) {
-                mRecentKeys[i] = new String(RECENTS_TASK_KEY + recentFiles[i].getName());
-                mRecentFiles[i] = recentFiles[i].getAbsolutePath();
-                if (DEBUG) {
-                    Slog.i(TAG, "   " + mRecentKeys[i]);
-                }
-            }
-        } else {
-            mRecentFiles = mRecentKeys = new String[0];
-        }
-    }
-
-    /**
-     * Task-file key:  RECENTS_TASK_KEY + leaf filename
-     * Thumbnail-file key: RECENTS_IMAGE_KEY + leaf filename
-     */
-    @Override
-    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState) {
-        FileBackupHelperBase.performBackup_checked(oldState, data, newState,
-                mRecentFiles, mRecentKeys);
-    }
-
-    @Override
-    public void restoreEntity(BackupDataInputStream data) {
-        final String key = data.getKey();
-        File output = null;
-        if (key.startsWith(RECENTS_TASK_KEY)) {
-            String name = key.substring(RECENTS_TASK_KEY.length());
-            output = new File(mRestoredTasksDir, name);
-            mRestoredTasksDir.mkdirs();
-        } else if (key.startsWith(RECENTS_IMAGE_KEY)) {
-            String name = key.substring(RECENTS_IMAGE_KEY.length());
-            output = new File(mRestoredImagesDir, name);
-            mRestoredImagesDir.mkdirs();
-        }
-
-        if (output != null) {
-            if (DEBUG) {
-                Slog.i(TAG, "Restoring key='"
-                        + key + "' to " + output.getAbsolutePath());
-            }
-            mTaskFileHelper.writeFile(output, data);
-        }
-    }
-
-    @Override
-    public void writeNewStateDescription(ParcelFileDescriptor newState) {
-        mTaskFileHelper.writeNewStateDescription(newState);
-    }
-
-}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8768f40..b22b914 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -96,6 +96,14 @@
     private static final boolean VDBG = false;
 
     /**
+     * Default MAC address reported to a client that does not have the
+     * android.permission.LOCAL_MAC_ADDRESS permission.
+     *
+     * @hide
+     */
+    public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
+
+    /**
      * Sentinel error value for this class. Guaranteed to not equal any other
      * integer constant in this class. Provided as a convenience for functions
      * that require a sentinel error value, for example:
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index f18b7ac..bd45007 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -80,18 +80,12 @@
 
     /**
      * The interpolator of the underlying Animator object. By default, we don't set the interpolator
-     * on the Animator and just use its default interpolator. If the interpolator is ever set on
-     * this Animator, then we use the interpolator that it was set to.
+     * on the Animator and just use its default interpolator. If the interpolator is set to a
+     * non-null value on this Animator, then we use the interpolator that it was set to.
      */
     private TimeInterpolator mInterpolator;
 
     /**
-     * A flag indicating whether the interpolator has been set on this object. If not, we don't set
-     * the interpolator on the underlying Animator, but instead just use its default interpolator.
-     */
-    private boolean mInterpolatorSet = false;
-
-    /**
      * Listener for the lifecycle events of the underlying ValueAnimator object.
      */
     private Animator.AnimatorListener mListener = null;
@@ -338,7 +332,6 @@
      * @return This object, allowing calls to methods in this class to be chained.
      */
     public ViewPropertyAnimator setInterpolator(TimeInterpolator interpolator) {
-        mInterpolatorSet = true;
         mInterpolator = interpolator;
         return this;
     }
@@ -349,7 +342,7 @@
      * @return The timing interpolator for this animation.
      */
     public TimeInterpolator getInterpolator() {
-        if (mInterpolatorSet) {
+        if (mInterpolator != null) {
             return mInterpolator;
         } else {
             // Just return the default from ValueAnimator, since that's what we'd get if
@@ -897,7 +890,7 @@
         if (mDurationSet) {
             animator.setDuration(mDuration);
         }
-        if (mInterpolatorSet) {
+        if (mInterpolator != null) {
             animator.setInterpolator(mInterpolator);
         }
         animator.start();
diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java
index a80abce5..f485460 100644
--- a/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -16,14 +16,12 @@
 
 package com.android.server.backup;
 
-import android.app.ActivityManagerNative;
 import android.app.IWallpaperManager;
 import android.app.backup.BackupDataInput;
 import android.app.backup.BackupDataOutput;
 import android.app.backup.BackupAgentHelper;
 import android.app.backup.FullBackup;
 import android.app.backup.FullBackupDataOutput;
-import android.app.backup.RecentsBackupHelper;
 import android.app.backup.WallpaperBackupHelper;
 import android.content.Context;
 import android.os.Environment;
@@ -45,7 +43,6 @@
     // Names of the helper tags within the dataset.  Changing one of these names will
     // break the ability to restore from datasets that predate the change.
     private static final String WALLPAPER_HELPER = "wallpaper";
-    private static final String RECENTS_HELPER = "recents";
     private static final String SYNC_SETTINGS_HELPER = "account_sync_settings";
     private static final String PREFERRED_HELPER = "preferred_activities";
     private static final String NOTIFICATION_HELPER = "notifications";
@@ -92,7 +89,6 @@
             }
         }
         addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, files, keys));
-        addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
         addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
         addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -127,7 +123,6 @@
         addHelper("system_files", new WallpaperBackupHelper(this,
                 new String[] { WALLPAPER_IMAGE },
                 new String[] { WALLPAPER_IMAGE_KEY} ));
-        addHelper(RECENTS_HELPER, new RecentsBackupHelper(this));
         addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this));
         addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper());
         addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this));
@@ -200,13 +195,4 @@
             }
         }
     }
-
-    @Override
-    public void onRestoreFinished() {
-        try {
-            ActivityManagerNative.getDefault().systemBackupRestored();
-        } catch (RemoteException e) {
-            // Not possible since this code is running in the system process.
-        }
-    }
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 608d718..595f9f0 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -898,7 +898,9 @@
         android:label="@string/permlab_changeWimaxState"
         android:protectionLevel="dangerous" />
 
-    <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+    <!--@SystemApi Allows applications to the the local WiFi and Bluetooth MAC address.
+        @hide
+    -->
     <permission android:name="android.permission.SCORE_NETWORKS"
         android:protectionLevel="signature|system" />
 
@@ -2447,6 +2449,10 @@
     <permission android:name="android.permission.KILL_UID"
                 android:protectionLevel="signature" />
 
+    <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+    <permission android:name="android.permission.LOCAL_MAC_ADDRESS"
+                android:protectionLevel="signature" />
+
     <!-- The system process is explicitly the only one allowed to launch the
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd
index 2801c18..3b5fdbd 100644
--- a/docs/html/preview/index.jd
+++ b/docs/html/preview/index.jd
@@ -22,21 +22,9 @@
           Test your apps and give us feedback!
         </p>
 
-        <a class="dac-hero-cta" href="{@docRoot}preview/overview.html">
-          <span class="dac-sprite dac-auto-chevron"></span>
-          Preview Program Overview
-        </a><br>
-        <a class="dac-hero-cta" href="{@docRoot}preview/api-overview.html">
-          <span class="dac-sprite dac-auto-chevron"></span>
-          Review the API changes
-        </a><br>
         <a class="dac-hero-cta" href="{@docRoot}preview/setup-sdk.html">
           <span class="dac-sprite dac-auto-chevron"></span>
-          Set up the Preview SDK
-        </a><br>
-        <a class="dac-hero-cta" href="https://code.google.com/p/android-developer-preview/">
-          <span class="dac-sprite dac-auto-chevron"></span>
-          Report issues
+          Get started
         </a><br>
 
       </div>
@@ -55,6 +43,7 @@
     <i class="dac-sprite dac-arrow-down-gray"></i>
   </a>
 </div>
+
 <section class="dac-section dac-gray dac-small dac-invert" id="latest"><div class="wrap">
   <h2 class="norule">Latest</h2>
   <div class="resource-widget resource-flow-layout col-16"
@@ -62,22 +51,3 @@
        data-cardSizes="6x6"
        data-maxResults="3"></div>
 </div></section>
-
-<section class="dac-section dac-light"><div class="wrap">
-  <h1 class="dac-section-title">Android Data Binding</h1>
-  <div class="dac-section-subtitle">
-    A new way to manage your app's UI. 
-  </div>
-
-  <ul class="dac-section-links">
-    <li class="dac-section-link"><a href="">
-      <span class="dac-sprite dac-auto-chevron"></span>
-      Overview and Usage
-    </a></li>
-    <li class="dac-section-link"><a href="/google/play/filters.html">
-      <span class="dac-sprite dac-auto-chevron"></span>
-      User Guide
-    </a></li>
-
-  </ul>
-</div></section>
\ No newline at end of file
diff --git a/docs/html/tools/devices/index.jd b/docs/html/tools/devices/index.jd
index 1ea4c47..6263c8b 100644
--- a/docs/html/tools/devices/index.jd
+++ b/docs/html/tools/devices/index.jd
@@ -5,16 +5,16 @@
  <p>An Android Virtual Device (AVD) is an emulator configuration that lets you model an actual
   device by defining hardware and software options to be emulated by the Android Emulator.</p>
 
-  <p>The easiest way to create an AVD is to use the graphical <a href= 
-  "{@docRoot}tools/devices/managing-avds.html">AVD Manager</a>, which you launch
-  from Eclipse by clicking <strong>Window &gt; AVD Manager</strong>. You can also start the AVD
-Manager from the command line by calling the <code>android</code> tool with the <code>avd</code>
-options, from the <strong>&lt;sdk>/tools/</strong> directory.</p>
+  <p>The easiest way to create an AVD is to use the graphical
+  <a href="{@docRoot}tools/devices/managing-avds.html">AVD Manager</a>, which you launch
+  from Android Studio by clicking <strong>Tools &gt; Android &gt; AVD Manager</strong>. You can
+  also start the AVD Manager from the command line by calling the <code>android</code> tool with
+ the <code>avd</code> options, from the <strong>&lt;sdk>/tools/</strong> directory.</p>
 
   <p>You can also create AVDs on the command line by passing the <code>android</code> tool options.
-  For more information on how to create AVDs in this manner, see <a href= 
-  "{@docRoot}tools/devices/managing-avds-cmdline.html">Managing Virtual
-  Devices from the Command Line</a>.</p>
+  For more information on how to create AVDs in this manner, see
+  <a href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing Virtual Devices from the
+  Command Line</a>.</p>
 
   <p>An AVD consists of:</p>
 
diff --git a/docs/html/tools/devices/managing-avds-cmdline.jd b/docs/html/tools/devices/managing-avds-cmdline.jd
index ba353c1..c16b1f8 100644
--- a/docs/html/tools/devices/managing-avds-cmdline.jd
+++ b/docs/html/tools/devices/managing-avds-cmdline.jd
@@ -84,8 +84,8 @@
 
 <h2 id="AVDCmdLine">Creating AVDs</h2>
 
-<p>In addition to creating AVDs with the 
-<a href="{@docRoot}tools/devices/managing-avds-cmdline.html">AVD Manager user interface</a>,
+<p>In addition to creating AVDs with the
+<a href="{@docRoot}tools/help/avd-manager.html">AVD Manager user interface</a>,
 you can also create them by passing in command line arguments to the <code>android</code> tool.
 </p>
 
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index ea60040..28c26ff 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -19,7 +19,6 @@
 import android.animation.AnimatorSet;
 import android.animation.Animator.AnimatorListener;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -128,19 +127,13 @@
  * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation
  */
 public class AnimatedVectorDrawable extends Drawable implements Animatable {
-    private static final String LOGTAG = "AnimatedVectorDrawable";
+    private static final String LOGTAG = AnimatedVectorDrawable.class.getSimpleName();
 
     private static final String ANIMATED_VECTOR = "animated-vector";
     private static final String TARGET = "target";
 
     private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false;
 
-    /**
-     * The resources against which this drawable was created. Used to attempt
-     * to inflate animators if applyTheme() doesn't get called.
-     */
-    private Resources mRes;
-
     private AnimatedVectorDrawableState mAnimatedVectorState;
 
     private boolean mMutated;
@@ -151,7 +144,6 @@
 
     private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res) {
         mAnimatedVectorState = new AnimatedVectorDrawableState(state, mCallback, res);
-        mRes = res;
     }
 
     @Override
@@ -281,7 +273,6 @@
     @Override
     public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-        final AnimatedVectorDrawableState state = mAnimatedVectorState;
 
         int eventType = parser.getEventType();
         float pathErrorScale = 1;
@@ -299,10 +290,10 @@
                         vectorDrawable.setAllowCaching(false);
                         vectorDrawable.setCallback(mCallback);
                         pathErrorScale = vectorDrawable.getPixelSize();
-                        if (state.mVectorDrawable != null) {
-                            state.mVectorDrawable.setCallback(null);
+                        if (mAnimatedVectorState.mVectorDrawable != null) {
+                            mAnimatedVectorState.mVectorDrawable.setCallback(null);
                         }
-                        state.mVectorDrawable = vectorDrawable;
+                        mAnimatedVectorState.mVectorDrawable = vectorDrawable;
                     }
                     a.recycle();
                 } else if (TARGET.equals(tagName)) {
@@ -311,25 +302,12 @@
                     final String target = a.getString(
                             R.styleable.AnimatedVectorDrawableTarget_name);
 
-                    final int animResId = a.getResourceId(
+                    int id = a.getResourceId(
                             R.styleable.AnimatedVectorDrawableTarget_animation, 0);
-                    if (animResId != 0) {
-                        if (theme != null) {
-                            final Animator objectAnimator = AnimatorInflater.loadAnimator(
-                                    res, theme, animResId, pathErrorScale);
-                            setupAnimatorsForTarget(target, objectAnimator);
-                        } else {
-                            // The animation may be theme-dependent. As a
-                            // workaround until Animator has full support for
-                            // applyTheme(), postpone loading the animator
-                            // until we have a theme in applyTheme().
-                            if (state.mPendingAnims == null) {
-                                state.mPendingAnims = new ArrayList<>(1);
-                            }
-                            state.mPendingAnims.add(
-                                    new PendingAnimator(animResId, pathErrorScale, target));
-
-                        }
+                    if (id != 0) {
+                        Animator objectAnimator = AnimatorInflater.loadAnimator(res, theme, id,
+                                pathErrorScale);
+                        setupAnimatorsForTarget(target, objectAnimator);
                     }
                     a.recycle();
                 }
@@ -337,13 +315,6 @@
 
             eventType = parser.next();
         }
-
-        // If we don't have any pending animations, we don't need to hold a
-        // reference to the resources.
-        if (state.mPendingAnims == null) {
-            mRes = null;
-        }
-
         setupAnimatorSet();
     }
 
@@ -369,29 +340,6 @@
         if (vectorDrawable != null && vectorDrawable.canApplyTheme()) {
             vectorDrawable.applyTheme(t);
         }
-
-        if (t != null) {
-            inflatePendingAnimators(t.getResources(), t);
-        }
-    }
-
-    /**
-     * Inflates pending animators, if any, against a theme. Clears the list of
-     * pending animators.
-     *
-     * @param t the theme against which to inflate the animators
-     */
-    private void inflatePendingAnimators(@NonNull Resources res, @Nullable Theme t) {
-        final ArrayList<PendingAnimator> pendingAnims = mAnimatedVectorState.mPendingAnims;
-        if (pendingAnims != null) {
-            mAnimatedVectorState.mPendingAnims = null;
-
-            for (int i = 0, count = pendingAnims.size(); i < count; i++) {
-                final PendingAnimator pendingAnimator = pendingAnims.get(i);
-                final Animator objectAnimator = pendingAnimator.newInstance(res, t);
-                setupAnimatorsForTarget(pendingAnimator.target, objectAnimator);
-            }
-        }
     }
 
     /**
@@ -433,7 +381,6 @@
         // we add this array into the mAnimatorSet.
         private ArrayList<Animator> mTempAnimators;
         ArrayMap<Animator, String> mTargetNameMap;
-        ArrayList<PendingAnimator> mPendingAnims;
 
         public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy,
                 Callback owner, Resources res) {
@@ -456,7 +403,7 @@
                     final int numAnimators = copy.mTargetNameMap.size();
                     // Deep copy a animator set, and then setup the target map again.
                     mAnimatorSet = copy.mAnimatorSet.clone();
-                    mTargetNameMap = new ArrayMap<>(numAnimators);
+                    mTargetNameMap = new ArrayMap<Animator, String>(numAnimators);
                     // Since the new AnimatorSet is cloned from the old one, the order must be the
                     // same inside the array.
                     ArrayList<Animator> oldAnim = copy.mAnimatorSet.getChildAnimations();
@@ -471,9 +418,6 @@
                         mTargetNameMap.put(newAnim.get(i), targetName);
                     }
                 }
-
-                // Shallow copy since the array is immutable after inflate().
-                mPendingAnims = copy.mPendingAnims;
             } else {
                 mVectorDrawable = new VectorDrawable();
             }
@@ -482,7 +426,7 @@
         @Override
         public boolean canApplyTheme() {
             return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
-                    || mPendingAnims != null || super.canApplyTheme();
+                    || super.canApplyTheme();
         }
 
         @Override
@@ -501,32 +445,12 @@
         }
     }
 
-    /**
-     * Basically a constant state for Animators until we actually implement
-     * constant states for Animators.
-     */
-    private static class PendingAnimator {
-        public final int animResId;
-        public final float pathErrorScale;
-        public final String target;
-
-        public PendingAnimator(int animResId, float pathErrorScale, String target) {
-            this.animResId = animResId;
-            this.pathErrorScale = pathErrorScale;
-            this.target = target;
-        }
-
-        public Animator newInstance(Resources res, Theme theme) {
-            return AnimatorInflater.loadAnimator(res, theme, animResId, pathErrorScale);
-        }
-    }
-
     private void setupAnimatorsForTarget(String name, Animator animator) {
         Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name);
         animator.setTarget(target);
         if (mAnimatedVectorState.mTempAnimators == null) {
-            mAnimatedVectorState.mTempAnimators = new ArrayList<>();
-            mAnimatedVectorState.mTargetNameMap = new ArrayMap<>();
+            mAnimatedVectorState.mTempAnimators = new ArrayList<Animator>();
+            mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>();
         }
         mAnimatedVectorState.mTempAnimators.add(animator);
         mAnimatedVectorState.mTargetNameMap.put(animator, name);
@@ -550,23 +474,6 @@
         if (isStarted()) {
             return;
         }
-
-        // Check for uninflated animators. We can remove this after we add
-        // support for Animator.applyTheme(). See comments in inflate().
-        if (mAnimatedVectorState.mPendingAnims != null) {
-            // Attempt to load animators without applying a theme.
-            if (mRes != null) {
-                inflatePendingAnimators(mRes, null);
-                mRes = null;
-            } else {
-                Log.e(LOGTAG, "Failed to load animators. Either the AnimatedVectorDrawable must be"
-                        + " created using a Resources object or applyTheme() must be called with"
-                        + " a non-null Theme object.");
-            }
-
-            mAnimatedVectorState.mPendingAnims = null;
-        }
-
         mAnimatedVectorState.mAnimatorSet.start();
         invalidateSelf();
     }
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 161a7ba7..d21762b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -192,13 +192,20 @@
 
     /**
      * The write mode indicating the write operation will block until all data has been written,
-     * to be used in {@link #write(ByteBuffer, int, int)}
+     * to be used as the actual value of the writeMode parameter in
+     * {@link #write(byte[], int, int, int)}, {@link #write(short[], int, int, int)},
+     * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and
+     * {@link #write(ByteBuffer, int, int, long)}.
      */
     public final static int WRITE_BLOCKING = 0;
+
     /**
      * The write mode indicating the write operation will return immediately after
-     * queuing as much audio data for playback as possible without blocking, to be used in
-     * {@link #write(ByteBuffer, int, int)}.
+     * queuing as much audio data for playback as possible without blocking,
+     * to be used as the actual value of the writeMode parameter in
+     * {@link #write(ByteBuffer, int, int)}, {@link #write(short[], int, int, int)},
+     * {@link #write(float[], int, int, int)}, {@link #write(ByteBuffer, int, int)}, and
+     * {@link #write(ByteBuffer, int, int, long)}.
      */
     public final static int WRITE_NON_BLOCKING = 1;
 
@@ -1458,14 +1465,27 @@
     //--------------------
     /**
      * Starts playing an AudioTrack.
+     * <p>
      * If track's creation mode is {@link #MODE_STATIC}, you must have called one of
-     * the {@link #write(byte[], int, int)}, {@link #write(short[], int, int)},
-     * or {@link #write(float[], int, int, int)} methods.
-     * If the mode is {@link #MODE_STREAM}, you can optionally prime the
-     * output buffer by writing up to bufferSizeInBytes (from constructor) before starting.
-     * This priming will avoid an immediate underrun, but is not required.
+     * the write methods ({@link #write(byte[], int, int)}, {@link #write(byte[], int, int, int)},
+     * {@link #write(short[], int, int)}, {@link #write(short[], int, int, int)},
+     * {@link #write(float[], int, int, int)}, or {@link #write(ByteBuffer, int, int)}) prior to
+     * play().
+     * <p>
+     * If the mode is {@link #MODE_STREAM}, you can optionally prime the data path prior to
+     * calling play(), by writing up to <code>bufferSizeInBytes</code> (from constructor).
+     * If you don’t call write() first, or if you call write() but with an insufficient amount of
+     * data, then the track will be in underrun state at play().  In this case,
+     * playback will not actually start playing until the data path is filled to a
+     * device-specific minimum level.  This requirement for the path to be filled
+     * to a minimum level is also true when resuming audio playback after calling stop().
+     * Similarly the buffer will need to be filled up again after
+     * the track underruns due to failure to call write() in a timely manner with sufficient data.
+     * For portability, an application should prime the data path to the maximum allowed
+     * by writing data until the write() method returns a short transfer count.
+     * This allows play() to start immediately, and reduces the chance of underrun.
      *
-     * @throws IllegalStateException
+     * @throws IllegalStateException if the track isn't properly initialized
      */
     public void play()
     throws IllegalStateException {
@@ -1570,21 +1590,30 @@
      * or copies audio data for later playback (static buffer mode).
      * The format specified in the AudioTrack constructor should be
      * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
-     * In streaming mode, will block until all data has been written to the audio sink.
+     * <p>
+     * In streaming mode, the write will normally block until all the data has been enqueued for
+     * playback, and will return a full transfer count.  However, if the track is stopped or paused
+     * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error
+     * occurs during the write, then the write may return a short transfer count.
+     * <p>
      * In static buffer mode, copies the data to the buffer starting at offset 0.
-     * Note that the actual playback of this data might occur after this function
-     * returns. This function is thread safe with respect to {@link #stop} calls,
-     * in which case all of the specified data might not be written to the audio sink.
+     * Note that the actual playback of this data might occur after this function returns.
      *
      * @param audioData the array that holds the data to play.
      * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
      *    starts.
      * @param sizeInBytes the number of bytes to read in audioData after the offset.
-     * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     * @return zero or the positive number of bytes that were written, or
+     *    {@link #ERROR_INVALID_OPERATION}
+     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
      *    the parameters don't resolve to valid data and indexes, or
      *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *    needs to be recreated.
+     *    The dead object error code is not returned if some data was successfully transferred.
+     *    In this case, the error is returned at the next write().
+     *
+     * This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code>
+     * set to  {@link #WRITE_BLOCKING}.
      */
     public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
         return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING);
@@ -1595,11 +1624,17 @@
      * or copies audio data for later playback (static buffer mode).
      * The format specified in the AudioTrack constructor should be
      * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
-     * In streaming mode, will block until all data has been written to the audio sink.
-     * In static buffer mode, copies the data to the buffer starting at offset 0.
-     * Note that the actual playback of this data might occur after this function
-     * returns. This function is thread safe with respect to {@link #stop} calls,
-     * in which case all of the specified data might not be written to the audio sink.
+     * <p>
+     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
+     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+     * for playback, and will return a full transfer count.  However, if the write mode is
+     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+     * interrupts the write by calling stop or pause, or an I/O error
+     * occurs during the write, then the write may return a short transfer count.
+     * <p>
+     * In static buffer mode, copies the data to the buffer starting at offset 0,
+     * and the write mode is ignored.
+     * Note that the actual playback of this data might occur after this function returns.
      *
      * @param audioData the array that holds the data to play.
      * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
@@ -1611,11 +1646,14 @@
      *         to the audio sink.
      *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     * @return zero or the positive number of bytes that were written, or
+     *    {@link #ERROR_INVALID_OPERATION}
+     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
      *    the parameters don't resolve to valid data and indexes, or
      *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *    needs to be recreated.
+     *    The dead object error code is not returned if some data was successfully transferred.
+     *    In this case, the error is returned at the next write().
      */
     public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
             @WriteMode int writeMode) {
@@ -1653,21 +1691,30 @@
      * or copies audio data for later playback (static buffer mode).
      * The format specified in the AudioTrack constructor should be
      * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
-     * In streaming mode, will block until all data has been written to the audio sink.
+     * <p>
+     * In streaming mode, the write will normally block until all the data has been enqueued for
+     * playback, and will return a full transfer count.  However, if the track is stopped or paused
+     * on entry, or another thread interrupts the write by calling stop or pause, or an I/O error
+     * occurs during the write, then the write may return a short transfer count.
+     * <p>
      * In static buffer mode, copies the data to the buffer starting at offset 0.
-     * Note that the actual playback of this data might occur after this function
-     * returns. This function is thread safe with respect to {@link #stop} calls,
-     * in which case all of the specified data might not be written to the audio sink.
+     * Note that the actual playback of this data might occur after this function returns.
      *
      * @param audioData the array that holds the data to play.
      * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
      *     starts.
      * @param sizeInShorts the number of shorts to read in audioData after the offset.
-     * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     * @return zero or the positive number of shorts that were written, or
+     *    {@link #ERROR_INVALID_OPERATION}
+     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
      *    the parameters don't resolve to valid data and indexes, or
      *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *    needs to be recreated.
+     *    The dead object error code is not returned if some data was successfully transferred.
+     *    In this case, the error is returned at the next write().
+     *
+     * This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code>
+     * set to  {@link #WRITE_BLOCKING}.
      */
     public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
         return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING);
@@ -1678,11 +1725,16 @@
      * or copies audio data for later playback (static buffer mode).
      * The format specified in the AudioTrack constructor should be
      * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
-     * In streaming mode, will block until all data has been written to the audio sink.
+     * <p>
+     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
+     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+     * for playback, and will return a full transfer count.  However, if the write mode is
+     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+     * interrupts the write by calling stop or pause, or an I/O error
+     * occurs during the write, then the write may return a short transfer count.
+     * <p>
      * In static buffer mode, copies the data to the buffer starting at offset 0.
-     * Note that the actual playback of this data might occur after this function
-     * returns. This function is thread safe with respect to {@link #stop} calls,
-     * in which case all of the specified data might not be written to the audio sink.
+     * Note that the actual playback of this data might occur after this function returns.
      *
      * @param audioData the array that holds the data to play.
      * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
@@ -1694,11 +1746,14 @@
      *         to the audio sink.
      *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     * @return zero or the positive number of shorts that were written, or
+     *    {@link #ERROR_INVALID_OPERATION}
+     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
      *    the parameters don't resolve to valid data and indexes, or
      *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *    needs to be recreated.
+     *    The dead object error code is not returned if some data was successfully transferred.
+     *    In this case, the error is returned at the next write().
      */
     public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
             @WriteMode int writeMode) {
@@ -1736,14 +1791,18 @@
      * or copies audio data for later playback (static buffer mode).
      * The format specified in the AudioTrack constructor should be
      * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array.
+     * <p>
+     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
+     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+     * for playback, and will return a full transfer count.  However, if the write mode is
+     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+     * interrupts the write by calling stop or pause, or an I/O error
+     * occurs during the write, then the write may return a short transfer count.
+     * <p>
      * In static buffer mode, copies the data to the buffer starting at offset 0,
      * and the write mode is ignored.
-     * In streaming mode, the blocking behavior will depend on the write mode.
-     * <p>
-     * Note that the actual playback of this data might occur after this function
-     * returns. This function is thread safe with respect to {@link #stop} calls,
-     * in which case all of the specified data might not be written to the audio sink.
-     * <p>
+     * Note that the actual playback of this data might occur after this function returns.
+     *
      * @param audioData the array that holds the data to play.
      *     The implementation does not clip for sample values within the nominal range
      *     [-1.0f, 1.0f], provided that all gains in the audio pipeline are
@@ -1763,11 +1822,14 @@
      *         to the audio sink.
      *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+     * @return zero or the positive number of floats that were written, or
+     *    {@link #ERROR_INVALID_OPERATION}
+     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
      *    the parameters don't resolve to valid data and indexes, or
      *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *    needs to be recreated.
+     *    The dead object error code is not returned if some data was successfully transferred.
+     *    In this case, the error is returned at the next write().
      */
     public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
             @WriteMode int writeMode) {
@@ -1811,9 +1873,19 @@
     /**
      * Writes the audio data to the audio sink for playback (streaming mode),
      * or copies audio data for later playback (static buffer mode).
-     * In static buffer mode, copies the data to the buffer starting at its 0 offset, and the write
-     * mode is ignored.
-     * In streaming mode, the blocking behavior will depend on the write mode.
+     * The audioData in ByteBuffer should match the format specified in the AudioTrack constructor.
+     * <p>
+     * In streaming mode, the blocking behavior depends on the write mode.  If the write mode is
+     * {@link #WRITE_BLOCKING}, the write will normally block until all the data has been enqueued
+     * for playback, and will return a full transfer count.  However, if the write mode is
+     * {@link #WRITE_NON_BLOCKING}, or the track is stopped or paused on entry, or another thread
+     * interrupts the write by calling stop or pause, or an I/O error
+     * occurs during the write, then the write may return a short transfer count.
+     * <p>
+     * In static buffer mode, copies the data to the buffer starting at offset 0,
+     * and the write mode is ignored.
+     * Note that the actual playback of this data might occur after this function returns.
+     *
      * @param audioData the buffer that holds the data to play, starting at the position reported
      *     by <code>audioData.position()</code>.
      *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
@@ -1827,10 +1899,12 @@
      *         to the audio sink.
      *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return 0 or a positive number of bytes that were written, or
+     * @return zero or the positive number of bytes that were written, or
      *     {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
      *     {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *     needs to be recreated.
+     *     The dead object error code is not returned if some data was successfully transferred.
+     *     In this case, the error is returned at the next write().
      */
     public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
             @WriteMode int writeMode) {
@@ -1877,8 +1951,8 @@
     }
 
     /**
-     * Writes the audio data to the audio sink for playback (streaming mode) on a HW_AV_SYNC track.
-     * In streaming mode, the blocking behavior will depend on the write mode.
+     * Writes the audio data to the audio sink for playback in streaming mode on a HW_AV_SYNC track.
+     * The blocking behavior will depend on the write mode.
      * @param audioData the buffer that holds the data to play, starting at the position reported
      *     by <code>audioData.position()</code>.
      *     <BR>Note that upon return, the buffer position (<code>audioData.position()</code>) will
@@ -1892,10 +1966,12 @@
      *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
      * @param timestamp The timestamp of the first decodable audio frame in the provided audioData.
-     * @return 0 or a positive number of bytes that were written, or
+     * @return zero or a positive number of bytes that were written, or
      *     {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
      *     {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
      *     needs to be recreated.
+     *     The dead object error code is not returned if some data was successfully transferred.
+     *     In this case, the error is returned at the next write().
      */
     public int write(ByteBuffer audioData, int sizeInBytes,
             @WriteMode int writeMode, long timestamp) {
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 1cabcdfc..e03f449 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -16,6 +16,7 @@
 
 package com.android.keyguard;
 
+import android.app.ActivityOptions;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -42,7 +43,7 @@
             .setPackage("com.android.phone")
             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                     | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                    | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
     KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
 
@@ -127,6 +128,7 @@
             KeyguardUpdateMonitor.getInstance(mContext).reportEmergencyCallAction(
                     true /* bypassHandler */);
             getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
+                    ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
                     new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 17e2cb5..3feec9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -59,6 +59,12 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int ownMaxHeight = mMaxViewHeight;
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
+        if (hasFixedHeight) {
+            // We have a height set in our layout, so we want to be at most as big as given
+            ownMaxHeight = Math.min(MeasureSpec.getSize(heightMeasureSpec), ownMaxHeight);
+        }
         int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
         int maxChildHeight = 0;
         int childCount = getChildCount();
@@ -85,7 +91,7 @@
                 mMatchParentViews.add(child);
             }
         }
-        int ownHeight = Math.min(ownMaxHeight, maxChildHeight);
+        int ownHeight = hasFixedHeight ? ownMaxHeight : Math.min(ownMaxHeight, maxChildHeight);
         newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
         for (View child : mMatchParentViews) {
             child.measure(getChildMeasureSpec(
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f5d27f9..c46fa76 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.Manifest;
 import android.app.ActivityManager;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
@@ -909,16 +910,22 @@
             mCallbacks.finishBroadcast();
         }
     }
+
     public String getAddress() {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM,
-                                                "Need BLUETOOTH permission");
+                "Need BLUETOOTH permission");
 
         if ((Binder.getCallingUid() != Process.SYSTEM_UID) &&
-            (!checkIfCallerIsForegroundUser())) {
+                (!checkIfCallerIsForegroundUser())) {
             Log.w(TAG,"getAddress(): not allowed for non-active and non system user");
             return null;
         }
 
+        if (mContext.checkCallingOrSelfPermission(Manifest.permission.LOCAL_MAC_ADDRESS)
+                != PackageManager.PERMISSION_GRANTED) {
+            return BluetoothAdapter.DEFAULT_MAC_ADDRESS;
+        }
+
         synchronized(mConnection) {
             if (mBluetooth != null) {
                 try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a8ab667..2d74618 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6164,17 +6164,6 @@
         }
     }
 
-    @Override
-    public void systemBackupRestored() {
-        synchronized (this) {
-            if (mSystemReady) {
-                mTaskPersister.restoreTasksFromOtherDeviceLocked();
-            } else {
-                Slog.w(TAG, "System backup restored before system is ready");
-            }
-        }
-    }
-
     final void ensureBootCompleted() {
         boolean booting;
         boolean enableScreen;
@@ -11327,7 +11316,6 @@
 
             mRecentTasks.clear();
             mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
-            mTaskPersister.restoreTasksFromOtherDeviceLocked();
             mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
             mTaskPersister.startPersisting();
 
@@ -16191,18 +16179,12 @@
                                         removeUriPermissionsForPackageLocked(ssp, userId, true);
 
                                         removeTasksByPackageNameLocked(ssp, userId);
-                                        if (userId == UserHandle.USER_OWNER) {
-                                            mTaskPersister.removeFromPackageCache(ssp);
-                                        }
                                         mBatteryStatsService.notePackageUninstalled(ssp);
                                     }
                                 } else {
                                     cleanupDisabledPackageComponentsLocked(ssp, userId,
                                             intent.getStringArrayExtra(
                                                     Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
-                                    if (userId == UserHandle.USER_OWNER) {
-                                        mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
-                                    }
                                 }
                             }
                             break;
@@ -16217,9 +16199,6 @@
                                 intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
                         mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
 
-                        if (userId == UserHandle.USER_OWNER) {
-                            mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp);
-                        }
                         try {
                             ApplicationInfo ai = AppGlobals.getPackageManager().
                                     getApplicationInfo(ssp, 0, 0);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index f3b18f5..ca1fd6a 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,8 +17,6 @@
 package com.android.server.am;
 
 import static com.android.server.am.ActivityManagerDebugConfig.*;
-import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
-import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
 
 import android.app.ActivityManager.TaskDescription;
@@ -85,7 +83,7 @@
     private static final String ATTR_USERID = "user_id";
     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
-    static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
+    private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
@@ -94,7 +92,7 @@
     final IApplicationToken.Stub appToken; // window manager token
     final ActivityInfo info; // all about me
     final ApplicationInfo appInfo; // information about activity's app
-    int launchedFromUid; // always the uid who started the activity.
+    final int launchedFromUid; // always the uid who started the activity.
     final String launchedFromPackage; // always the package who started the activity.
     final int userId;          // Which user is this running for?
     final Intent intent;    // the original intent that generated us
@@ -1178,8 +1176,8 @@
         }
     }
 
-    static ActivityRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
-            throws IOException, XmlPullParserException {
+    static ActivityRecord restoreFromXml(XmlPullParser in,
+            ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
         Intent intent = null;
         PersistableBundle persistentState = null;
         int launchedFromUid = 0;
@@ -1194,7 +1192,7 @@
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
             final String attrValue = in.getAttributeValue(attrNdx);
-            if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
+            if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
             if (ATTR_ID.equals(attrName)) {
                 createTime = Long.valueOf(attrValue);
@@ -1220,15 +1218,15 @@
                 (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
             if (event == XmlPullParser.START_TAG) {
                 final String name = in.getName();
-                if (DEBUG_PERSISTER || DEBUG_RESTORER)
+                if (TaskPersister.DEBUG)
                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
                 if (TAG_INTENT.equals(name)) {
                     intent = Intent.restoreFromXml(in);
-                    if (DEBUG_PERSISTER || DEBUG_RESTORER)
+                    if (TaskPersister.DEBUG)
                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
                     persistentState = PersistableBundle.restoreFromXml(in);
-                    if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
+                    if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
                             "ActivityRecord: persistentState=" + persistentState);
                 } else {
                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 318cd45..ef1559a 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -59,8 +59,7 @@
 
 public class TaskPersister {
     static final String TAG = "TaskPersister";
-    static final boolean DEBUG_PERSISTER = false;
-    static final boolean DEBUG_RESTORER = false;
+    static final boolean DEBUG = false;
 
     /** When not flushing don't write out files faster than this */
     private static final long INTER_WRITE_DELAY_MS = 500;
@@ -81,21 +80,10 @@
     private static final String IMAGES_DIRNAME = "recent_images";
     static final String IMAGE_EXTENSION = ".png";
 
-    // Directory where restored historical task XML/PNG files are placed.  This directory
-    // contains subdirs named after TASKS_DIRNAME and IMAGES_DIRNAME mirroring the
-    // ancestral device's dataset.  This needs to match the RECENTS_TASK_RESTORE_DIR
-    // value in RecentsBackupHelper.
-    private static final String RESTORED_TASKS_DIRNAME = "restored_" + TASKS_DIRNAME;
-
-    // Max time to wait for the application/package of a restored task to be installed
-    // before giving up.
-    private static final long MAX_INSTALL_WAIT_TIME = DateUtils.DAY_IN_MILLIS;
-
     private static final String TAG_TASK = "task";
 
     static File sImagesDir;
     static File sTasksDir;
-    static File sRestoredTasksDir;
 
     private final ActivityManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
@@ -129,23 +117,11 @@
 
     ArrayList<WriteQueueItem> mWriteQueue = new ArrayList<WriteQueueItem>();
 
-    // Map of tasks that were backed-up on a different device that can be restored on this device.
-    // Data organization: <packageNameOfAffiliateTask, listOfAffiliatedTasksChains>
-    private ArrayMap<String, List<List<OtherDeviceTask>>> mOtherDeviceTasksMap =
-                new ArrayMap<>(10);
-    // Local cache of package names to uid used when restoring a task from another device.
-    private ArrayMap<String, Integer> mPackageUidMap;
-
-    // The next time in milliseconds we will remove expired task from
-    // {@link #mOtherDeviceTasksMap} and disk. Set to {@link Long.MAX_VALUE} to never clean-up
-    // tasks.
-    private long mExpiredTasksCleanupTime = Long.MAX_VALUE;
-
     TaskPersister(File systemDir, ActivityStackSupervisor stackSupervisor,
             RecentTasks recentTasks) {
         sTasksDir = new File(systemDir, TASKS_DIRNAME);
         if (!sTasksDir.exists()) {
-            if (DEBUG_PERSISTER) Slog.d(TAG, "Creating tasks directory " + sTasksDir);
+            if (DEBUG) Slog.d(TAG, "Creating tasks directory " + sTasksDir);
             if (!sTasksDir.mkdir()) {
                 Slog.e(TAG, "Failure creating tasks directory " + sTasksDir);
             }
@@ -153,14 +129,12 @@
 
         sImagesDir = new File(systemDir, IMAGES_DIRNAME);
         if (!sImagesDir.exists()) {
-            if (DEBUG_PERSISTER) Slog.d(TAG, "Creating images directory " + sTasksDir);
+            if (DEBUG) Slog.d(TAG, "Creating images directory " + sTasksDir);
             if (!sImagesDir.mkdir()) {
                 Slog.e(TAG, "Failure creating images directory " + sImagesDir);
             }
         }
 
-        sRestoredTasksDir = new File(systemDir, RESTORED_TASKS_DIRNAME);
-
         mStackSupervisor = stackSupervisor;
         mService = stackSupervisor.mService;
         mRecentTasks = recentTasks;
@@ -179,8 +153,8 @@
             final WriteQueueItem item = mWriteQueue.get(queueNdx);
             if (item instanceof ImageWriteQueueItem &&
                     ((ImageWriteQueueItem) item).mFilename.startsWith(taskString)) {
-                if (DEBUG_PERSISTER) Slog.d(TAG, "Removing "
-                        + ((ImageWriteQueueItem) item).mFilename + " from write queue");
+                if (DEBUG) Slog.d(TAG, "Removing " + ((ImageWriteQueueItem) item).mFilename +
+                        " from write queue");
                 mWriteQueue.remove(queueNdx);
             }
         }
@@ -225,9 +199,9 @@
             } else if (mNextWriteTime == 0) {
                 mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
             }
-            if (DEBUG_PERSISTER) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush
-                    + " mNextWriteTime=" + mNextWriteTime + " mWriteQueue.size="
-                    + mWriteQueue.size() + " Callers=" + Debug.getCallers(4));
+            if (DEBUG) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush + " mNextWriteTime="
+                    + mNextWriteTime + " mWriteQueue.size=" + mWriteQueue.size()
+                    + " Callers=" + Debug.getCallers(4));
             notifyAll();
         }
 
@@ -269,7 +243,7 @@
             } else if (mNextWriteTime == 0) {
                 mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
             }
-            if (DEBUG_PERSISTER) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
+            if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
                     SystemClock.uptimeMillis() + " mNextWriteTime=" +
                     mNextWriteTime + " Callers=" + Debug.getCallers(4));
             notifyAll();
@@ -303,12 +277,12 @@
     }
 
     private StringWriter saveToXml(TaskRecord task) throws IOException, XmlPullParserException {
-        if (DEBUG_PERSISTER) Slog.d(TAG, "saveToXml: task=" + task);
+        if (DEBUG) Slog.d(TAG, "saveToXml: task=" + task);
         final XmlSerializer xmlSerializer = new FastXmlSerializer();
         StringWriter stringWriter = new StringWriter();
         xmlSerializer.setOutput(stringWriter);
 
-        if (DEBUG_PERSISTER) xmlSerializer.setFeature(
+        if (DEBUG) xmlSerializer.setFeature(
                     "http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
         // save task
@@ -367,7 +341,7 @@
 
         for (int taskNdx = 0; taskNdx < recentFiles.length; ++taskNdx) {
             File taskFile = recentFiles[taskNdx];
-            if (DEBUG_PERSISTER) Slog.d(TAG, "restoreTasksLocked: taskFile=" + taskFile.getName());
+            if (DEBUG) Slog.d(TAG, "restoreTasksLocked: taskFile=" + taskFile.getName());
             BufferedReader reader = null;
             boolean deleteFile = false;
             try {
@@ -380,12 +354,11 @@
                         event != XmlPullParser.END_TAG) {
                     final String name = in.getName();
                     if (event == XmlPullParser.START_TAG) {
-                        if (DEBUG_PERSISTER)
-                                Slog.d(TAG, "restoreTasksLocked: START_TAG name=" + name);
+                        if (DEBUG) Slog.d(TAG, "restoreTasksLocked: START_TAG name=" + name);
                         if (TAG_TASK.equals(name)) {
                             final TaskRecord task =
                                     TaskRecord.restoreFromXml(in, mStackSupervisor);
-                            if (DEBUG_PERSISTER) Slog.d(TAG, "restoreTasksLocked: restored task=" +
+                            if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
                                     task);
                             if (task != null) {
                                 task.isPersistable = true;
@@ -414,15 +387,14 @@
                 deleteFile = true;
             } finally {
                 IoUtils.closeQuietly(reader);
-                if (!DEBUG_PERSISTER && deleteFile) {
-                    if (true || DEBUG_PERSISTER)
-                            Slog.d(TAG, "Deleting file=" + taskFile.getName());
+                if (deleteFile) {
+                    if (DEBUG) Slog.d(TAG, "Deleting file=" + taskFile.getName());
                     taskFile.delete();
                 }
             }
         }
 
-        if (!DEBUG_PERSISTER) {
+        if (!DEBUG) {
             removeObsoleteFiles(recoveredTaskIds);
         }
 
@@ -453,8 +425,8 @@
     }
 
     private static void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, File[] files) {
-        if (DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds="
-                    + persistentTaskIds + " files=" + files);
+        if (DEBUG) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds=" + persistentTaskIds +
+                " files=" + files);
         if (files == null) {
             Slog.e(TAG, "File error accessing recents directory (too many files open?).");
             return;
@@ -467,15 +439,14 @@
                 final int taskId;
                 try {
                     taskId = Integer.valueOf(filename.substring(0, taskIdEnd));
-                    if (DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
+                    if (DEBUG) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
                 } catch (Exception e) {
                     Slog.wtf(TAG, "removeObsoleteFile: Can't parse file=" + file.getName());
                     file.delete();
                     continue;
                 }
                 if (!persistentTaskIds.contains(taskId)) {
-                    if (true || DEBUG_PERSISTER) Slog.d(TAG, "removeObsoleteFile: deleting file=" +
-                            file.getName());
+                    if (DEBUG) Slog.d(TAG, "removeObsoleteFile: deleting file=" + file.getName());
                     file.delete();
                 }
             }
@@ -488,441 +459,10 @@
     }
 
     static Bitmap restoreImage(String filename) {
-        if (DEBUG_PERSISTER) Slog.d(TAG, "restoreImage: restoring " + filename);
+        if (DEBUG) Slog.d(TAG, "restoreImage: restoring " + filename);
         return BitmapFactory.decodeFile(sImagesDir + File.separator + filename);
     }
 
-    /**
-     * Tries to restore task that were backed-up on a different device onto this device.
-     */
-    void restoreTasksFromOtherDeviceLocked() {
-        readOtherDeviceTasksFromDisk();
-        addOtherDeviceTasksToRecentsLocked();
-    }
-
-    /**
-     * Read the tasks that were backed-up on a different device and can be restored to this device
-     * from disk and populated {@link #mOtherDeviceTasksMap} with the information. Also sets up
-     * time to clear out other device tasks that have not been restored on this device
-     * within the allotted time.
-     */
-    private void readOtherDeviceTasksFromDisk() {
-        synchronized (mOtherDeviceTasksMap) {
-            // Clear out current map and expiration time.
-            mOtherDeviceTasksMap.clear();
-            mExpiredTasksCleanupTime = Long.MAX_VALUE;
-
-            final File[] taskFiles;
-            if (!sRestoredTasksDir.exists()
-                    || (taskFiles = sRestoredTasksDir.listFiles()) == null) {
-                // Nothing to do if there are no tasks to restore.
-                return;
-            }
-
-            long earliestMtime = System.currentTimeMillis();
-            SparseArray<List<OtherDeviceTask>> tasksByAffiliateIds =
-                        new SparseArray<>(taskFiles.length);
-
-            // Read new tasks from disk
-            for (int i = 0; i < taskFiles.length; ++i) {
-                final File taskFile = taskFiles[i];
-                if (DEBUG_RESTORER) Slog.d(TAG, "readOtherDeviceTasksFromDisk: taskFile="
-                            + taskFile.getName());
-
-                final OtherDeviceTask task = OtherDeviceTask.createFromFile(taskFile);
-
-                if (task == null) {
-                    // Go ahead and remove the file on disk if we are unable to create a task from
-                    // it.
-                    if (DEBUG_RESTORER) Slog.e(TAG, "Unable to create task for file="
-                                + taskFile.getName() + "...deleting file.");
-                    taskFile.delete();
-                    continue;
-                }
-
-                List<OtherDeviceTask> tasks = tasksByAffiliateIds.get(task.mAffiliatedTaskId);
-                if (tasks == null) {
-                    tasks = new ArrayList<>();
-                    tasksByAffiliateIds.put(task.mAffiliatedTaskId, tasks);
-                }
-                tasks.add(task);
-                final long taskMtime = taskFile.lastModified();
-                if (earliestMtime > taskMtime) {
-                    earliestMtime = taskMtime;
-                }
-            }
-
-            if (tasksByAffiliateIds.size() > 0) {
-                // Sort each affiliated tasks chain by taskId which is the order they were created
-                // that should always be correct...Then add to task map.
-                for (int i = 0; i < tasksByAffiliateIds.size(); i++) {
-                    List<OtherDeviceTask> chain = tasksByAffiliateIds.valueAt(i);
-                    Collections.sort(chain);
-                    // Package name of the root task in the affiliate chain.
-                    final String packageName =
-                            chain.get(chain.size()-1).mComponentName.getPackageName();
-                    List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.get(packageName);
-                    if (chains == null) {
-                        chains = new ArrayList<>();
-                        mOtherDeviceTasksMap.put(packageName, chains);
-                    }
-                    chains.add(chain);
-                }
-
-                // Set expiration time.
-                mExpiredTasksCleanupTime = earliestMtime + MAX_INSTALL_WAIT_TIME;
-                if (DEBUG_RESTORER) Slog.d(TAG, "Set Expiration time to "
-                            + DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
-                            DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
-            }
-        }
-    }
-
-    /**
-     * Removed any expired tasks from {@link #mOtherDeviceTasksMap} and disk if their expiration
-     * time is less than or equal to {@link #mExpiredTasksCleanupTime}.
-     */
-    private void removeExpiredTasksIfNeeded() {
-        synchronized (mOtherDeviceTasksMap) {
-            final long now = System.currentTimeMillis();
-            final boolean noMoreTasks = mOtherDeviceTasksMap.isEmpty();
-            if (noMoreTasks || now < mExpiredTasksCleanupTime) {
-                if (noMoreTasks && mPackageUidMap != null) {
-                    // All done! package->uid map no longer needed.
-                    mPackageUidMap = null;
-                }
-                return;
-            }
-
-            long earliestNonExpiredMtime = now;
-            mExpiredTasksCleanupTime = Long.MAX_VALUE;
-
-            // Remove expired backed-up tasks that have not been restored. We only want to
-            // remove task if it is safe to remove all tasks in the affiliation chain.
-            for (int i = mOtherDeviceTasksMap.size() - 1; i >= 0 ; i--) {
-
-                List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.valueAt(i);
-                for (int j = chains.size() - 1; j >= 0 ; j--) {
-
-                    List<OtherDeviceTask> chain = chains.get(j);
-                    boolean removeChain = true;
-                    for (int k = chain.size() - 1; k >= 0 ; k--) {
-                        OtherDeviceTask task = chain.get(k);
-                        final long taskLastModified = task.mFile.lastModified();
-                        if ((taskLastModified + MAX_INSTALL_WAIT_TIME) > now) {
-                            // File has not expired yet...but we keep looping to get the earliest
-                            // mtime.
-                            if (earliestNonExpiredMtime > taskLastModified) {
-                                earliestNonExpiredMtime = taskLastModified;
-                            }
-                            removeChain = false;
-                        }
-                    }
-                    if (removeChain) {
-                        for (int k = chain.size() - 1; k >= 0; k--) {
-                            final File file = chain.get(k).mFile;
-                            if (DEBUG_RESTORER) Slog.d(TAG, "Deleting expired file="
-                                    + file.getName() + " mapped to not installed component="
-                                    + chain.get(k).mComponentName);
-                            file.delete();
-                        }
-                        chains.remove(j);
-                    }
-                }
-                if (chains.isEmpty()) {
-                    final String packageName = mOtherDeviceTasksMap.keyAt(i);
-                    mOtherDeviceTasksMap.removeAt(i);
-                    if (DEBUG_RESTORER) Slog.d(TAG, "Removed package=" + packageName
-                                + " from task map");
-                }
-            }
-
-            // Reset expiration time if there is any task remaining.
-            if (!mOtherDeviceTasksMap.isEmpty()) {
-                mExpiredTasksCleanupTime = earliestNonExpiredMtime + MAX_INSTALL_WAIT_TIME;
-                if (DEBUG_RESTORER) Slog.d(TAG, "Reset expiration time to "
-                            + DateUtils.formatDateTime(mService.mContext, mExpiredTasksCleanupTime,
-                            DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME));
-            } else {
-                // All done! package->uid map no longer needed.
-                mPackageUidMap = null;
-            }
-        }
-    }
-
-    /**
-     * Removes the input package name from the local package->uid map.
-     */
-    void removeFromPackageCache(String packageName) {
-        synchronized (mOtherDeviceTasksMap) {
-            if (mPackageUidMap != null) {
-                mPackageUidMap.remove(packageName);
-            }
-        }
-    }
-
-    /**
-     * Tries to add all backed-up tasks from another device to this device recent's list.
-     */
-    private void addOtherDeviceTasksToRecentsLocked() {
-        synchronized (mOtherDeviceTasksMap) {
-            for (int i = mOtherDeviceTasksMap.size() - 1; i >= 0; i--) {
-                addOtherDeviceTasksToRecentsLocked(mOtherDeviceTasksMap.keyAt(i));
-            }
-        }
-    }
-
-    /**
-     * Tries to add backed-up tasks that are associated with the input package from
-     * another device to this device recent's list.
-     */
-    void addOtherDeviceTasksToRecentsLocked(String packageName) {
-        synchronized (mOtherDeviceTasksMap) {
-            List<List<OtherDeviceTask>> chains = mOtherDeviceTasksMap.get(packageName);
-            if (chains == null) {
-                return;
-            }
-
-            for (int i = chains.size() - 1; i >= 0; i--) {
-                List<OtherDeviceTask> chain = chains.get(i);
-                if (!canAddOtherDeviceTaskChain(chain)) {
-                    if (DEBUG_RESTORER) Slog.d(TAG, "Can't add task chain at index=" + i
-                            + " for package=" + packageName);
-                    continue;
-                }
-
-                // Generate task records for this chain.
-                List<TaskRecord> tasks = new ArrayList<>();
-                TaskRecord prev = null;
-                for (int j = chain.size() - 1; j >= 0; j--) {
-                    TaskRecord task = createTaskRecordLocked(chain.get(j));
-                    if (task == null) {
-                        // There was a problem in creating one of this task records in this chain.
-                        // There is no way we can continue...
-                        if (DEBUG_RESTORER) Slog.d(TAG, "Can't create task record for file="
-                                + chain.get(j).mFile + " for package=" + packageName);
-                        break;
-                    }
-
-                    // Wire-up affiliation chain.
-                    if (prev == null) {
-                        task.mPrevAffiliate = null;
-                        task.mPrevAffiliateTaskId = INVALID_TASK_ID;
-                        task.mAffiliatedTaskId = task.taskId;
-                    } else {
-                        prev.mNextAffiliate = task;
-                        prev.mNextAffiliateTaskId = task.taskId;
-                        task.mAffiliatedTaskId = prev.mAffiliatedTaskId;
-                        task.mPrevAffiliate = prev;
-                        task.mPrevAffiliateTaskId = prev.taskId;
-                    }
-                    prev = task;
-                    tasks.add(0, task);
-                }
-
-                // Add tasks to recent's if we were able to create task records for all the tasks
-                // in the chain.
-                if (tasks.size() == chain.size()) {
-                    // Make sure there is space in recent's to add the new task. If there is space
-                    // to the to the back.
-                    // TODO: Would be more fancy to interleave the new tasks into recent's based on
-                    // {@link TaskRecord.mLastTimeMoved} and drop the oldest recent's vs. just
-                    // adding to the back of the list.
-                    int spaceLeft =
-                            ActivityManager.getMaxRecentTasksStatic() - mRecentTasks.size();
-                    if (spaceLeft >= tasks.size()) {
-                        mRecentTasks.addAll(mRecentTasks.size(), tasks);
-                        for (int k = tasks.size() - 1; k >= 0; k--) {
-                            // Persist new tasks.
-                            wakeup(tasks.get(k), false);
-                        }
-
-                        if (DEBUG_RESTORER) Slog.d(TAG, "Added " + tasks.size()
-                                    + " tasks to recent's for" + " package=" + packageName);
-                    } else {
-                        if (DEBUG_RESTORER) Slog.d(TAG, "Didn't add to recents. tasks.size("
-                                    + tasks.size() + ") != chain.size(" + chain.size()
-                                    + ") for package=" + packageName);
-                    }
-                } else {
-                    if (DEBUG_RESTORER) Slog.v(TAG, "Unable to add restored tasks to recents "
-                            + tasks.size() + " tasks for package=" + packageName);
-                }
-
-                // Clean-up structures
-                for (int j = chain.size() - 1; j >= 0; j--) {
-                    chain.get(j).mFile.delete();
-                }
-                chains.remove(i);
-                if (chains.isEmpty()) {
-                    // The fate of all backed-up tasks associated with this package has been
-                    // determine. Go ahead and remove it from the to-process list.
-                    mOtherDeviceTasksMap.remove(packageName);
-                    if (DEBUG_RESTORER)
-                            Slog.d(TAG, "Removed package=" + packageName + " from restore map");
-                }
-            }
-        }
-    }
-
-    /**
-     * Creates and returns {@link TaskRecord} for the task from another device that can be used on
-     * this device. Returns null if the operation failed.
-     */
-    private TaskRecord createTaskRecordLocked(OtherDeviceTask other) {
-        File file = other.mFile;
-        BufferedReader reader = null;
-        TaskRecord task = null;
-        if (DEBUG_RESTORER) Slog.d(TAG, "createTaskRecordLocked: file=" + file.getName());
-
-        try {
-            reader = new BufferedReader(new FileReader(file));
-            final XmlPullParser in = Xml.newPullParser();
-            in.setInput(reader);
-
-            int event;
-            while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
-                    && event != XmlPullParser.END_TAG) {
-                final String name = in.getName();
-                if (event == XmlPullParser.START_TAG) {
-
-                    if (TAG_TASK.equals(name)) {
-                        // Create a task record using a task id that is valid for this device.
-                        task = TaskRecord.restoreFromXml(
-                                in, mStackSupervisor, mStackSupervisor.getNextTaskId());
-                        if (DEBUG_RESTORER)
-                                Slog.d(TAG, "createTaskRecordLocked: restored task=" + task);
-
-                        if (task != null) {
-                            task.isPersistable = true;
-                            task.inRecents = true;
-                            // Task can/should only be backed-up/restored for device owner.
-                            task.userId = UserHandle.USER_OWNER;
-                            // Clear out affiliated ids that are no longer valid on this device.
-                            task.mAffiliatedTaskId = INVALID_TASK_ID;
-                            task.mPrevAffiliateTaskId = INVALID_TASK_ID;
-                            task.mNextAffiliateTaskId = INVALID_TASK_ID;
-                            // Set up uids valid for this device.
-                            Integer uid = mPackageUidMap.get(task.realActivity.getPackageName());
-                            if (uid == null) {
-                                // How did this happen???
-                                Slog.wtf(TAG, "Can't find uid for task=" + task
-                                        + " in mPackageUidMap=" + mPackageUidMap);
-                                return null;
-                            }
-                            task.effectiveUid = task.mCallingUid = uid;
-                            for (int i = task.mActivities.size() - 1; i >= 0; --i) {
-                                final ActivityRecord activity = task.mActivities.get(i);
-                                uid = mPackageUidMap.get(activity.launchedFromPackage);
-                                if (uid == null) {
-                                    // How did this happen??
-                                    Slog.wtf(TAG, "Can't find uid for activity=" + activity
-                                            + " in mPackageUidMap=" + mPackageUidMap);
-                                    return null;
-                                }
-                                activity.launchedFromUid = uid;
-                            }
-
-                        } else {
-                            Slog.e(TAG, "Unable to create task for backed-up file=" + file + ": "
-                                        + fileToString(file));
-                        }
-                    } else {
-                        Slog.wtf(TAG, "createTaskRecordLocked Unknown xml event=" + event
-                                    + " name=" + name);
-                    }
-                }
-                XmlUtils.skipCurrentTag(in);
-            }
-        } catch (Exception e) {
-            Slog.wtf(TAG, "Unable to parse " + file + ". Error ", e);
-            Slog.e(TAG, "Failing file: " + fileToString(file));
-        } finally {
-            IoUtils.closeQuietly(reader);
-        }
-
-        return task;
-    }
-
-    /**
-     * Returns true if the input task chain backed-up from another device can be restored on this
-     * device. Also, sets the {@link OtherDeviceTask#mUid} on the input tasks if they can be
-     * restored.
-     */
-    private boolean canAddOtherDeviceTaskChain(List<OtherDeviceTask> chain) {
-
-        final ArraySet<ComponentName> validComponents = new ArraySet<>();
-        final IPackageManager pm = AppGlobals.getPackageManager();
-        for (int i = 0; i < chain.size(); i++) {
-
-            OtherDeviceTask task = chain.get(i);
-            // Quick check, we can't add the task chain if any of its task files don't exist.
-            if (!task.mFile.exists()) {
-                if (DEBUG_RESTORER) Slog.d(TAG,
-                        "Can't add chain due to missing file=" + task.mFile);
-                return false;
-            }
-
-            // Verify task package is installed.
-            if (!isPackageInstalled(task.mComponentName.getPackageName())) {
-                return false;
-            }
-            // Verify that all the launch packages are installed.
-            if (task.mLaunchPackages != null) {
-                for (int j = task.mLaunchPackages.size() - 1; j >= 0; --j) {
-                    if (!isPackageInstalled(task.mLaunchPackages.valueAt(j))) {
-                        return false;
-                    }
-                }
-            }
-
-            if (validComponents.contains(task.mComponentName)) {
-                // Existance of component has already been verified.
-                continue;
-            }
-
-            // Check to see if the specific component is installed.
-            try {
-                if (pm.getActivityInfo(task.mComponentName, 0, UserHandle.USER_OWNER) == null) {
-                    // Component isn't installed...
-                    return false;
-                }
-                validComponents.add(task.mComponentName);
-            } catch (RemoteException e) {
-                // Should not happen???
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if the input package name is installed. If the package is installed, an entry
-     * for the package is added to {@link #mPackageUidMap}.
-     */
-    private boolean isPackageInstalled(final String packageName) {
-        if (mPackageUidMap != null && mPackageUidMap.containsKey(packageName)) {
-            return true;
-        }
-        try {
-            int uid = AppGlobals.getPackageManager().getPackageUid(
-                    packageName, UserHandle.USER_OWNER);
-            if (uid == -1) {
-                // package doesn't exist...
-                return false;
-            }
-            if (mPackageUidMap == null) {
-                mPackageUidMap = new ArrayMap<>();
-            }
-            mPackageUidMap.put(packageName, uid);
-            return true;
-        } catch (RemoteException e) {
-            // Should not happen???
-            return false;
-        }
-    }
-
     private class LazyTaskWriterThread extends Thread {
 
         LazyTaskWriterThread(String name) {
@@ -941,21 +481,20 @@
                     probablyDone = mWriteQueue.isEmpty();
                 }
                 if (probablyDone) {
-                    if (DEBUG_PERSISTER) Slog.d(TAG, "Looking for obsolete files.");
+                    if (DEBUG) Slog.d(TAG, "Looking for obsolete files.");
                     persistentTaskIds.clear();
                     synchronized (mService) {
-                        if (DEBUG_PERSISTER) Slog.d(TAG, "mRecents=" + mRecentTasks);
+                        if (DEBUG) Slog.d(TAG, "mRecents=" + mRecentTasks);
                         for (int taskNdx = mRecentTasks.size() - 1; taskNdx >= 0; --taskNdx) {
                             final TaskRecord task = mRecentTasks.get(taskNdx);
-                            if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: task=" + task +
+                            if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
                                     " persistable=" + task.isPersistable);
                             if ((task.isPersistable || task.inRecents)
                                     && (task.stack == null || !task.stack.isHomeStack())) {
-                                if (DEBUG_PERSISTER)
-                                        Slog.d(TAG, "adding to persistentTaskIds task=" + task);
+                                if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
                                 persistentTaskIds.add(task.taskId);
                             } else {
-                                if (DEBUG_PERSISTER) Slog.d(TAG,
+                                if (DEBUG) Slog.d(TAG,
                                         "omitting from persistentTaskIds task=" + task);
                             }
                         }
@@ -969,7 +508,7 @@
                     if (mNextWriteTime != FLUSH_QUEUE) {
                         // The next write we don't have to wait so long.
                         mNextWriteTime = SystemClock.uptimeMillis() + INTER_WRITE_DELAY_MS;
-                        if (DEBUG_PERSISTER) Slog.d(TAG, "Next write time may be in " +
+                        if (DEBUG) Slog.d(TAG, "Next write time may be in " +
                                 INTER_WRITE_DELAY_MS + " msec. (" + mNextWriteTime + ")");
                     }
 
@@ -979,13 +518,8 @@
                             mNextWriteTime = 0; // idle.
                             TaskPersister.this.notifyAll(); // wake up flush() if needed.
                         }
-
-                        // See if we need to remove any expired back-up tasks before waiting.
-                        removeExpiredTasksIfNeeded();
-
                         try {
-                            if (DEBUG_PERSISTER)
-                                    Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
+                            if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
                             TaskPersister.this.wait();
                         } catch (InterruptedException e) {
                         }
@@ -995,12 +529,11 @@
                     item = mWriteQueue.remove(0);
 
                     long now = SystemClock.uptimeMillis();
-                    if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: now=" + now
-                                + " mNextWriteTime=" + mNextWriteTime + " mWriteQueue.size="
-                                + mWriteQueue.size());
+                    if (DEBUG) Slog.d(TAG, "LazyTaskWriter: now=" + now + " mNextWriteTime=" +
+                            mNextWriteTime + " mWriteQueue.size=" + mWriteQueue.size());
                     while (now < mNextWriteTime) {
                         try {
-                            if (DEBUG_PERSISTER) Slog.d(TAG, "LazyTaskWriter: waiting " +
+                            if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting " +
                                     (mNextWriteTime - now));
                             TaskPersister.this.wait(mNextWriteTime - now);
                         } catch (InterruptedException e) {
@@ -1015,7 +548,7 @@
                     ImageWriteQueueItem imageWriteQueueItem = (ImageWriteQueueItem) item;
                     final String filename = imageWriteQueueItem.mFilename;
                     final Bitmap bitmap = imageWriteQueueItem.mImage;
-                    if (DEBUG_PERSISTER) Slog.d(TAG, "writing bitmap: filename=" + filename);
+                    if (DEBUG) Slog.d(TAG, "writing bitmap: filename=" + filename);
                     FileOutputStream imageFile = null;
                     try {
                         imageFile = new FileOutputStream(new File(sImagesDir, filename));
@@ -1029,12 +562,12 @@
                     // Write out one task.
                     StringWriter stringWriter = null;
                     TaskRecord task = ((TaskWriteQueueItem) item).mTask;
-                    if (DEBUG_PERSISTER) Slog.d(TAG, "Writing task=" + task);
+                    if (DEBUG) Slog.d(TAG, "Writing task=" + task);
                     synchronized (mService) {
                         if (task.inRecents) {
                             // Still there.
                             try {
-                                if (DEBUG_PERSISTER) Slog.d(TAG, "Saving task=" + task);
+                                if (DEBUG) Slog.d(TAG, "Saving task=" + task);
                                 stringWriter = saveToXml(task);
                             } catch (IOException e) {
                             } catch (XmlPullParserException e) {
@@ -1064,127 +597,4 @@
             }
         }
     }
-
-    /**
-     * Helper class for holding essential information about task that were backed-up on a different
-     * device that can be restored on this device.
-     */
-    private static class OtherDeviceTask implements Comparable<OtherDeviceTask> {
-        final File mFile;
-        // See {@link TaskRecord} for information on the fields below.
-        final ComponentName mComponentName;
-        final int mTaskId;
-        final int mAffiliatedTaskId;
-
-        // Names of packages that launched activities in this task. All packages listed here need
-        // to be installed on the current device in order for the task to be restored successfully.
-        final ArraySet<String> mLaunchPackages;
-
-        private OtherDeviceTask(File file, ComponentName componentName, int taskId,
-                int affiliatedTaskId, ArraySet<String> launchPackages) {
-            mFile = file;
-            mComponentName = componentName;
-            mTaskId = taskId;
-            mAffiliatedTaskId = (affiliatedTaskId == INVALID_TASK_ID) ? taskId: affiliatedTaskId;
-            mLaunchPackages = launchPackages;
-        }
-
-        @Override
-        public int compareTo(OtherDeviceTask another) {
-            return mTaskId - another.mTaskId;
-        }
-
-        /**
-         * Creates a new {@link OtherDeviceTask} object based on the contents of the input file.
-         *
-         * @param file input file that contains the complete task information.
-         * @return new {@link OtherDeviceTask} object or null if we failed to create the object.
-         */
-        static OtherDeviceTask createFromFile(File file) {
-            if (file == null || !file.exists()) {
-                if (DEBUG_RESTORER)
-                    Slog.d(TAG, "createFromFile: file=" + file + " doesn't exist.");
-                return null;
-            }
-
-            BufferedReader reader = null;
-
-            try {
-                reader = new BufferedReader(new FileReader(file));
-                final XmlPullParser in = Xml.newPullParser();
-                in.setInput(reader);
-
-                int event;
-                while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
-                        event != XmlPullParser.START_TAG) {
-                    // Skip to the start tag or end of document
-                }
-
-                if (event == XmlPullParser.START_TAG) {
-                    final String name = in.getName();
-
-                    if (TAG_TASK.equals(name)) {
-                        final int outerDepth = in.getDepth();
-                        ComponentName componentName = null;
-                        int taskId = INVALID_TASK_ID;
-                        int taskAffiliation = INVALID_TASK_ID;
-                        for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
-                            final String attrName = in.getAttributeName(j);
-                            final String attrValue = in.getAttributeValue(j);
-                            if (TaskRecord.ATTR_REALACTIVITY.equals(attrName)) {
-                                componentName = ComponentName.unflattenFromString(attrValue);
-                            } else if (TaskRecord.ATTR_TASKID.equals(attrName)) {
-                                taskId = Integer.valueOf(attrValue);
-                            } else if (TaskRecord.ATTR_TASK_AFFILIATION.equals(attrName)) {
-                                taskAffiliation = Integer.valueOf(attrValue);
-                            }
-                        }
-                        if (componentName == null || taskId == INVALID_TASK_ID) {
-                            if (DEBUG_RESTORER) Slog.e(TAG,
-                                    "createFromFile: FAILED componentName=" + componentName
-                                    + " taskId=" + taskId + " file=" + file);
-                            return null;
-                        }
-
-                        ArraySet<String> launchPackages = null;
-                        while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
-                                (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
-                            if (event == XmlPullParser.START_TAG) {
-                                if (TaskRecord.TAG_ACTIVITY.equals(in.getName())) {
-                                    for (int j = in.getAttributeCount() - 1; j >= 0; --j) {
-                                        if (ActivityRecord.ATTR_LAUNCHEDFROMPACKAGE.equals(
-                                                in.getAttributeName(j))) {
-                                            if (launchPackages == null) {
-                                                launchPackages = new ArraySet();
-                                            }
-                                            launchPackages.add(in.getAttributeValue(j));
-                                        }
-                                    }
-                                } else {
-                                    XmlUtils.skipCurrentTag(in);
-                                }
-                            }
-                        }
-                        if (DEBUG_RESTORER) Slog.d(TAG, "creating OtherDeviceTask from file="
-                                + file.getName() + " componentName=" + componentName
-                                + " taskId=" + taskId + " launchPackages=" + launchPackages);
-                        return new OtherDeviceTask(file, componentName, taskId,
-                                taskAffiliation, launchPackages);
-                    } else {
-                        Slog.wtf(TAG,
-                                "createFromFile: Unknown xml event=" + event + " name=" + name);
-                    }
-                } else {
-                    Slog.wtf(TAG, "createFromFile: Unable to find start tag in file=" + file);
-                }
-            } catch (IOException | XmlPullParserException e) {
-                Slog.wtf(TAG, "Unable to parse " + file + ". Error ", e);
-            } finally {
-                IoUtils.closeQuietly(reader);
-            }
-
-            // Something went wrong...
-            return null;
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f653e9e..417c7c3 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -28,8 +28,6 @@
 import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
-import static com.android.server.am.TaskPersister.DEBUG_PERSISTER;
-import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
 
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -71,7 +69,7 @@
     private static final String TAG_AFFINITYINTENT = "affinity_intent";
     static final String ATTR_REALACTIVITY = "real_activity";
     private static final String ATTR_ORIGACTIVITY = "orig_activity";
-    static final String TAG_ACTIVITY = "activity";
+    private static final String TAG_ACTIVITY = "activity";
     private static final String ATTR_AFFINITY = "affinity";
     private static final String ATTR_ROOT_AFFINITY = "root_affinity";
     private static final String ATTR_ROOTHASRESET = "root_has_reset";
@@ -970,10 +968,6 @@
 
     static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
             throws IOException, XmlPullParserException {
-        return restoreFromXml(in, stackSupervisor, INVALID_TASK_ID);
-    }
-    static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor,
-            int inTaskId) throws IOException, XmlPullParserException {
         Intent intent = null;
         Intent affinityIntent = null;
         ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
@@ -993,7 +987,7 @@
         long lastActiveTime = -1;
         long lastTimeOnTop = 0;
         boolean neverRelinquishIdentity = true;
-        int taskId = inTaskId;
+        int taskId = INVALID_TASK_ID;
         final int outerDepth = in.getDepth();
         TaskDescription taskDescription = new TaskDescription();
         int taskAffiliation = INVALID_TASK_ID;
@@ -1008,8 +1002,8 @@
         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
             final String attrName = in.getAttributeName(attrNdx);
             final String attrValue = in.getAttributeValue(attrNdx);
-            if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
-                        "TaskRecord: attribute name=" + attrName + " value=" + attrValue);
+            if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
+                    attrName + " value=" + attrValue);
             if (ATTR_TASKID.equals(attrName)) {
                 if (taskId == INVALID_TASK_ID) taskId = Integer.valueOf(attrValue);
             } else if (ATTR_REALACTIVITY.equals(attrName)) {
@@ -1071,16 +1065,16 @@
                 (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
             if (event == XmlPullParser.START_TAG) {
                 final String name = in.getName();
-                if (DEBUG_PERSISTER || DEBUG_RESTORER)
-                        Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" + name);
+                if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
+                        name);
                 if (TAG_AFFINITYINTENT.equals(name)) {
                     affinityIntent = Intent.restoreFromXml(in);
                 } else if (TAG_INTENT.equals(name)) {
                     intent = Intent.restoreFromXml(in);
                 } else if (TAG_ACTIVITY.equals(name)) {
                     ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor);
-                    if (DEBUG_PERSISTER || DEBUG_RESTORER)
-                            Slog.d(TaskPersister.TAG, "TaskRecord: activity=" + activity);
+                    if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
+                            activity);
                     if (activity != null) {
                         activities.add(activity);
                     }
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 75198e5..dbfd4ef 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -42,6 +42,14 @@
     private static final EnumMap<SupplicantState, DetailedState> stateMap =
             new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);
 
+    /**
+     * Default MAC address reported to a client that does not have the
+     * android.permission.LOCAL_MAC_ADDRESS permission.
+     *
+     * @hide
+     */
+    public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
+
     static {
         stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
         stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
@@ -91,7 +99,7 @@
     private int mFrequency;
 
     private InetAddress mIpAddress;
-    private String mMacAddress;
+    private String mMacAddress = DEFAULT_MAC_ADDRESS;
 
     /**
      * @hide