Merge "IMS: add the api to get IMS registration information." into lmp-mr1-dev
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index e250ec7..d40a2c0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -90,6 +90,7 @@
     private final boolean mCountdownConditionSupported;
     private final int mFirstConditionIndex;
     private final TransitionHelper mTransitionHelper = new TransitionHelper();
+    private final Uri mForeverId;
 
     private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
 
@@ -134,6 +135,7 @@
         mMaxConditions = MathUtils.constrain(res.getInteger(R.integer.zen_mode_max_conditions),
                 minConditions, 100);
         mMaxOptionalConditions = mMaxConditions - minConditions;
+        mForeverId = Condition.newId(mContext).appendPath("forever").build();
         if (DEBUG) Log.d(mTag, "new ZenModePanel");
     }
 
@@ -338,12 +340,11 @@
     }
 
     private void refreshExitConditionText() {
-        final String forever = mContext.getString(com.android.internal.R.string.zen_mode_forever);
         if (mExitCondition == null) {
-            mExitConditionText = forever;
+            mExitConditionText = foreverSummary();
         } else if (isCountdown(mExitCondition)) {
             final Condition condition = parseExistingTimeCondition(mExitCondition);
-            mExitConditionText = condition != null ? condition.summary : forever;
+            mExitConditionText = condition != null ? condition.summary : foreverSummary();
         } else {
             mExitConditionText = mExitCondition.summary;
         }
@@ -473,9 +474,9 @@
         final int conditionCount = mConditions == null ? 0 : mConditions.length;
         if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
         // forever
-        bind(null, mZenConditions.getChildAt(FOREVER_CONDITION_INDEX));
+        bind(forever(), mZenConditions.getChildAt(FOREVER_CONDITION_INDEX));
         // countdown
-        if (mCountdownConditionSupported) {
+        if (mCountdownConditionSupported && mTimeCondition != null) {
             bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
         }
         // provider conditions
@@ -483,7 +484,8 @@
             bind(mConditions[i], mZenConditions.getChildAt(mFirstConditionIndex + i));
         }
         // hide the rest
-        for (int i = mZenConditions.getChildCount() - 1; i > mFirstConditionIndex + conditionCount; i--) {
+        for (int i = mZenConditions.getChildCount() - 1; i > mFirstConditionIndex + conditionCount;
+                i--) {
             mZenConditions.getChildAt(i).setVisibility(GONE);
         }
         // ensure something is selected
@@ -492,6 +494,15 @@
         }
     }
 
+    private Condition forever() {
+        return new Condition(mForeverId, foreverSummary(), "", "", 0 /*icon*/, Condition.STATE_TRUE,
+                0 /*flags*/);
+    }
+
+    private String foreverSummary() {
+        return mContext.getString(com.android.internal.R.string.zen_mode_forever);
+    }
+
     private ConditionTag getConditionTagAt(int index) {
         return (ConditionTag) mZenConditions.getChildAt(index).getTag();
     }
@@ -556,8 +567,13 @@
         return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
     }
 
+    private boolean isForever(Condition c) {
+        return c != null && mForeverId.equals(c.id);
+    }
+
     private void bind(final Condition condition, final View row) {
-        final boolean enabled = condition == null || condition.state == Condition.STATE_TRUE;
+        if (condition == null) throw new IllegalArgumentException("condition must not be null");
+        final boolean enabled = condition.state == Condition.STATE_TRUE;
         final ConditionTag tag =
                 row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();
         row.setTag(tag);
@@ -604,14 +620,9 @@
         if (tag.line2 == null) {
             tag.line2 = (TextView) row.findViewById(android.R.id.text2);
         }
-        final String line1, line2;
-        if (condition == null) {
-            line1 = mContext.getString(com.android.internal.R.string.zen_mode_forever);
-            line2 = null;
-        } else {
-            line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1 : condition.summary;
-            line2 = condition.line2;
-        }
+        final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
+                : condition.summary;
+        final String line2 = condition.line2;
         tag.line1.setText(line1);
         if (TextUtils.isEmpty(line2)) {
             tag.line2.setVisibility(GONE);
@@ -731,16 +742,17 @@
 
     private void select(final Condition condition) {
         if (DEBUG) Log.d(mTag, "select " + condition);
+        final boolean isForever = isForever(condition);
         if (mController != null) {
             AsyncTask.execute(new Runnable() {
                 @Override
                 public void run() {
-                    mController.setExitCondition(condition);
+                    mController.setExitCondition(isForever ? null : condition);
                 }
             });
         }
         setExitCondition(condition);
-        if (condition == null) {
+        if (isForever) {
             mPrefs.setMinuteIndex(-1);
         } else if (isCountdown(condition) && mBucketIndex != -1) {
             mPrefs.setMinuteIndex(mBucketIndex);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b1f14a9..766e4c7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4036,9 +4036,6 @@
                     }
                     mNetworkForRequestId.put(nri.request.requestId, newNetwork);
                     newNetwork.addRequest(nri.request);
-                    if (nri.isRequest && nri.request.legacyType != TYPE_NONE) {
-                        mLegacyTypeTracker.add(nri.request.legacyType, newNetwork);
-                    }
                     keep = true;
                     // Tell NetworkFactories about the new score, so they can stop
                     // trying to connect if they know they cannot match it.
@@ -4089,6 +4086,13 @@
                                 1000);
                     }
                 }
+            }
+
+            // do this after the default net is switched, but
+            // before LegacyTypeTracker sends legacy broadcasts
+            notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE);
+
+            if (isNewDefault) {
                 // Maintain the illusion: since the legacy API only
                 // understands one network at a time, we must pretend
                 // that the current default network disconnected before
@@ -4119,7 +4123,27 @@
             } catch (RemoteException ignored) {
             }
 
-            notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE);
+            // This has to happen after the notifyNetworkCallbacks as that tickles each
+            // ConnectivityManager instance so that legacy requests correctly bind dns
+            // requests to this network.  The legacy users are listening for this bcast
+            // and will generally do a dns request so they can ensureRouteToHost and if
+            // they do that before the callbacks happen they'll use the default network.
+            //
+            // TODO: Is there still a race here? We send the broadcast
+            // after sending the callback, but if the app can receive the
+            // broadcast before the callback, it might still break.
+            //
+            // This *does* introduce a race where if the user uses the new api
+            // (notification callbacks) and then uses the old api (getNetworkInfo(type))
+            // they may get old info.  Reverse this after the old startUsing api is removed.
+            // This is on top of the multiple intent sequencing referenced in the todo above.
+            for (int i = 0; i < newNetwork.networkRequests.size(); i++) {
+                NetworkRequest nr = newNetwork.networkRequests.valueAt(i);
+                if (nr.legacyType != TYPE_NONE && isRequest(nr)) {
+                    // legacy type tracker filters out repeat adds
+                    mLegacyTypeTracker.add(nr.legacyType, newNetwork);
+                }
+            }
 
             // A VPN generally won't get added to the legacy tracker in the "for (nri)" loop above,
             // because usually there are no NetworkRequests it satisfies (e.g., mDefaultRequest
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index e6990c6..f40010d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1248,7 +1248,7 @@
     }
 
     private void invokeDeviceEventListener(HdmiDeviceInfo info, int status) {
-        if (info.isSourceType() && !hideDevicesBehindLegacySwitch(info)) {
+        if (!hideDevicesBehindLegacySwitch(info)) {
             mService.invokeDeviceEventListeners(info, status);
         }
     }
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 430a8ff..7786034 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -1108,6 +1108,7 @@
     private final class HdmiDeviceEventListener extends IHdmiDeviceEventListener.Stub {
         @Override
         public void onStatusChanged(HdmiDeviceInfo deviceInfo, int status) {
+            if (!deviceInfo.isSourceType()) return;
             synchronized (mLock) {
                 int messageType = 0;
                 Object obj = null;