Merge "Handle apps that share a UID with the system_server correctly." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 943fef5..23c7d03 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22705,7 +22705,7 @@
   public class UserManager {
     method public android.os.Bundle getApplicationRestrictions(java.lang.String);
     method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
-    method public java.lang.String getBadgedLabelForUser(java.lang.String, android.os.UserHandle);
+    method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
     method public long getSerialNumberForUser(android.os.UserHandle);
     method public int getUserCount();
     method public android.os.UserHandle getUserForSerialNumber(long);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0bab7b2..de5b9c4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2205,6 +2205,7 @@
                     cl, component.getClassName(), r.intent);
             StrictMode.incrementExpectedActivityCount(activity.getClass());
             r.intent.setExtrasClassLoader(cl);
+            r.intent.prepareToEnterProcess();
             if (r.state != null) {
                 r.state.setClassLoader(cl);
             }
@@ -2429,6 +2430,7 @@
         for (int i=0; i<N; i++) {
             Intent intent = intents.get(i);
             intent.setExtrasClassLoader(r.activity.getClassLoader());
+            intent.prepareToEnterProcess();
             r.activity.mFragments.noteStateNotSaved();
             mInstrumentation.callActivityOnNewIntent(r.activity, intent);
         }
@@ -2552,6 +2554,7 @@
         try {
             java.lang.ClassLoader cl = packageInfo.getClassLoader();
             data.intent.setExtrasClassLoader(cl);
+            data.intent.prepareToEnterProcess();
             data.setExtrasClassLoader(cl);
             receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
         } catch (Exception e) {
@@ -2753,6 +2756,7 @@
         if (s != null) {
             try {
                 data.intent.setExtrasClassLoader(s.getClassLoader());
+                data.intent.prepareToEnterProcess();
                 try {
                     if (!data.rebind) {
                         IBinder binder = s.onBind(data.intent);
@@ -2781,6 +2785,7 @@
         if (s != null) {
             try {
                 data.intent.setExtrasClassLoader(s.getClassLoader());
+                data.intent.prepareToEnterProcess();
                 boolean doRebind = s.onUnbind(data.intent);
                 try {
                     if (doRebind) {
@@ -2856,6 +2861,7 @@
             try {
                 if (data.args != null) {
                     data.args.setExtrasClassLoader(s.getClassLoader());
+                    data.args.prepareToEnterProcess();
                 }
                 int res;
                 if (!data.taskRemoved) {
@@ -3506,6 +3512,7 @@
             try {
                 if (ri.mData != null) {
                     ri.mData.setExtrasClassLoader(r.activity.getClassLoader());
+                    ri.mData.prepareToEnterProcess();
                 }
                 if (DEBUG_RESULTS) Slog.v(TAG,
                         "Delivering result to activity " + r + " : " + ri);
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 7a16ef8..d19604b 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -810,20 +810,16 @@
         }
     }
 
-    /**
-     * Prepare this {@link ClipData} to leave an app process.
-     *
-     * @hide
-     */
-    public void prepareToLeaveUser(int userId) {
+    /** @hide */
+    public void fixUris(int contentUserHint) {
         final int size = mItems.size();
         for (int i = 0; i < size; i++) {
             final Item item = mItems.get(i);
             if (item.mIntent != null) {
-                item.mIntent.prepareToLeaveUser(userId);
+                item.mIntent.fixUris(contentUserHint);
             }
             if (item.mUri != null) {
-                item.mUri = maybeAddUserId(item.mUri, userId);
+                item.mUri = maybeAddUserId(item.mUri, contentUserHint);
             }
         }
     }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 287ea35..ae60476 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.content.pm.ApplicationInfo;
+import android.provider.MediaStore;
 import android.util.ArraySet;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -38,6 +39,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.StrictMode;
+import android.os.UserHandle;
 import android.provider.DocumentsContract;
 import android.provider.DocumentsProvider;
 import android.provider.OpenableColumns;
@@ -3937,6 +3939,7 @@
     private Rect mSourceBounds;
     private Intent mSelector;
     private ClipData mClipData;
+    private int mContentUserHint = UserHandle.USER_CURRENT;
 
     // ---------------------------------------------------------------------
 
@@ -3956,6 +3959,7 @@
         this.mPackage = o.mPackage;
         this.mComponent = o.mComponent;
         this.mFlags = o.mFlags;
+        this.mContentUserHint = o.mContentUserHint;
         if (o.mCategories != null) {
             this.mCategories = new ArraySet<String>(o.mCategories);
         }
@@ -4660,6 +4664,11 @@
         return mClipData;
     }
 
+    /** @hide */
+    public int getContentUserHint() {
+        return mContentUserHint;
+    }
+
     /**
      * Sets the ClassLoader that will be used when unmarshalling
      * any Parcelable values from the extras of this Intent.
@@ -5679,6 +5688,16 @@
     }
 
     /**
+     * This is NOT a secure mechanism to identify the user who sent the intent.
+     * When the intent is sent to a different user, it is used to fix uris by adding the userId
+     * who sent the intent.
+     * @hide
+     */
+    public void setContentUserHint(int contentUserHint) {
+        mContentUserHint = contentUserHint;
+    }
+
+    /**
      * Add extended data to the intent.  The name must include a package
      * prefix, for example the app com.android.contacts would use names
      * like "com.android.contacts.ShowAll".
@@ -6731,6 +6750,7 @@
     @FillInFlags
     public int fillIn(Intent other, @FillInFlags int flags) {
         int changes = 0;
+        boolean mayHaveCopiedUris = false;
         if (other.mAction != null
                 && (mAction == null || (flags&FILL_IN_ACTION) != 0)) {
             mAction = other.mAction;
@@ -6742,6 +6762,7 @@
             mData = other.mData;
             mType = other.mType;
             changes |= FILL_IN_DATA;
+            mayHaveCopiedUris = true;
         }
         if (other.mCategories != null
                 && (mCategories == null || (flags&FILL_IN_CATEGORIES) != 0)) {
@@ -6771,6 +6792,7 @@
                 && (mClipData == null || (flags&FILL_IN_CLIP_DATA) != 0)) {
             mClipData = other.mClipData;
             changes |= FILL_IN_CLIP_DATA;
+            mayHaveCopiedUris = true;
         }
         // Component is special: it can -only- be set if explicitly allowed,
         // since otherwise the sender could force the intent somewhere the
@@ -6788,12 +6810,14 @@
         if (mExtras == null) {
             if (other.mExtras != null) {
                 mExtras = new Bundle(other.mExtras);
+                mayHaveCopiedUris = true;
             }
         } else if (other.mExtras != null) {
             try {
                 Bundle newb = new Bundle(other.mExtras);
                 newb.putAll(mExtras);
                 mExtras = newb;
+                mayHaveCopiedUris = true;
             } catch (RuntimeException e) {
                 // Modifying the extras can cause us to unparcel the contents
                 // of the bundle, and if we do this in the system process that
@@ -6803,6 +6827,10 @@
                 Log.w("Intent", "Failure filling in extras", e);
             }
         }
+        if (mayHaveCopiedUris && mContentUserHint == UserHandle.USER_CURRENT
+                && other.mContentUserHint != UserHandle.USER_CURRENT) {
+            mContentUserHint = other.mContentUserHint;
+        }
         return changes;
     }
 
@@ -7030,8 +7058,15 @@
             first = false;
             b.append("(has extras)");
         }
+        if (mContentUserHint != UserHandle.USER_CURRENT) {
+            if (!first) {
+                b.append(' ');
+            }
+            first = false;
+            b.append("u=").append(mContentUserHint);
+        }
         if (mSelector != null) {
-            b.append(" sel={");
+            b.append(" sel=");
             mSelector.toShortString(b, secure, comp, extras, clip);
             b.append("}");
         }
@@ -7208,7 +7243,7 @@
         } else {
             out.writeInt(0);
         }
-
+        out.writeInt(mContentUserHint);
         out.writeBundle(mExtras);
     }
 
@@ -7257,7 +7292,7 @@
         if (in.readInt() != 0) {
             mClipData = new ClipData(in);
         }
-
+        mContentUserHint = in.readInt();
         mExtras = in.readBundle();
     }
 
@@ -7467,39 +7502,50 @@
     }
 
     /**
-     * Prepare this {@link Intent} to be sent to another user
-     *
      * @hide
      */
-    public void prepareToLeaveUser(int userId) {
+    public void prepareToEnterProcess() {
+        if (mContentUserHint != UserHandle.USER_CURRENT) {
+            fixUris(mContentUserHint);
+            mContentUserHint = UserHandle.USER_CURRENT;
+        }
+    }
+
+    /**
+     * @hide
+     */
+     public void fixUris(int contentUserHint) {
         Uri data = getData();
         if (data != null) {
-            mData = maybeAddUserId(data, userId);
-        }
-        if (mSelector != null) {
-            mSelector.prepareToLeaveUser(userId);
+            mData = maybeAddUserId(data, contentUserHint);
         }
         if (mClipData != null) {
-            mClipData.prepareToLeaveUser(userId);
+            mClipData.fixUris(contentUserHint);
         }
         String action = getAction();
         if (ACTION_SEND.equals(action)) {
             final Uri stream = getParcelableExtra(EXTRA_STREAM);
             if (stream != null) {
-                putExtra(EXTRA_STREAM, maybeAddUserId(stream, userId));
+                putExtra(EXTRA_STREAM, maybeAddUserId(stream, contentUserHint));
             }
-        }
-        if (ACTION_SEND_MULTIPLE.equals(action)) {
+        } else if (ACTION_SEND_MULTIPLE.equals(action)) {
             final ArrayList<Uri> streams = getParcelableArrayListExtra(EXTRA_STREAM);
             if (streams != null) {
                 ArrayList<Uri> newStreams = new ArrayList<Uri>();
                 for (int i = 0; i < streams.size(); i++) {
-                    newStreams.add(maybeAddUserId(streams.get(i), userId));
+                    newStreams.add(maybeAddUserId(streams.get(i), contentUserHint));
                 }
                 putParcelableArrayListExtra(EXTRA_STREAM, newStreams);
             }
+        } else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
+                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(action)
+                || MediaStore.ACTION_VIDEO_CAPTURE.equals(action)) {
+            final Uri output = getParcelableExtra(MediaStore.EXTRA_OUTPUT);
+            if (output != null) {
+                putExtra(MediaStore.EXTRA_OUTPUT, maybeAddUserId(output, contentUserHint));
+            }
         }
-    }
+     }
 
     /**
      * Migrate any {@link #EXTRA_STREAM} in {@link #ACTION_SEND} and
@@ -7590,6 +7636,20 @@
                 }
             } catch (ClassCastException e) {
             }
+        } else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
+                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(action)
+                || MediaStore.ACTION_VIDEO_CAPTURE.equals(action)) {
+            final Uri output;
+            try {
+                output = getParcelableExtra(MediaStore.EXTRA_OUTPUT);
+            } catch (ClassCastException e) {
+                return false;
+            }
+            if (output != null) {
+                setClipData(ClipData.newRawUri("", output));
+                addFlags(FLAG_GRANT_WRITE_URI_PERMISSION|FLAG_GRANT_READ_URI_PERMISSION);
+                return true;
+            }
         }
 
         return false;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 45edf28..a506c42 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -772,7 +772,7 @@
      * @return A label that combines the original label and a badge as
      *         determined by the system.
      */
-    public String getBadgedLabelForUser(String label, UserHandle user) {
+    public CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user) {
         UserInfo userInfo = getUserIfProfile(user.getIdentifier());
         if (userInfo != null && userInfo.isManagedProfile()) {
             return Resources.getSystem().getString(
@@ -782,6 +782,15 @@
     }
 
     /**
+     * Kept during L development to simplify updating unbundled apps.
+     * TODO: Remove after 2014-08-04
+     * @hide
+     */
+    public String getBadgedLabelForUser(String label, UserHandle user) {
+        return (String) getBadgedLabelForUser((CharSequence) label, user);
+    }
+
+    /**
      * If the target user is a managed profile of the calling user or the caller
      * is itself a managed profile, then this returns a drawable to use as a small
      * icon to include in a view to distinguish it from the original icon.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 325917e..d137f0c 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -256,6 +256,11 @@
      * object in the extra field. This is useful for applications that only need a small image.
      * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
      * value of EXTRA_OUTPUT.
+     * As of {@link android.os.Build.VERSION_CODES#L}, this uri can also be supplied through
+     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
+     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
+     * If you don't set a ClipData, it will be copied there for you when calling
+     * {@link Context#startActivity(Intent)}.
      * @see #EXTRA_OUTPUT
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -276,6 +281,11 @@
      * object in the extra field. This is useful for applications that only need a small image.
      * If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri
      * value of EXTRA_OUTPUT.
+     * As of {@link android.os.Build.VERSION_CODES#L}, this uri can also be supplied through
+     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
+     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
+     * If you don't set a ClipData, it will be copied there for you when calling
+     * {@link Context#startActivity(Intent)}.
      *
      * @see #ACTION_IMAGE_CAPTURE
      * @see #EXTRA_OUTPUT
@@ -294,6 +304,11 @@
      * where the video is written. If EXTRA_OUTPUT is not present the video will be
      * written to the standard location for videos, and the Uri of that location will be
      * returned in the data field of the Uri.
+     * As of {@link android.os.Build.VERSION_CODES#L}, this uri can also be supplied through
+     * {@link android.content.Intent#setClipData(ClipData)}. If using this approach, you still must
+     * supply the uri through the EXTRA_OUTPUT field for compatibility with old applications.
+     * If you don't set a ClipData, it will be copied there for you when calling
+     * {@link Context#startActivity(Intent)}.
      * @see #EXTRA_OUTPUT
      * @see #EXTRA_VIDEO_QUALITY
      * @see #EXTRA_SIZE_LIMIT
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 1967213..53220d0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1623,12 +1623,14 @@
         if (!mEnded) {
             ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
             int numOldAnims = runningAnimators.size();
-            WindowId windowId = sceneRoot.getWindowId();
-            for (int i = numOldAnims - 1; i >= 0; i--) {
-                AnimationInfo info = runningAnimators.valueAt(i);
-                if (info.view != null && windowId.equals(info.windowId)) {
-                    Animator anim = runningAnimators.keyAt(i);
-                    anim.pause();
+            if (sceneRoot != null) {
+                WindowId windowId = sceneRoot.getWindowId();
+                for (int i = numOldAnims - 1; i >= 0; i--) {
+                    AnimationInfo info = runningAnimators.valueAt(i);
+                    if (info.view != null && windowId.equals(info.windowId)) {
+                        Animator anim = runningAnimators.keyAt(i);
+                        anim.pause();
+                    }
                 }
             }
             if (mListeners != null && mListeners.size() > 0) {
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index da99dd6..7c30d2a 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -50,6 +50,12 @@
     /**
      * Sets whether the application's {@link WebView} instances should send and
      * accept cookies.
+     * By default this is set to true and the WebView accepts cookies.
+     * <p>
+     * When this is true
+     * {@link CookieManager#setAcceptThirdPartyCookies setAcceptThirdPartyCookies} and
+     * {@link CookieManager#setAcceptFileSchemeCookies setAcceptFileSchemeCookies}
+     * can be used to control the policy for those specific types of cookie.
      *
      * @param accept whether {@link WebView} instances should send and accept
      *               cookies
@@ -291,9 +297,10 @@
     /**
      * Sets whether the application's {@link WebView} instances should send and
      * accept cookies for file scheme URLs.
-     * Use of cookies with file scheme URLs is potentially insecure. Do not use
-     * this feature unless you can be sure that no unintentional sharing of
-     * cookie data can take place.
+     * Use of cookies with file scheme URLs is potentially insecure and turned
+     * off by default.
+     * Do not use this feature unless you can be sure that no unintentional
+     * sharing of cookie data can take place.
      * <p>
      * Note that calls to this method will have no effect if made after a
      * {@link WebView} or CookieManager instance has been created.
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index ebfa46b..1c364c0 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -24,7 +24,7 @@
  * @deprecated The WebView now automatically syncs cookies as necessary.
  *             You no longer need to create or use the CookieSyncManager.
  *             To manually force a sync you can use the CookieManager
- *             method {@link CookieManager#flush} which is synchronous
+ *             method {@link CookieManager#flush} which is a synchronous
  *             replacement for {@link #sync}.
  *             <p>
  *
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 0eadde1..1c01353 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -89,7 +89,7 @@
             Slog.e(TAG, "PackageManagerService is dead?");
         }
         if (canForward) {
-            newIntent.prepareToLeaveUser(callingUserId);
+            newIntent.setContentUserHint(callingUserId);
 
             final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser(
                         newIntent, MATCH_DEFAULT_ONLY, userDest.getIdentifier());
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index f3125f1..a7c9105 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -38,6 +38,10 @@
           android:label="@string/app_name"
           android:exported="true"
           android:launchMode="singleInstance" >
+          <intent-filter>
+              <action android:name="android.intent.action.MAIN" />
+              <category android:name="android.intent.category.LAUNCHER" />
+          </intent-filter>
       </activity>
     </application>
 </manifest>
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
index 01b107b..06a06bf 100644
--- a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
@@ -17,9 +17,9 @@
   -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
     <Button android:id="@+id/enable_trust"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -28,6 +28,10 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:text="Revoke trust" />
+    <Button android:id="@+id/crash"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="Crash" />
     <CheckBox android:id="@+id/report_unlock_attempts"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
index 8e293fb..6b5f78b 100644
--- a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -37,6 +37,7 @@
 
         findViewById(R.id.enable_trust).setOnClickListener(this);
         findViewById(R.id.revoke_trust).setOnClickListener(this);
+        findViewById(R.id.crash).setOnClickListener(this);
 
         mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
         mReportUnlockAttempts.setOnCheckedChangeListener(this);
@@ -56,6 +57,8 @@
                     null /* extra */);
         } else if (id == R.id.revoke_trust) {
             SampleTrustAgent.sendRevokeTrust(this);
+        } else if (id == R.id.crash) {
+            throw new RuntimeException("crash");
         }
     }
 
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index e3ac1c1..6f64e17 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -26,7 +26,7 @@
     android:fitsSystemWindows="true"
     android:descendantFocusability="afterDescendants">
 
-    <FrameLayout
+    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
             android:id="@+id/backdrop"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
@@ -41,7 +41,7 @@
                    android:layout_height="match_parent"
                    android:scaleType="centerCrop"
                    android:visibility="invisible" />
-    </FrameLayout>
+    </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
 
     <View android:id="@+id/scrim_behind"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index ad98168..d113139 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -31,30 +31,14 @@
 import com.android.systemui.R;
 
 /** A dialog that provides controls for adjusting the screen brightness. */
-public class BrightnessDialog extends Activity implements
-        BrightnessController.BrightnessStateChangeCallback {
-    private final Handler mHandler = new Handler();
+public class BrightnessDialog extends Activity {
 
     private BrightnessController mBrightnessController;
-    private int mBrightnessDialogLongTimeout;
-    private int mBrightnessDialogShortTimeout;
-
-    private final Runnable mDismissDialogRunnable = new Runnable() {
-        public void run() {
-            finish();
-        };
-    };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        final Resources r = getResources();
-        mBrightnessDialogLongTimeout = r.getInteger(
-                R.integer.quick_settings_brightness_dialog_long_timeout);
-        mBrightnessDialogShortTimeout = r.getInteger(
-                R.integer.quick_settings_brightness_dialog_short_timeout);
-
         final Window window = getWindow();
         final WindowManager.LayoutParams lp = window.getAttributes();
 
@@ -79,33 +63,13 @@
         final ToggleSlider slider = (ToggleSlider) findViewById(R.id.brightness_slider);
         mBrightnessController = new BrightnessController(this, icon, slider);
         mBrightnessController.registerCallbacks();
-        mBrightnessController.addStateChangedCallback(this);
-
-        dismissBrightnessDialog(mBrightnessDialogLongTimeout);
     }
 
     @Override
     protected void onStop() {
         super.onStop();
 
-        mBrightnessController.removeStateChangedCallback(this);
         mBrightnessController.unregisterCallbacks();
-
-        removeAllBrightnessDialogCallbacks();
-    }
-
-    public void onBrightnessLevelChanged() {
-        dismissBrightnessDialog(mBrightnessDialogShortTimeout);
-    }
-
-    private void dismissBrightnessDialog(int timeout) {
-        removeAllBrightnessDialogCallbacks();
-
-        mHandler.postDelayed(mDismissDialogRunnable, timeout);
-    }
-
-    private void removeAllBrightnessDialogCallbacks() {
-        mHandler.removeCallbacks(mDismissDialogRunnable);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
index ce5ab5a..c75bd28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -65,13 +65,7 @@
     }
 
     private void applyColor(Notification notification, StatusBarIconView view) {
-        if (notification.color == Notification.COLOR_DEFAULT) {
-            if (mNotificationColorUtil.isGrayscale(view.getDrawable())) {
-                view.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
-            }
-        } else {
-            view.setColorFilter(notification.color, PorterDuff.Mode.SRC_ATOP);
-        }
+        view.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
     }
 
     private void updateMoreText() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3aaace4..e6ffde0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -100,7 +100,7 @@
                     .withLayer()
 
                     // Make it disappear faster, as the focus should be on the activity behind.
-                    .setDuration(duration / 3)
+                    .setDuration(duration / 2)
                     .setInterpolator(mFadeOutInterpolator)
                     .setStartDelay(delay)
                     .withEndAction(new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b3b70e8..acfdb06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -93,11 +93,13 @@
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
 import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -401,6 +403,8 @@
     private boolean mDozing;
 
     private Interpolator mLinearOutSlowIn;
+    private Interpolator mLinearInterpolator = new LinearInterpolator();
+    private Interpolator mBackdropInterpolator = new AccelerateDecelerateInterpolator();
     private Interpolator mAlphaIn = new PathInterpolator(0f, 0.2f, 1f, 1f);
     private Interpolator mAlphaOut = new PathInterpolator(0f, 0f, 0.8f, 1f);
 
@@ -1701,7 +1705,7 @@
                                 + " to "
                                 + mBackdropBack.getDrawable());
                     }
-                    mBackdropFront.animate().withLayer()
+                    mBackdropFront.animate()
                             .setDuration(250)
                             .alpha(0f).withEndAction(mHideBackdropFront);
                 }
@@ -1713,16 +1717,29 @@
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
                 }
-                mBackdrop.animate().withLayer()
-                        .alpha(0f).withEndAction(new Runnable() {
-                    @Override
-                    public void run() {
-                        mBackdrop.setVisibility(View.GONE);
-                        mBackdropFront.animate().cancel();
-                        mBackdropBack.animate().cancel();
-                        mHandler.post(mHideBackdropFront);
-                    }
-                });
+                mBackdrop.animate()
+                        .alpha(0f)
+                        .setInterpolator(mBackdropInterpolator)
+                        .setDuration(300)
+                        .setStartDelay(0)
+                        .withEndAction(new Runnable() {
+                            @Override
+                            public void run() {
+                                mBackdrop.setVisibility(View.GONE);
+                                mBackdropFront.animate().cancel();
+                                mBackdropBack.animate().cancel();
+                                mHandler.post(mHideBackdropFront);
+                            }
+                        });
+                if (mKeyguardFadingAway) {
+                    mBackdrop.animate()
+
+                            // Make it disappear faster, as the focus should be on the activity behind.
+                            .setDuration(mKeyguardFadingAwayDuration / 2)
+                            .setStartDelay(mKeyguardFadingAwayDelay)
+                            .setInterpolator(mLinearInterpolator)
+                            .start();
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 314e906..f38b280 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6644,6 +6644,11 @@
         if (data == null && clip == null) {
             return null;
         }
+        // Default userId for uris in the intent (if they don't specify it themselves)
+        int contentUserHint = intent.getContentUserHint();
+        if (contentUserHint == UserHandle.USER_CURRENT) {
+            contentUserHint = UserHandle.getUserId(callingUid);
+        }
         final IPackageManager pm = AppGlobals.getPackageManager();
         int targetUid;
         if (needed != null) {
@@ -6663,7 +6668,7 @@
             }
         }
         if (data != null) {
-            GrantUri grantUri = GrantUri.resolve(UserHandle.getUserId(callingUid), data);
+            GrantUri grantUri = GrantUri.resolve(contentUserHint, data);
             targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, mode,
                     targetUid);
             if (targetUid > 0) {
@@ -6677,7 +6682,7 @@
             for (int i=0; i<clip.getItemCount(); i++) {
                 Uri uri = clip.getItemAt(i).getUri();
                 if (uri != null) {
-                    GrantUri grantUri = GrantUri.resolve(UserHandle.getUserId(callingUid), uri);
+                    GrantUri grantUri = GrantUri.resolve(contentUserHint, uri);
                     targetUid = checkGrantUriPermissionLocked(callingUid, targetPkg, grantUri, mode,
                             targetUid);
                     if (targetUid > 0) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 91bc7e3..390fbba 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2575,7 +2575,7 @@
                     + " res=" + resultCode + " data=" + resultData);
             if (resultTo.userId != r.userId) {
                 if (resultData != null) {
-                    resultData.prepareToLeaveUser(r.userId);
+                    resultData.setContentUserHint(r.userId);
                 }
             }
             if (r.info.applicationInfo.uid > 0) {
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index f18939f..51009af 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -24,6 +24,7 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
@@ -41,6 +42,13 @@
     private static final int MSG_GRANT_TRUST = 1;
     private static final int MSG_REVOKE_TRUST = 2;
     private static final int MSG_TRUST_TIMEOUT = 3;
+    private static final int MSG_RESTART_TIMEOUT = 4;
+
+    /**
+     * Time in uptime millis that we wait for the service connection, both when starting
+     * and when the service disconnects.
+     */
+    private static final long RESTART_TIMEOUT_MILLIS = 5 * 60000;
 
     /**
      * Long extra for {@link #MSG_GRANT_TRUST}
@@ -53,6 +61,8 @@
     private final ComponentName mName;
 
     private ITrustAgentService mTrustAgentService;
+    private boolean mBound;
+    private long mScheduledRestartUptimeMillis;
 
     // Trust state
     private boolean mTrusted;
@@ -95,6 +105,10 @@
                     }
                     mTrustManagerService.updateTrust(mUserId);
                     break;
+                case MSG_RESTART_TIMEOUT:
+                    unbind();
+                    mTrustManagerService.resetAgent(mName, mUserId);
+                    break;
             }
         }
     };
@@ -123,6 +137,7 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString());
+            mHandler.removeMessages(MSG_RESTART_TIMEOUT);
             mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
             mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
             setCallback(mCallback);
@@ -134,6 +149,9 @@
             mTrustAgentService = null;
             mTrustManagerService.mArchive.logAgentDied(mUserId, name);
             mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+            if (mBound) {
+                scheduleRestart();
+            }
         }
     };
 
@@ -144,9 +162,12 @@
         mTrustManagerService = trustManagerService;
         mUserId = user.getIdentifier();
         mName = intent.getComponent();
-        if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) {
-            if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString());
-            // TODO: retry somehow?
+        // Schedules a restart for when connecting times out. If the connection succeeds,
+        // the restart is canceled in mCallback's onConnected.
+        scheduleRestart();
+        mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user);
+        if (!mBound) {
+            Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString());
         }
     }
 
@@ -184,14 +205,38 @@
     }
 
     public void unbind() {
+        if (!mBound) {
+            return;
+        }
         if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString());
         mTrustManagerService.mArchive.logAgentStopped(mUserId, mName);
         mContext.unbindService(mConnection);
+        mBound = false;
         mTrustAgentService = null;
         mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+        mHandler.removeMessages(MSG_RESTART_TIMEOUT);
     }
 
     public boolean isConnected() {
         return mTrustAgentService != null;
     }
+
+    public boolean isBound() {
+        return mBound;
+    }
+
+    /**
+     * If not connected, returns the time at which the agent is restarted.
+     *
+     * @return restart time in uptime millis.
+     */
+    public long getScheduledRestartUptimeMillis() {
+        return mScheduledRestartUptimeMillis;
+    }
+
+    private void scheduleRestart() {
+        mHandler.removeMessages(MSG_RESTART_TIMEOUT);
+        mScheduledRestartUptimeMillis = SystemClock.uptimeMillis() + RESTART_TIMEOUT_MILLIS;
+        mHandler.sendEmptyMessageAtTime(MSG_RESTART_TIMEOUT, mScheduledRestartUptimeMillis);
+    }
 }
diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java
index 56950d2..5e32d86 100644
--- a/services/core/java/com/android/server/trust/TrustArchive.java
+++ b/services/core/java/com/android/server/trust/TrustArchive.java
@@ -130,7 +130,7 @@
         }
     }
 
-    private static String formatDuration(long duration) {
+    public static String formatDuration(long duration) {
         StringBuilder sb = new StringBuilder();
         TimeUtils.formatDuration(duration, sb);
         return sb.toString();
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 1aec569..6f72b94 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -45,6 +45,7 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.service.trust.TrustAgentService;
@@ -99,12 +100,6 @@
 
     private UserManager mUserManager;
 
-    /**
-     * Cache for {@link #refreshAgentList()}
-     */
-    private final ArraySet<AgentInfo> mObsoleteAgents = new ArraySet<AgentInfo>();
-
-
     public TrustManagerService(Context context) {
         super(context);
         mContext = context;
@@ -168,8 +163,8 @@
         List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
         LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
 
-        mObsoleteAgents.clear();
-        mObsoleteAgents.addAll(mActiveAgents);
+        ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>();
+        obsoleteAgents.addAll(mActiveAgents);
 
         for (UserInfo userInfo : userInfos) {
             int disabledFeatures = lockPatternUtils.getDevicePolicyManager()
@@ -208,14 +203,14 @@
                             new Intent().setComponent(name), userInfo.getUserHandle());
                     mActiveAgents.add(agentInfo);
                 } else {
-                    mObsoleteAgents.remove(agentInfo);
+                    obsoleteAgents.remove(agentInfo);
                 }
             }
         }
 
         boolean trustMayHaveChanged = false;
-        for (int i = 0; i < mObsoleteAgents.size(); i++) {
-            AgentInfo info = mObsoleteAgents.valueAt(i);
+        for (int i = 0; i < obsoleteAgents.size(); i++) {
+            AgentInfo info = obsoleteAgents.valueAt(i);
             if (info.agent.isTrusted()) {
                 trustMayHaveChanged = true;
             }
@@ -228,6 +223,43 @@
         }
     }
 
+    private void removeAgentsOfPackage(String packageName) {
+        boolean trustMayHaveChanged = false;
+        for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
+            AgentInfo info = mActiveAgents.valueAt(i);
+            if (packageName.equals(info.component.getPackageName())) {
+                Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
+                if (info.agent.isTrusted()) {
+                    trustMayHaveChanged = true;
+                }
+                info.agent.unbind();
+                mActiveAgents.removeAt(i);
+            }
+        }
+        if (trustMayHaveChanged) {
+            updateTrustAll();
+        }
+    }
+
+    public void resetAgent(ComponentName name, int userId) {
+        boolean trustMayHaveChanged = false;
+        for (int i = mActiveAgents.size() - 1; i >= 0; i--) {
+            AgentInfo info = mActiveAgents.valueAt(i);
+            if (name.equals(info.component) && userId == info.userId) {
+                Log.i(TAG, "Resetting agent " + info.component.flattenToShortString());
+                if (info.agent.isTrusted()) {
+                    trustMayHaveChanged = true;
+                }
+                info.agent.unbind();
+                mActiveAgents.removeAt(i);
+            }
+        }
+        if (trustMayHaveChanged) {
+            updateTrust(userId);
+        }
+        refreshAgentList();
+    }
+
     private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
         if (resolveInfo == null || resolveInfo.serviceInfo == null
                 || resolveInfo.serviceInfo.metaData == null) return null;
@@ -448,11 +480,18 @@
                 if (info.userId != user.id) { continue; }
                 boolean trusted = info.agent.isTrusted();
                 fout.print("    "); fout.println(info.component.flattenToShortString());
-                fout.print("     connected=" + dumpBool(info.agent.isConnected()));
+                fout.print("     bound=" + dumpBool(info.agent.isBound()));
+                fout.print(", connected=" + dumpBool(info.agent.isConnected()));
                 fout.println(", trusted=" + dumpBool(trusted));
                 if (trusted) {
                     fout.println("      message=\"" + info.agent.getMessage() + "\"");
                 }
+                if (!info.agent.isConnected()) {
+                    String restartTime = TrustArchive.formatDuration(
+                            info.agent.getScheduledRestartUptimeMillis()
+                                    - SystemClock.uptimeMillis());
+                    fout.println("      restartScheduledAt=" + restartTime);
+                }
                 if (!simpleNames.add(TrustArchive.getSimpleName(info.component))) {
                     duplicateSimpleNames = true;
                 }
@@ -501,6 +540,11 @@
             // We're interested in all changes, even if just some components get enabled / disabled.
             return true;
         }
+
+        @Override
+        public void onPackageDisappeared(String packageName, int reason) {
+            removeAgentsOfPackage(packageName);
+        }
     };
 
     private class DevicePolicyReceiver extends BroadcastReceiver {