Merge "Restrict access to the resolution PendingIntent created by EuiccController to EuiccResolutionUiDispatcherActivity" into rvc-dev
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 5e3c224..8f987b7 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -265,16 +265,18 @@
                     // Right now, this is only used for the PUK-unlocking
                     // process.
                     EventSimStateChangedBag bag = (EventSimStateChangedBag)msg.obj;
-                    if (bag.mIccStatus == IccCardConstants.INTENT_VALUE_ICC_READY
-                            || bag.mIccStatus == IccCardConstants.INTENT_VALUE_ICC_LOADED) {
+                    if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(bag.mIccStatus)
+                            || IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(bag.mIccStatus)) {
                         // when the right event is triggered and there
                         // are UI objects in the foreground, we close
                         // them to display the lock panel.
                         if (mPUKEntryActivity != null) {
+                            Log.i(LOG_TAG, "Dismiss puk entry activity");
                             mPUKEntryActivity.finish();
                             mPUKEntryActivity = null;
                         }
                         if (mPUKEntryProgressDialog != null) {
+                            Log.i(LOG_TAG, "Dismiss puk progress dialog");
                             mPUKEntryProgressDialog.dismiss();
                             mPUKEntryProgressDialog = null;
                         }
@@ -528,6 +530,7 @@
      * or SIM READYing process is over.
      */
     void setPukEntryActivity(Activity activity) {
+        Log.i(LOG_TAG, "setPukEntryActivity - set to " + (activity == null ? "null" : "activity"));
         mPUKEntryActivity = activity;
     }
 
@@ -545,6 +548,8 @@
      * READYing process
      */
     void setPukEntryProgressDialog(ProgressDialog dialog) {
+        Log.i(LOG_TAG, "setPukEntryProgressDialog - set to "
+                + (dialog == null ? "null" : "activity"));
         mPUKEntryProgressDialog = dialog;
     }
 
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index 8eaa336..c520063 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -363,7 +363,7 @@
         // Check to see if a UI exists for the PUK activation.  If it does
         // exist, then it indicates that we're trying to unblock the PUK.
         if ((app.getPUKEntryActivity() != null) && (state == MmiCode.State.COMPLETE)) {
-            if (DBG) log("displaying PUK unblocking progress dialog.");
+            log("displaying PUK unblocking progress dialog.");
 
             // create the progress dialog, make sure the flags and type are
             // set correctly.
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 73d6023..22fa4a0 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -256,8 +256,7 @@
                 public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {
                     Log.d(this, "onConnectionPropertiesChanged: Connection: %s,"
                             + " connectionProperties: %s", c, connectionProperties);
-                    int properties = ImsConference.this.getConnectionProperties();
-                    setConnectionProperties(applyHostProperties(properties, connectionProperties));
+                    updateConnectionProperties(connectionProperties);
                 }
 
                 @Override
@@ -269,7 +268,7 @@
                 @Override
                 public void onExtrasChanged(Connection c, Bundle extras) {
                     Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + extras);
-                    putExtras(extras);
+                    updateExtras(extras);
                 }
 
                 @Override
@@ -449,7 +448,6 @@
                 mConferenceHost.getConnectionCapabilities(),
                 mConferenceHost.isCarrierVideoConferencingSupported());
         setConnectionCapabilities(capabilities);
-
     }
 
     /**
@@ -1200,6 +1198,12 @@
         // data from the time of merge.
         connection.setCallDirection(participant.getCallDirection());
 
+        // Ensure important attributes of the parent get copied to child.
+        connection.setConnectionProperties(applyHostPropertiesToChild(
+                connection.getConnectionProperties(), parent.getConnectionProperties()));
+        connection.setStatusHints(parent.getStatusHints());
+        connection.setExtras(getChildExtrasFromHostBundle(parent.getExtras()));
+
         Log.i(this, "createConferenceParticipantConnection: participant=%s, connection=%s",
                 participant, connection);
 
@@ -1441,11 +1445,17 @@
             Phone phone = mConferenceHost.getPhone();
             if (phone != null) {
                 Context context = phone.getContext();
-                setStatusHints(new StatusHints(
+                StatusHints hints = new StatusHints(
                         context.getString(R.string.status_hint_label_wifi_call),
                         Icon.createWithResource(
                                 context, R.drawable.ic_signal_wifi_4_bar_24dp),
-                        null /* extras */));
+                        null /* extras */);
+                setStatusHints(hints);
+
+                // Ensure the children know they're a WIFI call as well.
+                for (Connection c : getConnections()) {
+                    c.setStatusHints(hints);
+                }
             }
         } else {
             setStatusHints(null);
@@ -1453,6 +1463,69 @@
     }
 
     /**
+     * Updates the conference's properties based on changes to the host.
+     * Also ensures pertinent properties from the host such as the WIFI property are copied to the
+     * children as well.
+     * @param connectionProperties The new host properties.
+     */
+    private void updateConnectionProperties(int connectionProperties) {
+        int properties = ImsConference.this.getConnectionProperties();
+        setConnectionProperties(applyHostProperties(properties, connectionProperties));
+
+        for (Connection c : getConnections()) {
+            c.setConnectionProperties(applyHostPropertiesToChild(c.getConnectionProperties(),
+                    connectionProperties));
+        }
+    }
+
+    /**
+     * Updates extras in the conference based on changes made in the parent.
+     * Also copies select extras (e.g. EXTRA_CALL_NETWORK_TYPE) to the children as well.
+     * @param extras The extras to copy.
+     */
+    private void updateExtras(Bundle extras) {
+        putExtras(extras);
+
+        if (extras == null) {
+            return;
+        }
+
+        Bundle childBundle = getChildExtrasFromHostBundle(extras);
+        for (Connection c : getConnections()) {
+            c.putExtras(childBundle);
+        }
+    }
+
+    /**
+     * Given an extras bundle from the host, returns a new bundle containing those extras which are
+     * releveant to the children.
+     * @param extras The host extras.
+     * @return The extras pertinent to the children.
+     */
+    private Bundle getChildExtrasFromHostBundle(Bundle extras) {
+        Bundle extrasToCopy = new Bundle();
+        if (extras != null && extras.containsKey(TelecomManager.EXTRA_CALL_NETWORK_TYPE)) {
+            int networkType = extras.getInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE);
+            extrasToCopy.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, networkType);
+        }
+        return extrasToCopy;
+    }
+
+    /**
+     * Given the properties from a conference host applies and changes to the host's properties to
+     * the child as well.
+     * @param childProperties The existing child properties.
+     * @param hostProperties The properties from the host.
+     * @return The child properties with the applicable host bits set/unset.
+     */
+    private int applyHostPropertiesToChild(int childProperties, int hostProperties) {
+        childProperties = changeBitmask(childProperties,
+                Connection.PROPERTY_WIFI,
+                (hostProperties & Connection.PROPERTY_WIFI) != 0);
+        return childProperties;
+    }
+
+    /**
      * Builds a string representation of the {@link ImsConference}.
      *
      * @return String representing the conference.
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index f172d67..f13d709 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.never;
@@ -27,17 +28,22 @@
 import static org.mockito.Mockito.when;
 
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Looper;
 import android.telecom.Call;
 import android.telecom.Conference;
 import android.telecom.Connection;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.StatusHints;
+import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.ims.internal.ConferenceParticipant;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -65,6 +71,53 @@
         when(mMockTelecomAccountRegistry.getAddress(any(PhoneAccountHandle.class)))
                 .thenReturn(null);
     }
+    @Test
+    @SmallTest
+    public void testPropertyPropagation() {
+        when(mMockTelecomAccountRegistry.isUsingSimCallManager(any(PhoneAccountHandle.class)))
+                .thenReturn(false);
+        mConferenceHost.setConnectionProperties(Connection.PROPERTY_ASSISTED_DIALING
+                | Connection.PROPERTY_WIFI);
+        Bundle extras = new Bundle();
+        extras.putInt(TelecomManager.EXTRA_CALL_NETWORK_TYPE, TelephonyManager.NETWORK_TYPE_IWLAN);
+        mConferenceHost.putTelephonyExtras(extras);
+        mConferenceHost.setStatusHints(new StatusHints("WIFIs", null, null));
+
+        ImsConference imsConference = new ImsConference(mMockTelecomAccountRegistry,
+                mMockTelephonyConnectionServiceProxy, mConferenceHost,
+                null /* phoneAccountHandle */, () -> true /* featureFlagProxy */,
+                new ImsConference.CarrierConfiguration.Builder().build());
+
+        ConferenceParticipant participant1 = new ConferenceParticipant(
+                Uri.parse("tel:6505551212"),
+                "A",
+                Uri.parse("sip:6505551212@testims.com"),
+                Connection.STATE_ACTIVE,
+                Call.Details.DIRECTION_OUTGOING);
+        ConferenceParticipant participant2 = new ConferenceParticipant(
+                Uri.parse("tel:6505551213"),
+                "A",
+                Uri.parse("sip:6505551213@testims.com"),
+                Connection.STATE_ACTIVE,
+                Call.Details.DIRECTION_INCOMING);
+        imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+                Arrays.asList(participant1, participant2));
+        assertEquals(2, imsConference.getNumberOfParticipants());
+        ArgumentCaptor<Connection> captor = ArgumentCaptor.forClass(Connection.class);
+        verify(mMockTelephonyConnectionServiceProxy, times(2)).addExistingConnection(
+                any(PhoneAccountHandle.class), captor.capture(),
+                eq(imsConference));
+
+        // Make sure they're set on the initially created participants.
+        for (Connection c : captor.getAllValues()) {
+            assertEquals(0, c.getConnectionProperties() & Connection.PROPERTY_ASSISTED_DIALING);
+            assertEquals(Connection.PROPERTY_WIFI,
+                    c.getConnectionProperties() & Connection.PROPERTY_WIFI);
+            assertNotNull(c.getStatusHints());
+            assertEquals(TelephonyManager.NETWORK_TYPE_IWLAN, c.getExtras().getInt(
+                    TelecomManager.EXTRA_CALL_NETWORK_TYPE));
+        }
+    }
 
     @Test
     @SmallTest