Merge "Fix bugs around inflated child fragments Framework edition"
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index ec21882..af41db0 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -37,6 +37,8 @@
 import android.view.Window;
 import android.widget.ImageView;
 
+import com.android.internal.view.OneShotPreDrawListener;
+
 import java.util.ArrayList;
 import java.util.Collection;
 
@@ -570,16 +572,9 @@
     protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
         final View decorView = getDecor();
         if (decorView != null) {
-            decorView.getViewTreeObserver().addOnPreDrawListener(
-                    new ViewTreeObserver.OnPreDrawListener() {
-                        @Override
-                        public boolean onPreDraw() {
-                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                            notifySharedElementEnd(snapshots);
-                            return true;
-                        }
-                    }
-            );
+            OneShotPreDrawListener.add(decorView, () -> {
+                notifySharedElementEnd(snapshots);
+            });
         }
     }
 
@@ -816,6 +811,7 @@
                 if (moveWithParent && !isInTransitionGroup(parent, decor)) {
                     GhostViewListeners listener = new GhostViewListeners(view, parent, decor);
                     parent.getViewTreeObserver().addOnPreDrawListener(listener);
+                    parent.addOnAttachStateChangeListener(listener);
                     mGhostViewListeners.add(listener);
                 }
             }
@@ -842,8 +838,7 @@
         int numListeners = mGhostViewListeners.size();
         for (int i = 0; i < numListeners; i++) {
             GhostViewListeners listener = mGhostViewListeners.get(i);
-            ViewGroup parent = (ViewGroup) listener.getView().getParent();
-            parent.getViewTreeObserver().removeOnPreDrawListener(listener);
+            listener.removeListener();
         }
         mGhostViewListeners.clear();
 
@@ -874,15 +869,9 @@
     protected void scheduleGhostVisibilityChange(final int visibility) {
         final View decorView = getDecor();
         if (decorView != null) {
-            decorView.getViewTreeObserver()
-                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                        @Override
-                        public boolean onPreDraw() {
-                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                            setGhostVisibility(visibility);
-                            return true;
-                        }
-                    });
+            OneShotPreDrawListener.add(decorView, () -> {
+                setGhostVisibility(visibility);
+            });
         }
     }
 
@@ -988,16 +977,19 @@
         }
     }
 
-    private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
+    private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener,
+            View.OnAttachStateChangeListener {
         private View mView;
         private ViewGroup mDecor;
         private View mParent;
         private Matrix mMatrix = new Matrix();
+        private ViewTreeObserver mViewTreeObserver;
 
         public GhostViewListeners(View view, View parent, ViewGroup decor) {
             mView = view;
             mParent = parent;
             mDecor = decor;
+            mViewTreeObserver = parent.getViewTreeObserver();
         }
 
         public View getView() {
@@ -1008,13 +1000,32 @@
         public boolean onPreDraw() {
             GhostView ghostView = GhostView.getGhost(mView);
             if (ghostView == null) {
-                mParent.getViewTreeObserver().removeOnPreDrawListener(this);
+                removeListener();
             } else {
                 GhostView.calculateMatrix(mView, mDecor, mMatrix);
                 ghostView.setMatrix(mMatrix);
             }
             return true;
         }
+
+        public void removeListener() {
+            if (mViewTreeObserver.isAlive()) {
+                mViewTreeObserver.removeOnPreDrawListener(this);
+            } else {
+                mParent.getViewTreeObserver().removeOnPreDrawListener(this);
+            }
+            mParent.removeOnAttachStateChangeListener(this);
+        }
+
+        @Override
+        public void onViewAttachedToWindow(View v) {
+            mViewTreeObserver = v.getViewTreeObserver();
+        }
+
+        @Override
+        public void onViewDetachedFromWindow(View v) {
+            removeListener();
+        }
     }
 
     static class SharedElementOriginalState {
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 60046b5..f2616ff 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -22,9 +22,10 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.view.Window;
 
+import com.android.internal.view.OneShotPreDrawListener;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
@@ -321,18 +322,12 @@
                 }
                 if (delayExitBack && decor != null) {
                     final ViewGroup finalDecor = decor;
-                    decor.getViewTreeObserver().addOnPreDrawListener(
-                            new ViewTreeObserver.OnPreDrawListener() {
-                                @Override
-                                public boolean onPreDraw() {
-                                    finalDecor.getViewTreeObserver().removeOnPreDrawListener(this);
-                                    if (mReturnExitCoordinator != null) {
-                                        mReturnExitCoordinator.startExit(activity.mResultCode,
-                                                activity.mResultData);
-                                    }
-                                    return true;
-                                }
-                            });
+                    OneShotPreDrawListener.add(decor, () -> {
+                        if (mReturnExitCoordinator != null) {
+                            mReturnExitCoordinator.startExit(activity.mResultCode,
+                                    activity.mResultData);
+                        }
+                    });
                 } else {
                     mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
                 }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 27a0200..3464c4d 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -30,10 +30,11 @@
 import android.view.ViewGroup;
 import android.view.ViewGroupOverlay;
 import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnPreDrawListener;
 import android.view.Window;
 import android.view.accessibility.AccessibilityEvent;
 
+import com.android.internal.view.OneShotPreDrawListener;
+
 import java.util.ArrayList;
 
 /**
@@ -58,7 +59,7 @@
     private boolean mAreViewsReady;
     private boolean mIsViewsTransitionStarted;
     private Transition mEnterViewsTransition;
-    private OnPreDrawListener mViewsReadyListener;
+    private OneShotPreDrawListener mViewsReadyListener;
     private final boolean mIsCrossTask;
 
     public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
@@ -74,12 +75,17 @@
         mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
         final View decorView = getDecor();
         if (decorView != null) {
-            decorView.getViewTreeObserver().addOnPreDrawListener(
+            final ViewTreeObserver viewTreeObserver = decorView.getViewTreeObserver();
+            viewTreeObserver.addOnPreDrawListener(
                     new ViewTreeObserver.OnPreDrawListener() {
                         @Override
                         public boolean onPreDraw() {
                             if (mIsReadyForTransition) {
-                                decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+                                if (viewTreeObserver.isAlive()) {
+                                    viewTreeObserver.removeOnPreDrawListener(this);
+                                } else {
+                                    decorView.getViewTreeObserver().removeOnPreDrawListener(this);
+                                }
                             }
                             return mIsReadyForTransition;
                         }
@@ -147,16 +153,10 @@
                 (sharedElements.isEmpty() || !sharedElements.valueAt(0).isLayoutRequested()))) {
             viewsReady(sharedElements);
         } else {
-            mViewsReadyListener = new ViewTreeObserver.OnPreDrawListener() {
-                @Override
-                public boolean onPreDraw() {
-                    mViewsReadyListener = null;
-                    decor.getViewTreeObserver().removeOnPreDrawListener(this);
-                    viewsReady(sharedElements);
-                    return true;
-                }
-            };
-            decor.getViewTreeObserver().addOnPreDrawListener(mViewsReadyListener);
+            mViewsReadyListener = OneShotPreDrawListener.add(decor, () -> {
+                mViewsReadyListener = null;
+                viewsReady(sharedElements);
+            });
             decor.invalidate();
         }
     }
@@ -206,19 +206,13 @@
             moveSharedElementsToOverlay();
             mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
         } else if (decorView != null) {
-            decorView.getViewTreeObserver()
-                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                        @Override
-                        public boolean onPreDraw() {
-                            decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                            if (mResultReceiver != null) {
-                                Bundle state = captureSharedElementState();
-                                moveSharedElementsToOverlay();
-                                mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
-                            }
-                            return true;
-                        }
-                    });
+            OneShotPreDrawListener.add(decorView, () -> {
+                if (mResultReceiver != null) {
+                    Bundle state = captureSharedElementState();
+                    moveSharedElementsToOverlay();
+                    mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
+                }
+            });
         }
         if (allowOverlappingTransitions()) {
             startEnterTransitionOnly();
@@ -271,7 +265,7 @@
             mIsReadyForTransition = true;
             final ViewGroup decor = getDecor();
             if (decor != null && mViewsReadyListener != null) {
-                decor.getViewTreeObserver().removeOnPreDrawListener(mViewsReadyListener);
+                mViewsReadyListener.removeListener();
                 mViewsReadyListener = null;
             }
             showViews(mTransitioningViews, true);
@@ -457,20 +451,11 @@
             public void onSharedElementsReady() {
                 final View decorView = getDecor();
                 if (decorView != null) {
-                    decorView.getViewTreeObserver()
-                            .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                                @Override
-                                public boolean onPreDraw() {
-                                    decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                                    startTransition(new Runnable() {
-                                        @Override
-                                        public void run() {
-                                            startSharedElementTransition(sharedElementState);
-                                        }
-                                    });
-                                    return false;
-                                }
-                            });
+                    OneShotPreDrawListener.add(decorView, () -> {
+                        startTransition(() -> {
+                                startSharedElementTransition(sharedElementState);
+                        });
+                    });
                     decorView.invalidate();
                 }
             }
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index b5b6e4a..6a79e6c 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -34,9 +34,10 @@
 import android.transition.TransitionManager;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.view.Window;
 
+import com.android.internal.view.OneShotPreDrawListener;
+
 import java.util.ArrayList;
 
 /**
@@ -168,15 +169,9 @@
         });
         final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle,
                 mSharedElementNames);
-        decorView.getViewTreeObserver()
-                .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        decorView.getViewTreeObserver().removeOnPreDrawListener(this);
-                        setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots);
-                        return true;
-                    }
-                });
+        OneShotPreDrawListener.add(decorView, () -> {
+            setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots);
+        });
         setGhostVisibility(View.INVISIBLE);
         scheduleGhostVisibilityChange(View.INVISIBLE);
         if (mListener != null) {
diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java
index d27dff5..088fd08 100644
--- a/core/java/android/app/FragmentTransition.java
+++ b/core/java/android/app/FragmentTransition.java
@@ -24,7 +24,8 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
+
+import com.android.internal.view.OneShotPreDrawListener;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -320,16 +321,9 @@
                 && exitingFragment.mHidden && exitingFragment.mHiddenChanged) {
             exitingFragment.setHideReplaced(true);
             final View fragmentView = exitingFragment.getView();
-            final ViewGroup container = exitingFragment.mContainer;
-            container.getViewTreeObserver().addOnPreDrawListener(
-                    new ViewTreeObserver.OnPreDrawListener() {
-                        @Override
-                        public boolean onPreDraw() {
-                            container.getViewTreeObserver().removeOnPreDrawListener(this);
-                            setViewVisibility(exitingViews, View.INVISIBLE);
-                            return true;
-                        }
-                    });
+            OneShotPreDrawListener.add(exitingFragment.mContainer, () -> {
+                setViewVisibility(exitingViews, View.INVISIBLE);
+            });
             exitTransition.addListener(new Transition.TransitionListenerAdapter() {
                 @Override
                 public void onTransitionEnd(Transition transition) {
@@ -364,30 +358,22 @@
             final Transition enterTransition, final ArrayList<View> enteringViews,
             final Transition exitTransition, final ArrayList<View> exitingViews) {
 
-        sceneRoot.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+        OneShotPreDrawListener.add(sceneRoot, () -> {
+            if (enterTransition != null) {
+                enterTransition.removeTarget(nonExistentView);
+                ArrayList<View> views = configureEnteringExitingViews(
+                        enterTransition, inFragment, sharedElementsIn, nonExistentView);
+                enteringViews.addAll(views);
+            }
 
-                        if (enterTransition != null) {
-                            enterTransition.removeTarget(nonExistentView);
-                            ArrayList<View> views = configureEnteringExitingViews(
-                                    enterTransition, inFragment, sharedElementsIn, nonExistentView);
-                            enteringViews.addAll(views);
-                        }
-
-                        if (exitingViews != null) {
-                            ArrayList<View> tempExiting = new ArrayList<>();
-                            tempExiting.add(nonExistentView);
-                            replaceTargets(exitTransition, exitingViews, tempExiting);
-                            exitingViews.clear();
-                            exitingViews.add(nonExistentView);
-                        }
-
-                        return true;
-                    }
-                });
+            if (exitingViews != null) {
+                ArrayList<View> tempExiting = new ArrayList<>();
+                tempExiting.add(nonExistentView);
+                replaceTargets(exitTransition, exitingViews, tempExiting);
+                exitingViews.clear();
+                exitingViews.add(nonExistentView);
+            }
+        });
     }
 
     /**
@@ -541,19 +527,13 @@
             epicenterView = null;
         }
 
-        sceneRoot.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
-                        callSharedElementStartEnd(inFragment, outFragment, inIsPop,
-                                inSharedElements, false);
-                        if (epicenterView != null) {
-                            epicenterView.getBoundsOnScreen(epicenter);
-                        }
-                        return true;
-                    }
-                });
+        OneShotPreDrawListener.add(sceneRoot, () -> {
+            callSharedElementStartEnd(inFragment, outFragment, inIsPop,
+                    inSharedElements, false);
+            if (epicenterView != null) {
+                epicenterView.getBoundsOnScreen(epicenter);
+            }
+        });
         return sharedElementTransition;
     }
 
@@ -643,36 +623,30 @@
 
         TransitionSet finalSharedElementTransition = sharedElementTransition;
 
-        sceneRoot.getViewTreeObserver().addOnPreDrawListener(
-                new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
-                        ArrayMap<String, View> inSharedElements = captureInSharedElements(
-                                nameOverrides, finalSharedElementTransition, fragments);
+        OneShotPreDrawListener.add(sceneRoot, () -> {
+            ArrayMap<String, View> inSharedElements = captureInSharedElements(
+                    nameOverrides, finalSharedElementTransition, fragments);
 
-                        if (inSharedElements != null) {
-                            sharedElementsIn.addAll(inSharedElements.values());
-                            sharedElementsIn.add(nonExistentView);
-                        }
+            if (inSharedElements != null) {
+                sharedElementsIn.addAll(inSharedElements.values());
+                sharedElementsIn.add(nonExistentView);
+            }
 
-                        callSharedElementStartEnd(inFragment, outFragment, inIsPop,
-                                inSharedElements, false);
-                        if (finalSharedElementTransition != null) {
-                            finalSharedElementTransition.getTargets().clear();
-                            finalSharedElementTransition.getTargets().addAll(sharedElementsIn);
-                            replaceTargets(finalSharedElementTransition, sharedElementsOut,
-                                    sharedElementsIn);
+            callSharedElementStartEnd(inFragment, outFragment, inIsPop,
+                    inSharedElements, false);
+            if (finalSharedElementTransition != null) {
+                finalSharedElementTransition.getTargets().clear();
+                finalSharedElementTransition.getTargets().addAll(sharedElementsIn);
+                replaceTargets(finalSharedElementTransition, sharedElementsOut,
+                        sharedElementsIn);
 
-                            final View inEpicenterView = getInEpicenterView(inSharedElements,
-                                    fragments, enterTransition, inIsPop);
-                            if (inEpicenterView != null) {
-                                inEpicenterView.getBoundsOnScreen(inEpicenter);
-                            }
-                        }
-                        return true;
-                    }
-                });
+                final View inEpicenterView = getInEpicenterView(inSharedElements,
+                        fragments, enterTransition, inIsPop);
+                if (inEpicenterView != null) {
+                    inEpicenterView.getBoundsOnScreen(inEpicenter);
+                }
+            }
+        });
         return sharedElementTransition;
     }
 
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 857610d..fd6cddb 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -147,13 +147,7 @@
             if (cursor == null) {
                 return null;
             }
-
-            if ("com.google.android.gms".equals(mPackageName)) {
-                // They're casting to a concrete subclass, sigh
-                return cursor;
-            } else {
-                return new CursorWrapperInner(cursor);
-            }
+            return new CursorWrapperInner(cursor);
         } catch (DeadObjectException e) {
             if (!mStable) {
                 mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 479f493..6e4d78d 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -242,14 +242,20 @@
 
         Transition mTransition;
         ViewGroup mSceneRoot;
+        final ViewTreeObserver mViewTreeObserver;
 
         MultiListener(Transition transition, ViewGroup sceneRoot) {
             mTransition = transition;
             mSceneRoot = sceneRoot;
+            mViewTreeObserver = mSceneRoot.getViewTreeObserver();
         }
 
         private void removeListeners() {
-            mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+            if (mViewTreeObserver.isAlive()) {
+                mViewTreeObserver.removeOnPreDrawListener(this);
+            } else {
+                mSceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
+            }
             mSceneRoot.removeOnAttachStateChangeListener(this);
         }
 
diff --git a/core/java/com/android/internal/view/OneShotPreDrawListener.java b/core/java/com/android/internal/view/OneShotPreDrawListener.java
new file mode 100644
index 0000000..98ffd82
--- /dev/null
+++ b/core/java/com/android/internal/view/OneShotPreDrawListener.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.view;
+
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+/**
+ * An OnPreDrawListener that will remove itself after one OnPreDraw call. Typical
+ * usage is:
+ * <pre><code>
+ *     OneShotPreDrawListener.add(view, () -> { view.doSomething(); })
+ * </code></pre>
+ * <p>
+ * The onPreDraw always returns true.
+ * <p>
+ * The listener will also remove itself from the ViewTreeObserver when the view
+ * is detached from the view hierarchy. In that case, the Runnable will never be
+ * executed.
+ */
+public class OneShotPreDrawListener implements ViewTreeObserver.OnPreDrawListener,
+        View.OnAttachStateChangeListener {
+    private final View mView;
+    private ViewTreeObserver mViewTreeObserver;
+    private final Runnable mRunnable;
+
+    private OneShotPreDrawListener(View view, Runnable runnable) {
+        mView = view;
+        mViewTreeObserver = view.getViewTreeObserver();
+        mRunnable = runnable;
+    }
+
+    /**
+     * Creates a OneShotPreDrawListener and adds it to view's ViewTreeObserver.
+     * @param view The view whose ViewTreeObserver the OnPreDrawListener should listen.
+     * @param runnable The Runnable to execute in the OnPreDraw (once)
+     * @return The added OneShotPreDrawListener. It can be removed prior to
+     * the onPreDraw by calling {@link #removeListener()}.
+     */
+    public static OneShotPreDrawListener add(View view, Runnable runnable) {
+        OneShotPreDrawListener listener = new OneShotPreDrawListener(view, runnable);
+        view.getViewTreeObserver().addOnPreDrawListener(listener);
+        view.addOnAttachStateChangeListener(listener);
+        return listener;
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        removeListener();
+        mRunnable.run();
+        return true;
+    }
+
+    /**
+     * Removes the listener from the ViewTreeObserver. This is useful to call if the
+     * callback should be removed prior to {@link #onPreDraw()}.
+     */
+    public void removeListener() {
+        if (mViewTreeObserver.isAlive()) {
+            mViewTreeObserver.removeOnPreDrawListener(this);
+        } else {
+            mView.getViewTreeObserver().removeOnPreDrawListener(this);
+        }
+        mView.removeOnAttachStateChangeListener(this);
+    }
+
+    @Override
+    public void onViewAttachedToWindow(View v) {
+        mViewTreeObserver = v.getViewTreeObserver();
+    }
+
+    @Override
+    public void onViewDetachedFromWindow(View v) {
+        removeListener();
+    }
+}
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 0de46e6..7e417b4 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -93,7 +93,7 @@
     if (jbitmap) {
         // Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
         // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
-        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
+        android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
     }
 
     sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
index 6bd82e9..0920488 100644
--- a/core/jni/android_os_HwBlob.h
+++ b/core/jni/android_os_HwBlob.h
@@ -20,6 +20,7 @@
 #include <android-base/macros.h>
 #include <jni.h>
 #include <hidl/HidlSupport.h>
+#include <hwbinder/Parcel.h>
 #include <utils/RefBase.h>
 #include <utils/Vector.h>
 
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 1a67cee..a10d807 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -26,6 +26,7 @@
 
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
+#include <hidl/HidlTransportSupport.h>
 #include <hidl/Status.h>
 #include <nativehelper/ScopedLocalRef.h>
 
@@ -383,7 +384,7 @@
     hardware::Parcel *parcel =
         JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
-    status_t err = status.writeToParcel(parcel);
+    status_t err = ::android::hardware::writeToParcel(status, parcel);
     signalExceptionForError(env, err);
 }
 
@@ -394,7 +395,7 @@
         JHwParcel::GetNativeContext(env, thiz)->getParcel();
 
     Status status;
-    status_t err = status.readFromParcel(*parcel);
+    status_t err = ::android::hardware::readFromParcel(&status, *parcel);
     signalExceptionForError(env, err);
 }
 
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index e410d71..9c4cb09 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -133,7 +133,7 @@
 
     // Shaders
     bool hasBitmap;
-    bool isBitmapNpot;
+    bool useShaderBasedWrap;
 
     bool hasVertexAlpha;
     bool useShadowAlphaInterp;
@@ -180,7 +180,7 @@
         modulate = false;
 
         hasBitmap = false;
-        isBitmapNpot = false;
+        useShaderBasedWrap = false;
 
         hasGradient = false;
         gradientType = kGradientLinear;
@@ -234,7 +234,7 @@
         if (hasAlpha8Texture) key |= PROGRAM_KEY_A8_TEXTURE;
         if (hasBitmap) {
             key |= PROGRAM_KEY_BITMAP;
-            if (isBitmapNpot) {
+            if (useShaderBasedWrap) {
                 key |= PROGRAM_KEY_BITMAP_NPOT;
                 key |= getEnumForWrap(bitmapWrapS) << PROGRAM_BITMAP_WRAPS_SHIFT;
                 key |= getEnumForWrap(bitmapWrapT) << PROGRAM_BITMAP_WRAPT_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 1afc978..0c2309f 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -707,7 +707,7 @@
     if (blendFramebuffer) {
         generateBlend(shader, "blendFramebuffer", description.framebufferMode);
     }
-    if (description.isBitmapNpot) {
+    if (description.useShaderBasedWrap) {
         generateTextureWrap(shader, description.bitmapWrapS, description.bitmapWrapT);
     }
     if (description.hasGradient) {
@@ -736,7 +736,7 @@
             shader.append(gFS_Main_FetchGradient[gradientIndex(description)]);
         }
         if (description.hasBitmap) {
-            if (!description.isBitmapNpot) {
+            if (!description.useShaderBasedWrap) {
                 shader.append(gFS_Main_FetchBitmap);
             } else {
                 shader.append(gFS_Main_FetchBitmapNpot);
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 971c2a3..34e6a06 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -58,7 +58,7 @@
 }
 
 static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
-    caches->textureState().bindTexture(texture->id());
+    caches->textureState().bindTexture(texture->target(), texture->id());
     texture->setWrapST(wrapS, wrapT);
 }
 
@@ -218,10 +218,13 @@
     const float height = outData->bitmapTexture->height();
 
     description->hasBitmap = true;
-    if (!caches.extensions().hasNPot()
+    // gralloc doesn't support non-clamp modes
+    if (hwuiBitmap->isHardware() || (!caches.extensions().hasNPot()
             && (!isPowerOfTwo(width) || !isPowerOfTwo(height))
-            && (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode)) {
-        description->isBitmapNpot = true;
+            && (xy[0] != SkShader::kClamp_TileMode || xy[1] != SkShader::kClamp_TileMode))) {
+        // need non-clamp mode, but it's not supported for this draw,
+        // so enable custom shader logic to mimic
+        description->useShaderBasedWrap = true;
         description->bitmapWrapS = gTileModes[xy[0]];
         description->bitmapWrapT = gTileModes[xy[1]];
 
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 2077b0e..c028f115 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -413,7 +413,6 @@
     case PixelStorageType::Heap:
         return mPixelStorage.heap.address;
     case PixelStorageType::Hardware:
-        LOG_ALWAYS_FATAL_IF("Can't get address for hardware bitmap");
         return nullptr;
     }
 }
@@ -470,6 +469,12 @@
     outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
 }
 
+void Bitmap::getSkBitmapForShaders(SkBitmap* outBitmap) {
+    outBitmap->setInfo(info(), rowBytes());
+    outBitmap->setPixelRef(this);
+    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
+}
+
 void Bitmap::getBounds(SkRect* bounds) const {
     SkASSERT(bounds);
     bounds->set(0, 0, SkIntToScalar(info().width()), SkIntToScalar(info().height()));
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 3940381..663238c 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -85,6 +85,10 @@
 
     void getSkBitmap(SkBitmap* outBitmap);
 
+    // Ugly hack: in case of hardware bitmaps, it sets nullptr as pixels pointer
+    // so it would crash if anyone tries to render this bitmap.
+    void getSkBitmapForShaders(SkBitmap* outBitmap);
+
     int getAshmemFd() const;
     size_t getAllocationByteCount() const;
 
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
new file mode 100644
index 0000000..9b0b950
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "TestSceneBase.h"
+#include "utils/Color.h"
+#include "tests/common/BitmapAllocationTestUtils.h"
+
+class BitmapShaders;
+
+static bool _BitmapShaders(
+        BitmapAllocationTestUtils::registerBitmapAllocationScene<BitmapShaders>(
+                "bitmapShader", "Draws bitmap shaders with repeat and mirror modes."));
+
+class BitmapShaders : public TestScene {
+public:
+    BitmapShaders(BitmapAllocationTestUtils::BitmapAllocator allocator)
+        : TestScene()
+        , mAllocator(allocator) { }
+
+    sp<RenderNode> card;
+    void createContent(int width, int height, Canvas& canvas) override {
+        canvas.drawColor(Color::Grey_200, SkBlendMode::kSrcOver);
+        sk_sp<Bitmap> hwuiBitmap = mAllocator(200, 200, kRGBA_8888_SkColorType,
+                            [](SkBitmap& skBitmap) {
+            skBitmap.eraseColor(Color::White);
+            SkCanvas skCanvas(skBitmap);
+            SkPaint skPaint;
+            skPaint.setColor(Color::Red_500);
+            skCanvas.drawRect(SkRect::MakeWH(100, 100), skPaint);
+            skPaint.setColor(Color::Blue_500);
+            skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
+        });
+
+        SkBitmap bitmap;
+        SkPaint paint;
+        hwuiBitmap->getSkBitmapForShaders(&bitmap);
+
+        sk_sp<SkShader> repeatShader = SkMakeBitmapShader(bitmap,
+                SkShader::TileMode::kRepeat_TileMode,
+                SkShader::TileMode::kRepeat_TileMode,
+                nullptr,
+                kNever_SkCopyPixelsMode,
+                nullptr);
+        paint.setShader(std::move(repeatShader));
+        canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
+
+        sk_sp<SkShader> mirrorShader = SkMakeBitmapShader(bitmap,
+                SkShader::TileMode::kMirror_TileMode,
+                SkShader::TileMode::kMirror_TileMode,
+                nullptr,
+                kNever_SkCopyPixelsMode,
+                nullptr);
+        paint.setShader(std::move(mirrorShader));
+        canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
+    }
+
+    void doFrame(int frameNr) override { }
+
+    BitmapAllocationTestUtils::BitmapAllocator mAllocator;
+};
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6eb8927..271107f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -208,6 +208,7 @@
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.Base64;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.ExceptionUtils;
@@ -286,6 +287,7 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.SecureRandom;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
@@ -337,7 +339,7 @@
  *
  * <pre>
  * $ runtest -c android.content.pm.PackageManagerTests frameworks-core
- * $ cts-tradefed run commandAndExit cts -m AppSecurityTests
+ * $ cts-tradefed run commandAndExit cts -m CtsAppSecurityHostTestCases
  * </pre>
  */
 public class PackageManagerService extends IPackageManager.Stub {
@@ -10412,9 +10414,9 @@
                     .getPrivAppPermissions(pkg.packageName);
             boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);
             if (!whitelisted) {
-                Slog.e(TAG, "Not granting privileged permission " + perm + " for package "
+                // Log for now. TODO Enforce permissions
+                Slog.w(TAG, "Privileged permission " + perm + " for package "
                         + pkg.packageName + " - not in privapp-permissions whitelist");
-                return false;
             }
         }
         boolean allowed = (compareSignatures(
@@ -14281,11 +14283,13 @@
     }
 
     private File getNextCodePath(File targetDir, String packageName) {
-        int suffix = 1;
         File result;
+        SecureRandom random = new SecureRandom();
+        byte[] bytes = new byte[16];
         do {
+            random.nextBytes(bytes);
+            String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
             result = new File(targetDir, packageName + "-" + suffix);
-            suffix++;
         } while (result.exists());
         return result;
     }
diff --git a/tools/preload2/Android.mk b/tools/preload2/Android.mk
index ce877b3..09d95ff 100644
--- a/tools/preload2/Android.mk
+++ b/tools/preload2/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 
 # To connect to devices (and take hprof dumps).
-LOCAL_STATIC_JAVA_LIBRARIES := ddmlib-prebuilt
+LOCAL_STATIC_JAVA_LIBRARIES := ddmlib-prebuilt tools-common-prebuilt
 
 # To process hprof dumps.
 LOCAL_STATIC_JAVA_LIBRARIES += perflib-prebuilt trove-prebuilt guavalib