Self-Managed Incoming Call Disambiguation UX.

- Handle auto-disconnect of foreground call when answering a self-managed
call.
- Enforce restriction that the PhoneAccount associated with a self-managed
CS must have a label which is the app's name.
- Ensure self-managed phone accounts can't be registered with
call provider, connection manager, or sim sub capabilities.
- Add "incoming call" UX which is shown when a new incoming call from a
self-managed CS comes in and there is an existing call for another CS.

Test: Unit, manual
Bug: 34159263
Change-Id: I371be9baa6f56c77aa83349977c0131f0e319047
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index cc6470e..ec49696 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -169,7 +169,8 @@
 
         <activity android:name="com.android.server.telecom.testapps.SelfManagedCallingActivity"
                   android:label="@string/selfManagedCallingActivityLabel"
-                  android:process="com.android.server.telecom.testapps.SelfMangingCallingApp">
+                  android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
+                  android:theme="@android:style/Theme.Material.Light">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />
               <category android:name="android.intent.category.DEFAULT" />
diff --git a/testapps/res/layout/self_managed_sample_main.xml b/testapps/res/layout/self_managed_sample_main.xml
index 144d6ec..e30ef42 100644
--- a/testapps/res/layout/self_managed_sample_main.xml
+++ b/testapps/res/layout/self_managed_sample_main.xml
@@ -24,63 +24,80 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/checkIfPermittedBeforeCallingButton" />
-    <TableLayout
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="This app provides two sample implementations of the self-managed ConnectionService API.  Use this UI to add simulated self-managed calls:" />
+
+    <RadioGroup
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <RadioButton
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Sample Source 1"
+            android:id="@+id/useAcct1Button"
+            android:background="@color/test_call_a_color"/>
+        <RadioButton
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Sample Source 2"
+            android:id="@+id/useAcct2Button"
+            android:background="@color/test_call_b_color"/>
+    </RadioGroup>
+
+    <RadioGroup
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <RadioButton
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Video Call"
+            android:id="@+id/videoCallButton"/>
+        <RadioButton
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Audio Call"
+            android:id="@+id/audioCallButton"/>
+    </RadioGroup>
+
+    <LinearLayout android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content">
-        <TableRow android:layout_span="2">
-            <RadioGroup>
-                <RadioButton
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="Acct 1"
-                    android:id="@+id/useAcct1Button"/>
-                <RadioButton
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:text="Acct 2"
-                    android:id="@+id/useAcct2Button"/>
-            </RadioGroup>
-        </TableRow>
-        <TableRow android:layout_span="2">
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Place call:" />
-        </TableRow>
-        <TableRow>
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Number:" />
-            <EditText
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:id="@+id/phoneNumber" />
-        </TableRow>
-        <TableRow>
-            <Button
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Outgoing Call"
-                android:id="@+id/placeOutgoingCallButton" />
-            <Button
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Incoming Call"
-                android:id="@+id/placeIncomingCallButton" />
-            <Button
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="Incoming Call (Delay)"
-                android:id="@+id/placeIncomingCallDelayButton" />
-        </TableRow>
-        <TableRow android:layout_span="2">
-            <ListView
-                android:id="@+id/callList"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:listSelector="@null"
-                android:divider="@null" />
-        </TableRow>
-    </TableLayout>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Number:" />
+        <EditText
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/phoneNumber"
+            android:text="tel:555-1212"/>
+    </LinearLayout>
+
+    <LinearLayout android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content">
+
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Outgoing Call"
+            android:id="@+id/placeOutgoingCallButton" />
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Incoming Call"
+            android:id="@+id/placeIncomingCallButton" />
+    </LinearLayout>
+
+    <ListView
+        android:id="@+id/callList"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:listSelector="@null"
+        android:divider="@null" />
 </LinearLayout>
\ No newline at end of file
diff --git a/testapps/res/values/colors.xml b/testapps/res/values/colors.xml
new file mode 100644
index 0000000..3939e78
--- /dev/null
+++ b/testapps/res/values/colors.xml
@@ -0,0 +1,20 @@
+<!--
+  ~ Copyright (C) 2017 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
+  -->
+
+<resources>
+    <color name="test_call_a_color">#f2eebf</color>
+    <color name="test_call_b_color">#afc5e6</color>
+</resources>
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java
index 1d6367e..4275079 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallList.java
@@ -43,6 +43,8 @@
 
     public static String SELF_MANAGED_ACCOUNT_1 = "1";
     public static String SELF_MANAGED_ACCOUNT_2 = "2";
+    public static String SELF_MANAGED_NAME_1 = "SuperCall";
+    public static String SELF_MANAGED_NAME_2 = "Mega Call";
 
     private static SelfManagedCallList sInstance;
     private static ComponentName COMPONENT_NAME = new ComponentName(
@@ -89,20 +91,23 @@
     }
 
     public void registerPhoneAccounts(Context context) {
-        registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_1, SELF_MANAGED_ADDRESS_1);
-        registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_2, SELF_MANAGED_ADDRESS_2);
+        registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_1, SELF_MANAGED_ADDRESS_1,
+                SELF_MANAGED_NAME_1);
+        registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_2, SELF_MANAGED_ADDRESS_2,
+                SELF_MANAGED_NAME_2);
     }
 
-    public void registerPhoneAccount(Context context, String id, Uri address) {
+    public void registerPhoneAccount(Context context, String id, Uri address, String name) {
         PhoneAccountHandle handle = new PhoneAccountHandle(COMPONENT_NAME, id);
         mPhoneAccounts.put(id, handle);
-        PhoneAccount.Builder builder = PhoneAccount.builder(handle, id)
+        PhoneAccount.Builder builder = PhoneAccount.builder(handle, name)
                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
                 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
                 .setAddress(address)
                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
                         PhoneAccount.CAPABILITY_VIDEO_CALLING |
-                        PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING);
+                        PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING)
+                .setShortDescription(name);
 
         TelecomManager.from(context).registerPhoneAccount(builder.build());
     }
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java
index 29d3c5f..b46d5e1 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallListAdapter.java
@@ -26,6 +26,8 @@
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 
+import com.android.server.telecom.testapps.R;
+
 import java.util.List;
 
 public class SelfManagedCallListAdapter extends BaseAdapter {
@@ -124,6 +126,12 @@
         SelfManagedConnection connection = mConnections.get(position);
         PhoneAccountHandle phoneAccountHandle = connection.getExtras().getParcelable(
                 SelfManagedConnection.EXTRA_PHONE_ACCOUNT_HANDLE);
+        if (phoneAccountHandle.getId().equals(SelfManagedCallList.SELF_MANAGED_ACCOUNT_1)) {
+            result.setBackgroundColor(result.getContext().getColor(R.color.test_call_a_color));
+        } else {
+            result.setBackgroundColor(result.getContext().getColor(R.color.test_call_b_color));
+        }
+
         CallAudioState audioState = connection.getCallAudioState();
         String audioRoute = "?";
         if (audioState != null) {
@@ -148,9 +156,9 @@
         String callType;
         if (connection.isIncomingCall()) {
             if (connection.isIncomingCallUiShowing()) {
-                callType = "Incoming - Show Incoming UX";
+                callType = "Incoming(our ux) ";
             } else {
-                callType = "Incoming - DO NOT SHOW Incoming UX";
+                callType = "Incoming(sys ux) ";
             }
         } else {
             callType = "Outgoing";
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java
index c8f6157..4dfa012 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedCallingActivity.java
@@ -22,6 +22,7 @@
 import android.telecom.ConnectionRequest;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
@@ -46,9 +47,10 @@
     private CheckBox mCheckIfPermittedBeforeCalling;
     private Button mPlaceOutgoingCallButton;
     private Button mPlaceIncomingCallButton;
-    private Button mPlaceIncomingCallDelayButton;
     private RadioButton mUseAcct1Button;
     private RadioButton mUseAcct2Button;
+    private RadioButton mVideoCallButton;
+    private RadioButton mAudioCallButton;
     private EditText mNumber;
     private ListView mListView;
     private SelfManagedCallListAdapter mListAdapter;
@@ -102,21 +104,10 @@
             }
         });
 
-        mPlaceIncomingCallDelayButton = (Button) findViewById(R.id.placeIncomingCallDelayButton);
-        mPlaceIncomingCallDelayButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                // Delay the incoming call so that we can turn off the screen and
-                try {
-                    Thread.sleep(5000);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-                placeIncomingCall();
-            }
-        });
         mUseAcct1Button = (RadioButton) findViewById(R.id.useAcct1Button);
         mUseAcct2Button = (RadioButton) findViewById(R.id.useAcct2Button);
+        mVideoCallButton = (RadioButton) findViewById(R.id.videoCallButton);
+        mAudioCallButton = (RadioButton) findViewById(R.id.audioCallButton);
         mNumber = (EditText) findViewById(R.id.phoneNumber);
         mListView = (ListView) findViewById(R.id.callList);
         mCallList.setListener(mCallListListener);
@@ -150,6 +141,10 @@
         Bundle extras = new Bundle();
         extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                 getSelectedPhoneAccountHandle());
+        if (mVideoCallButton.isChecked()) {
+            extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
+                    VideoProfile.STATE_BIDIRECTIONAL);
+        }
         tm.placeCall(Uri.parse(mNumber.getText().toString()), extras);
     }
 
@@ -167,6 +162,10 @@
         Bundle extras = new Bundle();
         extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
                 Uri.parse(mNumber.getText().toString()));
+        if (mVideoCallButton.isChecked()) {
+            extras.putInt(TelecomManager.EXTRA_INCOMING_VIDEO_STATE,
+                    VideoProfile.STATE_BIDIRECTIONAL);
+        }
         tm.addNewIncomingCall(getSelectedPhoneAccountHandle(), extras);
     }
 }
\ No newline at end of file
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java
index 051948b..766efa5 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnection.java
@@ -27,6 +27,7 @@
 import android.telecom.Connection;
 import android.telecom.ConnectionService;
 import android.telecom.DisconnectCause;
+import android.telecom.VideoProfile;
 
 import com.android.server.telecom.testapps.R;
 
@@ -129,6 +130,36 @@
         notificationManager.notify(CALL_NOTIFICATION, mCallId, builder.build());
     }
 
+    @Override
+    public void onHold() {
+        setOnHold();
+    }
+
+    @Override
+    public void onUnhold() {
+        setActive();
+    }
+
+    @Override
+    public void onAnswer(int videoState) {
+        setConnectionActive();
+    }
+
+    @Override
+    public void onAnswer() {
+        onAnswer(VideoProfile.STATE_AUDIO_ONLY);
+    }
+
+    @Override
+    public void onReject() {
+        setConnectionDisconnected(DisconnectCause.REJECTED);
+    }
+
+    @Override
+    public void onDisconnect() {
+        setConnectionDisconnected(DisconnectCause.LOCAL);
+    }
+
     public void setConnectionActive() {
         mMediaPlayer.start();
         setActive();
diff --git a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java
index e1a01ba..1d52a3b 100644
--- a/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/SelfManagedConnectionService.java
@@ -23,8 +23,10 @@
 import android.telecom.Log;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
 
 import java.util.Objects;
+import java.util.Random;
 
 /**
  * Sample implementation of the self-managed {@link ConnectionService} API.
@@ -32,6 +34,8 @@
  * See {@link android.telecom} for more information on self-managed {@link ConnectionService}s.
  */
 public class SelfManagedConnectionService extends ConnectionService {
+    private static final String[] TEST_NAMES = {"Tom Smith", "Jane Appleseed", "Joseph Engleton",
+            "Claudia McPherson", "Chris P. Bacon", "Seymour Butz", "Hugh Mungus", "Anita Bath"};
     private final SelfManagedCallList mCallList = SelfManagedCallList.getInstance();
 
     @Override
@@ -60,13 +64,17 @@
         mCallList.notifyCreateOutgoingConnectionFailed(request);
     }
 
-
     private Connection createSelfManagedConnection(ConnectionRequest request, boolean isIncoming) {
         SelfManagedConnection connection = new SelfManagedConnection(mCallList,
                 getApplicationContext(), isIncoming);
         connection.setListener(mCallList.getConnectionListener());
         connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
         connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+        connection.setAudioModeIsVoip(true);
+        connection.setVideoState(request.getVideoState());
+        Random random = new Random();
+        connection.setCallerDisplayName(TEST_NAMES[random.nextInt(TEST_NAMES.length)],
+                TelecomManager.PRESENTATION_ALLOWED);
         connection.setExtras(request.getExtras());
         if (isIncoming) {
             connection.setIsIncomingCallUiShowing(request.shouldShowIncomingCallUi());