Merge "DO NOT MERGE Change hasVoicemailNumber to getVoicemailNumber" into m-wireless-dev
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 82a5a81..09b8dd7 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -1122,6 +1122,7 @@
         call.setConnectionCapabilities(parcelableConference.getConnectionCapabilities());
         call.setVideoState(parcelableConference.getVideoState());
         call.setVideoProvider(parcelableConference.getVideoProvider());
+        call.setStatusHints(parcelableConference.getStatusHints());
 
         // TODO: Move this to be a part of addCall()
         call.addListener(this);
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index fc5e099..a53bf99 100644
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -443,7 +443,8 @@
             try {
                 synchronized (mLock) {
                     logIncoming("setStatusHints %s %s", callId, statusHints);
-                    if (mCallIdMapper.isValidCallId(callId)) {
+                    if (mCallIdMapper.isValidCallId(callId)
+                            || mCallIdMapper.isValidConferenceId(callId)) {
                         Call call = mCallIdMapper.getCall(callId);
                         if (call != null) {
                             call.setStatusHints(statusHints);
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 4c44bd7..370effe 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -37,6 +37,7 @@
 import android.telecom.InCallService;
 import android.telecom.ParcelableCall;
 import android.telecom.TelecomManager;
+import android.telecom.VideoCallImpl;
 import android.util.ArrayMap;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
@@ -87,7 +88,7 @@
 
         @Override
         public void onVideoCallProviderChanged(Call call) {
-            updateCall(call);
+            updateCall(call, true /* videoProviderChanged */);
         }
 
         @Override
@@ -170,9 +171,8 @@
             for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
                 ComponentName componentName = entry.getKey();
                 IInCallService inCallService = entry.getValue();
-
                 ParcelableCall parcelableCall = toParcelableCall(call,
-                        componentName.equals(mInCallComponentName) /* includeVideoProvider */);
+                        true /* includeVideoProvider */);
                 try {
                     inCallService.addCall(parcelableCall);
                 } catch (RemoteException ignored) {
@@ -382,9 +382,7 @@
                 try {
                     // Track the call if we don't already know about it.
                     addCall(call);
-                    inCallService.addCall(toParcelableCall(
-                            call,
-                            componentName.equals(mInCallComponentName) /* includeVideoProvider */));
+                    inCallService.addCall(toParcelableCall(call, true /* includeVideoProvider */));
                 } catch (RemoteException ignored) {
                 }
             }
@@ -436,18 +434,28 @@
     }
 
     /**
-     * Informs all {@link InCallService} instances of the updated call information.  Changes to the
-     * video provider are only communicated to the default in-call UI.
+     * Informs all {@link InCallService} instances of the updated call information.
      *
      * @param call The {@link Call}.
      */
     private void updateCall(Call call) {
+        updateCall(call, false /* videoProviderChanged */);
+    }
+
+    /**
+     * Informs all {@link InCallService} instances of the updated call information.
+     *
+     * @param call The {@link Call}.
+     * @param videoProviderChanged {@code true} if the video provider changed, {@code false}
+     *      otherwise.
+     */
+    private void updateCall(Call call, boolean videoProviderChanged) {
         if (!mInCallServices.isEmpty()) {
             for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
                 ComponentName componentName = entry.getKey();
                 IInCallService inCallService = entry.getValue();
                 ParcelableCall parcelableCall = toParcelableCall(call,
-                        componentName.equals(mInCallComponentName) /* includeVideoProvider */);
+                        videoProviderChanged /* includeVideoProvider */);
                 Log.v(this, "updateCall %s ==> %s", call, parcelableCall);
                 try {
                     inCallService.updateCall(parcelableCall);
@@ -461,8 +469,10 @@
      * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance.
      *
      * @param call The {@link Call} to parcel.
-     * @param includeVideoProvider When {@code true}, the {@link IVideoProvider} is included in the
-     *      parceled call.  When {@code false}, the {@link IVideoProvider} is not included.
+     * @param includeVideoProvider {@code true} if the video provider should be parcelled with the
+     *      {@link Call}, {@code false} otherwise.  Since the {@link ParcelableCall#getVideoCall()}
+     *      method creates a {@link VideoCallImpl} instance on access it is important for the
+     *      recipient of the {@link ParcelableCall} to know if the video provider changed.
      * @return The {@link ParcelableCall} containing all call information from the {@link Call}.
      */
     private ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider) {
@@ -552,6 +562,7 @@
                 call.getCallerDisplayNamePresentation(),
                 call.getGatewayInfo(),
                 call.getTargetPhoneAccount(),
+                includeVideoProvider,
                 includeVideoProvider ? call.getVideoProvider() : null,
                 parentCallId,
                 childCallIds,
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index 1b296d4..39b1629 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -53,7 +53,8 @@
         </service>
 
         <activity android:name="com.android.server.telecom.testapps.TestCallActivity"
-                  android:label="@string/testCallActivityLabel">
+                  android:label="@string/testCallActivityLabel"
+                  android:process="com.android.server.telecom.testapps.TestInCallService">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -75,6 +76,10 @@
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:scheme="int" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.server.telecom.testapps.ACTION_SEND_UPDATE_REQUEST_FROM_TEST_INCALL_SERVICE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
         </activity>
 
         <receiver android:name="com.android.server.telecom.testapps.CallNotificationReceiver"
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java b/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java
index 4ac151f..8198cd8 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallActivity.java
@@ -51,6 +51,12 @@
     public static final String ACTION_SEND_UPGRADE_REQUEST =
             "android.telecom.testapps.ACTION_SEND_UPGRADE_REQUEST";
 
+    /**
+     * Sends an upgrade to video request for any live calls.
+     */
+    public static final String ACTION_SEND_UPDATE_REQUEST_FROM_TEST_INCALL_SERVICE =
+            "android.server.telecom.testapps.ACTION_SEND_UPDATE_REQUEST_FROM_TEST_INCALL_SERVICE";
+
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -65,6 +71,8 @@
             CallNotificationReceiver.hangupCalls(this);
         } else if (ACTION_SEND_UPGRADE_REQUEST.equals(action)) {
             CallNotificationReceiver.sendUpgradeRequest(this, data);
+        } else if (ACTION_SEND_UPDATE_REQUEST_FROM_TEST_INCALL_SERVICE.equals(action)) {
+            TestCallList.getInstance().sendUpgradeToVideoRequest();
         } else {
             CallServiceNotifier.getInstance().updateNotification(this);
         }
diff --git a/testapps/src/com/android/server/telecom/testapps/TestCallList.java b/testapps/src/com/android/server/telecom/testapps/TestCallList.java
new file mode 100644
index 0000000..fb02bbd
--- /dev/null
+++ b/testapps/src/com/android/server/telecom/testapps/TestCallList.java
@@ -0,0 +1,160 @@
+/*
+ * 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.telecom.testapps;
+
+import android.telecom.Call;
+import android.telecom.CameraCapabilities;
+import android.telecom.InCallService;
+import android.telecom.VideoProfile;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Maintains a list of calls received via the {@link TestInCallServiceImpl}.
+ */
+public class TestCallList extends Call.Listener {
+    private static final TestCallList INSTANCE = new TestCallList();
+    private static final String TAG = "TestCallList";
+
+    private class TestVideoCallListener extends InCallService.VideoCall.Listener {
+        private Call mCall;
+
+        public TestVideoCallListener(Call call) {
+            mCall = call;
+        }
+
+        @Override
+        public void onSessionModifyRequestReceived(VideoProfile videoProfile) {
+            Log.v(TAG,
+                    "onSessionModifyRequestReceived: videoState = " + videoProfile.getVideoState()
+                            + " call = " + mCall);
+        }
+
+        @Override
+        public void onSessionModifyResponseReceived(int status, VideoProfile requestedProfile,
+                VideoProfile responseProfile) {
+            Log.v(TAG,
+                    "onSessionModifyResponseReceived: status = " + status + " videoState = "
+                            + responseProfile.getVideoState()
+                            + " call = " + mCall);
+        }
+
+        @Override
+        public void onCallSessionEvent(int event) {
+
+        }
+
+        @Override
+        public void onPeerDimensionsChanged(int width, int height) {
+
+        }
+
+        @Override
+        public void onVideoQualityChanged(int videoQuality) {
+            Log.v(TAG,
+                    "onVideoQualityChanged: videoQuality = " + videoQuality + " call = " + mCall);
+        }
+
+        @Override
+        public void onCallDataUsageChanged(long dataUsage) {
+
+        }
+
+        @Override
+        public void onCameraCapabilitiesChanged(CameraCapabilities cameraCapabilities) {
+
+        }
+    }
+
+    // The calls the call list knows about.
+    private Set<Call> mCalls = new ArraySet<Call>();
+    private Map<Call, TestVideoCallListener> mVideoCallListeners =
+            new ArrayMap<Call, TestVideoCallListener>();
+
+    /**
+     * Singleton accessor.
+     */
+    public static TestCallList getInstance() {
+        return INSTANCE;
+    }
+
+    public void addCall(Call call) {
+        if (mCalls.contains(call)) {
+            Log.e(TAG, "addCall: Call already added.");
+            return;
+        }
+        Log.v(TAG, "addCall: " + call + " " + System.identityHashCode(this));
+        mCalls.add(call);
+        call.addListener(this);
+    }
+
+    public void removeCall(Call call) {
+        if (!mCalls.contains(call)) {
+            Log.e(TAG, "removeCall: Call cannot be removed -- doesn't exist.");
+            return;
+        }
+        Log.v(TAG, "removeCall: " + call);
+        mCalls.remove(call);
+        call.removeListener(this);
+    }
+
+    public void clearCalls() {
+        mCalls.clear();
+        for (Call call : mVideoCallListeners.keySet()) {
+            if (call.getVideoCall() != null) {
+                call.getVideoCall().setVideoCallListener(null);
+            }
+        }
+        mVideoCallListeners.clear();
+    }
+
+    /**
+     * For any video calls tracked, sends an upgrade to video request.
+     */
+    public void sendUpgradeToVideoRequest() {
+        Log.v(TAG, "sendUpgradeToVideoRequest "+mCalls.size()+ " " + System.identityHashCode(this));
+
+        for (Call call : mCalls) {
+            InCallService.VideoCall videoCall = call.getVideoCall();
+            Log.v(TAG, "sendUpgradeToVideoRequest: checkCall "+call);
+            if (videoCall == null) {
+                continue;
+            }
+
+            Log.v(TAG, "send upgrade to video request for call: " + call);
+            videoCall.sendSessionModifyRequest(new VideoProfile(
+                    VideoProfile.VideoState.BIDIRECTIONAL));
+        }
+    }
+
+    @Override
+    public void onVideoCallChanged(Call call, InCallService.VideoCall videoCall) {
+        Log.v(TAG, "onVideoCallChanged: call = " + call + " " + System.identityHashCode(this));
+        if (videoCall != null) {
+            if (!mVideoCallListeners.containsKey(call)) {
+                TestVideoCallListener listener = new TestVideoCallListener(call);
+                videoCall.setVideoCallListener(listener);
+                mVideoCallListeners.put(call, listener);
+                Log.v(TAG, "onVideoCallChanged: added new listener");
+            }
+        }
+    }
+}
diff --git a/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java b/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java
index 1d7e805..68bbac9 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestInCallServiceImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.telecom.testapps;
 
+import android.telecom.Call;
 import android.telecom.InCallService;
 import android.telecom.Phone;
 import android.util.Log;
@@ -34,12 +35,15 @@
 
     private Phone.Listener mPhoneListener = new Phone.Listener() {
         @Override
-        public void onCallAdded(Phone phone, android.telecom.Call call) {
-            Log.i(TAG, "onCallAdded: "+call.toString());
+        public void onCallAdded(Phone phone, Call call) {
+            Log.i(TAG, "onCallAdded: " + call.toString());
+            TestCallList.getInstance().addCall(call);
         }
+
         @Override
-        public void onCallRemoved(Phone phone, android.telecom.Call call) {
+        public void onCallRemoved(Phone phone, Call call) {
             Log.i(TAG, "onCallRemoved: "+call.toString());
+            TestCallList.getInstance().removeCall(call);
         }
     };
 
@@ -48,7 +52,7 @@
         Log.i(TAG, "onPhoneCreated");
         mPhone = phone;
         mPhone.addListener(mPhoneListener);
-
+        TestCallList.getInstance().clearCalls();
     }
 
     @Override
@@ -56,5 +60,6 @@
         Log.i(TAG, "onPhoneDestroyed");
         mPhone.removeListener(mPhoneListener);
         mPhone = null;
+        TestCallList.getInstance().clearCalls();
     }
 }