Merge "Suppress logging to avoid showing phone no." into lmp-mr1-dev
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d053ceb..68df6f1 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -424,6 +424,10 @@
     <!-- Integer indicating wpa_supplicant scan interval in milliseconds -->
     <integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>
 
+    <!-- Integer indicating amount of time failed networks areblacklisted for the purpose
+         of network switching in milliseconds -->
+    <integer translatable="false" name="config_wifi_network_switching_blacklist_time">172800000</integer>
+
     <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
     <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e47d5f7..1055547 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -327,6 +327,7 @@
   <java-symbol type="integer" name="config_wifi_framework_scan_result_rssi_level_patchup_value" />
   <java-symbol type="integer" name="config_wifi_framework_current_network_boost" />
   <java-symbol type="string"  name="config_wifi_random_mac_oui" />
+  <java-symbol type="integer"  name="config_wifi_network_switching_blacklist_time" />
 
   <java-symbol type="bool" name="editable_voicemailnumber" />
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 4bbe6ed..cdf8150 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -273,7 +273,7 @@
             layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
     if (mRenderState) {
         int memused = 0;
-        for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin();
+        for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
                 it != mRenderState->mActiveLayers.end(); it++) {
             const Layer* layer = *it;
             log.appendFormat("    Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 9aa29ca..05259ff 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -69,17 +69,25 @@
 }
 
 Layer::~Layer() {
-    renderState.requireGLContext();
     renderState.unregisterLayer(this);
     SkSafeUnref(colorFilter);
-    removeFbo();
-    deleteTexture();
+
+    if (stencil || fbo || texture.id) {
+        renderState.requireGLContext();
+        removeFbo();
+        deleteTexture();
+    }
 
     delete[] mesh;
     delete deferredList;
     delete renderer;
 }
 
+void Layer::onGlContextLost() {
+    removeFbo();
+    deleteTexture();
+}
+
 uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
     return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
 }
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 64d1d12..e196cb1 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -286,6 +286,12 @@
     void postDecStrong();
 
     /**
+     * Lost the GL context but the layer is still around, mark it invalid internally
+     * so the dtor knows not to do any GL work
+     */
+    void onGlContextLost();
+
+    /**
      * Bounds of the layer.
      */
     Rect layer;
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index d1f5f4e..ca640e5 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -41,6 +41,10 @@
     mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
 }
 
+static void layerLostGlContext(Layer* layer) {
+    layer->onGlContextLost();
+}
+
 void RenderState::onGLContextDestroyed() {
 /*
     size_t size = mActiveLayers.size();
@@ -73,6 +77,7 @@
         LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
     }
 */
+    std::for_each(mActiveLayers.begin(), mActiveLayers.end(), layerLostGlContext);
     mAssetAtlas.terminate();
 }
 
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index 1ecfb1c..9ac9356 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -53,10 +53,10 @@
 
     void debugOverdraw(bool enable, bool clear);
 
-    void registerLayer(const Layer* layer) {
+    void registerLayer(Layer* layer) {
         mActiveLayers.insert(layer);
     }
-    void unregisterLayer(const Layer* layer) {
+    void unregisterLayer(Layer* layer) {
         mActiveLayers.erase(layer);
     }
 
@@ -90,7 +90,7 @@
     renderthread::RenderThread& mRenderThread;
     Caches* mCaches;
     AssetAtlas mAssetAtlas;
-    std::set<const Layer*> mActiveLayers;
+    std::set<Layer*> mActiveLayers;
     std::set<renderthread::CanvasContext*> mRegisteredContexts;
 
     GLsizei mViewportWidth;
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 0d6b91a..53ab264 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -214,6 +214,11 @@
          * the underlying data could be mapped as a pointer in JNI without doing
          * any copies with {@code GetDirectBufferAddress}.</p>
          *
+         * <p>For raw formats, each plane is only guaranteed to contain data
+         * up to the last pixel in the last row. In other words, the stride
+         * after the last row may not be mapped into the buffer. This is a
+         * necessary requirement for any interleaved format.</p>
+         *
          * @return the byte buffer containing the image data for this plane.
          */
         public abstract ByteBuffer getBuffer();
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 3f4736d..890b039 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -351,7 +351,7 @@
     int bytesPerPixel = 0;
 
     dataSize = ySize = cSize = cStride = 0;
-    int32_t fmt = buffer->format;
+    int32_t fmt = buffer->flexFormat;
 
     bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
     fmt = applyFormatOverrides(fmt, readerFormat);
@@ -363,18 +363,21 @@
                 (idx == 1) ?
                     buffer->dataCb :
                 buffer->dataCr;
+            // only map until last pixel
             if (idx == 0) {
-                dataSize = buffer->stride * buffer->height;
+                dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
             } else {
-                dataSize = buffer->chromaStride * buffer->height / 2;
+                dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
+                        buffer->chromaStep * (buffer->width / 2 - 1) + 1;
             }
             break;
         // NV21
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             cr = buffer->data + (buffer->stride * buffer->height);
             cb = cr + 1;
-            ySize = buffer->width * buffer->height;
-            cSize = buffer->width * buffer->height / 2;
+            // only map until last pixel
+            ySize = buffer->width * (buffer->height - 1) + buffer->width;
+            cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
 
             pData =
                 (idx == 0) ?
@@ -488,7 +491,7 @@
     int pixelStride = 0;
     ALOG_ASSERT(buffer != NULL, "buffer is NULL");
 
-    int32_t fmt = buffer->format;
+    int32_t fmt = buffer->flexFormat;
 
     fmt = applyFormatOverrides(fmt, readerFormat);
 
@@ -549,7 +552,7 @@
     int rowStride = 0;
     ALOG_ASSERT(buffer != NULL, "buffer is NULL");
 
-    int32_t fmt = buffer->format;
+    int32_t fmt = buffer->flexFormat;
 
     fmt = applyFormatOverrides(fmt, readerFormat);
 
@@ -797,7 +800,7 @@
         return ACQUIRE_NO_BUFFERS;
     }
 
-    if (buffer->format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+    if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
         jniThrowException(env, "java/lang/UnsupportedOperationException",
                 "NV21 format is not supported by ImageReader");
         return -1;
@@ -826,8 +829,10 @@
     }
 
     int bufFmt = buffer->format;
+    if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+        bufFmt = buffer->flexFormat;
+    }
     if (imgReaderFmt != bufFmt) {
-
         if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
                 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
             // Special casing for when producer switches to a format compatible with flexible YUV
@@ -849,7 +854,7 @@
             String8 msg;
             msg.appendFormat("The producer output buffer format 0x%x doesn't "
                     "match the ImageReader's configured buffer format 0x%x.",
-                    buffer->format, ctx->getBufferFormat());
+                    bufFmt, ctx->getBufferFormat());
             jniThrowException(env, "java/lang/UnsupportedOperationException",
                     msg.string());
             return -1;
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
index 59d5605..7f48768 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceHandler.java
@@ -62,11 +62,6 @@
     void process(ActiveSource newActive, int deviceType) {
         // Seq #17
         HdmiCecLocalDeviceTv tv = mSource;
-        ActiveSource activeSource = tv.getActiveSource();
-        if (activeSource.equals(newActive)) {
-            invokeCallback(HdmiControlManager.RESULT_SUCCESS);
-            return;
-        }
         HdmiDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress);
         if (device == null) {
             tv.startNewDeviceAction(newActive, deviceType);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 43ef457..664f541 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.HdmiPortInfo;
 import android.hardware.hdmi.HdmiRecordSources;
 import android.hardware.hdmi.HdmiTimerRecordSources;
 import android.hardware.hdmi.IHdmiControlCallback;
@@ -878,6 +879,17 @@
         return oldStatus;
     }
 
+    @ServiceThreadOnly
+    private void updateArcFeatureStatus(int portId, boolean isConnected) {
+        assertRunOnServiceThread();
+        // HEAC 2.4, HEACT 5-15
+        // Should not activate ARC if +5V status is false.
+        HdmiPortInfo portInfo = mService.getPortInfo(portId);
+        if (portInfo.isArcSupported()) {
+            changeArcFeatureEnabled(isConnected);
+        }
+    }
+
     private void notifyArcStatusToAudioService(boolean enabled) {
         // Note that we don't set any name to ARC.
         mService.getAudioManager().setWiredDeviceConnectionState(
@@ -1456,6 +1468,25 @@
     }
 
     /**
+     * Returns the {@link HdmiDeviceInfo} instance whose physical address matches
+     * the given routing path. This is the version accessible safely from threads
+     * other than service thread.
+     *
+     * @param path routing path or physical address
+     * @return {@link HdmiDeviceInfo} if the matched info is found; otherwise null
+     */
+    HdmiDeviceInfo getSafeDeviceInfoByPath(int path) {
+        synchronized (mLock) {
+            for (HdmiDeviceInfo info : mSafeAllDeviceInfos) {
+                if (info.getPhysicalAddress() == path) {
+                    return info;
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
      * Whether a device of the specified physical address and logical address exists
      * in a device info list. However, both are minimal condition and it could
      * be different device from the original one.
@@ -1490,6 +1521,7 @@
             // It covers seq #40, #43.
             hotplugActions.get(0).pollAllDevicesNow();
         }
+        updateArcFeatureStatus(portId, connected);
     }
 
     private void removeCecSwitches(int portId) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 9f78c61..49a96d8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1196,7 +1196,7 @@
             }
             int activePath = tv.getActivePath();
             if (activePath != HdmiDeviceInfo.PATH_INVALID) {
-                HdmiDeviceInfo info = tv.getDeviceInfoByPath(activePath);
+                HdmiDeviceInfo info = tv.getSafeDeviceInfoByPath(activePath);
                 return (info != null) ? info : new HdmiDeviceInfo(activePath, tv.getActivePortId());
             }
             return null;
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 722be71..1bbd038 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -38,6 +38,7 @@
 
     private static final int POLLING_INTERVAL_MS = 5000;
     private static final int TIMEOUT_COUNT = 3;
+    private static final int AVR_COUNT_MAX = 3;
 
     // State in which waits for next polling
     private static final int STATE_WAIT_FOR_NEXT_POLLING = 1;
@@ -48,6 +49,12 @@
 
     private int mTimeoutCount = 0;
 
+    // Counter used to ensure the connection to AVR is stable. Occasional failure to get
+    // polling response from AVR despite its presence leads to unstable status flipping.
+    // This is a workaround to deal with it, by removing the device only if the removal
+    // is detected {@code AVR_COUNT_MAX} times in a row.
+    private int mAvrStatusCount = 0;
+
     /**
      * Constructor
      *
@@ -148,10 +155,22 @@
         BitSet removed = complement(currentInfos, polledResult);
         int index = -1;
         while ((index = removed.nextSetBit(index + 1)) != -1) {
+            if (index == Constants.ADDR_AUDIO_SYSTEM) {
+                ++mAvrStatusCount;
+                Slog.w(TAG, "Ack not returned from AVR. count: " + mAvrStatusCount);
+                if (mAvrStatusCount < AVR_COUNT_MAX) {
+                    continue;
+                }
+            }
             Slog.v(TAG, "Remove device by hot-plug detection:" + index);
             removeDevice(index);
         }
 
+        // Reset the counter if the ack is returned from AVR.
+        if (!removed.get(Constants.ADDR_AUDIO_SYSTEM)) {
+            mAvrStatusCount = 0;
+        }
+
         // Next, check added devices.
         BitSet added = complement(polledResult, currentInfos);
         index = -1;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8d438e3..526a3b2 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -640,13 +640,9 @@
      */
     /** {@hide} */
     public String getDeviceId(int slotId) {
-        // FIXME methods taking slot id should not use subscription, instead us Uicc directly
-        int[] subId = SubscriptionManager.getSubId(slotId);
-        if (subId == null || subId.length == 0) {
-            return null;
-        }
+        // FIXME this assumes phoneId == slotId
         try {
-            return getSubscriberInfo().getDeviceIdForSubscriber(subId[0]);
+            return getSubscriberInfo().getDeviceIdForPhone(slotId);
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index eec5333..c91a59c 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -33,10 +33,10 @@
     String getNaiForSubscriber(int subId);
 
     /**
-     * Retrieves the unique device ID of a subId for the device, e.g., IMEI
+     * Retrieves the unique device ID of a phone for the device, e.g., IMEI
      * for GSM phones.
      */
-    String getDeviceIdForSubscriber(int subId);
+    String getDeviceIdForPhone(int phoneId);
 
     /**
      * Retrieves the IMEI.
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 6543c03..87db951 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -688,6 +688,31 @@
 
     /**
      * @hide
+     * Last time the system tried to roam and failed because of authentication failure or DHCP
+     * RENEW failure.
+     */
+    public long lastRoamingFailure;
+
+    /** @hide */
+    public static int ROAMING_FAILURE_IP_CONFIG = 1;
+    /** @hide */
+    public static int ROAMING_FAILURE_AUTH_FAILURE = 2;
+
+    /**
+     * @hide
+     * Initial amount of time this Wifi configuration gets blacklisted for network switching
+     * because of roaming failure
+     */
+    public long roamingFailureBlackListTimeMilli = 1000;
+
+    /**
+     * @hide
+     * Last roaming failure reason code
+     */
+    public int lastRoamingFailureReason;
+
+    /**
+     * @hide
      * Last time the system was disconnected to this configuration.
      */
     public long lastDisconnected;
@@ -1148,6 +1173,18 @@
                 sbuf.append( "sec");
             }
         }
+        if (this.lastRoamingFailure != 0) {
+            sbuf.append('\n');
+            long diff = now_ms - this.lastRoamingFailure;
+            if (diff <= 0) {
+                sbuf.append("lastRoamingFailure since <incorrect>");
+            } else {
+                sbuf.append("lastRoamingFailure: ").append(Long.toString(diff/1000));
+                sbuf.append( "sec");
+            }
+        }
+        sbuf.append("roamingFailureBlackListTimeMilli: ").
+                append(Long.toString(this.roamingFailureBlackListTimeMilli));
         sbuf.append('\n');
         if (this.linkedConfigurations != null) {
             for(String key : this.linkedConfigurations.keySet()) {
@@ -1518,6 +1555,9 @@
             lastConnected = source.lastConnected;
             lastDisconnected = source.lastDisconnected;
             lastConnectionFailure = source.lastConnectionFailure;
+            lastRoamingFailure = source.lastRoamingFailure;
+            lastRoamingFailureReason = source.lastRoamingFailureReason;
+            roamingFailureBlackListTimeMilli = source.roamingFailureBlackListTimeMilli;
             numConnectionFailures = source.numConnectionFailures;
             numIpConfigFailures = source.numIpConfigFailures;
             numAuthFailures = source.numAuthFailures;
@@ -1587,6 +1627,9 @@
         dest.writeInt(lastUpdateUid);
         dest.writeLong(blackListTimestamp);
         dest.writeLong(lastConnectionFailure);
+        dest.writeLong(lastRoamingFailure);
+        dest.writeInt(lastRoamingFailureReason);
+        dest.writeLong(roamingFailureBlackListTimeMilli);
         dest.writeInt(numConnectionFailures);
         dest.writeInt(numIpConfigFailures);
         dest.writeInt(numAuthFailures);
@@ -1649,6 +1692,9 @@
                 config.lastUpdateUid = in.readInt();
                 config.blackListTimestamp = in.readLong();
                 config.lastConnectionFailure = in.readLong();
+                config.lastRoamingFailure = in.readLong();
+                config.lastRoamingFailureReason = in.readInt();
+                config.roamingFailureBlackListTimeMilli = in.readLong();
                 config.numConnectionFailures = in.readInt();
                 config.numIpConfigFailures = in.readInt();
                 config.numAuthFailures = in.readInt();