Merge "Fix a flicker when window is removed during entering animation" into nyc-dev
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index 0d25f80..7ed827c 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -230,11 +230,12 @@
     }
 
     /**
-     * Gets a value. Valid value types are {@link String}, {@link Boolean}, and
-     * {@link Number} implementations.
+     * Gets a value. Valid value types are {@link String}, {@link Boolean},
+     * {@link Number}, and {@code byte[]} implementations.
      *
      * @param key the value to get
-     * @return the data for the value
+     * @return the data for the value, or {@code null} if the value is missing or if {@code null}
+     *         was previously added with the given {@code key}
      */
     public Object get(String key) {
         return mValues.get(key);
@@ -255,7 +256,7 @@
      * Gets a value and converts it to a Long.
      *
      * @param key the value to get
-     * @return the Long value, or null if the value is missing or cannot be converted
+     * @return the Long value, or {@code null} if the value is missing or cannot be converted
      */
     public Long getAsLong(String key) {
         Object value = mValues.get(key);
@@ -280,7 +281,7 @@
      * Gets a value and converts it to an Integer.
      *
      * @param key the value to get
-     * @return the Integer value, or null if the value is missing or cannot be converted
+     * @return the Integer value, or {@code null} if the value is missing or cannot be converted
      */
     public Integer getAsInteger(String key) {
         Object value = mValues.get(key);
@@ -305,7 +306,7 @@
      * Gets a value and converts it to a Short.
      *
      * @param key the value to get
-     * @return the Short value, or null if the value is missing or cannot be converted
+     * @return the Short value, or {@code null} if the value is missing or cannot be converted
      */
     public Short getAsShort(String key) {
         Object value = mValues.get(key);
@@ -330,7 +331,7 @@
      * Gets a value and converts it to a Byte.
      *
      * @param key the value to get
-     * @return the Byte value, or null if the value is missing or cannot be converted
+     * @return the Byte value, or {@code null} if the value is missing or cannot be converted
      */
     public Byte getAsByte(String key) {
         Object value = mValues.get(key);
@@ -355,7 +356,7 @@
      * Gets a value and converts it to a Double.
      *
      * @param key the value to get
-     * @return the Double value, or null if the value is missing or cannot be converted
+     * @return the Double value, or {@code null} if the value is missing or cannot be converted
      */
     public Double getAsDouble(String key) {
         Object value = mValues.get(key);
@@ -380,7 +381,7 @@
      * Gets a value and converts it to a Float.
      *
      * @param key the value to get
-     * @return the Float value, or null if the value is missing or cannot be converted
+     * @return the Float value, or {@code null} if the value is missing or cannot be converted
      */
     public Float getAsFloat(String key) {
         Object value = mValues.get(key);
@@ -405,7 +406,7 @@
      * Gets a value and converts it to a Boolean.
      *
      * @param key the value to get
-     * @return the Boolean value, or null if the value is missing or cannot be converted
+     * @return the Boolean value, or {@code null} if the value is missing or cannot be converted
      */
     public Boolean getAsBoolean(String key) {
         Object value = mValues.get(key);
@@ -428,7 +429,8 @@
      * any other types to byte arrays.
      *
      * @param key the value to get
-     * @return the byte[] value, or null is the value is missing or not a byte[]
+     * @return the {@code byte[]} value, or {@code null} is the value is missing or not a
+     *         {@code byte[]}
      */
     public byte[] getAsByteArray(String key) {
         Object value = mValues.get(key);
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 50e7356..0f64b92 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1431,10 +1431,9 @@
      *            row. The keys should be the column names and the values the
      *            column values
      * @param conflictAlgorithm for insert conflict resolver
-     * @return the row ID of the newly inserted row
-     * OR the primary key of the existing row if the input param 'conflictAlgorithm' =
-     * {@link #CONFLICT_IGNORE}
-     * OR -1 if any error
+     * @return the row ID of the newly inserted row OR <code>-1</code> if either the
+     *            input parameter <code>conflictAlgorithm</code> = {@link #CONFLICT_IGNORE}
+     *            or an error occurred.
      */
     public long insertWithOnConflict(String table, String nullColumnHack,
             ContentValues initialValues, int conflictAlgorithm) {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9b74fc0..fe24230 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1803,7 +1803,21 @@
          */
         public final void setSurfaceInsets(View view, boolean manual, boolean preservePrevious) {
             final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
-            surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+            // Partial workaround for b/28318973. Every inset change causes a freeform window
+            // to jump a little for a few frames. If we never allow surface insets to decrease,
+            // they will stabilize quickly (often from the very beginning, as most windows start
+            // as focused).
+            // TODO(b/22668382) to fix this properly.
+            if (surfaceInset == 0) {
+                // OK to have 0 (this is the case for non-freeform windows).
+                surfaceInsets.set(0, 0, 0, 0);
+            } else {
+                surfaceInsets.set(
+                        Math.max(surfaceInset, surfaceInsets.left),
+                        Math.max(surfaceInset, surfaceInsets.top),
+                        Math.max(surfaceInset, surfaceInsets.right),
+                        Math.max(surfaceInset, surfaceInsets.bottom));
+            }
             hasManualSurfaceInsets = manual;
             preservePreviousSurfaceInsets = preservePrevious;
         }
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index fdf9e31..8ca12ae 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -1172,7 +1172,8 @@
 
     <style name="Widget.Holo.Light.FastScroll" parent="Widget.Holo.FastScroll" />
 
-    <style name="Widget.Holo.SuggestionItem" parent="TextAppearance.Holo.Medium">
+    <style name="Widget.Holo.SuggestionItem">
+        <item name="textAppearance">@android:style/TextAppearance.Holo.Medium</item>
         <item name="background">@color/white</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
@@ -1188,9 +1189,9 @@
         <item name="textColor">@color/black</item>
     </style>
 
-    <style name="TextAppearance.Holo.SuggestionHighlight" parent="TextAppearance.SuggestionHighlight" />
+    <style name="TextAppearance.Holo.SuggestionHighlight" parent="@android:style/TextAppearance.SuggestionHighlight" />
 
-    <style name="Widget.Holo.SuggestionButton" parent="Widget.Holo.SuggestionItem">
+    <style name="Widget.Holo.SuggestionButton" parent="@android:style/Widget.Holo.SuggestionItem">
         <item name="background">#E9E9E9</item>
         <item name="textColor">@color/black</item>
     </style>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 6752e3c..3ed8daa 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -1001,7 +1001,8 @@
         <item name="contentDescription">@string/media_route_button_content_description</item>
     </style>
 
-    <style name="Widget.Material.SuggestionItem" parent="@android:style/TextAppearance.Material.Body1">
+    <style name="Widget.Material.SuggestionItem">
+        <item name="textAppearance">@android:style/TextAppearance.Material.Body1</item>
         <item name="textColor">?attr/textColorSecondary</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
@@ -1016,11 +1017,12 @@
         <item name="textSize">14sp</item>
     </style>
 
-    <style name="TextAppearance.Material.TextSuggestionHighlight" parent="Widget.Material.SuggestionItem">
+    <style name="TextAppearance.Material.TextSuggestionHighlight">
         <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
-    <style name="Widget.Material.SuggestionButton" parent="@android:style/TextAppearance.Material.Button">
+    <style name="Widget.Material.SuggestionButton">
+        <item name="textAppearance">@android:style/TextAppearance.Material.Button</item>
         <item name="textColor">?attr/colorAccent</item>
         <item name="drawablePadding">8dip</item>
         <item name="gravity">start|center_vertical</item>
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index 110418a..dc78bb9 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -733,19 +733,21 @@
 
 <p>
   Android N introduces APK Signature Scheme v2, a new app-signing scheme that
-  offers faster app install times and better protection against unauthorized
-  alterations to APK files. Android Studio 2.2 and Gradle provide built-in
-  support for APK Signature Scheme v2.
+  offers faster app install times and more protection against unauthorized
+  alterations to APK files. By default, Android Studio 2.2 and the Android
+  Plugin for Gradle 2.2 sign your app using both APK Signature Scheme v2 and
+  the traditional signing scheme, which uses JAR signing.
 </p>
 
 <p>
-  Although we recommend applying APK Signature Scheme v2 to your app, the new
-  scheme is not mandatory. If your app doesn't build properly when using the
-  APK Signature Scheme v2, you can use the traditional signing scheme—which
-  uses JAR signing—instead. To use the traditional scheme, open the
-  module-level <code>build.gradle</code> file and add the
-  <code>v2SigningEnabled</code> parameter to your release signing
-  configuration, setting this parameter's value to <code>false</code>:
+  Although we recommend applying APK Signature Scheme v2 to your app, this new
+  scheme is not mandatory. If your app doesn't build properly when using APK
+  Signature Scheme v2, you can disable the new scheme. The disabling process
+  causes Android Studio 2.2 and the Android Plugin for Gradle 2.2 to sign your
+  app using only the traditional signing scheme. To sign with only the
+  traditional scheme, open the module-level <code>build.gradle</code> file, then
+  add the line <code>v2SigningEnabled false</code> to your release signing
+  configuration:
 </p>
 
 <pre>
@@ -764,12 +766,18 @@
   }
 </pre>
 
+<p class="caution"><strong>Caution: </strong> If you sign your app using APK
+  Signature Scheme v2 and make further changes to the app, the app's signature
+  is invalidated. For this reason, use tools such as <code>zipalign</code>
+  before signing your app using APK Signature Scheme v2, not after.
+</p>
+
 <p>
-  For more information, see the following guides, which describe how to <a href=
-  "{@docRoot}studio/tools/publishing/app-signing.html#release-mode"> sign an app
-  in Android Studio</a> and how to <a href=
+  For more information, read the Android Studio documents that describe how to
+  <a href="{@docRoot}studio/tools/publishing/app-signing.html#release-mode">
+  sign an app</a> in Android Studio and how to <a href=
   "{@docRoot}studio/tools/building/configuring-gradle.html#signing"> configure
-  the Gradle build file for signing apps</a>.
+  the build file for signing apps</a> using the Android Plugin for Gradle.
 </p>
 
 <h2 id="scoped_directory_access">Scoped directory access</h2>
diff --git a/docs/html/preview/features/data-saver.jd b/docs/html/preview/features/data-saver.jd
index d5cdf27..c4cab18 100644
--- a/docs/html/preview/features/data-saver.jd
+++ b/docs/html/preview/features/data-saver.jd
@@ -14,7 +14,7 @@
         <a href="#status">Checking Data Saver Preferences</a>
         <ol>
           <li>
-            <a href="#request-whitelist">Requesting Whitelist Permissions</a>
+            <a href="#request-whitelist">Requesting whitelist permissions</a>
           </li>
         </ol>
       </li>
@@ -138,15 +138,17 @@
   If your app needs to use data in the background, it can request whitelist
   permissions by sending a
   <code>Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS</code>
-  (<code>"android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS"</code>)
-  intent with a <code>package:&lt;your-app-id&gt;</code> URI.
+  intent containing a URI of your app's package name: for example,
+  <code>package:MY_APP_ID</code>.
 </p>
 
 <p>
-  Sending the intent and URI launches the <strong>Settings</strong> app, and
-  displays your app's <strong>App Data Usage</strong> page to the user. The
-  user can then decide whether to enable background data for your app.
-  It is good practice to prompt the user before sending this intent.
+  Sending the intent and URI launches the <strong>Settings</strong> app and
+  displays data usage settings for your app. The user can then decide whether
+  to enable background data for your app. Before you send this intent, it is
+  good practice to first ask the user if they want to launch the
+  <strong>Settings</strong> app for the purpose of enabling background data
+  usage.
 </p>
 
 <h2 id="monitor-changes">
@@ -156,9 +158,8 @@
 <p>
   Apps can monitor changes to Data Saver preferences by creating a {@link
   android.content.BroadcastReceiver} to listen for {@code
-  ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED} ({@code
-  "android.net.conn.RESTRICT_BACKGROUND_CHANGED"}) and dynamically registering
-  the receiver with {@link android.content.Context#registerReceiver
+  ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED} and dynamically
+  registering the receiver with {@link android.content.Context#registerReceiver
   Context.registerReceiver()}. When an app receives this broadcast, it should
   <a href="#status">check if the new Data Saver preferences affect its
   permissions</a> by calling {@code
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 6e1ff06..5b2ce07 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -123,6 +123,7 @@
     private final Rect mTouchRegion = new Rect();
     private boolean mAnimatingForIme;
     private boolean mAdjustedForIme;
+    private int mImeHeight;
     private WindowState mDelayedImeWin;
     private boolean mAdjustedForDivider;
     private float mDividerAnimationStart;
@@ -296,8 +297,9 @@
 
     void setAdjustedForIme(
             boolean adjustedForIme, boolean adjustedForDivider,
-            boolean animate, WindowState imeWin) {
-        if (mAdjustedForIme != adjustedForIme || mAdjustedForDivider != adjustedForDivider) {
+            boolean animate, WindowState imeWin, int imeHeight) {
+        if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight)
+                || mAdjustedForDivider != adjustedForDivider) {
             if (animate) {
                 startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
             } else {
@@ -305,10 +307,15 @@
                 notifyAdjustedForImeChanged(adjustedForIme || adjustedForDivider, 0 /* duration */);
             }
             mAdjustedForIme = adjustedForIme;
+            mImeHeight = imeHeight;
             mAdjustedForDivider = adjustedForDivider;
         }
     }
 
+    int getImeHeightAdjustedFor() {
+        return mImeHeight;
+    }
+
     void positionDockedStackedDivider(Rect frame) {
         TaskStack stack = mDisplayContent.getDockedStackLocked();
         if (stack == null) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 58468f6..7426329 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -849,10 +849,10 @@
      *
      * @param imeWin The IME window.
      */
-    void setAdjustedForIme(WindowState imeWin) {
+    void setAdjustedForIme(WindowState imeWin, boolean forceUpdate) {
         mImeWin = imeWin;
         mImeGoingAway = false;
-        if (!mAdjustedForIme) {
+        if (!mAdjustedForIme || forceUpdate) {
             mAdjustedForIme = true;
             mAdjustImeAmount = 0f;
             mAdjustDividerAmount = 0f;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d817036..8fa9efb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7566,6 +7566,9 @@
         final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
         final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
         final boolean dockMinimized = displayContent.mDividerControllerLocked.isMinimizedDock();
+        final int imeHeight = mPolicy.getInputMethodWindowVisibleHeightLw();
+        final boolean imeHeightChanged = imeVisible &&
+                imeHeight != displayContent.mDividerControllerLocked.getImeHeightAdjustedFor();
 
         // The divider could be adjusted for IME position, or be thinner than usual,
         // or both. There are three possible cases:
@@ -7579,13 +7582,13 @@
                 final TaskStack stack = stacks.get(i);
                 final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
                 if (stack.isVisibleLocked() && (imeOnBottom || isDockedOnBottom)) {
-                    stack.setAdjustedForIme(imeWin);
+                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
                 } else {
                     stack.resetAdjustedForIme(false);
                 }
             }
             displayContent.mDividerControllerLocked.setAdjustedForIme(
-                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin);
+                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
         } else {
             final ArrayList<TaskStack> stacks = displayContent.getStacks();
             for (int i = stacks.size() - 1; i >= 0; --i) {
@@ -7593,7 +7596,7 @@
                 stack.resetAdjustedForIme(!dockVisible);
             }
             displayContent.mDividerControllerLocked.setAdjustedForIme(
-                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin);
+                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
         }
     }