Merge "fix null pointer crash" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 0548d32..5fac213 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23,7 +23,6 @@
     field public static final java.lang.String BIND_CARRIER_CONFIG_SERVICE = "android.permission.BIND_CARRIER_CONFIG_SERVICE";
     field public static final java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
-    field public static final java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
     field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
@@ -32,6 +31,7 @@
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
     field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
@@ -14694,6 +14694,7 @@
 
   public final class AudioDeviceInfo {
     method public int[] getChannelCounts();
+    method public int[] getChannelIndexMasks();
     method public int[] getChannelMasks();
     method public int[] getFormats();
     method public int getId();
@@ -30315,16 +30316,12 @@
 
   public final class PhoneAccount implements android.os.Parcelable {
     method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
-    method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
     method public int describeContents();
     method public android.telecom.PhoneAccountHandle getAccountHandle();
     method public android.net.Uri getAddress();
     method public int getCapabilities();
     method public int getHighlightColor();
-    method public android.graphics.Bitmap getIconBitmap();
-    method public java.lang.String getIconPackageName();
-    method public int getIconResId();
-    method public int getIconTint();
+    method public android.graphics.drawable.Icon getIcon();
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getShortDescription();
     method public android.net.Uri getSubscriptionAddress();
@@ -30340,7 +30337,6 @@
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
     field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
-    field public static final int NO_ICON_TINT = 0; // 0x0
     field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
     field public static final java.lang.String SCHEME_SIP = "sip";
     field public static final java.lang.String SCHEME_TEL = "tel";
@@ -30355,11 +30351,7 @@
     method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setCapabilities(int);
     method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
-    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.Bitmap);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.drawable.Icon);
     method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
     method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
@@ -38811,8 +38803,7 @@
   }
 
   public abstract class WebResourceError {
-    ctor public WebResourceError();
-    method public abstract java.lang.String getDescription();
+    method public abstract java.lang.CharSequence getDescription();
     method public abstract int getErrorCode();
   }
 
@@ -38842,12 +38833,6 @@
 
   public abstract class WebResourceResponseBase {
     ctor public WebResourceResponseBase();
-    method public abstract java.io.InputStream getData();
-    method public abstract java.lang.String getEncoding();
-    method public abstract java.lang.String getMimeType();
-    method public abstract java.lang.String getReasonPhrase();
-    method public abstract java.util.Map<java.lang.String, java.lang.String> getResponseHeaders();
-    method public abstract int getStatusCode();
   }
 
   public abstract class WebSettings {
@@ -39179,6 +39164,7 @@
     method public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
     method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
     method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponseBase);
+    method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponse);
     method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
     method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
     method public void onScaleChanged(android.webkit.WebView, float, float);
diff --git a/api/system-current.txt b/api/system-current.txt
index bc79363..d727b22 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -32,7 +32,7 @@
     field public static final java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
     field public static final java.lang.String BIND_CONDITION_PROVIDER_SERVICE = "android.permission.BIND_CONDITION_PROVIDER_SERVICE";
-    field public static final java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
+    field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
@@ -43,6 +43,7 @@
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
@@ -9671,6 +9672,7 @@
     field public static final int INSTALL_FAILED_NO_SHARED_USER = -6; // 0xfffffffa
     field public static final int INSTALL_FAILED_OLDER_SDK = -12; // 0xfffffff4
     field public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23; // 0xffffffe9
+    field public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26; // 0xffffffe6
     field public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; // 0xfffffff6
     field public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; // 0xfffffff8
     field public static final int INSTALL_FAILED_TEST_ONLY = -15; // 0xfffffff1
@@ -15905,6 +15907,7 @@
 
   public final class AudioDeviceInfo {
     method public int[] getChannelCounts();
+    method public int[] getChannelIndexMasks();
     method public int[] getChannelMasks();
     method public int[] getFormats();
     method public int getId();
@@ -32497,16 +32500,12 @@
 
   public final class PhoneAccount implements android.os.Parcelable {
     method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
-    method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
     method public int describeContents();
     method public android.telecom.PhoneAccountHandle getAccountHandle();
     method public android.net.Uri getAddress();
     method public int getCapabilities();
     method public int getHighlightColor();
-    method public android.graphics.Bitmap getIconBitmap();
-    method public java.lang.String getIconPackageName();
-    method public int getIconResId();
-    method public int getIconTint();
+    method public android.graphics.drawable.Icon getIcon();
     method public java.lang.CharSequence getLabel();
     method public java.lang.CharSequence getShortDescription();
     method public android.net.Uri getSubscriptionAddress();
@@ -32523,7 +32522,6 @@
     field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
     field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
-    field public static final int NO_ICON_TINT = 0; // 0x0
     field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
     field public static final java.lang.String SCHEME_SIP = "sip";
     field public static final java.lang.String SCHEME_TEL = "tel";
@@ -32538,11 +32536,7 @@
     method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setCapabilities(int);
     method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
-    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int, int);
-    method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.Bitmap);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.drawable.Icon);
     method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
     method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
@@ -41133,7 +41127,7 @@
 
   public abstract class WebResourceError {
     ctor public WebResourceError();
-    method public abstract java.lang.String getDescription();
+    method public abstract java.lang.CharSequence getDescription();
     method public abstract int getErrorCode();
   }
 
@@ -41148,6 +41142,7 @@
   public class WebResourceResponse extends android.webkit.WebResourceResponseBase {
     ctor public WebResourceResponse(java.lang.String, java.lang.String, java.io.InputStream);
     ctor public WebResourceResponse(java.lang.String, java.lang.String, int, java.lang.String, java.util.Map<java.lang.String, java.lang.String>, java.io.InputStream);
+    ctor public WebResourceResponse(boolean, java.lang.String, java.lang.String, int, java.lang.String, java.util.Map<java.lang.String, java.lang.String>, java.io.InputStream);
     method public java.io.InputStream getData();
     method public java.lang.String getEncoding();
     method public java.lang.String getMimeType();
@@ -41163,12 +41158,6 @@
 
   public abstract class WebResourceResponseBase {
     ctor public WebResourceResponseBase();
-    method public abstract java.io.InputStream getData();
-    method public abstract java.lang.String getEncoding();
-    method public abstract java.lang.String getMimeType();
-    method public abstract java.lang.String getReasonPhrase();
-    method public abstract java.util.Map<java.lang.String, java.lang.String> getResponseHeaders();
-    method public abstract int getStatusCode();
   }
 
   public abstract class WebSettings {
@@ -41545,6 +41534,7 @@
     method public void onReceivedError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceError);
     method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
     method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponseBase);
+    method public void onReceivedHttpError(android.webkit.WebView, android.webkit.WebResourceRequest, android.webkit.WebResourceResponse);
     method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
     method public void onReceivedSslError(android.webkit.WebView, android.webkit.SslErrorHandler, android.net.http.SslError);
     method public void onScaleChanged(android.webkit.WebView, float, float);
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index c74bbdd..34699d8 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -234,4 +234,15 @@
         }
         return false;
     }
+
+    /**
+     * @hide
+     */
+    public void setAppInactive(String packageName, boolean inactive) {
+        try {
+            mService.setAppInactive(packageName, inactive, UserHandle.myUserId());
+        } catch (RemoteException e) {
+            // fall through
+        }
+    }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 202a8a7..2ca0306 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -653,6 +653,16 @@
     public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;
 
     /**
+     * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+     * the old package has target SDK high enough to support runtime permission and
+     * the new package has target SDK low enough to not support runtime permissions.
+     * @hide
+     */
+    @SystemApi
+    public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26;
+
+    /**
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser was given a path that is not a file, or does not end with the expected
@@ -4512,6 +4522,7 @@
             case INSTALL_FAILED_PACKAGE_CHANGED: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_FAILED_UID_CHANGED: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_FAILED_VERSION_DOWNGRADE: return PackageInstaller.STATUS_FAILURE_INVALID;
+            case INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_NOT_APK: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_BAD_MANIFEST: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION: return PackageInstaller.STATUS_FAILURE_INVALID;
diff --git a/core/java/android/webkit/WebResourceError.java b/core/java/android/webkit/WebResourceError.java
index 080d174..11f1b6f1 100644
--- a/core/java/android/webkit/WebResourceError.java
+++ b/core/java/android/webkit/WebResourceError.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import android.annotation.SystemApi;
+
 /**
  * Encapsulates information about errors occured during loading of web resources. See
  * {@link WebViewClient#onReceivedError(WebView, WebResourceRequest, WebResourceError) WebViewClient.onReceivedError(WebView, WebResourceRequest, WebResourceError)}
@@ -35,5 +37,12 @@
      *
      * @return The description of the error
      */
-    public abstract String getDescription();
+    public abstract CharSequence getDescription();
+
+    /**
+     * This class can not be subclassed by applications.
+     * @hide
+     */
+    @SystemApi
+    public WebResourceError() {}
 }
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index a42aaa7..3a925c8 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -20,12 +20,15 @@
 import java.io.StringBufferInputStream;
 import java.util.Map;
 
+import android.annotation.SystemApi;
+
 /**
  * Encapsulates a resource response. Applications can return an instance of this
  * class from {@link WebViewClient#shouldInterceptRequest} to provide a custom
  * response when the WebView requests a particular resource.
  */
 public class WebResourceResponse extends WebResourceResponseBase {
+    private boolean mImmutable;
     private String mMimeType;
     private String mEncoding;
     private int mStatusCode;
@@ -80,13 +83,15 @@
      * @param mimeType The resource response's MIME type
      */
     public void setMimeType(String mimeType) {
+        checkImmutable();
         mMimeType = mimeType;
     }
 
     /**
-     * {@inheritDoc}
+     * Gets the resource response's MIME type.
+     *
+     * @return The resource response's MIME type
      */
-    @Override
     public String getMimeType() {
         return mMimeType;
     }
@@ -98,13 +103,15 @@
      * @param encoding The resource response's encoding
      */
     public void setEncoding(String encoding) {
+        checkImmutable();
         mEncoding = encoding;
     }
 
     /**
-     * {@inheritDoc}
+     * Gets the resource response's encoding.
+     *
+     * @return The resource response's encoding
      */
-    @Override
     public String getEncoding() {
         return mEncoding;
     }
@@ -118,6 +125,7 @@
      *                     and not empty.
      */
     public void setStatusCodeAndReasonPhrase(int statusCode, String reasonPhrase) {
+        checkImmutable();
         if (statusCode < 100)
             throw new IllegalArgumentException("statusCode can't be less than 100.");
         if (statusCode > 599)
@@ -140,17 +148,19 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Gets the resource response's status code.
+     *
+     * @return The resource response's status code.
      */
-    @Override
     public int getStatusCode() {
         return mStatusCode;
     }
 
     /**
-     * {@inheritDoc}
+     * Gets the description of the resource response's status code.
+     *
+     * @return The description of the resource response's status code.
      */
-    @Override
     public String getReasonPhrase() {
         return mReasonPhrase;
     }
@@ -161,13 +171,15 @@
      * @param headers Mapping of header name -> header value.
      */
     public void setResponseHeaders(Map<String, String> headers) {
+        checkImmutable();
         mResponseHeaders = headers;
     }
 
     /**
-     * {@inheritDoc}
+     * Gets the headers for the resource response.
+     *
+     * @return The headers for the resource response.
      */
-    @Override
     public Map<String, String> getResponseHeaders() {
         return mResponseHeaders;
     }
@@ -180,6 +192,7 @@
      *             StringBufferInputStream.
      */
     public void setData(InputStream data) {
+        checkImmutable();
         // If data is (or is a subclass of) StringBufferInputStream
         if (data != null && StringBufferInputStream.class.isAssignableFrom(data.getClass())) {
             throw new IllegalArgumentException("StringBufferInputStream is deprecated and must " +
@@ -189,10 +202,32 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Gets the input stream that provides the resource response's data.
+     *
+     * @return The input stream that provides the resource response's data
      */
-    @Override
     public InputStream getData() {
         return mInputStream;
     }
+
+    /**
+     * The internal version of the constructor that doesn't perform arguments checks.
+     * @hide
+     */
+    @SystemApi
+    public WebResourceResponse(boolean immutable, String mimeType, String encoding, int statusCode,
+            String reasonPhrase, Map<String, String> responseHeaders, InputStream data) {
+        mImmutable = immutable;
+        mMimeType = mimeType;
+        mEncoding = encoding;
+        mStatusCode = statusCode;
+        mReasonPhrase = reasonPhrase;
+        mResponseHeaders = responseHeaders;
+        mInputStream = data;
+    }
+
+    private void checkImmutable() {
+        if (mImmutable)
+            throw new IllegalStateException("This WebResourceResponse instance is immutable");
+    }
 }
diff --git a/core/java/android/webkit/WebResourceResponseBase.java b/core/java/android/webkit/WebResourceResponseBase.java
index cffde82..69eb397 100644
--- a/core/java/android/webkit/WebResourceResponseBase.java
+++ b/core/java/android/webkit/WebResourceResponseBase.java
@@ -16,53 +16,9 @@
 
 package android.webkit;
 
-import java.io.InputStream;
-import java.util.Map;
-
 /**
- * Encapsulates a resource response received from the server.
- * This is an abstract class used by WebView callbacks.
+ * This class will be deleted after updated WebView.apk will be submitted
+ * into the Android tree.
  */
 public abstract class WebResourceResponseBase {
-    /**
-     * Gets the resource response's MIME type.
-     *
-     * @return The resource response's MIME type
-     */
-    public abstract String getMimeType();
-
-    /**
-     * Gets the resource response's encoding.
-     *
-     * @return The resource response's encoding
-     */
-    public abstract String getEncoding();
-
-    /**
-     * Gets the resource response's status code.
-     *
-     * @return The resource response's status code.
-     */
-    public abstract int getStatusCode();
-
-    /**
-     * Gets the description of the resource response's status code.
-     *
-     * @return The description of the resource response's status code.
-     */
-    public abstract String getReasonPhrase();
-
-    /**
-     * Gets the headers for the resource response.
-     *
-     * @return The headers for the resource response.
-     */
-    public abstract Map<String, String> getResponseHeaders();
-
-    /**
-     * Gets the input stream that provides the resource response's data.
-     *
-     * @return The input stream that provides the resource response's data
-     */
-    public abstract InputStream getData();
 }
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 3a40de6..feed2b8 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -233,11 +233,20 @@
     public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
         if (request.isForMainFrame()) {
             onReceivedError(view,
-                    error.getErrorCode(), error.getDescription(), request.getUrl().toString());
+                    error.getErrorCode(), error.getDescription().toString(),
+                    request.getUrl().toString());
         }
     }
 
     /**
+     * This method will be deleted after updated WebView.apk will be submitted
+     * into the Android tree.
+     */
+    public void onReceivedHttpError(
+            WebView view, WebResourceRequest request, WebResourceResponseBase errorResponse) {
+    }
+
+    /**
      * Notify the host application that an HTTP error has been received from the server while
      * loading a resource.  HTTP errors have status codes &gt;= 400.  This callback will be called
      * for any resource (iframe, image, etc), not just for the main page. Thus, it is recommended to
@@ -248,7 +257,7 @@
      * @param errorResponse Information about the error occured.
      */
     public void onReceivedHttpError(
-            WebView view, WebResourceRequest request, WebResourceResponseBase errorResponse) {
+            WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
     }
 
     /**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index edff537..4c034b3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1107,6 +1107,11 @@
     <permission android:name="android.permission.CAPTURE_TV_INPUT"
         android:protectionLevel="signatureOrSystem" />
 
+    <!-- @hide Allows TvInputService to access DVB device.
+   <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.DVB_DEVICE"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- @hide Allows enabling/disabling OEM unlock
    <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.OEM_UNLOCK_STATE"
@@ -1184,10 +1189,20 @@
         android:protectionLevel="system|signature" />
 
     <!-- Must be required by a {@link android.telecom.ConnectionService},
-         to ensure that only the system can bind to it. -->
+         to ensure that only the system can bind to it.
+         @deprecated {@link android.telecom.ConnectionService}s should require
+                 android.permission.BIND_TELECOM_CONNECTION_SERVICE instead.
+         @SystemApi
+         @hide -->
     <permission android:name="android.permission.BIND_CONNECTION_SERVICE"
         android:protectionLevel="system|signature" />
 
+    <!-- Must be required by a {@link android.telecom.ConnectionService},
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+        android:protectionLevel="system|signature" />
+
+
     <!-- @SystemApi Allows an application to control the in-call experience.
          @hide -->
     <permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index b2c3ab7..668a14a 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -18,9 +18,9 @@
 
 import android.annotation.DrawableRes;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
@@ -29,15 +29,16 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.UserHandle;
 import android.util.Log;
 
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
-import java.lang.IllegalArgumentException;
-import java.lang.Override;
+import java.io.OutputStream;
 
 /**
  * An umbrella container for several serializable graphics representations, including Bitmaps,
@@ -57,6 +58,8 @@
     private static final int TYPE_DATA     = 3;
     private static final int TYPE_URI      = 4;
 
+    private static final int VERSION_STREAM_SERIALIZER = 1;
+
     private final int mType;
 
     // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed
@@ -281,16 +284,81 @@
         return loadDrawable(context);
     }
 
+    /**
+     * Writes a serialized version of an Icon to the specified stream.
+     *
+     * @param stream The stream on which to serialize the Icon.
+     * @hide
+     */
+    public void writeToStream(OutputStream stream) throws IOException {
+        DataOutputStream dataStream = new DataOutputStream(stream);
+
+        dataStream.writeInt(VERSION_STREAM_SERIALIZER);
+        dataStream.writeByte(mType);
+
+        switch (mType) {
+            case TYPE_BITMAP:
+                getBitmap().compress(Bitmap.CompressFormat.PNG, 100, dataStream);
+                break;
+            case TYPE_DATA:
+                dataStream.writeInt(getDataLength());
+                dataStream.write(getDataBytes(), getDataOffset(), getDataLength());
+                break;
+            case TYPE_RESOURCE:
+                dataStream.writeUTF(getResPackage());
+                dataStream.writeInt(getResId());
+                break;
+            case TYPE_URI:
+                dataStream.writeUTF(getUriString());
+                break;
+        }
+    }
+
     private Icon(int mType) {
         this.mType = mType;
     }
 
     /**
+     * Create an Icon from the specified stream.
+     *
+     * @param stream The input stream from which to reconstruct the Icon.
+     * @hide
+     */
+    public static Icon createFromStream(InputStream stream) throws IOException {
+        DataInputStream inputStream = new DataInputStream(stream);
+
+        final int version = inputStream.readInt();
+        if (version >= VERSION_STREAM_SERIALIZER) {
+            final int type = inputStream.readByte();
+            switch (type) {
+                case TYPE_BITMAP:
+                    return createWithBitmap(BitmapFactory.decodeStream(inputStream));
+                case TYPE_DATA:
+                    final int length = inputStream.readInt();
+                    final byte[] data = new byte[length];
+                    inputStream.read(data, 0 /* offset */, length);
+                    return createWithData(data, 0 /* offset */, length);
+                case TYPE_RESOURCE:
+                    final String packageName = inputStream.readUTF();
+                    final int resId = inputStream.readInt();
+                    return createWithResource(packageName, resId);
+                case TYPE_URI:
+                    final String uriOrPath = inputStream.readUTF();
+                    return createWithContentUri(uriOrPath);
+            }
+        }
+        return null;
+    }
+
+    /**
      * Create an Icon pointing to a drawable resource.
      * @param res Resources for a package containing the resource in question
      * @param resId ID of the drawable resource
      */
     public static Icon createWithResource(Resources res, @DrawableRes int resId) {
+        if (res == null) {
+            throw new IllegalArgumentException("Resource must not be null.");
+        }
         final Icon rep = new Icon(TYPE_RESOURCE);
         rep.mObj1 = res;
         rep.mInt1 = resId;
@@ -304,6 +372,9 @@
      * @param resId ID of the drawable resource
      */
     public static Icon createWithResource(String resPackage, @DrawableRes int resId) {
+        if (resPackage == null) {
+            throw new IllegalArgumentException("Resource package name must not be null.");
+        }
         final Icon rep = new Icon(TYPE_RESOURCE);
         rep.mInt1 = resId;
         rep.mString1 = resPackage;
@@ -315,6 +386,9 @@
      * @param bits A valid {@link android.graphics.Bitmap} object
      */
     public static Icon createWithBitmap(Bitmap bits) {
+        if (bits == null) {
+            throw new IllegalArgumentException("Bitmap must not be null.");
+        }
         final Icon rep = new Icon(TYPE_BITMAP);
         rep.mObj1 = bits;
         return rep;
@@ -329,6 +403,9 @@
      * @param length Length of the bitmap data
      */
     public static Icon createWithData(byte[] data, int offset, int length) {
+        if (data == null) {
+            throw new IllegalArgumentException("Data must not be null.");
+        }
         final Icon rep = new Icon(TYPE_DATA);
         rep.mObj1 = data;
         rep.mInt1 = length;
@@ -342,6 +419,9 @@
      * @param uri A uri referring to local content:// or file:// image data.
      */
     public static Icon createWithContentUri(String uri) {
+        if (uri == null) {
+            throw new IllegalArgumentException("Uri must not be null.");
+        }
         final Icon rep = new Icon(TYPE_URI);
         rep.mString1 = uri;
         return rep;
@@ -353,6 +433,9 @@
      * @param uri A uri referring to local content:// or file:// image data.
      */
     public static Icon createWithContentUri(Uri uri) {
+        if (uri == null) {
+            throw new IllegalArgumentException("Uri must not be null.");
+        }
         final Icon rep = new Icon(TYPE_URI);
         rep.mString1 = uri.toString();
         return rep;
@@ -365,6 +448,9 @@
      *           a type that {@link android.graphics.BitmapFactory} can decode.
      */
     public static Icon createWithFilePath(String path) {
+        if (path == null) {
+            throw new IllegalArgumentException("Path must not be null.");
+        }
         final Icon rep = new Icon(TYPE_URI);
         rep.mString1 = path;
         return rep;
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 566f8dc..4ecb930 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.annotation.NonNull;
 import android.util.SparseIntArray;
 
 /**
@@ -151,27 +152,38 @@
     /**
      * @return An array of sample rates supported by the audio device.
      */
-    public int[] getSampleRates() {
+    public @NonNull int[] getSampleRates() {
         return mPort.samplingRates();
     }
 
     /**
-     * @return An array of channel masks ({@link AudioFormat#CHANNEL_IN_STEREO},
-     * {@link AudioFormat#CHANNEL_OUT_7POINT1) for which this audio device can be configured.
+     * @return An array of channel position masks (e.g. {@link AudioFormat#CHANNEL_IN_STEREO},
+     * {@link AudioFormat#CHANNEL_OUT_7POINT1}) for which this audio device can be configured.
      *
      * @see AudioFormat
      */
-    public int[] getChannelMasks() {
+    public @NonNull int[] getChannelMasks() {
         return mPort.channelMasks();
     }
 
     /**
-     * @return An array of channel counts (1, 2, 4....) for which this audio device
+     * @return An array of channel index masks for which this audio device can be configured.
+     *
+     * @see AudioFormat
+     */
+    public @NonNull int[] getChannelIndexMasks() {
+        // TODO: implement
+        return new int[0];
+    }
+
+    /**
+     * @return An array of channel counts (1, 2, 4, ...) for which this audio device
      * can be configured.
      */
-    public int[] getChannelCounts() {
+    public @NonNull int[] getChannelCounts() {
         int[] masks = getChannelMasks();
         int[] counts = new int[masks.length];
+        // TODO: consider channel index masks
         for (int mask_index = 0; mask_index < masks.length; mask_index++) {
             counts[mask_index] = isSink()
                     ? AudioFormat.channelCountFromOutChannelMask(masks[mask_index])
@@ -181,12 +193,16 @@
     }
 
     /**
-     * @return An array of audio format IDs (@link AudioFormat#ENCODING_PCM_16BIT,
-     * {@link AudioFormat#ENCODING_PCM_FLOAT}...) supported by the audio device.
+     * @return An array of audio encodings (e.g. {@link AudioFormat#ENCODING_PCM_16BIT},
+     * {@link AudioFormat#ENCODING_PCM_FLOAT}) supported by the audio device.
+     * <code>ENCODING_PCM_FLOAT</code> indicates the device supports more
+     * than 16 bits of integer precision.  Specifying <code>ENCODING_PCM_FLOAT</code>
+     * with {@link AudioTrack} or {@link AudioRecord} can preserve at least 24 bits of
+     * integer precision to that device.
      *
      * @see AudioFormat
      */
-    public int[] getFormats() {
+    public @NonNull int[] getFormats() {
         return mPort.formats();
     }
 
diff --git a/media/java/android/media/tv/DvbDeviceInfo.aidl b/media/java/android/media/tv/DvbDeviceInfo.aidl
new file mode 100644
index 0000000..4851050
--- /dev/null
+++ b/media/java/android/media/tv/DvbDeviceInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ *
+ * Copyright 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.
+ */
+
+package android.media.tv;
+
+parcelable DvbDeviceInfo;
\ No newline at end of file
diff --git a/media/java/android/media/tv/DvbDeviceInfo.java b/media/java/android/media/tv/DvbDeviceInfo.java
new file mode 100644
index 0000000..1885a34
--- /dev/null
+++ b/media/java/android/media/tv/DvbDeviceInfo.java
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package android.media.tv;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.media.tv.TvInputManager;
+import android.util.Log;
+
+import java.lang.IllegalArgumentException;
+
+/**
+ * Simple container for information about DVB device.
+ * Not for third-party developers.
+ *
+ * @hide
+ */
+public final class DvbDeviceInfo implements Parcelable {
+    static final String TAG = "DvbDeviceInfo";
+
+    public static final Parcelable.Creator<DvbDeviceInfo> CREATOR =
+            new Parcelable.Creator<DvbDeviceInfo>() {
+                @Override
+                public DvbDeviceInfo createFromParcel(Parcel source) {
+                    try {
+                        return new DvbDeviceInfo(source);
+                    } catch (Exception e) {
+                        Log.e(TAG, "Exception creating DvbDeviceInfo from parcel", e);
+                        return null;
+                    }
+                }
+
+                @Override
+                public DvbDeviceInfo[] newArray(int size) {
+                    return new DvbDeviceInfo[size];
+                }
+            };
+
+    private final int mAdapterId;
+    private final int mDeviceId;
+
+    private DvbDeviceInfo(Parcel source) {
+        mAdapterId = source.readInt();
+        mDeviceId = source.readInt();
+    }
+
+    /**
+     * Constructs a new {@link DvbDeviceInfo} with the given adapter ID and device ID.
+     */
+    public DvbDeviceInfo(int adapterId, int deviceId) {
+        mAdapterId = adapterId;
+        mDeviceId = deviceId;
+    }
+
+    /**
+     * Returns the adapter ID of DVB device, in terms of enumerating the DVB device adapters
+     * installed in the system. The adapter ID counts from zero.
+     */
+    public int getAdapterId() {
+        return mAdapterId;
+    }
+
+    /**
+     * Returns the device ID of DVB device, in terms of enumerating the DVB devices attached to
+     * the same device adapter. The device ID counts from zero.
+     */
+    public int getDeviceId() {
+        return mDeviceId;
+    }
+
+    // Parcelable
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mAdapterId);
+        dest.writeInt(mDeviceId);
+    }
+}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 078fb2f..6fe5dbb 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.graphics.Rect;
+import android.media.tv.DvbDeviceInfo;
 import android.media.tv.ITvInputClient;
 import android.media.tv.ITvInputHardware;
 import android.media.tv.ITvInputHardwareCallback;
@@ -29,6 +30,7 @@
 import android.media.tv.TvTrackInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.view.Surface;
 
 /**
@@ -91,4 +93,8 @@
     boolean captureFrame(in String inputId, in Surface surface, in TvStreamConfig config,
             int userId);
     boolean isSingleSessionActive(int userId);
+
+    // For DVB device binding
+    List<DvbDeviceInfo> getDvbDeviceList();
+    ParcelFileDescriptor openDvbDevice(in DvbDeviceInfo info, int device);
 }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 705aa3d6..e74860e 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -21,12 +21,14 @@
 import android.annotation.SystemApi;
 import android.graphics.Rect;
 import android.media.MediaPlayer;
+import android.media.tv.DvbDeviceInfo;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -42,6 +44,7 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.lang.IllegalArgumentException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -55,6 +58,25 @@
 public final class TvInputManager {
     private static final String TAG = "TvInputManager";
 
+    static final int DVB_DEVICE_START = 0;
+    static final int DVB_DEVICE_END = 2;
+
+    /**
+     * A demux device of DVB API for controlling the filters of DVB hardware/software.
+     * @hide
+     */
+    public static final int DVB_DEVICE_DEMUX = DVB_DEVICE_START;
+     /**
+     * A DVR device of DVB API for reading transport streams.
+     * @hide
+     */
+    public static final int DVB_DEVICE_DVR = 1;
+    /**
+     * A frontend device of DVB API for controlling the tuner and DVB demodulator hardware.
+     * @hide
+     */
+    public static final int DVB_DEVICE_FRONTEND = DVB_DEVICE_END;
+
     static final int VIDEO_UNAVAILABLE_REASON_START = 0;
     static final int VIDEO_UNAVAILABLE_REASON_END = 4;
 
@@ -1258,6 +1280,43 @@
     }
 
     /**
+     * Returns the list of currently available DVB devices on the system.
+     *
+     * @return the list of {@link DvbDeviceInfo} objects representing available DVB devices.
+     * @hide
+     */
+    public List<DvbDeviceInfo> getDvbDeviceList() {
+        try {
+            return mService.getDvbDeviceList();
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns a {@link ParcelFileDescriptor} of a specified DVB device for a given
+     * {@link DvbDeviceInfo}
+     *
+     * @param info A {@link DvbDeviceInfo} to open a DVB device.
+     * @param device A DVB device. The DVB device can be {@link DVB_DEVICE_DEMUX},
+     *            {@link DVB_DEVICE_DVR} or {@link DVB_DEVICE_FRONTEND}.
+     * @return a {@link ParcelFileDescriptor} of a specified DVB device for a given
+     *            {@link DvbDeviceInfo}, or {@code null} if the given {@link DvbDeviceInfo} was
+     *            invalid or the specified DVB device was busy with a previous request.
+     * @hide
+     */
+    public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device) {
+        try {
+            if (DVB_DEVICE_START > device || DVB_DEVICE_END < device) {
+                throw new IllegalArgumentException("Invalid DVB device: " + device);
+            }
+            return mService.openDvbDevice(info, device);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
      * The Session provides the per-session functionality of TV inputs.
      * @hide
      */
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 84ae3b4..6c1bd97 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -738,12 +738,16 @@
             // do not create a new audio track if current track is compatible with sample parameters
     #ifdef USE_SHARED_MEM_BUFFER
             newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
-                    channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
+                    channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData,
+                    0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
+                    AudioTrack::TRANSFER_DEFAULT,
+                    NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes());
     #else
             uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
             newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
                     channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
-                    bufferFrames);
+                    bufferFrames, AUDIO_SESSION_ALLOCATE, AudioTrack::TRANSFER_DEFAULT,
+                    NULL /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/, mSoundPool->attributes());
     #endif
             oldTrack = mAudioTrack;
             status = newTrack->initCheck();
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b702e35..377a9a4 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -48,6 +48,8 @@
     <string name="wifi_security_psk_generic">@string/wifi_security_wpa_wpa2</string>
     <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP security -->
     <string name="wifi_security_eap">802.1x EAP</string>
+    <!-- Do not translate.  Concise terminology for Passpoint network -->
+    <string name="wifi_security_passpoint">Passpoint</string>
 
     <!-- Summary for the remembered network. -->
     <string name="wifi_remembered">Saved</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 1ad7a51..7049d6a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -248,6 +248,9 @@
 
     public String getSecurityString(boolean concise) {
         Context context = mContext;
+        if (mConfig != null && mConfig.isPasspoint()) {
+            return context.getString(R.string.wifi_security_passpoint);
+        }
         switch(security) {
             case SECURITY_EAP:
                 return concise ? context.getString(R.string.wifi_security_short_eap) :
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 080665aa..0462035 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -34,6 +34,8 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -47,6 +49,21 @@
  * service as usual.  The UI handler is only used by the {@link OverlayDisplayWindow}.
  * </p><p>
  * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
+ * </p><p>
+ * This adapter is configured via the
+ * {@link android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES} setting. This setting should be
+ * formatted as follows:
+ * <pre>
+ * [mode1]|[mode2]|...,[flag1],[flag2],...
+ * </pre>
+ * with each mode specified as:
+ * <pre>
+ * [width]x[height]/[densityDpi]
+ * </pre>
+ * Supported flags:
+ * <ul>
+ * <li><pre>secure</pre>: creates a secure display</li>
+ * </ul>
  * </p>
  */
 final class OverlayDisplayAdapter extends DisplayAdapter {
@@ -58,8 +75,10 @@
     private static final int MAX_WIDTH = 4096;
     private static final int MAX_HEIGHT = 4096;
 
-    private static final Pattern SETTING_PATTERN =
-            Pattern.compile("(\\d+)x(\\d+)/(\\d+)(,[a-z]+)*");
+    private static final Pattern DISPLAY_PATTERN =
+            Pattern.compile("([^,]+)(,[a-z]+)*");
+    private static final Pattern MODE_PATTERN =
+            Pattern.compile("(\\d+)x(\\d+)/(\\d+)");
 
     // Unique id prefix for overlay displays.
     private static final String UNIQUE_ID_PREFIX = "overlay:";
@@ -136,40 +155,49 @@
 
         int count = 0;
         for (String part : value.split(";")) {
-            Matcher matcher = SETTING_PATTERN.matcher(part);
-            if (matcher.matches()) {
+            Matcher displayMatcher = DISPLAY_PATTERN.matcher(part);
+            if (displayMatcher.matches()) {
                 if (count >= 4) {
                     Slog.w(TAG, "Too many overlay display devices specified: " + value);
                     break;
                 }
-                try {
-                    int width = Integer.parseInt(matcher.group(1), 10);
-                    int height = Integer.parseInt(matcher.group(2), 10);
-                    int densityDpi = Integer.parseInt(matcher.group(3), 10);
-                    String flagString = matcher.group(4);
-                    if (width >= MIN_WIDTH && width <= MAX_WIDTH
-                            && height >= MIN_HEIGHT && height <= MAX_HEIGHT
-                            && densityDpi >= DisplayMetrics.DENSITY_LOW
-                            && densityDpi <= DisplayMetrics.DENSITY_XXHIGH) {
-                        int number = ++count;
-                        String name = getContext().getResources().getString(
-                                com.android.internal.R.string.display_manager_overlay_display_name,
-                                number);
-                        int gravity = chooseOverlayGravity(number);
-                        boolean secure = flagString != null && flagString.contains(",secure");
-
-                        Slog.i(TAG, "Showing overlay display device #" + number
-                                + ": name=" + name + ", width=" + width + ", height=" + height
-                                + ", densityDpi=" + densityDpi + ", secure=" + secure);
-
-                        mOverlays.add(new OverlayDisplayHandle(name,
-                                width, height, densityDpi, gravity, secure, number));
+                String modeString = displayMatcher.group(1);
+                String flagString = displayMatcher.group(2);
+                ArrayList<OverlayMode> modes = new ArrayList<>();
+                for (String mode : modeString.split("\\|")) {
+                    Matcher modeMatcher = MODE_PATTERN.matcher(mode);
+                    if (modeMatcher.matches()) {
+                        try {
+                            int width = Integer.parseInt(modeMatcher.group(1), 10);
+                            int height = Integer.parseInt(modeMatcher.group(2), 10);
+                            int densityDpi = Integer.parseInt(modeMatcher.group(3), 10);
+                            if (width >= MIN_WIDTH && width <= MAX_WIDTH
+                                    && height >= MIN_HEIGHT && height <= MAX_HEIGHT
+                                    && densityDpi >= DisplayMetrics.DENSITY_LOW
+                                    && densityDpi <= DisplayMetrics.DENSITY_XXHIGH) {
+                                modes.add(new OverlayMode(width, height, densityDpi));
+                                continue;
+                            }
+                        } catch (NumberFormatException ex) {
+                        }
+                    } else if (mode.isEmpty()) {
                         continue;
                     }
-                } catch (NumberFormatException ex) {
                 }
-            } else if (part.isEmpty()) {
-                continue;
+                if (!modes.isEmpty()) {
+                    int number = ++count;
+                    String name = getContext().getResources().getString(
+                            com.android.internal.R.string.display_manager_overlay_display_name,
+                            number);
+                    int gravity = chooseOverlayGravity(number);
+                    boolean secure = flagString != null && flagString.contains(",secure");
+
+                    Slog.i(TAG, "Showing overlay display device #" + number
+                            + ": name=" + name + ", modes=" + Arrays.toString(modes.toArray()));
+
+                    mOverlays.add(new OverlayDisplayHandle(name, modes, gravity, secure, number));
+                    continue;
+                }
             }
             Slog.w(TAG, "Malformed overlay display devices setting: " + value);
         }
@@ -189,36 +217,41 @@
         }
     }
 
-    private final class OverlayDisplayDevice extends DisplayDevice {
+    private abstract class OverlayDisplayDevice extends DisplayDevice {
         private final String mName;
-        private final int mWidth;
-        private final int mHeight;
         private final float mRefreshRate;
         private final long mDisplayPresentationDeadlineNanos;
-        private final int mDensityDpi;
         private final boolean mSecure;
-        private final Display.Mode mMode;
+        private final List<OverlayMode> mRawModes;
+        private final Display.Mode[] mModes;
+        private final int mDefaultMode;
 
         private int mState;
         private SurfaceTexture mSurfaceTexture;
         private Surface mSurface;
         private DisplayDeviceInfo mInfo;
+        private int mActiveMode;
 
         public OverlayDisplayDevice(IBinder displayToken, String name,
-                int width, int height, float refreshRate, long presentationDeadlineNanos,
-                int densityDpi, boolean secure, int state,
+                List<OverlayMode> modes, int activeMode, int defaultMode,
+                float refreshRate, long presentationDeadlineNanos,
+                boolean secure, int state,
                 SurfaceTexture surfaceTexture, int number) {
             super(OverlayDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + number);
             mName = name;
-            mWidth = width;
-            mHeight = height;
             mRefreshRate = refreshRate;
             mDisplayPresentationDeadlineNanos = presentationDeadlineNanos;
-            mDensityDpi = densityDpi;
             mSecure = secure;
             mState = state;
             mSurfaceTexture = surfaceTexture;
-            mMode = createMode(width, height, refreshRate);
+            mRawModes = modes;
+            mModes = new Display.Mode[modes.size()];
+            for (int i = 0; i < modes.size(); i++) {
+                OverlayMode mode = modes.get(i);
+                mModes[i] = createMode(mode.mWidth, mode.mHeight, refreshRate);
+            }
+            mActiveMode = activeMode;
+            mDefaultMode = defaultMode;
         }
 
         public void destroyLocked() {
@@ -248,17 +281,19 @@
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
+                Display.Mode mode = mModes[mActiveMode];
+                OverlayMode rawMode = mRawModes.get(mActiveMode);
                 mInfo = new DisplayDeviceInfo();
                 mInfo.name = mName;
                 mInfo.uniqueId = getUniqueId();
-                mInfo.width = mWidth;
-                mInfo.height = mHeight;
-                mInfo.modeId = mMode.getModeId();
-                mInfo.defaultModeId = mMode.getModeId();
-                mInfo.supportedModes = new Display.Mode[] { mMode };
-                mInfo.densityDpi = mDensityDpi;
-                mInfo.xDpi = mDensityDpi;
-                mInfo.yDpi = mDensityDpi;
+                mInfo.width = mode.getPhysicalWidth();
+                mInfo.height = mode.getPhysicalHeight();
+                mInfo.modeId = mode.getModeId();
+                mInfo.defaultModeId = mModes[0].getModeId();
+                mInfo.supportedModes = mModes;
+                mInfo.densityDpi = rawMode.mDensityDpi;
+                mInfo.xDpi = rawMode.mDensityDpi;
+                mInfo.yDpi = rawMode.mDensityDpi;
                 mInfo.presentationDeadlineNanos = mDisplayPresentationDeadlineNanos +
                         1000000000L / (int) mRefreshRate;   // display's deadline + 1 frame
                 mInfo.flags = DisplayDeviceInfo.FLAG_PRESENTATION;
@@ -271,6 +306,40 @@
             }
             return mInfo;
         }
+
+        @Override
+        public void requestModeInTransactionLocked(int id) {
+            int index = -1;
+            if (id == 0) {
+                // Use the default.
+                index = 0;
+            } else {
+                for (int i = 0; i < mModes.length; i++) {
+                    if (mModes[i].getModeId() == id) {
+                        index = i;
+                        break;
+                    }
+                }
+            }
+            if (index == -1) {
+                Slog.w(TAG, "Unable to locate mode " + id + ", reverting to default.");
+                index = mDefaultMode;
+            }
+            if (mActiveMode == index) {
+                return;
+            }
+            mActiveMode = index;
+            mInfo = null;
+            sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
+            onModeChangedLocked(index);
+        }
+
+        /**
+         * Called when the device switched to a new mode.
+         *
+         * @param index index of the mode in the list of modes
+         */
+        public abstract void onModeChangedLocked(int index);
     }
 
     /**
@@ -280,27 +349,32 @@
      * Guarded by the {@link DisplayManagerService.SyncRoot} lock.
      */
     private final class OverlayDisplayHandle implements OverlayDisplayWindow.Listener {
+        private static final int DEFAULT_MODE_INDEX = 0;
+
         private final String mName;
-        private final int mWidth;
-        private final int mHeight;
-        private final int mDensityDpi;
+        private final List<OverlayMode> mModes;
         private final int mGravity;
         private final boolean mSecure;
         private final int mNumber;
 
         private OverlayDisplayWindow mWindow;
         private OverlayDisplayDevice mDevice;
+        private int mActiveMode;
 
-        public OverlayDisplayHandle(String name, int width,
-                int height, int densityDpi, int gravity, boolean secure, int number) {
+        public OverlayDisplayHandle(String name, List<OverlayMode> modes, int gravity,
+                boolean secure, int number) {
             mName = name;
-            mWidth = width;
-            mHeight = height;
-            mDensityDpi = densityDpi;
+            mModes = modes;
             mGravity = gravity;
             mSecure = secure;
             mNumber = number;
 
+            mActiveMode = 0;
+
+            showLocked();
+        }
+
+        private void showLocked() {
             mUiHandler.post(mShowRunnable);
         }
 
@@ -309,15 +383,28 @@
             mUiHandler.post(mDismissRunnable);
         }
 
+        private void onActiveModeChangedLocked(int index) {
+            mUiHandler.removeCallbacks(mResizeRunnable);
+            mActiveMode = index;
+            if (mWindow != null) {
+                mUiHandler.post(mResizeRunnable);
+            }
+        }
+
         // Called on the UI thread.
         @Override
         public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate,
                 long presentationDeadlineNanos, int state) {
             synchronized (getSyncRoot()) {
                 IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure);
-                mDevice = new OverlayDisplayDevice(displayToken, mName,
-                        mWidth, mHeight, refreshRate, presentationDeadlineNanos,
-                        mDensityDpi, mSecure, state, surfaceTexture, mNumber);
+                mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode,
+                        DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos,
+                        mSecure, state, surfaceTexture, mNumber) {
+                    @Override
+                    public void onModeChangedLocked(int index) {
+                        onActiveModeChangedLocked(index);
+                    }
+                };
 
                 sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
             }
@@ -347,9 +434,8 @@
 
         public void dumpLocked(PrintWriter pw) {
             pw.println("  " + mName + ":");
-            pw.println("    mWidth=" + mWidth);
-            pw.println("    mHeight=" + mHeight);
-            pw.println("    mDensityDpi=" + mDensityDpi);
+            pw.println("    mModes=" + Arrays.toString(mModes.toArray()));
+            pw.println("    mActiveMode=" + mActiveMode);
             pw.println("    mGravity=" + mGravity);
             pw.println("    mSecure=" + mSecure);
             pw.println("    mNumber=" + mNumber);
@@ -366,8 +452,9 @@
         private final Runnable mShowRunnable = new Runnable() {
             @Override
             public void run() {
+                OverlayMode mode = mModes.get(mActiveMode);
                 OverlayDisplayWindow window = new OverlayDisplayWindow(getContext(),
-                        mName, mWidth, mHeight, mDensityDpi, mGravity, mSecure,
+                        mName, mode.mWidth, mode.mHeight, mode.mDensityDpi, mGravity, mSecure,
                         OverlayDisplayHandle.this);
                 window.show();
 
@@ -392,5 +479,47 @@
                 }
             }
         };
+
+        // Runs on the UI thread.
+        private final Runnable mResizeRunnable = new Runnable() {
+            @Override
+            public void run() {
+                OverlayMode mode;
+                OverlayDisplayWindow window;
+                synchronized (getSyncRoot()) {
+                    if (mWindow == null) {
+                        return;
+                    }
+                    mode = mModes.get(mActiveMode);
+                    window = mWindow;
+                }
+                window.resize(mode.mWidth, mode.mHeight, mode.mDensityDpi);
+            }
+        };
+    }
+
+    /**
+     * A display mode for an overlay display.
+     */
+    private static final class OverlayMode {
+        final int mWidth;
+        final int mHeight;
+        final int mDensityDpi;
+
+        OverlayMode(int width, int height, int densityDpi) {
+            mWidth = width;
+            mHeight = height;
+            mDensityDpi = densityDpi;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder("{")
+                    .append("width=").append(mWidth)
+                    .append(", height=").append(mHeight)
+                    .append(", densityDpi=").append(mDensityDpi)
+                    .append("}")
+                    .toString();
+        }
     }
 }
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index 786889a..f23caf2 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -60,9 +60,9 @@
 
     private final Context mContext;
     private final String mName;
-    private final int mWidth;
-    private final int mHeight;
-    private final int mDensityDpi;
+    private int mWidth;
+    private int mHeight;
+    private int mDensityDpi;
     private final int mGravity;
     private final boolean mSecure;
     private final Listener mListener;
@@ -97,19 +97,9 @@
             Listener listener) {
         mContext = context;
         mName = name;
-        mWidth = width;
-        mHeight = height;
-        mDensityDpi = densityDpi;
         mGravity = gravity;
         mSecure = secure;
         mListener = listener;
-        mTitle = context.getResources().getString(
-                com.android.internal.R.string.display_manager_overlay_display_title,
-                mName, mWidth, mHeight, mDensityDpi);
-        if (secure) {
-            mTitle += context.getResources().getString(
-                    com.android.internal.R.string.display_manager_overlay_display_secure_suffix);
-        }
 
         mDisplayManager = (DisplayManager)context.getSystemService(
                 Context.DISPLAY_SERVICE);
@@ -119,6 +109,8 @@
         mDefaultDisplay = mWindowManager.getDefaultDisplay();
         updateDefaultDisplayInfo();
 
+        resize(width, height, densityDpi, false /* doLayout */);
+
         createWindow();
     }
 
@@ -145,6 +137,26 @@
         }
     }
 
+    public void resize(int width, int height, int densityDpi) {
+        resize(width, height, densityDpi, true /* doLayout */);
+    }
+
+    private void resize(int width, int height, int densityDpi, boolean doLayout) {
+        mWidth = width;
+        mHeight = height;
+        mDensityDpi = densityDpi;
+        mTitle = mContext.getResources().getString(
+                com.android.internal.R.string.display_manager_overlay_display_title,
+                mName, mWidth, mHeight, mDensityDpi);
+        if (mSecure) {
+            mTitle += mContext.getResources().getString(
+                    com.android.internal.R.string.display_manager_overlay_display_secure_suffix);
+        }
+        if (doLayout) {
+            relayout();
+        }
+    }
+
     public void relayout() {
         if (mWindowVisible) {
             updateWindowParams();
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 01aa0e6..145786f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11461,6 +11461,21 @@
                     replace = true;
                     if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
                 }
+
+                // Prevent apps opting out from runtime permissions
+                if (replace) {
+                    PackageParser.Package oldPackage = mPackages.get(pkgName);
+                    final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion;
+                    final int newTargetSdk = pkg.applicationInfo.targetSdkVersion;
+                    if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
+                            && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) {
+                        res.setError(PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE,
+                                "Package " + pkg.packageName + " new target SDK " + newTargetSdk
+                                        + " doesn't support runtime permissions but the old"
+                                        + " target SDK " + oldTargetSdk + " does.");
+                        return;
+                    }
+                }
             }
 
             PackageSetting ps = mSettings.mPackages.get(pkgName);
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e649e48..a869c20 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -39,6 +39,7 @@
 import android.graphics.Rect;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.media.tv.DvbDeviceInfo;
 import android.media.tv.ITvInputClient;
 import android.media.tv.ITvInputHardware;
 import android.media.tv.ITvInputHardwareCallback;
@@ -64,6 +65,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -80,23 +82,34 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.IllegalArgumentException;
+import java.lang.Integer;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /** This class provides a system service that manages television inputs. */
 public final class TvInputManagerService extends SystemService {
     private static final boolean DEBUG = false;
     private static final String TAG = "TvInputManagerService";
 
+    // Pattern for selecting the DVB frontend devices from the list of files in the /dev directory.
+    private static final Pattern sFrontEndDevicePattern =
+            Pattern.compile("^dvb([0-9]+)\\.frontend([0-9]+)$");
+
     private final Context mContext;
     private final TvInputHardwareManager mTvInputHardwareManager;
 
@@ -1507,6 +1520,74 @@
         }
 
         @Override
+        public List<DvbDeviceInfo> getDvbDeviceList() throws RemoteException {
+            if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires DVB_DEVICE permission");
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                ArrayList<DvbDeviceInfo> deviceInfos = new ArrayList<>();
+                File devDirectory = new File("/dev");
+                for (String fileName : devDirectory.list()) {
+                    Matcher matcher = sFrontEndDevicePattern.matcher(fileName);
+                    if (matcher.find()) {
+                        int adapterId = Integer.parseInt(matcher.group(1));
+                        int deviceId = Integer.parseInt(matcher.group(2));
+                        deviceInfos.add(new DvbDeviceInfo(adapterId, deviceId));
+                    }
+                }
+                return Collections.unmodifiableList(deviceInfos);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public ParcelFileDescriptor openDvbDevice(DvbDeviceInfo info, int device)
+                throws RemoteException {
+            if (mContext.checkCallingPermission(android.Manifest.permission.DVB_DEVICE)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Requires DVB_DEVICE permission");
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                String deviceFileName;
+                switch (device) {
+                    case TvInputManager.DVB_DEVICE_DEMUX:
+                        deviceFileName = String.format("/dev/dvb%d.demux%d", info.getAdapterId(),
+                                info.getDeviceId());
+                        break;
+                    case TvInputManager.DVB_DEVICE_DVR:
+                        deviceFileName = String.format("/dev/dvb%d.dvr%d", info.getAdapterId(),
+                                info.getDeviceId());
+                        break;
+                    case TvInputManager.DVB_DEVICE_FRONTEND:
+                        deviceFileName = String.format("/dev/dvb%d.frontend%d", info.getAdapterId(),
+                                info.getDeviceId());
+                        break;
+                    default:
+                        throw new IllegalArgumentException("Invalid DVB device: " + device);
+                }
+                try {
+                    // The DVB frontend device only needs to be opened in read/write mode, which
+                    // allows performing tuning operations. The DVB demux and DVR device are enough
+                    // to be opened in read only mode.
+                    return ParcelFileDescriptor.open(new File(deviceFileName),
+                            TvInputManager.DVB_DEVICE_FRONTEND == device
+                                    ? ParcelFileDescriptor.MODE_READ_WRITE
+                                    : ParcelFileDescriptor.MODE_READ_ONLY);
+                } catch (FileNotFoundException e) {
+                    return null;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int userId)
                 throws RemoteException {
             if (mContext.checkCallingPermission(
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 9033c9c..0357de2 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -289,11 +289,13 @@
         return mNextAppTransitionStartY;
     }
 
-    void prepare() {
+    boolean prepare() {
         if (!isRunning()) {
             mAppTransitionState = APP_STATE_IDLE;
             notifyAppTransitionPendingLocked();
+            return true;
         }
+        return false;
     }
 
     void goodToGo(AppWindowAnimator openingAppAnimator, AppWindowAnimator closingAppAnimator) {
@@ -953,8 +955,8 @@
                     : com.android.internal.R.anim.voice_activity_open_exit);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                     "applyAnimation voice:"
-                    + " anim=" + a + " transit=" + transit + " isEntrance=" + enter
-                    + " Callers=" + Debug.getCallers(3));
+                    + " anim=" + a + " transit=" + appTransitionToString(transit)
+                    + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3));
         } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE
                 || transit == TRANSIT_TASK_CLOSE
                 || transit == TRANSIT_TASK_TO_BACK)) {
@@ -963,22 +965,23 @@
                     : com.android.internal.R.anim.voice_activity_close_exit);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                     "applyAnimation voice:"
-                    + " anim=" + a + " transit=" + transit + " isEntrance=" + enter
-                    + " Callers=" + Debug.getCallers(3));
+                    + " anim=" + a + " transit=" + appTransitionToString(transit)
+                    + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = loadAnimationRes(mNextAppTransitionPackage, enter ?
                     mNextAppTransitionEnter : mNextAppTransitionExit);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                     "applyAnimation:"
                     + " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
-                    + " transit=" + transit + " isEntrance=" + enter
+                    + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter
                     + " Callers=" + Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) {
             a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                     "applyAnimation:"
-                            + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE"
-                            + " transit=" + transit + " Callers=" + Debug.getCallers(3));
+                    + " anim=" + a + " nextAppTransition=ANIM_CUSTOM_IN_PLACE"
+                    + " transit=" + appTransitionToString(transit)
+                    + " Callers=" + Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {
             a = createClipRevealAnimationLocked(transit, enter, appFrame);
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
@@ -990,7 +993,7 @@
             if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
                     "applyAnimation:"
                     + " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
-                    + " transit=" + transit + " isEntrance=" + enter
+                    + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter
                     + " Callers=" + Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
@@ -1003,7 +1006,7 @@
                         "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
                 Slog.v(TAG, "applyAnimation:"
                         + " anim=" + a + " nextAppTransition=" + animName
-                        + " transit=" + transit + " isEntrance=" + enter
+                        + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter
                         + " Callers=" + Debug.getCallers(3));
             }
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
@@ -1018,7 +1021,7 @@
                         "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
                 Slog.v(TAG, "applyAnimation:"
                         + " anim=" + a + " nextAppTransition=" + animName
-                        + " transit=" + transit + " isEntrance=" + enter
+                        + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter
                         + " Callers=" + Debug.getCallers(3));
             }
         } else {
@@ -1084,7 +1087,7 @@
                     "applyAnimation:"
                     + " anim=" + a
                     + " animAttr=0x" + Integer.toHexString(animAttr)
-                    + " transit=" + transit + " isEntrance=" + enter
+                    + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter
                     + " Callers=" + Debug.getCallers(3));
         }
         return a;
@@ -1188,7 +1191,7 @@
 
     @Override
     public String toString() {
-        return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
+        return "mNextAppTransition=" + appTransitionToString(mNextAppTransition);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 21011e8..3feec82 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -16,6 +16,11 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
+import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
+
 import android.graphics.Matrix;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -78,7 +83,11 @@
     boolean deferFinalFrameCleanup;
 
     /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
-    ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
+    ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<>();
+
+    /** True if the current animation was transferred from another AppWindowAnimator.
+     *  See {@link #transferCurrentAnimation}*/
+    boolean usingTransferredAnimation = false;
 
     static final Animation sDummyAnimation = new DummyAnimation();
 
@@ -102,9 +111,9 @@
         int zorder = anim.getZAdjustment();
         int adj = 0;
         if (zorder == Animation.ZORDER_TOP) {
-            adj = WindowManagerService.TYPE_LAYER_OFFSET;
+            adj = TYPE_LAYER_OFFSET;
         } else if (zorder == Animation.ZORDER_BOTTOM) {
-            adj = -WindowManagerService.TYPE_LAYER_OFFSET;
+            adj = -TYPE_LAYER_OFFSET;
         }
 
         if (animLayerAdjustment != adj) {
@@ -140,6 +149,7 @@
             mAppToken.allDrawn = false;
             mAppToken.deferClearAllDrawn = false;
         }
+        usingTransferredAnimation = false;
     }
 
     public boolean isAnimating() {
@@ -154,19 +164,38 @@
         deferThumbnailDestruction = false;
     }
 
+    void transferCurrentAnimation(
+            AppWindowAnimator toAppAnimator, WindowStateAnimator transferWinAnimator) {
+
+        if (animation != null) {
+            toAppAnimator.animation = animation;
+            animation = null;
+            toAppAnimator.animating = animating;
+            toAppAnimator.animLayerAdjustment = animLayerAdjustment;
+            animLayerAdjustment = 0;
+            toAppAnimator.updateLayers();
+            updateLayers();
+            toAppAnimator.usingTransferredAnimation = true;
+        }
+        if (transferWinAnimator != null) {
+            mAllAppWinAnimators.remove(transferWinAnimator);
+            toAppAnimator.mAllAppWinAnimators.add(transferWinAnimator);
+            transferWinAnimator.mAppAnimator = toAppAnimator;
+        }
+    }
+
     void updateLayers() {
-        final int N = mAppToken.allAppWindows.size();
+        final int windowCount = mAppToken.allAppWindows.size();
         final int adj = animLayerAdjustment;
         thumbnailLayer = -1;
-        for (int i=0; i<N; i++) {
+        for (int i = 0; i < windowCount; i++) {
             final WindowState w = mAppToken.allAppWindows.get(i);
             final WindowStateAnimator winAnimator = w.mWinAnimator;
             winAnimator.mAnimLayer = w.mLayer + adj;
             if (winAnimator.mAnimLayer > thumbnailLayer) {
                 thumbnailLayer = winAnimator.mAnimLayer;
             }
-            if (WindowManagerService.DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
-                    + winAnimator.mAnimLayer);
+            if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + winAnimator.mAnimLayer);
             if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
                 mService.setInputMethodAnimLayerAdjustment(adj);
             }
@@ -191,11 +220,11 @@
         // cache often used attributes locally
         final float tmpFloats[] = mService.mTmpFloats;
         thumbnailTransformation.getMatrix().getValues(tmpFloats);
-        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
+        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
                 "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
                 + ", " + tmpFloats[Matrix.MTRANS_Y], null);
         thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
-        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
+        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
                 "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
                 + " layer=" + thumbnailLayer
                 + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
@@ -228,14 +257,14 @@
                 deferFinalFrameCleanup = true;
                 hasMoreFrames = true;
             } else {
-                if (false && WindowManagerService.DEBUG_ANIM) Slog.v(
-                        TAG, "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames +
-                                ", xform=" + transformation);
+                if (false && DEBUG_ANIM) Slog.v(TAG,
+                        "Stepped animation in " + mAppToken + ": more=" + hasMoreFrames +
+                        ", xform=" + transformation);
                 deferFinalFrameCleanup = false;
                 animation = null;
                 clearThumbnail();
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                        TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
+                if (DEBUG_ANIM) Slog.v(TAG,
+                        "Finished animation in " + mAppToken + " @ " + currentTime);
             }
         }
         hasTransformation = hasMoreFrames;
@@ -258,8 +287,8 @@
             if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
                     && animation != null) {
                 if (!animating) {
-                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                        TAG, "Starting animation in " + mAppToken +
+                    if (DEBUG_ANIM) Slog.v(TAG,
+                        "Starting animation in " + mAppToken +
                         " @ " + currentTime + " scale="
                         + mService.getTransitionAnimationScaleLocked()
                         + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
@@ -306,8 +335,8 @@
             mService.moveInputMethodWindowsIfNeededLocked(true);
         }
 
-        if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                TAG, "Animation done in " + mAppToken
+        if (DEBUG_ANIM) Slog.v(TAG,
+                "Animation done in " + mAppToken
                 + ": reportedVisible=" + mAppToken.reportedVisible);
 
         transformation.clear();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 77694b6..4972ce4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -495,7 +495,7 @@
     String mLastANRState;
 
     /** All DisplayContents in the world, kept here */
-    SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>(2);
+    SparseArray<DisplayContent> mDisplayContents = new SparseArray<>(2);
 
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -511,7 +511,7 @@
             deathRecipient = d;
         }
     }
-    ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<RotationWatcher>();
+    ArrayList<RotationWatcher> mRotationWatchers = new ArrayList<>();
     int mDeferredRotationPauseCount;
 
     int mSystemDecorLayer = 0;
@@ -552,11 +552,10 @@
     private final PowerManager.WakeLock mScreenFrozenLock;
 
     final AppTransition mAppTransition;
-    boolean mStartingIconInTransition = false;
     boolean mSkipAppTransitionAnimation = false;
 
-    final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>();
-    final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>();
+    final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
+    final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
 
     boolean mIsTouchDevice;
 
@@ -581,7 +580,7 @@
     int mInputMethodAnimLayerAdjustment;
 
     WindowState mInputMethodWindow = null;
-    final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
+    final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<>();
 
     /** Temporary list for comparison. Always clear this after use so we don't end up with
      * orphaned windows references */
@@ -4146,8 +4145,8 @@
         }
 
         synchronized(mWindowMap) {
-            if (DEBUG_APP_TRANSITIONS) Slog.v(
-                    TAG, "Prepare app transition: transit=" + transit
+            if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:"
+                    + " transit=" + AppTransition.appTransitionToString(transit)
                     + " " + mAppTransition
                     + " alwaysKeepCurrent=" + alwaysKeepCurrent
                     + " Callers=" + Debug.getCallers(3));
@@ -4166,9 +4165,7 @@
                     mAppTransition.setAppTransition(transit);
                 }
             }
-            if (okToDisplay()) {
-                mAppTransition.prepare();
-                mStartingIconInTransition = false;
+            if (okToDisplay() && mAppTransition.prepare()) {
                 mSkipAppTransitionAnimation = false;
             }
             if (mAppTransition.isTransitionSet()) {
@@ -4295,19 +4292,16 @@
                 if (ttoken != null) {
                     WindowState startingWindow = ttoken.startingWindow;
                     if (startingWindow != null) {
-                        if (mStartingIconInTransition) {
-                            // In this case, the starting icon has already
-                            // been displayed, so start letting windows get
-                            // shown immediately without any more transitions.
-                            mSkipAppTransitionAnimation = true;
-                        }
+                        // In this case, the starting icon has already been displayed, so start
+                        // letting windows get shown immediately without any more transitions.
+                        mSkipAppTransitionAnimation = true;
+
                         if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
                                 "Moving existing starting " + startingWindow + " from " + ttoken
                                 + " to " + wtoken);
                         final long origId = Binder.clearCallingIdentity();
 
-                        // Transfer the starting window over to the new
-                        // token.
+                        // Transfer the starting window over to the new token.
                         wtoken.startingData = ttoken.startingData;
                         wtoken.startingView = ttoken.startingView;
                         wtoken.startingDisplayed = ttoken.startingDisplayed;
@@ -4321,7 +4315,6 @@
                         startingWindow.mToken = wtoken;
                         startingWindow.mRootToken = wtoken;
                         startingWindow.mAppToken = wtoken;
-                        startingWindow.mWinAnimator.mAppAnimator = wtoken.mAppAnimator;
 
                         if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
                             Slog.v(TAG, "Removing starting window: " + startingWindow);
@@ -4355,17 +4348,8 @@
                             wtoken.clientHidden = ttoken.clientHidden;
                             wtoken.sendAppVisibilityToClients();
                         }
-                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
-                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
-                        if (tAppAnimator.animation != null) {
-                            wAppAnimator.animation = tAppAnimator.animation;
-                            wAppAnimator.animating = tAppAnimator.animating;
-                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
-                            tAppAnimator.animation = null;
-                            tAppAnimator.animLayerAdjustment = 0;
-                            wAppAnimator.updateLayers();
-                            tAppAnimator.updateLayers();
-                        }
+                        ttoken.mAppAnimator.transferCurrentAnimation(
+                                wtoken.mAppAnimator, startingWindow.mWinAnimator);
 
                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                                 true /*updateInputWindows*/);
@@ -4465,7 +4449,6 @@
             }
 
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
-            mStartingIconInTransition = true;
             wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
                     labelRes, icon, logo, windowFlags);
             Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
@@ -4566,8 +4549,8 @@
                 changed = true;
             }
 
-            final int N = wtoken.allAppWindows.size();
-            for (int i=0; i<N; i++) {
+            final int windowsCount = wtoken.allAppWindows.size();
+            for (int i = 0; i < windowsCount; i++) {
                 WindowState win = wtoken.allAppWindows.get(i);
                 if (win == wtoken.startingWindow) {
                     continue;
@@ -4696,7 +4679,7 @@
             // If we are preparing an app transition, then delay changing
             // the visibility of this token until we execute that transition.
             if (okToDisplay() && mAppTransition.isTransitionSet()) {
-                if (!wtoken.startingDisplayed) {
+                if (!wtoken.startingDisplayed || mSkipAppTransitionAnimation) {
                     if (DEBUG_APP_TRANSITIONS) Slog.v(
                             TAG, "Setting dummy animation on: " + wtoken);
                     wtoken.mAppAnimator.setDummyAnimation();
@@ -9178,14 +9161,14 @@
     public int handleAppTransitionReadyLocked(WindowList windows) {
         int changes = 0;
         int i;
-        int NN = mOpeningApps.size();
+        int appsCount = mOpeningApps.size();
         boolean goodToGo = true;
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                "Checking " + NN + " opening apps (frozen="
+                "Checking " + appsCount + " opening apps (frozen="
                 + mDisplayFrozen + " timeout="
                 + mAppTransition.isTimeout() + ")...");
         if (!mAppTransition.isTimeout()) {
-            for (i=0; i<NN && goodToGo; i++) {
+            for (i = 0; i < appsCount && goodToGo; i++) {
                 AppWindowToken wtoken = mOpeningApps.valueAt(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "Check opening app=" + wtoken + ": allDrawn="
@@ -9238,7 +9221,6 @@
             if (mSkipAppTransitionAnimation) {
                 transit = AppTransition.TRANSIT_UNSET;
             }
-            mStartingIconInTransition = false;
             mSkipAppTransitionAnimation = false;
 
             mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
@@ -9287,17 +9269,17 @@
             // (2) Find the layout params of the top-most
             // application window in the tokens, which is
             // what will control the animation theme.
-            final int NC = mClosingApps.size();
-            NN = NC + mOpeningApps.size();
-            for (i=0; i<NN; i++) {
+            final int closingAppsCount = mClosingApps.size();
+            appsCount = closingAppsCount + mOpeningApps.size();
+            for (i = 0; i < appsCount; i++) {
                 final AppWindowToken wtoken;
-                if (i < NC) {
+                if (i < closingAppsCount) {
                     wtoken = mClosingApps.valueAt(i);
                     if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
                         closingAppHasWallpaper = true;
                     }
                 } else {
-                    wtoken = mOpeningApps.valueAt(i - NC);
+                    wtoken = mOpeningApps.valueAt(i - closingAppsCount);
                     if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
                         openingAppHasWallpaper = true;
                     }
@@ -9338,20 +9320,23 @@
                         transit = AppTransition.TRANSIT_WALLPAPER_INTRA_CLOSE;
                         break;
                 }
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "New transit: " + transit);
+                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+                        "New transit: " + AppTransition.appTransitionToString(transit));
             } else if ((oldWallpaper != null) && !mOpeningApps.isEmpty()
                     && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
                 // We are transitioning from an activity with
                 // a wallpaper to one without.
                 transit = AppTransition.TRANSIT_WALLPAPER_CLOSE;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "New transit away from wallpaper: " + transit);
+                        "New transit away from wallpaper: "
+                        + AppTransition.appTransitionToString(transit));
             } else if (mWallpaperTarget != null && mWallpaperTarget.isVisibleLw()) {
                 // We are transitioning from an activity without
                 // a wallpaper to now showing the wallpaper
                 transit = AppTransition.TRANSIT_WALLPAPER_OPEN;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "New transit into wallpaper: " + transit);
+                        "New transit into wallpaper: "
+                        + AppTransition.appTransitionToString(transit));
             } else {
                 mAnimateWallpaperWithTarget = true;
             }
@@ -9395,21 +9380,24 @@
                 }
             }
 
-            NN = mOpeningApps.size();
-            for (i=0; i<NN; i++) {
+            appsCount = mOpeningApps.size();
+            for (i = 0; i < appsCount; i++) {
                 AppWindowToken wtoken = mOpeningApps.valueAt(i);
                 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
-                appAnimator.clearThumbnail();
-                appAnimator.animation = null;
+
+                if (!appAnimator.usingTransferredAnimation) {
+                    appAnimator.clearThumbnail();
+                    appAnimator.animation = null;
+                }
                 wtoken.inPendingTransaction = false;
                 setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToShow = false;
 
                 appAnimator.mAllAppWinAnimators.clear();
-                final int N = wtoken.allAppWindows.size();
-                for (int j = 0; j < N; j++) {
+                final int windowsCount = wtoken.allAppWindows.size();
+                for (int j = 0; j < windowsCount; j++) {
                     appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
                 }
                 mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
@@ -9417,7 +9405,7 @@
 
                 if (animLp != null) {
                     int layer = -1;
-                    for (int j=0; j<wtoken.windows.size(); j++) {
+                    for (int j = 0; j < wtoken.windows.size(); j++) {
                         WindowState win = wtoken.windows.get(j);
                         if (win.mWinAnimator.mAnimLayer > layer) {
                             layer = win.mWinAnimator.mAnimLayer;
@@ -9429,8 +9417,8 @@
                     }
                 }
             }
-            NN = mClosingApps.size();
-            for (i=0; i<NN; i++) {
+            appsCount = mClosingApps.size();
+            for (i = 0; i < appsCount; i++) {
                 AppWindowToken wtoken = mClosingApps.valueAt(i);
                 final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
@@ -9454,7 +9442,7 @@
 
                 if (animLp != null) {
                     int layer = -1;
-                    for (int j=0; j<wtoken.windows.size(); j++) {
+                    for (int j = 0; j < wtoken.windows.size(); j++) {
                         WindowState win = wtoken.windows.get(j);
                         if (win.mWinAnimator.mAnimLayer > layer) {
                             layer = win.mWinAnimator.mAnimLayer;
@@ -11407,8 +11395,7 @@
                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
                     pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
             pw.print("  mTraversalScheduled="); pw.println(mTraversalScheduled);
-            pw.print("  mStartingIconInTransition="); pw.print(mStartingIconInTransition);
-                    pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
+            pw.print(" mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
             pw.println("  mLayoutToAnim:");
             mAppTransition.dump(pw, "    ");
         }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index bfd6cc0..f7bcf2a 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -100,7 +100,7 @@
 
     static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 4
             : 1L * 24 * 60 * ONE_MINUTE; // 1 day
-    static final long DEFAULT_CHECK_IDLE_INTERVAL = DEBUG ? ONE_MINUTE / 4
+    static final long DEFAULT_CHECK_IDLE_INTERVAL = DEBUG ? ONE_MINUTE
             : 8 * 60 * ONE_MINUTE; // 8 hours
     static final long DEFAULT_PAROLE_INTERVAL = DEBUG ? ONE_MINUTE * 10
             : 24 * 60 * ONE_MINUTE; // 24 hours between paroles
@@ -336,6 +336,7 @@
 
     /** Check all running users' apps to see if they enter an idle state. */
     void checkIdleStates() {
+        if (DEBUG) Slog.d(TAG, "Checking idle state");
         final int[] runningUsers;
         try {
             runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 6b8ca69..199100b 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -50,7 +50,7 @@
  * <pre>
  * &lt;service android:name="com.example.package.MyConnectionService"
  *    android:label="@string/some_label_for_my_connection_service"
- *    android:permission="android.permission.BIND_CONNECTION_SERVICE"&gt;
+ *    android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"&gt;
  *  &lt;intent-filter&gt;
  *   &lt;action android:name="android.telecom.ConnectionService" /&gt;
  *  &lt;/intent-filter&gt;
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 86475b1..f05a1ef 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -26,6 +26,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -127,6 +128,7 @@
 
     /**
      * Indicating no icon tint is set.
+     * @hide
      */
     public static final int NO_ICON_TINT = 0;
 
@@ -144,14 +146,11 @@
     private final Uri mAddress;
     private final Uri mSubscriptionAddress;
     private final int mCapabilities;
-    private final int mIconResId;
-    private final String mIconPackageName;
-    private final Bitmap mIconBitmap;
-    private final int mIconTint;
     private final int mHighlightColor;
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
     private final List<String> mSupportedUriSchemes;
+    private final Icon mIcon;
 
     /**
      * Helper class for creating a {@link PhoneAccount}.
@@ -161,14 +160,11 @@
         private Uri mAddress;
         private Uri mSubscriptionAddress;
         private int mCapabilities;
-        private int mIconResId;
-        private String mIconPackageName;
-        private Bitmap mIconBitmap;
-        private int mIconTint = NO_ICON_TINT;
         private int mHighlightColor = NO_HIGHLIGHT_COLOR;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
         private List<String> mSupportedUriSchemes = new ArrayList<String>();
+        private Icon mIcon;
 
         /**
          * Creates a builder with the specified {@link PhoneAccountHandle} and label.
@@ -189,14 +185,11 @@
             mAddress = phoneAccount.getAddress();
             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
             mCapabilities = phoneAccount.getCapabilities();
-            mIconResId = phoneAccount.getIconResId();
-            mIconPackageName = phoneAccount.getIconPackageName();
-            mIconBitmap = phoneAccount.getIconBitmap();
-            mIconTint = phoneAccount.getIconTint();
             mHighlightColor = phoneAccount.getHighlightColor();
             mLabel = phoneAccount.getLabel();
             mShortDescription = phoneAccount.getShortDescription();
             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
+            mIcon = phoneAccount.getIcon();
         }
 
         /**
@@ -233,65 +226,12 @@
         }
 
         /**
-         * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
+         * Sets the icon. See {@link PhoneAccount#getIcon}.
          *
-         * @param packageContext The package from which to load an icon.
-         * @param iconResId The resource in {@code iconPackageName} representing the icon.
-         * @return The builder.
+         * @param icon The icon to set.
          */
-        public Builder setIcon(Context packageContext, int iconResId) {
-            return setIcon(packageContext.getPackageName(), iconResId);
-        }
-
-        /**
-         * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
-         *
-         * @param iconPackageName The package from which to load an icon.
-         * @param iconResId The resource in {@code iconPackageName} representing the icon.
-         * @return The builder.
-         */
-        public Builder setIcon(String iconPackageName, int iconResId) {
-            return setIcon(iconPackageName, iconResId, NO_ICON_TINT);
-        }
-
-        /**
-         * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
-         *
-         * @param packageContext The package from which to load an icon.
-         * @param iconResId The resource in {@code iconPackageName} representing the icon.
-         * @param iconTint A color with which to tint this icon.
-         * @return The builder.
-         */
-        public Builder setIcon(Context packageContext, int iconResId, int iconTint) {
-            return setIcon(packageContext.getPackageName(), iconResId, iconTint);
-        }
-
-        /**
-         * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
-         *
-         * @param iconPackageName The package from which to load an icon.
-         * @param iconResId The resource in {@code iconPackageName} representing the icon.
-         * @param iconTint A color with which to tint this icon.
-         * @return The builder.
-         */
-        public Builder setIcon(String iconPackageName, int iconResId, int iconTint) {
-            this.mIconPackageName = iconPackageName;
-            this.mIconResId = iconResId;
-            this.mIconTint = iconTint;
-            return this;
-        }
-
-        /**
-         * Sets the icon. See {@link PhoneAccount#createIconDrawable}.
-         *
-         * @param iconBitmap The icon bitmap.
-         * @return The builder.
-         */
-        public Builder setIcon(Bitmap iconBitmap) {
-            this.mIconBitmap = iconBitmap;
-            this.mIconPackageName = null;
-            this.mIconResId = NO_RESOURCE_ID;
-            this.mIconTint = NO_ICON_TINT;
+        public Builder setIcon(Icon icon) {
+            mIcon = icon;
             return this;
         }
 
@@ -363,10 +303,7 @@
                     mAddress,
                     mSubscriptionAddress,
                     mCapabilities,
-                    mIconResId,
-                    mIconPackageName,
-                    mIconBitmap,
-                    mIconTint,
+                    mIcon,
                     mHighlightColor,
                     mLabel,
                     mShortDescription,
@@ -379,10 +316,7 @@
             Uri address,
             Uri subscriptionAddress,
             int capabilities,
-            int iconResId,
-            String iconPackageName,
-            Bitmap iconBitmap,
-            int iconTint,
+            Icon icon,
             int highlightColor,
             CharSequence label,
             CharSequence shortDescription,
@@ -391,10 +325,7 @@
         mAddress = address;
         mSubscriptionAddress = subscriptionAddress;
         mCapabilities = capabilities;
-        mIconResId = iconResId;
-        mIconPackageName = iconPackageName;
-        mIconBitmap = iconBitmap;
-        mIconTint = iconTint;
+        mIcon = icon;
         mHighlightColor = highlightColor;
         mLabel = label;
         mShortDescription = shortDescription;
@@ -497,6 +428,15 @@
     }
 
     /**
+     * The icon to represent this {@code PhoneAccount}.
+     *
+     * @return The icon.
+     */
+    public Icon getIcon() {
+        return mIcon;
+    }
+
+    /**
      * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
      * scheme.
      *
@@ -518,59 +458,6 @@
     }
 
     /**
-     * The icon resource ID for the icon of this {@code PhoneAccount}.
-     * <p>
-     * Creators of a {@code PhoneAccount} who possess the icon in static resources should prefer
-     * this method of indicating the icon rather than using {@link #getIconBitmap()}, since it
-     * leads to less resource usage.
-     * <p>
-     * Clients wishing to display a {@code PhoneAccount} should use {@link #createIconDrawable(Context)}.
-     *
-     * @return A resource ID.
-     */
-    public int getIconResId() {
-        return mIconResId;
-    }
-
-    /**
-     * The package name from which to load the icon of this {@code PhoneAccount}.
-     * <p>
-     * If this property is {@code null}, the resource {@link #getIconResId()} will be loaded from
-     * the package in the {@link ComponentName} of the {@link #getAccountHandle()}.
-     * <p>
-     * Clients wishing to display a {@code PhoneAccount} should use {@link #createIconDrawable(Context)}.
-     *
-     * @return A package name.
-     */
-    public String getIconPackageName() {
-        return mIconPackageName;
-    }
-
-    /**
-     * A tint to apply to the icon of this {@code PhoneAccount}.
-     *
-     * @return A hexadecimal color value.
-     */
-    public int getIconTint() {
-        return mIconTint;
-    }
-
-    /**
-     * A literal icon bitmap to represent this {@code PhoneAccount} in a user interface.
-     * <p>
-     * If this property is specified, it is to be considered the preferred icon. Otherwise, the
-     * resource specified by {@link #getIconResId()} should be used.
-     * <p>
-     * Clients wishing to display a {@code PhoneAccount} should use
-     * {@link #createIconDrawable(Context)}.
-     *
-     * @return A bitmap.
-     */
-    public Bitmap getIconBitmap() {
-        return mIconBitmap;
-    }
-
-    /**
      * A highlight color to use in displaying information about this {@code PhoneAccount}.
      *
      * @return A hexadecimal color value.
@@ -579,41 +466,6 @@
         return mHighlightColor;
     }
 
-    /**
-     * Builds and returns an icon {@code Drawable} to represent this {@code PhoneAccount} in a user
-     * interface. Uses the properties {@link #getIconResId()}, {@link #getIconPackageName()}, and
-     * {@link #getIconBitmap()} as necessary.
-     *
-     * @param context A {@code Context} to use for loading {@code Drawable}s.
-     *
-     * @return An icon for this {@code PhoneAccount}.
-     */
-    public Drawable createIconDrawable(Context context) {
-        if (mIconBitmap != null) {
-            return new BitmapDrawable(context.getResources(), mIconBitmap);
-        }
-
-        if (mIconResId != 0) {
-            try {
-                Context packageContext = context.createPackageContext(mIconPackageName, 0);
-                try {
-                    Drawable iconDrawable = packageContext.getDrawable(mIconResId);
-                    if (mIconTint != NO_ICON_TINT) {
-                        iconDrawable.setTint(mIconTint);
-                    }
-                    return iconDrawable;
-                } catch (NotFoundException | MissingResourceException e) {
-                    Log.e(this, e, "Cannot find icon %d in package %s",
-                            mIconResId, mIconPackageName);
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.w(this, "Cannot find package %s", mIconPackageName);
-            }
-        }
-
-        return new ColorDrawable(Color.TRANSPARENT);
-    }
-
     //
     // Parcelable implementation
     //
@@ -644,19 +496,16 @@
             mSubscriptionAddress.writeToParcel(out, flags);
         }
         out.writeInt(mCapabilities);
-        out.writeInt(mIconResId);
-        out.writeString(mIconPackageName);
-        if (mIconBitmap == null) {
-            out.writeInt(0);
-        } else {
-            out.writeInt(1);
-            mIconBitmap.writeToParcel(out, flags);
-        }
-        out.writeInt(mIconTint);
         out.writeInt(mHighlightColor);
         out.writeCharSequence(mLabel);
         out.writeCharSequence(mShortDescription);
         out.writeStringList(mSupportedUriSchemes);
+        if (mIcon == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(1);
+            mIcon.writeToParcel(out, flags);
+        }
     }
 
     public static final Creator<PhoneAccount> CREATOR
@@ -689,18 +538,15 @@
             mSubscriptionAddress = null;
         }
         mCapabilities = in.readInt();
-        mIconResId = in.readInt();
-        mIconPackageName = in.readString();
-        if (in.readInt() > 0) {
-            mIconBitmap = Bitmap.CREATOR.createFromParcel(in);
-        } else {
-            mIconBitmap = null;
-        }
-        mIconTint = in.readInt();
         mHighlightColor = in.readInt();
         mLabel = in.readCharSequence();
         mShortDescription = in.readCharSequence();
         mSupportedUriSchemes = Collections.unmodifiableList(in.createStringArrayList());
+        if (in.readInt() > 0) {
+            mIcon = Icon.CREATOR.createFromParcel(in);
+        } else {
+            mIcon = null;
+        }
     }
 
     @Override
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index b2c036c..c8ed2b0 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -333,16 +333,24 @@
      * displayed to the user.
      */
 
-    /** Property is displayed normally. */
+    /**
+     * Indicates that the address or number of a call is allowed to be displayed for caller ID.
+    */
     public static final int PRESENTATION_ALLOWED = 1;
 
-    /** Property was blocked. */
+    /**
+     * Indicates that the address or number of a call is blocked by the other party.
+     */
     public static final int PRESENTATION_RESTRICTED = 2;
 
-    /** Presentation was not specified or is unknown. */
+    /**
+     * Indicates that the address or number of a call is not specified or known by the carrier.
+     */
     public static final int PRESENTATION_UNKNOWN = 3;
 
-    /** Property should be displayed as a pay phone. */
+    /**
+     * Indicates that the address or number of a call belongs to a pay phone.
+     */
     public static final int PRESENTATION_PAYPHONE = 4;
 
     private static final String TAG = "TelecomManager";
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 030a5d5..a2b1858 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -757,7 +757,7 @@
      * of state change events.
      * <p>
      * <b>Note:</b> If an application's target SDK version is
-     * {@link android.os.Build.VERSION_CODES#MNC} or newer, network
+     * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network
      * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may
      * instead be sent through another network, such as cellular data,
      * Bluetooth tethering, or Ethernet. For example, traffic will never use a
@@ -776,7 +776,7 @@
      * @return {@code true} if the operation succeeded
      */
     public boolean enableNetwork(int netId, boolean disableOthers) {
-        final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.MNC;
+        final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
         if (pin) {
             registerPinningNetworkCallback();
         }