Merge "Update CarrierService long lived binding API" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index f47e4c3..d266f1e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12301,7 +12301,6 @@
     method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void invalidateSelf();
     method public boolean isAutoMirrored();
-    method public boolean isDither();
     method public boolean isFilterBitmap();
     method public boolean isStateful();
     method public final boolean isVisible();
@@ -12321,7 +12320,7 @@
     method public void setChangingConfigurations(int);
     method public abstract void setColorFilter(android.graphics.ColorFilter);
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public void setDither(boolean);
+    method public deprecated void setDither(boolean);
     method public void setFilterBitmap(boolean);
     method public void setHotspot(float, float);
     method public void setHotspotBounds(int, int, int, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3e01cd7..a7c0f49 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -12627,7 +12627,6 @@
     method public void inflate(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public void invalidateSelf();
     method public boolean isAutoMirrored();
-    method public boolean isDither();
     method public boolean isFilterBitmap();
     method public boolean isStateful();
     method public final boolean isVisible();
@@ -12647,7 +12646,7 @@
     method public void setChangingConfigurations(int);
     method public abstract void setColorFilter(android.graphics.ColorFilter);
     method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
-    method public void setDither(boolean);
+    method public deprecated void setDither(boolean);
     method public void setFilterBitmap(boolean);
     method public void setHotspot(float, float);
     method public void setHotspotBounds(int, int, int, int);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f9b41a93..c51c061 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2090,7 +2090,7 @@
          <p>Declaring the permission implies intention to use the API and the user of the
          device can grant permission through the Settings application. -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
-        android:protectionLevel="signature|development|appop" />
+        android:protectionLevel="signature|system|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <!-- @hide Allows an application to change the app idle state of an app.
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index f059727..fcd7f63 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -362,11 +362,6 @@
         invalidateSelf();
     }
 
-    @Override
-    public boolean isDither() {
-        return mBitmapState.mPaint.isDither();
-    }
-
     /**
      * Indicates the repeat behavior of this drawable on the X axis.
      *
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 7af78a7..32af59a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -269,26 +269,16 @@
     }
 
     /**
-     * Set to true to have the drawable dither its colors when drawn to a device
-     * with fewer than 8-bits per color component.
+     * Set to true to have the drawable dither its colors when drawn to a
+     * device with fewer than 8-bits per color component.
      *
-     * <p>This can improve the look on those devices, but can also slow down
-     * the drawing a little.</p>
-     *
-     * @see #isDither()
      * @see android.graphics.Paint#setDither(boolean);
+     * @deprecated This property is ignored.
      */
+    @Deprecated
     public void setDither(boolean dither) {}
 
     /**
-     * @return whether this drawable dithers its colors
-     * @see #setDither(boolean)
-     */
-    public boolean isDither() {
-        return false;
-    }
-
-    /**
      * Set to true to have the drawable filter its bitmaps with bilinear
      * sampling when they are scaled or rotated.
      *
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 1759f53..b344b86 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -167,11 +167,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mDrawableContainerState.mDither;
-    }
-
-    @Override
     public void setColorFilter(ColorFilter colorFilter) {
         mDrawableContainerState.mHasColorFilter = true;
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 626991d..a11b2cd 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -826,11 +826,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mGradientState.mDither;
-    }
-
-    @Override
     public ColorFilter getColorFilter() {
         return mColorFilter;
     }
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 90891f6..8373c7f 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -1248,16 +1248,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        final Drawable dr = getFirstNonNullDrawable();
-        if (dr != null) {
-            return dr.isDither();
-        } else {
-            return super.isDither();
-        }
-    }
-
-    @Override
     public void setAlpha(int alpha) {
         final ChildDrawable[] array = mLayerState.mChildren;
         final int N = mLayerState.mNum;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index adf53e3..152fe6a 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -374,11 +374,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mPaint == null ? DEFAULT_DITHER : mPaint.isDither();
-    }
-
-    @Override
     public void setAutoMirrored(boolean mirrored) {
         mNinePatchState.mAutoMirrored = mirrored;
     }
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index a669d3c..30b588e 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -328,11 +328,6 @@
     }
 
     @Override
-    public boolean isDither() {
-        return mShapeState.mPaint.isDither();
-    }
-
-    @Override
     protected void onBoundsChange(Rect bounds) {
         super.onBoundsChange(bounds);
         updateShape();
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 64333ad6..003a274 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -272,7 +272,7 @@
     /**
      * Tunes to a given channel.
      *
-     * @param inputId The ID of TV input which will play the given channel.
+     * @param inputId The ID of the TV input for the given channel.
      * @param channelUri The URI of a channel.
      */
     public void tune(@NonNull String inputId, Uri channelUri) {
@@ -282,9 +282,9 @@
     /**
      * Tunes to a given channel.
      *
-     * @param inputId The ID of TV input which will play the given channel.
+     * @param inputId The ID of TV input for the given channel.
      * @param channelUri The URI of a channel.
-     * @param params Extra parameters which might be handled with the tune event.
+     * @param params Extra parameters.
      * @hide
      */
     @SystemApi
@@ -298,22 +298,26 @@
                 sMainTvView = new WeakReference<>(this);
             }
         }
-        if (mSessionCallback != null && mSessionCallback.mInputId.equals(inputId)) {
+        if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) {
             if (mSession != null) {
                 mSession.tune(channelUri, params);
             } else {
-                // Session is not created yet. Replace the channel which will be set once the
-                // session is made.
+                // createSession() was called but the actual session for the given inputId has not
+                // yet been created. Just replace the existing tuning params in the callback with
+                // the new ones and tune later in onSessionCreated(). It is not necessary to create
+                // a new callback because this tuning request was made on the same inputId.
                 mSessionCallback.mChannelUri = channelUri;
                 mSessionCallback.mTuneParams = params;
             }
         } else {
             resetInternal();
-            // When createSession() is called multiple times before the callback is called,
-            // only the callback of the last createSession() call will be actually called back.
-            // The previous callbacks will be ignored. For the logic, mSessionCallback
-            // is newly assigned for every createSession request and compared with
-            // MySessionCreateCallback.this.
+            // In case createSession() is called multiple times across different inputId's before
+            // any session is created (e.g. when quickly tuning to a channel from input A and then
+            // to another channel from input B), only the callback for the last createSession()
+            // should be invoked. (The previous callbacks are simply ignored.) To do that, we create
+            // a new callback each time and keep mSessionCallback pointing to the last one. If
+            // MySessionCallback.this is different from mSessionCallback, we know that this callback
+            // is obsolete and should ignore it.
             mSessionCallback = new MySessionCallback(inputId, channelUri, params);
             if (mTvInputManager != null) {
                 mTvInputManager.createSession(inputId, mSessionCallback, mHandler);
@@ -337,6 +341,7 @@
     }
 
     private void resetInternal() {
+        mSessionCallback = null;
         mPendingAppPrivateCommands.clear();
         if (mSession != null) {
             setSessionSurface(null);
@@ -344,7 +349,6 @@
             mUseRequestedSurfaceLayout = false;
             mSession.release();
             mSession = null;
-            mSessionCallback = null;
             resetSurfaceView();
         }
     }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 458150c..7204aec 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1504,6 +1504,8 @@
         try {
             final NativeDaemonEvent res = mConnector.execute("volume", "benchmark", volId);
             return Long.parseLong(res.getMessage());
+        } catch (NativeDaemonTimeoutException e) {
+            return Long.MAX_VALUE;
         } catch (NativeDaemonConnectorException e) {
             throw e.rethrowAsParcelableException();
         }
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 78c7f38..e7979e4 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -421,7 +421,7 @@
             event = mResponseQueue.remove(sequenceNumber, timeout, logCmd);
             if (event == null) {
                 loge("timed-out waiting for response to " + logCmd);
-                throw new NativeDaemonFailureException(logCmd, event);
+                throw new NativeDaemonTimeoutException(logCmd, event);
             }
             if (VDBG) log("RMV <- {" + event + "}");
             events.add(event);
diff --git a/services/core/java/com/android/server/NativeDaemonTimeoutException.java b/services/core/java/com/android/server/NativeDaemonTimeoutException.java
new file mode 100644
index 0000000..658f7d6
--- /dev/null
+++ b/services/core/java/com/android/server/NativeDaemonTimeoutException.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.android.server;
+
+/**
+ * An exception that indicates there was a timeout with a
+ * {@link NativeDaemonConnector} operation.
+ */
+public class NativeDaemonTimeoutException extends NativeDaemonConnectorException {
+    public NativeDaemonTimeoutException(String command, NativeDaemonEvent event) {
+        super(command, event);
+    }
+}
+
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2da24cc..dbf0f17 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -310,6 +310,7 @@
     static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
     static final int SCAN_REQUIRE_KNOWN = 1<<12;
     static final int SCAN_MOVE = 1<<13;
+    static final int SCAN_INITIAL = 1<<14;
 
     static final int REMOVE_CHATTY = 1<<16;
 
@@ -1840,7 +1841,7 @@
 
             // Set flag to monitor and not change apk file paths when
             // scanning install directories.
-            final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
+            final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
 
             final ArraySet<String> alreadyDexOpted = new ArraySet<String>();
 
@@ -11327,7 +11328,7 @@
 
     private boolean shouldCheckUpgradeKeySetLP(PackageSetting oldPs, int scanFlags) {
         // Can't rotate keys during boot or if sharedUser.
-        if (oldPs == null || (scanFlags&SCAN_BOOTING) != 0 || oldPs.sharedUser != null
+        if (oldPs == null || (scanFlags&SCAN_INITIAL) != 0 || oldPs.sharedUser != null
                 || !oldPs.keySetData.isUsingUpgradeKeySets()) {
             return false;
         }
@@ -11711,6 +11712,10 @@
                 || (args.volumeUuid != null));
         boolean replace = false;
         int scanFlags = SCAN_NEW_INSTALL | SCAN_UPDATE_SIGNATURE;
+        if (args.move != null) {
+            // moving a complete application; perfom an initial scan on the new install location
+            scanFlags |= SCAN_INITIAL;
+        }
         // Result object to be returned
         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
 
@@ -15007,7 +15012,7 @@
             for (PackageSetting ps : packages) {
                 final PackageParser.Package pkg;
                 try {
-                    pkg = scanPackageLI(ps.codePath, parseFlags, 0, 0, null);
+                    pkg = scanPackageLI(ps.codePath, parseFlags, SCAN_INITIAL, 0L, null);
                     loaded.add(pkg.applicationInfo);
                 } catch (PackageManagerException e) {
                     Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());