Merge "add local focus mode and input event injection API to Window" into klp-dev
diff --git a/api/current.txt b/api/current.txt
index d11d70c..e4f31b0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20716,6 +20716,7 @@
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
     field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
     field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS";
+    field public static final java.lang.String ACTION_NFC_PAYMENT_SETTINGS = "android.settings.NFC_PAYMENT_SETTINGS";
     field public static final java.lang.String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS";
     field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 17e8dd9..be831d7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1527,9 +1527,26 @@
      */
     public boolean setDeviceOwner(String packageName) throws IllegalArgumentException,
             IllegalStateException {
+        return setDeviceOwner(packageName, null);
+    }
+
+    /**
+     * @hide
+     * Sets the given package as the device owner. The package must already be installed and there
+     * shouldn't be an existing device owner registered, for this call to succeed. Also, this
+     * method must be called before the device is provisioned.
+     * @param packageName the package name of the application to be registered as the device owner.
+     * @param ownerName the human readable name of the institution that owns this device.
+     * @return whether the package was successfully registered as the device owner.
+     * @throws IllegalArgumentException if the package name is null or invalid
+     * @throws IllegalStateException if a device owner is already registered or the device has
+     *         already been provisioned.
+     */
+    public boolean setDeviceOwner(String packageName, String ownerName)
+            throws IllegalArgumentException, IllegalStateException {
         if (mService != null) {
             try {
-                return mService.setDeviceOwner(packageName);
+                return mService.setDeviceOwner(packageName, ownerName);
             } catch (RemoteException re) {
                 Log.w(TAG, "Failed to set device owner");
             }
@@ -1581,4 +1598,16 @@
         }
         return null;
     }
+
+    /** @hide */
+    public String getDeviceOwnerName() {
+        if (mService != null) {
+            try {
+                return mService.getDeviceOwnerName();
+            } catch (RemoteException re) {
+                Log.w(TAG, "Failed to get device owner");
+            }
+        }
+        return null;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b2a65bf..9659a91 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -98,7 +98,8 @@
     void reportFailedPasswordAttempt(int userHandle);
     void reportSuccessfulPasswordAttempt(int userHandle);
 
-    boolean setDeviceOwner(String packageName);
+    boolean setDeviceOwner(String packageName, String ownerName);
     boolean isDeviceOwner(String packageName);
     String getDeviceOwner();
+    String getDeviceOwnerName();
 }
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index ffa7d7e..3f7e3ef 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -188,7 +188,8 @@
                         currentGroup != null) {
                     final TypedArray a = res.obtainAttributes(attrs,
                             com.android.internal.R.styleable.AidFilter);
-                    String aid = a.getString(com.android.internal.R.styleable.AidFilter_name);
+                    String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
+                            toUpperCase();
                     if (isValidAid(aid) && !currentGroup.aids.contains(aid)) {
                         currentGroup.aids.add(aid);
                         mAids.add(aid);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4865fd0..585115a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -644,6 +644,23 @@
         "android.settings.NFCSHARING_SETTINGS";
 
     /**
+     * Activity Action: Show NFC Tap & Pay settings
+     * <p>
+     * This shows UI that allows the user to configure Tap&Pay
+     * settings.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_NFC_PAYMENT_SETTINGS =
+        "android.settings.NFC_PAYMENT_SETTINGS";
+
+    /**
      * Activity Action: Show Daydream settings.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20938f51..3dff1b0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12062,7 +12062,8 @@
     }
 
     /**
-     * Resolve padding depending on layout direction.
+     * Resolves padding depending on layout direction, if applicable, and
+     * recomputes internal padding values to adjust for scroll bars.
      *
      * @hide
      */
@@ -12102,11 +12103,11 @@
 
             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
 
-            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
-                    mUserPaddingBottom);
             onRtlPropertiesChanged(resolvedLayoutDirection);
         }
 
+        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+
         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
     }
 
@@ -14659,13 +14660,26 @@
      * @hide
      */
     protected void resolveDrawables() {
-        if (canResolveLayoutDirection()) {
-            if (mBackground != null) {
-                mBackground.setLayoutDirection(getLayoutDirection());
-            }
-            mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
-            onResolveDrawables(getLayoutDirection());
+        // Drawables resolution may need to happen before resolving the layout direction (which is
+        // done only during the measure() call).
+        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
+        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
+        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
+        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
+        // direction to be resolved as its resolved value will be the same as its raw value.
+        if (!isLayoutDirectionResolved() &&
+                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
+            return;
         }
+
+        final int layoutDirection = isLayoutDirectionResolved() ?
+                getLayoutDirection() : getRawLayoutDirection();
+
+        if (mBackground != null) {
+            mBackground.setLayoutDirection(layoutDirection);
+        }
+        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
+        onResolveDrawables(layoutDirection);
     }
 
     /**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3f391ad..0ed846b 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1243,6 +1243,12 @@
             mFastScroller = new FastScroller(this);
             mFastScroller.setEnabled(true);
         }
+
+        recomputePadding();
+
+        if (mFastScroller != null) {
+            mFastScroller.updateLayout();
+        }
     }
 
     /**
@@ -1303,7 +1309,7 @@
 
     @Override
     public int getVerticalScrollbarWidth() {
-        if (isFastScrollAlwaysVisible() && mFastScroller != null) {
+        if (mFastScroller != null && mFastScroller.isEnabled()) {
             return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth());
         }
         return super.getVerticalScrollbarWidth();
@@ -1327,6 +1333,14 @@
         }
     }
 
+    @Override
+    public void setScrollBarStyle(int style) {
+        super.setScrollBarStyle(style);
+        if (mFastScroller != null) {
+            mFastScroller.setScrollBarStyle(style);
+        }
+    }
+
     /**
      * If fast scroll is enabled, then don't draw the vertical scrollbar.
      * @hide
@@ -2787,7 +2801,6 @@
     @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
         super.onRtlPropertiesChanged(layoutDirection);
-
         if (mFastScroller != null) {
            mFastScroller.setScrollbarPosition(getVerticalScrollbarPosition());
         }
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 393720f..c48955f 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -131,6 +131,9 @@
     /** Whether there is a track image to display. */
     private final boolean mHasTrackImage;
 
+    /** Total width of decorations. */
+    private final int mWidth;
+
     /** Set containing decoration transition animations. */
     private AnimatorSet mDecorAnimation;
 
@@ -155,6 +158,9 @@
     /** The index of the current section. */
     private int mCurrentSection = -1;
 
+    /** The current scrollbar position. */
+    private int mScrollbarPosition = -1;
+
     /** Whether the list is long enough to need a fast scroller. */
     private boolean mLongList;
 
@@ -194,6 +200,9 @@
      */
     private int mOverlayPosition;
 
+    /** Current scrollbar style, including inset and overlay properties. */
+    private int mScrollBarStyle;
+
     /** Whether to precisely match the thumb position to the list. */
     private boolean mMatchDragPosition;
 
@@ -245,34 +254,44 @@
         final Resources res = context.getResources();
         final TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS);
 
-        mTrackImage = new ImageView(context);
+        final ImageView trackImage = new ImageView(context);
+        mTrackImage = trackImage;
+
+        int width = 0;
 
         // Add track to overlay if it has an image.
-        final int trackResId = ta.getResourceId(TRACK_DRAWABLE, 0);
-        if (trackResId != 0) {
+        final Drawable trackDrawable = ta.getDrawable(TRACK_DRAWABLE);
+        if (trackDrawable != null) {
             mHasTrackImage = true;
-            mTrackImage.setBackgroundResource(trackResId);
-            mOverlay.add(mTrackImage);
+            trackImage.setBackground(trackDrawable);
+            mOverlay.add(trackImage);
+            width = Math.max(width, trackDrawable.getIntrinsicWidth());
         } else {
             mHasTrackImage = false;
         }
 
-        mThumbImage = new ImageView(context);
+        final ImageView thumbImage = new ImageView(context);
+        mThumbImage = thumbImage;
 
         // Add thumb to overlay if it has an image.
         final Drawable thumbDrawable = ta.getDrawable(THUMB_DRAWABLE);
         if (thumbDrawable != null) {
-            mThumbImage.setImageDrawable(thumbDrawable);
-            mOverlay.add(mThumbImage);
+            thumbImage.setImageDrawable(thumbDrawable);
+            mOverlay.add(thumbImage);
+            width = Math.max(width, thumbDrawable.getIntrinsicWidth());
         }
 
         // If necessary, apply minimum thumb width and height.
         if (thumbDrawable.getIntrinsicWidth() <= 0 || thumbDrawable.getIntrinsicHeight() <= 0) {
-            mThumbImage.setMinimumWidth(res.getDimensionPixelSize(R.dimen.fastscroll_thumb_width));
-            mThumbImage.setMinimumHeight(
+            final int minWidth = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_width);
+            thumbImage.setMinimumWidth(minWidth);
+            thumbImage.setMinimumHeight(
                     res.getDimensionPixelSize(R.dimen.fastscroll_thumb_height));
+            width = Math.max(width, minWidth);
         }
 
+        mWidth = width;
+
         final int previewSize = res.getDimensionPixelSize(R.dimen.fastscroll_overlay_size);
         mPreviewImage = new ImageView(context);
         mPreviewImage.setMinimumWidth(previewSize);
@@ -297,10 +316,11 @@
         mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING);
         ta.recycle();
 
+        mScrollBarStyle = listView.getScrollBarStyle();
         mScrollCompleted = true;
         mState = STATE_VISIBLE;
-        mMatchDragPosition =
-                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
+        mMatchDragPosition = context.getApplicationInfo().targetSdkVersion
+                >= Build.VERSION_CODES.HONEYCOMB;
 
         getSectionsFromIndexer();
         refreshDrawablePressedState();
@@ -362,6 +382,14 @@
         return mAlwaysShow;
     }
 
+    public void setScrollBarStyle(int style) {
+        if (mScrollBarStyle != style) {
+            mScrollBarStyle = style;
+
+            updateLayout();
+        }
+    }
+
     /**
      * Immediately transitions the fast scroller decorations to a hidden state.
      */
@@ -375,25 +403,29 @@
                     View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
         }
 
-        mLayoutFromRight = position != View.SCROLLBAR_POSITION_LEFT;
+        if (mScrollbarPosition != position) {
+            mScrollbarPosition = position;
+            mLayoutFromRight = position != View.SCROLLBAR_POSITION_LEFT;
 
-        final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
-        mPreviewImage.setBackgroundResource(previewResId);
+            final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
+            mPreviewImage.setBackgroundResource(previewResId);
 
-        // Add extra padding for text.
-        final Drawable background = mPreviewImage.getBackground();
-        if (background != null) {
-            final Rect padding = mTempBounds;
-            background.getPadding(padding);
-            padding.offset(mPreviewPadding, mPreviewPadding);
-            mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+            // Add extra padding for text.
+            final Drawable background = mPreviewImage.getBackground();
+            if (background != null) {
+                final Rect padding = mTempBounds;
+                background.getPadding(padding);
+                padding.offset(mPreviewPadding, mPreviewPadding);
+                mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+            }
+
+            // Requires re-layout.
+            updateLayout();
         }
-
-        updateLayout();
     }
 
     public int getWidth() {
-        return mThumbImage.getWidth();
+        return mWidth;
     }
 
     public void onSizeChanged(int w, int h, int oldw, int oldh) {
@@ -437,7 +469,7 @@
     /**
      * Measures and layouts the scrollbar and decorations.
      */
-    private void updateLayout() {
+    public void updateLayout() {
         // Prevent re-entry when RTL properties change as a side-effect of
         // resolving padding.
         if (mUpdatingLayout) {
@@ -594,21 +626,36 @@
         out.set(left, top, right, bottom);
     }
 
+    /**
+     * Updates the container rectangle used for layout.
+     */
     private void updateContainerRect() {
         final AbsListView list = mList;
+        list.resolvePadding();
+
         final Rect container = mContainerRect;
         container.left = 0;
         container.top = 0;
         container.right = list.getWidth();
         container.bottom = list.getHeight();
 
-        final int scrollbarStyle = list.getScrollBarStyle();
+        final int scrollbarStyle = mScrollBarStyle;
         if (scrollbarStyle == View.SCROLLBARS_INSIDE_INSET
                 || scrollbarStyle == View.SCROLLBARS_INSIDE_OVERLAY) {
             container.left += list.getPaddingLeft();
             container.top += list.getPaddingTop();
             container.right -= list.getPaddingRight();
             container.bottom -= list.getPaddingBottom();
+
+            // In inset mode, we need to adjust for padded scrollbar width.
+            if (scrollbarStyle == View.SCROLLBARS_INSIDE_INSET) {
+                final int width = getWidth();
+                if (mScrollbarPosition == View.SCROLLBAR_POSITION_RIGHT) {
+                    container.right += width;
+                } else {
+                    container.left -= width;
+                }
+            }
         }
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3181164..9c21f0d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1378,6 +1378,8 @@
             } else {
                 dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
             }
+            resetResolvedDrawables();
+            resolveDrawables();
         }
     }
 
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 39c23cf..7eadbb5 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -31,6 +31,8 @@
 import com.android.internal.util.ArrayUtils;
 import dalvik.system.VMRuntime;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -212,6 +214,80 @@
         readFromParcel(in);
     }
 
+    public void add(ProcessStats other) {
+        ArrayMap<String, SparseArray<PackageState>> pkgMap = other.mPackages.getMap();
+        for (int ip=0; ip<pkgMap.size(); ip++) {
+            String pkgName = pkgMap.keyAt(ip);
+            SparseArray<PackageState> uids = pkgMap.valueAt(ip);
+            for (int iu=0; iu<uids.size(); iu++) {
+                int uid = uids.keyAt(iu);
+                PackageState otherState = uids.valueAt(iu);
+                final int NPROCS = otherState.mProcesses.size();
+                final int NSRVS = otherState.mServices.size();
+                for (int iproc=0; iproc<NPROCS; iproc++) {
+                    ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
+                    if (otherProc.mCommonProcess != otherProc) {
+                        if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+                                + " proc " + otherProc.mName);
+                        ProcessState thisProc = getProcessStateLocked(pkgName, uid,
+                                otherProc.mName);
+                        if (thisProc.mCommonProcess == thisProc) {
+                            if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
+                            thisProc.mMultiPackage = true;
+                            long now = SystemClock.uptimeMillis();
+                            final PackageState pkgState = getPackageStateLocked(pkgName, uid);
+                            thisProc = thisProc.clone(thisProc.mPackage, now);
+                            pkgState.mProcesses.put(thisProc.mName, thisProc);
+                        }
+                        thisProc.add(otherProc);
+                    }
+                }
+                for (int isvc=0; isvc<NSRVS; isvc++) {
+                    ServiceState otherSvc = otherState.mServices.valueAt(isvc);
+                    if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+                            + " service " + otherSvc.mName);
+                    ServiceState thisSvc = getServiceStateLocked(pkgName, uid,
+                            null, otherSvc.mName);
+                    thisSvc.add(otherSvc);
+                }
+            }
+        }
+
+        ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
+        for (int ip=0; ip<procMap.size(); ip++) {
+            SparseArray<ProcessState> uids = procMap.valueAt(ip);
+            for (int iu=0; iu<uids.size(); iu++) {
+                int uid = uids.keyAt(iu);
+                ProcessState otherProc = uids.valueAt(iu);
+                ProcessState thisProc = mProcesses.get(otherProc.mName, uid);
+                if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName);
+                if (thisProc == null) {
+                    if (DEBUG) Slog.d(TAG, "Creating new process!");
+                    thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mName);
+                    mProcesses.put(otherProc.mName, uid, thisProc);
+                    PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid);
+                    if (!thisState.mProcesses.containsKey(otherProc.mName)) {
+                        thisState.mProcesses.put(otherProc.mName, thisProc);
+                    }
+                }
+                thisProc.add(otherProc);
+            }
+        }
+
+        for (int i=0; i<ADJ_COUNT; i++) {
+            if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
+                    + other.mMemFactorDurations[i] + " from "
+                    + mMemFactorDurations[i]);
+            mMemFactorDurations[i] += other.mMemFactorDurations[i];
+        }
+
+        if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
+            mTimePeriodStartClock = other.mTimePeriodStartClock;
+            mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
+        }
+        mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
+    }
+
     public static final Parcelable.Creator<ProcessStats> CREATOR
             = new Parcelable.Creator<ProcessStats>() {
         public ProcessStats createFromParcel(Parcel in) {
@@ -1098,6 +1174,43 @@
         return true;
     }
 
+    static byte[] readFully(InputStream stream) throws IOException {
+        int pos = 0;
+        int avail = stream.available();
+        byte[] data = new byte[avail];
+        while (true) {
+            int amt = stream.read(data, pos, data.length-pos);
+            //Log.i("foo", "Read " + amt + " bytes at " + pos
+            //        + " of avail " + data.length);
+            if (amt <= 0) {
+                //Log.i("foo", "**** FINISHED READING: pos=" + pos
+                //        + " len=" + data.length);
+                return data;
+            }
+            pos += amt;
+            avail = stream.available();
+            if (avail > data.length-pos) {
+                byte[] newData = new byte[pos+avail];
+                System.arraycopy(data, 0, newData, 0, pos);
+                data = newData;
+            }
+        }
+    }
+
+    public void read(InputStream stream) {
+        try {
+            byte[] raw = readFully(stream);
+            Parcel in = Parcel.obtain();
+            in.unmarshall(raw, 0, raw.length);
+            in.setDataPosition(0);
+            stream.close();
+
+            readFromParcel(in);
+        } catch (IOException e) {
+            mReadError = "caught exception: " + e;
+        }
+    }
+
     public void readFromParcel(Parcel in) {
         final boolean hadData = mPackages.getMap().size() > 0
                 || mProcesses.getMap().size() > 0;
@@ -1289,7 +1402,7 @@
                     }
                     ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
                     if (serv == null) {
-                        serv = new ServiceState(this, pkgName, null);
+                        serv = new ServiceState(this, pkgName, serviceName, null);
                     }
                     if (!serv.readFromParcel(in)) {
                         return;
@@ -1437,6 +1550,21 @@
         return ps;
     }
 
+    public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
+            String processName, String className) {
+        final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
+        ProcessStats.ServiceState ss = as.mServices.get(className);
+        if (ss != null) {
+            ss.makeActive();
+            return ss;
+        }
+        final ProcessStats.ProcessState ps = processName != null
+                ? getProcessStateLocked(packageName, uid, processName) : null;
+        ss = new ProcessStats.ServiceState(this, packageName, className, ps);
+        as.mServices.put(className, ss);
+        return ss;
+    }
+
     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpAll) {
         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
@@ -1947,6 +2075,29 @@
             return pnew;
         }
 
+        void add(ProcessState other) {
+            for (int i=0; i<other.mDurationsTableSize; i++) {
+                int ent = other.mDurationsTable[i];
+                int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+                if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
+                        + other.mStats.getLong(ent, 0));
+                addDuration(state, other.mStats.getLong(ent, 0));
+            }
+            for (int i=0; i<other.mPssTableSize; i++) {
+                int ent = other.mPssTable[i];
+                int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+                addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
+                        other.mStats.getLong(ent, PSS_MINIMUM),
+                        other.mStats.getLong(ent, PSS_AVERAGE),
+                        other.mStats.getLong(ent, PSS_MAXIMUM),
+                        other.mStats.getLong(ent, PSS_USS_MINIMUM),
+                        other.mStats.getLong(ent, PSS_USS_AVERAGE),
+                        other.mStats.getLong(ent, PSS_USS_MAXIMUM));
+            }
+            mNumExcessiveWake += other.mNumExcessiveWake;
+            mNumExcessiveCpu += other.mNumExcessiveCpu;
+        }
+
         void resetSafely(long now) {
             mDurationsTable = null;
             mDurationsTableSize = 0;
@@ -2043,24 +2194,30 @@
             if (mCurState != STATE_NOTHING) {
                 long dur = now - mStartTime;
                 if (dur > 0) {
-                    int idx = binarySearch(mDurationsTable, mDurationsTableSize, mCurState);
-                    int off;
-                    if (idx >= 0) {
-                        off = mDurationsTable[idx];
-                    } else {
-                        mStats.mAddLongTable = mDurationsTable;
-                        mStats.mAddLongTableSize = mDurationsTableSize;
-                        off = mStats.addLongData(~idx, mCurState, 1);
-                        mDurationsTable = mStats.mAddLongTable;
-                        mDurationsTableSize = mStats.mAddLongTableSize;
-                    }
-                    long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
-                    longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
+                    addDuration(mCurState, dur);
                 }
             }
             mStartTime = now;
         }
 
+        void addDuration(int state, long dur) {
+            int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
+            int off;
+            if (idx >= 0) {
+                off = mDurationsTable[idx];
+            } else {
+                mStats.mAddLongTable = mDurationsTable;
+                mStats.mAddLongTableSize = mDurationsTableSize;
+                off = mStats.addLongData(~idx, state, 1);
+                mDurationsTable = mStats.mAddLongTable;
+                mDurationsTableSize = mStats.mAddLongTableSize;
+            }
+            long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+            if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
+                    + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
+            longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
+        }
+
         void incStartedServices(int memFactor, long now) {
             if (mCommonProcess != this) {
                 mCommonProcess.incStartedServices(memFactor, now);
@@ -2094,46 +2251,53 @@
             mLastPssState = mCurState;
             mLastPssTime = SystemClock.uptimeMillis();
             if (mCurState != STATE_NOTHING) {
-                int idx = binarySearch(mPssTable, mPssTableSize, mCurState);
-                int off;
-                if (idx >= 0) {
-                    off = mPssTable[idx];
-                } else {
-                    mStats.mAddLongTable = mPssTable;
-                    mStats.mAddLongTableSize = mPssTableSize;
-                    off = mStats.addLongData(~idx, mCurState, PSS_COUNT);
-                    mPssTable = mStats.mAddLongTable;
-                    mPssTableSize = mStats.mAddLongTableSize;
+                addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
+            }
+        }
+
+        void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
+                long avgUss, long maxUss) {
+            int idx = binarySearch(mPssTable, mPssTableSize, state);
+            int off;
+            if (idx >= 0) {
+                off = mPssTable[idx];
+            } else {
+                mStats.mAddLongTable = mPssTable;
+                mStats.mAddLongTableSize = mPssTableSize;
+                off = mStats.addLongData(~idx, state, PSS_COUNT);
+                mPssTable = mStats.mAddLongTable;
+                mPssTableSize = mStats.mAddLongTableSize;
+            }
+            long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+            idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
+            long count = longs[idx+PSS_SAMPLE_COUNT];
+            if (count == 0) {
+                longs[idx+PSS_SAMPLE_COUNT] = inCount;
+                longs[idx+PSS_MINIMUM] = minPss;
+                longs[idx+PSS_AVERAGE] = avgPss;
+                longs[idx+PSS_MAXIMUM] = maxPss;
+                longs[idx+PSS_USS_MINIMUM] = minUss;
+                longs[idx+PSS_USS_AVERAGE] = avgUss;
+                longs[idx+PSS_USS_MAXIMUM] = maxUss;
+            } else {
+                longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
+                if (longs[idx+PSS_MINIMUM] > minPss) {
+                    longs[idx+PSS_MINIMUM] = minPss;
                 }
-                long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
-                idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
-                long count = longs[idx+PSS_SAMPLE_COUNT];
-                if (count == 0) {
-                    longs[idx+PSS_SAMPLE_COUNT] = 1;
-                    longs[idx+PSS_MINIMUM] = pss;
-                    longs[idx+PSS_AVERAGE] = pss;
-                    longs[idx+PSS_MAXIMUM] = pss;
-                    longs[idx+PSS_USS_MINIMUM] = uss;
-                    longs[idx+PSS_USS_AVERAGE] = uss;
-                    longs[idx+PSS_USS_MAXIMUM] = uss;
-                } else {
-                    longs[idx+PSS_SAMPLE_COUNT] = count+1;
-                    if (longs[idx+PSS_MINIMUM] > pss) {
-                        longs[idx+PSS_MINIMUM] = pss;
-                    }
-                    longs[idx+PSS_AVERAGE] = (long)(
-                            ((longs[idx+PSS_AVERAGE]*(double)count)+pss) / (count+1) );
-                    if (longs[idx+PSS_MAXIMUM] < pss) {
-                        longs[idx+PSS_MAXIMUM] = pss;
-                    }
-                    if (longs[idx+PSS_USS_MINIMUM] > uss) {
-                        longs[idx+PSS_USS_MINIMUM] = uss;
-                    }
-                    longs[idx+PSS_USS_AVERAGE] = (long)(
-                            ((longs[idx+PSS_USS_AVERAGE]*(double)count)+uss) / (count+1) );
-                    if (longs[idx+PSS_USS_MAXIMUM] < uss) {
-                        longs[idx+PSS_USS_MAXIMUM] = uss;
-                    }
+                longs[idx+PSS_AVERAGE] = (long)(
+                        ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
+                                / (count+inCount) );
+                if (longs[idx+PSS_MAXIMUM] < maxPss) {
+                    longs[idx+PSS_MAXIMUM] = maxPss;
+                }
+                if (longs[idx+PSS_USS_MINIMUM] > minUss) {
+                    longs[idx+PSS_USS_MINIMUM] = minUss;
+                }
+                longs[idx+PSS_USS_AVERAGE] = (long)(
+                        ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
+                                / (count+inCount) );
+                if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
+                    longs[idx+PSS_USS_MAXIMUM] = maxUss;
                 }
             }
         }
@@ -2240,6 +2404,7 @@
     public static final class ServiceState {
         final ProcessStats mStats;
         final String mPackage;
+        final String mName;
         ProcessState mProc;
 
         int mActive = 1;
@@ -2264,9 +2429,10 @@
         public int mExecState = STATE_NOTHING;
         long mExecStartTime;
 
-        public ServiceState(ProcessStats processStats, String pkg, ProcessState proc) {
+        public ServiceState(ProcessStats processStats, String pkg, String name, ProcessState proc) {
             mStats = processStats;
             mPackage = pkg;
+            mName = name;
             mProc = proc;
         }
 
@@ -2287,6 +2453,17 @@
             return mActive > 0;
         }
 
+        void add(ServiceState other) {
+            for (int i=0; i<other.mDurationsTableSize; i++) {
+                int ent = other.mDurationsTable[i];
+                int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+                addStateTime(state, other.mStats.getLong(ent, 0));
+            }
+            mStartedCount += other.mStartedCount;
+            mBoundCount += other.mBoundCount;
+            mExecCount += other.mExecCount;
+        }
+
         void resetSafely(long now) {
             mDurationsTable = null;
             mDurationsTableSize = 0;
@@ -2321,9 +2498,8 @@
             return true;
         }
 
-        void addStateTime(int opType, int memFactor, long time) {
+        void addStateTime(int state, long time) {
             if (time > 0) {
-                int state = opType + (memFactor*SERVICE_COUNT);
                 int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
                 int off;
                 if (idx >= 0) {
@@ -2342,15 +2518,16 @@
 
         void commitStateTime(long now) {
             if (mStartedState != STATE_NOTHING) {
-                addStateTime(SERVICE_STARTED, mStartedState, now - mStartedStartTime);
+                addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
+                        now - mStartedStartTime);
                 mStartedStartTime = now;
             }
             if (mBoundState != STATE_NOTHING) {
-                addStateTime(SERVICE_BOUND, mBoundState, now - mBoundStartTime);
+                addStateTime(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
                 mBoundStartTime = now;
             }
             if (mExecState != STATE_NOTHING) {
-                addStateTime(SERVICE_EXEC, mExecState, now - mExecStartTime);
+                addStateTime(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
                 mExecStartTime = now;
             }
         }
@@ -2362,7 +2539,8 @@
             int state = started ? memFactor : STATE_NOTHING;
             if (mStartedState != state) {
                 if (mStartedState != STATE_NOTHING) {
-                    addStateTime(SERVICE_STARTED, mStartedState, now - mStartedStartTime);
+                    addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
+                            now - mStartedStartTime);
                 } else if (started) {
                     mStartedCount++;
                 }
@@ -2386,7 +2564,8 @@
             int state = bound ? memFactor : STATE_NOTHING;
             if (mBoundState != state) {
                 if (mBoundState != STATE_NOTHING) {
-                    addStateTime(SERVICE_BOUND, mBoundState, now - mBoundStartTime);
+                    addStateTime(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
+                            now - mBoundStartTime);
                 } else if (bound) {
                     mBoundCount++;
                 }
@@ -2402,7 +2581,7 @@
             int state = executing ? memFactor : STATE_NOTHING;
             if (mExecState != state) {
                 if (mExecState != STATE_NOTHING) {
-                    addStateTime(SERVICE_EXEC, mExecState, now - mExecStartTime);
+                    addStateTime(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
                 } else if (executing) {
                     mExecCount++;
                 }
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2c482ea..bacfdf6 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -18,6 +18,9 @@
 
 #include <stdio.h>
 
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 61ace4a..f5eb389 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -220,6 +220,8 @@
                 } else {
                     whichHeap = HEAP_ASHMEM;
                 }
+            } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
+                whichHeap = HEAP_NATIVE;
             } else if (strncmp(name, "[stack", 6) == 0) {
                 whichHeap = HEAP_STACK;
             } else if (strncmp(name, "/dev/", 5) == 0) {
@@ -246,6 +248,8 @@
             } else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
                 whichHeap = HEAP_ART;
                 is_swappable = true;
+            } else if (strncmp(name, "[anon:", 6) == 0) {
+                whichHeap = HEAP_UNKNOWN;
             } else if (nameLen > 0) {
                 whichHeap = HEAP_UNKNOWN_MAP;
             } else if (start == prevEnd && prevHeap == HEAP_SO) {
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 1cdc6f5..0ea4074 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -114,9 +114,13 @@
      * canvas.
      */
     public Canvas() {
-        // 0 means no native bitmap
-        mNativeCanvas = initRaster(0);
-        mFinalizer = new CanvasFinalizer(mNativeCanvas);
+        if (!isHardwareAccelerated()) {
+            // 0 means no native bitmap
+            mNativeCanvas = initRaster(0);
+            mFinalizer = new CanvasFinalizer(mNativeCanvas);
+        } else {
+            mFinalizer = null;
+        }
     }
 
     /**
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 331cf6e..69d9916 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -431,6 +431,8 @@
         mRasterizer = paint.mRasterizer;
         if (paint.mShader != null) {
             mShader = paint.mShader.copy();
+        } else {
+            mShader = null;
         }
         mTypeface = paint.mTypeface;
         mXfermode = paint.mXfermode;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d1bae1e..707f662 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1112,8 +1112,6 @@
     setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
-    finishDrawTexture();
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -1256,8 +1254,6 @@
                             GL_UNSIGNED_SHORT, NULL));
         }
 
-        finishDrawTexture();
-
 #if DEBUG_LAYERS_AS_REGIONS
         drawRegionRects(layer->region);
 #endif
@@ -2021,9 +2017,6 @@
     mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
 }
 
-void OpenGLRenderer::finishDrawTexture() {
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
@@ -2308,8 +2301,6 @@
 
     glDrawArrays(GL_TRIANGLES, 0, count);
 
-    finishDrawTexture();
-
     int slot = mCaches.currentProgram->getAttrib("colors");
     if (slot >= 0) {
         glDisableVertexAttribArray(slot);
@@ -3134,8 +3125,6 @@
                 mesh += (drawCount / 6) * 4;
             }
 
-            finishDrawTexture();
-
 #if DEBUG_LAYERS_AS_REGIONS
             drawRegionRects(layer->region);
 #endif
@@ -3270,8 +3259,6 @@
     setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
-    finishDrawTexture();
 }
 
 // Same values used by Skia
@@ -3488,8 +3475,6 @@
     setupDrawMesh(vertices, texCoords, vbo);
 
     glDrawArrays(drawMode, 0, elementsCount);
-
-    finishDrawTexture();
 }
 
 void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
@@ -3515,8 +3500,6 @@
     setupDrawMeshIndices(vertices, texCoords, vbo);
 
     glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, NULL);
-
-    finishDrawTexture();
 }
 
 void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
@@ -3546,8 +3529,6 @@
     setupDrawMesh(vertices, texCoords);
 
     glDrawArrays(drawMode, 0, elementsCount);
-
-    finishDrawTexture();
 }
 
 void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2f8a2f0..1c3bfdc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -1003,7 +1003,6 @@
     void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
     void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
     void setupDrawIndexedVertices(GLvoid* vertices);
-    void finishDrawTexture();
     void accountForClear(SkXfermode::Mode mode);
 
     bool updateLayer(Layer* layer, bool inFrame);
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
index fdecda3..84dad8c 100644
--- a/media/mca/filterfw/native/core/gl_env.cpp
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -26,6 +26,8 @@
 #include <string>
 #include <EGL/eglext.h>
 
+#include <gui/GLConsumer.h>
+
 namespace android {
 namespace filterfw {
 
diff --git a/media/mca/filterfw/native/core/gl_env.h b/media/mca/filterfw/native/core/gl_env.h
index 81e1e9d..a709638 100644
--- a/media/mca/filterfw/native/core/gl_env.h
+++ b/media/mca/filterfw/native/core/gl_env.h
@@ -31,6 +31,9 @@
 #include <gui/Surface.h>
 
 namespace android {
+
+class GLConsumer;
+
 namespace filterfw {
 
 class ShaderProgram;
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 4c81006..43f95c3 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -2378,7 +2378,7 @@
     }
 
     @Override
-    public boolean setDeviceOwner(String packageName) {
+    public boolean setDeviceOwner(String packageName, String ownerName) {
         if (packageName == null
                 || !DeviceOwner.isInstalled(packageName, mContext.getPackageManager())) {
             throw new IllegalArgumentException("Invalid package name " + packageName
@@ -2386,7 +2386,7 @@
         }
         synchronized (this) {
             if (mDeviceOwner == null && !isDeviceProvisioned()) {
-                mDeviceOwner = new DeviceOwner(packageName);
+                mDeviceOwner = new DeviceOwner(packageName, ownerName);
                 mDeviceOwner.writeOwnerFile();
                 return true;
             } else {
@@ -2415,6 +2415,17 @@
         return null;
     }
 
+    @Override
+    public String getDeviceOwnerName() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+        synchronized (this) {
+            if (mDeviceOwner != null) {
+                return mDeviceOwner.getName();
+            }
+        }
+        return null;
+    }
+
     private boolean isDeviceProvisioned() {
         return Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.DEVICE_PROVISIONED, 0) > 0;
@@ -2488,15 +2499,18 @@
     static class DeviceOwner {
         private static final String DEVICE_OWNER_XML = "device_owner.xml";
         private static final String TAG_DEVICE_OWNER = "device-owner";
+        private static final String ATTR_NAME = "name";
         private static final String ATTR_PACKAGE = "package";
         private String mPackageName;
+        private String mOwnerName;
 
         DeviceOwner() {
             readOwnerFile();
         }
 
-        DeviceOwner(String packageName) {
+        DeviceOwner(String packageName, String ownerName) {
             this.mPackageName = packageName;
+            this.mOwnerName = ownerName;
         }
 
         static boolean isRegistered() {
@@ -2508,6 +2522,10 @@
             return mPackageName;
         }
 
+        String getName() {
+            return mOwnerName;
+        }
+
         static boolean isInstalled(String packageName, PackageManager pm) {
             try {
                 PackageInfo pi;
@@ -2539,6 +2557,7 @@
                             "Device Owner file does not start with device-owner tag: found " + tag);
                 }
                 mPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+                mOwnerName = parser.getAttributeValue(null, ATTR_NAME);
                 input.close();
             } catch (XmlPullParserException xppe) {
                 Slog.e(TAG, "Error parsing device-owner file\n" + xppe);
@@ -2563,6 +2582,9 @@
                 out.startDocument(null, true);
                 out.startTag(null, TAG_DEVICE_OWNER);
                 out.attribute(null, ATTR_PACKAGE, mPackageName);
+                if (mOwnerName != null) {
+                    out.attribute(null, ATTR_NAME, mOwnerName);
+                }
                 out.endTag(null, TAG_DEVICE_OWNER);
                 out.endDocument();
                 out.flush();
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 81b5618..6611a24b 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -103,17 +103,7 @@
 
     public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
             String processName, String className) {
-        final ProcessStats.PackageState as = mProcessStats.getPackageStateLocked(packageName, uid);
-        ProcessStats.ServiceState ss = as.mServices.get(className);
-        if (ss != null) {
-            ss.makeActive();
-            return ss;
-        }
-        final ProcessStats.ProcessState ps = mProcessStats.getProcessStateLocked(packageName,
-                uid, processName);
-        ss = new ProcessStats.ServiceState(mProcessStats, packageName, ps);
-        as.mServices.put(className, ss);
-        return ss;
+        return mProcessStats.getServiceStateLocked(packageName, uid, processName, className);
     }
 
     public boolean isMemFactorLowered() {
@@ -271,40 +261,11 @@
         }
     }
 
-    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
-        int pos = 0;
-        int avail = stream.available();
-        byte[] data = new byte[avail];
-        while (true) {
-            int amt = stream.read(data, pos, data.length-pos);
-            //Log.i("foo", "Read " + amt + " bytes at " + pos
-            //        + " of avail " + data.length);
-            if (amt <= 0) {
-                //Log.i("foo", "**** FINISHED READING: pos=" + pos
-                //        + " len=" + data.length);
-                return data;
-            }
-            pos += amt;
-            avail = stream.available();
-            if (avail > data.length-pos) {
-                byte[] newData = new byte[pos+avail];
-                System.arraycopy(data, 0, newData, 0, pos);
-                data = newData;
-            }
-        }
-    }
-
     boolean readLocked(ProcessStats stats, AtomicFile file) {
         try {
             FileInputStream stream = file.openRead();
-
-            byte[] raw = readFully(stream);
-            Parcel in = Parcel.obtain();
-            in.unmarshall(raw, 0, raw.length);
-            in.setDataPosition(0);
+            stats.read(stream);
             stream.close();
-
-            stats.readFromParcel(in);
             if (stats.mReadError != null) {
                 Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
                 if (DEBUG) {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 6fa9cd0..73325cb 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -1272,6 +1272,11 @@
                             if (mIsWallpaper) {
                                 mService.dispatchWallpaperVisibility(w, true);
                             }
+                            // This draw means the difference between unique content and mirroring.
+                            // Run another pass through performLayout to set mHasContent in the
+                            // LogicalDisplay.
+                            mAnimator.setPendingLayoutChanges(w.getDisplayId(),
+                                    WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
                         } else {
                             w.mOrientationChanging = false;
                         }