Blanket copy of PhoneApp to services/Telephony.

First phase of splitting out InCallUI from PhoneApp.

Change-Id: I237341c4ff00e96c677caa4580b251ef3432931b
diff --git a/tests/Android.mk b/tests/Android.mk
new file mode 100644
index 0000000..7356cb8
--- /dev/null
+++ b/tests/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_PACKAGE_NAME := TeleServiceTests
+LOCAL_CERTIFICATE := platform
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_INSTRUMENTATION_FOR := Phone
+
+include $(BUILD_PACKAGE)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
new file mode 100644
index 0000000..af3f7e4
--- /dev/null
+++ b/tests/AndroidManifest.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.phone.tests">
+
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.PERFORM_CDMA_PROVISIONING" />
+
+    <application android:label="@string/app_name">
+        <uses-library android:name="android.test.runner" />
+
+        <!-- Miscellaneous phone app-related test activities -->
+
+        <!-- Test activity that mimics the behavior of 3rd party apps
+             firing off CALL and DIAL intents. -->
+        <!-- To run:
+                adb shell am start -n com.android.phone.tests/.CallDialTest
+        -->
+        <activity android:name="CallDialTest"
+                  android:label="@string/callDialTestLabel">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <!-- Test activity mimicking the PERFORM_CDMA_PROVISIONING behavior of
+             SetupWizard, useful for testing "non-interactive" OTASP. -->
+        <activity android:name="OtaspTestActivity"
+                  android:label="OtaspTest">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <service android:name="SendInstantTextTestService"
+                 android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE" >
+            <intent-filter>
+                <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
+                <data android:scheme="sms" />
+                <data android:scheme="smsto" />
+            </intent-filter>
+        </service>
+    </application>
+
+    <!--
+        The prefered way is to use 'runtest':
+           runtest phone-unit
+
+         runtest is a wrapper around 'adb shell'. The low level shell command is:
+           adb shell am instrument -w com.android.phone.tests/android.test.InstrumentationTestRunner
+
+         To run a single test case:
+           adb shell am instrument -w com.android.phone.tests/android.test.InstrumentationTestRunner
+                                   -e com.android.phone.unit.FooUnitTest
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.phone"
+        android:label="Phone application tests." />
+</manifest>
diff --git a/tests/res/layout/call_dial_test.xml b/tests/res/layout/call_dial_test.xml
new file mode 100644
index 0000000..dd9af39
--- /dev/null
+++ b/tests/res/layout/call_dial_test.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<!-- Ultra-simple test activity for testing CALL and DIAL intents. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:gravity="center_vertical|center_horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="64dip"
+    >
+
+    <TextView android:id="@+id/label1"
+              android:text="@string/callDialTestLabel"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:layout_marginTop="30dip"
+              android:textAppearance="?android:attr/textAppearanceLarge"
+              />
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="1" />
+
+    <!-- Phone number (or potentially a SIP address) to be used -->
+    <EditText android:id="@+id/number"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:paddingLeft="32dip"
+              android:paddingRight="32dip"
+              android:paddingTop="32dip"
+              android:paddingBottom="32dip"
+              android:textAppearance="?android:attr/textAppearanceLarge" />
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="2" />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        >
+        <Button android:id="@+id/callButton"
+            android:text="@string/callCommand"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:paddingLeft="32dip"
+            android:paddingRight="32dip"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            />
+        <Button android:id="@+id/dialButton"
+            android:text="@string/dialCommand"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:paddingLeft="32dip"
+            android:paddingRight="32dip"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            />
+    </LinearLayout>
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="2" />
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        >
+        <Button android:id="@+id/itelephonyCallButton"
+            android:text="@string/itelephonyCallCommand"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:paddingLeft="32dip"
+            android:paddingRight="32dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            />
+        <Button android:id="@+id/itelephonyDialButton"
+            android:text="@string/itelephonyDialCommand"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dip"
+            android:layout_marginRight="20dip"
+            android:paddingLeft="32dip"
+            android:paddingRight="32dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            />
+    </LinearLayout>
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="4" />
+
+</LinearLayout>
diff --git a/tests/res/layout/otasp_test_activity.xml b/tests/res/layout/otasp_test_activity.xml
new file mode 100644
index 0000000..371a6d4
--- /dev/null
+++ b/tests/res/layout/otasp_test_activity.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<!-- Ultra-simple test activity for triggering an OTASP call. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:gravity="center_vertical|center_horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="64dip"
+    >
+
+    <TextView android:id="@+id/label1"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:layout_marginTop="30dip"
+              android:textAppearance="?android:attr/textAppearanceLarge"
+              />
+
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="1" />
+
+    <ProgressBar android:id="@+id/progress_bar"
+              style="?android:attr/progressBarStyleHorizontal"
+              android:layout_width="240dip"
+              android:layout_height="wrap_content"
+              android:indeterminate="true"
+              android:visibility="invisible" />
+
+    <TextView android:id="@+id/result1"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:textAppearance="?android:attr/textAppearanceLarge"
+              android:visibility="invisible" />
+
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="1" />
+
+    <Button android:id="@+id/button1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="10dip"
+            android:layout_marginBottom="10dip"
+            android:paddingLeft="32dip"
+            android:paddingRight="32dip"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            />
+
+    <View android:layout_width="1dip"
+          android:layout_height="1dip"
+          android:layout_weight="1" />
+
+</LinearLayout>
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
new file mode 100644
index 0000000..d883518
--- /dev/null
+++ b/tests/res/values/donottranslate_strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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>
+    <!-- Application label -->
+    <string name="app_name">PhoneAppTests</string>
+
+    <!-- Strings for the CallDialTest activity -->
+    <string name="callDialTestLabel">CALL/DIAL test</string>
+    <string name="callCommand">CALL</string>
+    <string name="dialCommand">DIAL</string>
+    <string name="itelephonyCallCommand">ITelephony.call()</string>
+    <string name="itelephonyDialCommand">ITelephony.dial()</string>
+
+    <string name="instant_text_back_content">message: %s, Uri: %s, </string>
+</resources>
diff --git a/tests/src/com/android/phone/tests/CallDialTest.java b/tests/src/com/android/phone/tests/CallDialTest.java
new file mode 100644
index 0000000..5ea80d1
--- /dev/null
+++ b/tests/src/com/android/phone/tests/CallDialTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2010 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.phone.tests;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.phone.Constants;
+
+/**
+ * Test activity that mimics the behavior of 3rd party apps firing off
+ * CALL and DIAL intents.
+ */
+public class CallDialTest extends Activity implements View.OnClickListener {
+    private static final String LOG_TAG = "CallDialTest";
+
+    // UI elements
+    private TextView mLabel;
+    private EditText mNumber;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Intent intent = getIntent();
+        log("onCreate: intent = " + intent);
+
+        // Construct our basic UI:
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.call_dial_test);
+
+        mLabel = (TextView) findViewById(R.id.label1);
+
+        mNumber = (EditText) findViewById(R.id.number);
+        mNumber.setText("6505551234");  // Preload it with something useful
+
+        ((Button) findViewById(R.id.callButton)).setOnClickListener(this);
+        ((Button) findViewById(R.id.dialButton)).setOnClickListener(this);
+        ((Button) findViewById(R.id.itelephonyCallButton)).setOnClickListener(this);
+        ((Button) findViewById(R.id.itelephonyDialButton)).setOnClickListener(this);
+    }
+
+    @Override
+    protected void onResume() {
+        log("onResume()...");
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        log("onPause()...");
+        super.onPause();
+    }
+
+    // View.OnClickListener implementation
+    @Override
+    public void onClick(View view) {
+        int id = view.getId();
+        log("onClick(View " + view + ", id " + id + ")...");
+
+        switch (id) {
+            case R.id.callButton:
+                log("onClick: CALL...");
+                fireIntent(Intent.ACTION_CALL);
+                break;
+            case R.id.dialButton:
+                log("onClick: DIAL...");
+                fireIntent(Intent.ACTION_DIAL);
+                break;
+            case R.id.itelephonyCallButton:
+                log("onClick: ITelephony.call()...");
+                doITelephonyCall();
+                break;
+            case R.id.itelephonyDialButton:
+                log("onClick: ITelephony.dial()...");
+                doITelephonyDial();
+                break;
+            default:
+                Log.wtf(LOG_TAG, "onClick: unexpected View: " + view);
+                break;
+        }
+    }
+
+    private void fireIntent(String action) {
+        log("fireIntent(action = '" + action + "')...");
+
+        // Get a phone number or SIP address from the EditText widget
+        String number = mNumber.getText().toString();
+        log("==> number: '" + number + "'");
+
+        // Based on the number, fire off a CALL or DIAL intent:
+        // - if it's a fully qualified URI (with scheme), use it directly
+        // - if it looks like a SIP address, prepend sip:
+        // - if it's just a number, prepend tel: automatically
+        // - if it's blank, fire off a blank CALL or DIAL intent
+
+        Uri uri = null;
+        if (!TextUtils.isEmpty(number)) {
+            if (number.contains(":")) {
+                uri = Uri.parse(number);
+            } else if (PhoneNumberUtils.isUriNumber(number)) {
+                uri = Uri.fromParts(Constants.SCHEME_SIP, number, null);
+            } else {
+                uri = Uri.fromParts(Constants.SCHEME_TEL, number, null);
+            }
+        }
+        log("==> uri: " + uri);
+
+        Intent intent = new Intent(action, uri);
+        log("==> intent: " + intent);
+
+        try {
+            startActivity(intent);
+            Toast.makeText(this, "Starting activity...", Toast.LENGTH_SHORT).show();
+        } catch (ActivityNotFoundException e) {
+            Log.w(LOG_TAG, "testCall: ActivityNotFoundException for intent: " + intent);
+            Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
+        } catch (Exception e) {
+            Log.w(LOG_TAG, "testCall: Unexpected exception from startActivity(): " + e);
+            Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
+        }
+    }
+
+    private void doITelephonyCall() {
+        log("doITelephonyCall()...");
+
+        // Get a phone number from the EditText widget
+        String number = mNumber.getText().toString();
+        log("==> number: '" + number + "'");
+
+        try {
+            ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+            log("- phone: " + phone);
+            log("- calling call()...");
+            phone.call(getPackageName(), number);
+            log("  Done.");
+        } catch (RemoteException ex) {
+            Log.w(LOG_TAG, "RemoteException!", ex);
+        }
+    }
+
+    private void doITelephonyDial() {
+        log("doITelephonyDial()...");
+
+        // Get a phone number from the EditText widget
+        String number = mNumber.getText().toString();
+        log("==> number: '" + number + "'");
+
+        try {
+            ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+            log("- phone: " + phone);
+            log("- calling dial()...");
+            phone.dial(number);
+            log("  Done.");
+        } catch (RemoteException ex) {
+            Log.w(LOG_TAG, "RemoteException!", ex);
+        }
+    }
+
+    private void log(String msg) {
+        Log.i(LOG_TAG, msg);
+    }
+}
diff --git a/tests/src/com/android/phone/tests/OtaspTestActivity.java b/tests/src/com/android/phone/tests/OtaspTestActivity.java
new file mode 100644
index 0000000..ead86c3
--- /dev/null
+++ b/tests/src/com/android/phone/tests/OtaspTestActivity.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2010 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.phone.tests;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.phone.OtaUtils;
+
+/**
+ * Test activity that mimics the PERFORM_CDMA_PROVISIONING behavior of
+ * SetupWizard, useful for testing "non-interactive" OTASP.
+ * @see OtaUtils.startNonInteractiveOtasp
+ *
+ */
+public class OtaspTestActivity extends Activity implements View.OnClickListener {
+    private static final String LOG_TAG = "OtaspTestActivity";
+
+    // Request code used with startActivityForResult()
+    private static final int PERFORM_CDMA_PROVISIONING_REQUEST_CODE = 1;
+
+    // UI elements
+    private TextView mLabel;
+    private ProgressBar mProgressBar;
+    private TextView mResult;
+    private Button mButton;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Intent intent = getIntent();
+        Log.i(LOG_TAG, "##### onCreate: intent = " + intent);
+        Bundle extras = intent.getExtras();
+        if (extras != null) {
+            Log.i(LOG_TAG, "      - has extras: size = " + extras.size()); // forces an unparcel()
+            Log.i(LOG_TAG, "      - extras = " + extras);
+        }
+
+        // Construct our basic UI:
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.otasp_test_activity);
+
+        mLabel = (TextView) findViewById(R.id.label1);
+        mLabel.setText("OTA Test Activity");
+
+        mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+        mResult = (TextView) findViewById(R.id.result1);
+
+        mButton = (Button) findViewById(R.id.button1);
+        mButton.setText("Make test call");
+        mButton.setOnClickListener(this);
+
+
+        // We can be launched either:
+        //
+        // (1) Directly from the launcher, in which case the current intent
+        //     will simply be an ACTION_MAIN intent
+        //
+        // (2) Via the PendingIntent that we sent along (when we originally
+        //     fired off the ACTION_PERFORM_CDMA_PROVISIONING intent) that
+        //     allows the phone app to send us back a result code.
+        //     We can identify this case by the presence of the
+        //     EXTRA_OTASP_RESULT_CODE extra.
+
+        if (intent.hasExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE)) {
+            // Got a result from the OTASP call!
+            Log.i(LOG_TAG, "==> onCreate: got a result from the OTASP call!");
+
+            int resultCode = intent.getIntExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE,
+                                                OtaUtils.OTASP_UNKNOWN);
+            Log.i(LOG_TAG, "    - resultCode = " + resultCode);
+
+            String resultString;
+            switch (resultCode) {
+                case OtaUtils.OTASP_USER_SKIPPED:
+                    resultString = "User skipped!";
+                    break;
+                case OtaUtils.OTASP_SUCCESS:
+                    resultString = "Success!";
+                    break;
+                case OtaUtils.OTASP_FAILURE:
+                    resultString = "FAILURE";
+                    break;
+                default:
+                    resultString = "Unexpected code: " + resultCode;
+                    break;
+            }
+            Log.i(LOG_TAG, "    - result: " + resultString);
+            mResult.setText(resultString);
+            mResult.setVisibility(View.VISIBLE);
+            mProgressBar.setVisibility(View.INVISIBLE);
+
+        } else {
+            // We must have gotten here directly from the launcher.
+            // Leave the UI in its initial state.
+            Log.i(LOG_TAG, "==> onCreate: entered from the launcher.");
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        Log.i(LOG_TAG, "onNewIntent: intent=" + intent);
+        Bundle extras = intent.getExtras();
+        if (extras != null) Log.i(LOG_TAG, "      - intent extras = " + extras);
+
+        // This method isn't actually used since this test activity is not
+        // launched in "singleTop" mode.
+
+        // Activities that *are* launched in singleTop mode, like the SetupWizard,
+        // would have to handle the various PendingIntents here just like
+        // we do above in onCreate().
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.i(LOG_TAG, "onActivityResult: request " + requestCode
+              + " result " + resultCode + " data " + data);
+
+        // Note we receive this call immediately before onResume(), when
+        // we get re-started after launching the PERFORM_CDMA_PROVISIONING
+        // intent.
+
+        if (requestCode == PERFORM_CDMA_PROVISIONING_REQUEST_CODE) {
+            // The InCallScreenShowActivation activity can set the following
+            // result codes:
+            //
+            //   RESULT_INTERACTIVE_OTASP_STARTED
+            //   RESULT_NONINTERACTIVE_OTASP_STARTED
+            //   RESULT_NONINTERACTIVE_OTASP_FAILED
+            //
+            // but note that in practice we won't ever *get* the
+            // RESULT_INTERACTIVE_OTASP_STARTED result code, since the
+            // "interactive" OTASP sequence never actually finish()es;
+            // it ends by directly launching the Home activity.
+            //
+            // However, in non-interactive OTASP, the
+            // InCallScreenShowActivation activity will set one of the
+            // RESULT_NONINTERACTIVE_* codes and immediately
+            // finish(), so we *will* see that result here.
+            //
+            // Also, resultCode will be RESULT_CANCELED (= 0) if the
+            // InCallScreenShowActivation activity didn't return any
+            // result, or crashed.
+
+            switch (resultCode) {
+                case OtaUtils.RESULT_INTERACTIVE_OTASP_STARTED:
+                    Log.i(LOG_TAG, "==> onActivityResult: INTERACTIVE_OTASP_STARTED");
+                    break;
+                case OtaUtils.RESULT_NONINTERACTIVE_OTASP_STARTED:
+                    Log.i(LOG_TAG, "==> onActivityResult: NONINTERACTIVE_OTASP_STARTED");
+                    break;
+                case OtaUtils.RESULT_NONINTERACTIVE_OTASP_FAILED:
+                    Log.w(LOG_TAG, "==> onActivityResult: NONINTERACTIVE_OTASP_FAILED");
+                    // This means we couldn't even *initiate* an outgoing call
+                    // to start the OTASP process.  Not sure what could cause this.
+                    // TODO: Update UI to indicate the error.
+                    break;
+                case RESULT_CANCELED:
+                    Log.i(LOG_TAG, "==> onActivityResult: CANCELED");
+                    break;
+                default:
+                    Log.i(LOG_TAG, "==> onActivityResult: unknown result: " + resultCode);
+                    break;
+            }
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        Log.i(LOG_TAG, "onResume()...");
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        Log.i(LOG_TAG, "onPause()...");
+        super.onPause();
+    }
+
+    // View.OnClickListener implementation
+    @Override
+    public void onClick(View view) {
+        int id = view.getId();
+        Log.i(LOG_TAG, "onClick(View " + view + ", id " + id + ")...");
+
+        switch (id) {
+            case R.id.button1:
+                Log.i(LOG_TAG, "onClick: button1...");
+                makeTestCall();
+                break;
+            default:
+                Log.w(LOG_TAG, "onClick: unexpected View: " + view);
+                break;
+        }
+    }
+
+    private void makeTestCall() {
+        Log.i(LOG_TAG, "##### makeTestCall()...");
+
+        mProgressBar.setVisibility(View.VISIBLE);
+        mResult.setVisibility(View.INVISIBLE);
+
+        try {
+            Intent performProvisioningIntent =
+                    new Intent(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING);
+
+            // Set the magic extra to force "non-interactive mode" for the
+            // OTASP call.
+            performProvisioningIntent.putExtra(OtaUtils.EXTRA_OVERRIDE_INTERACTIVE_MODE, false);
+
+            // Pass a PendingIntent along with the
+            // ACTION_PERFORM_CDMA_PROVISIONING intent, which allows
+            // results to be sent back to us.
+            Intent resultIntent = new Intent(this, this.getClass());
+            PendingIntent pendingResultIntent =
+                    PendingIntent.getActivity(this, 0,
+                                              resultIntent, 0);
+            performProvisioningIntent.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT,
+                                               pendingResultIntent);
+
+            Log.i(LOG_TAG, "- Firing off PERFORM_CDMA_PROVISIONING intent: "
+                  + performProvisioningIntent);
+            Bundle extras = performProvisioningIntent.getExtras();
+            if (extras != null) Log.i(LOG_TAG, "      - intent extras = " + extras);
+
+            // Originally, we would simply call
+            //     startActivity(performProvisioningIntent);
+            // to launch the InCallScreenShowActivation activity and *not* expect
+            // a result.  (Note that calling the plain startActivity()
+            // method *guarantees* that your onActivityResult() method
+            // will NOT be called at all.)
+
+            // Now, we ask for a result:
+            startActivityForResult(performProvisioningIntent,
+                                   PERFORM_CDMA_PROVISIONING_REQUEST_CODE);
+
+            // On a non-voice-capable device, the InCallScreenShowActivation activity
+            // will kick off the OTASP call and immediately return, passing
+            // the code RESULT_STARTED_NONINTERACTIVE_OTASP to our
+            // onActivityResult method.
+
+        } catch (ActivityNotFoundException e) {
+            Log.w(LOG_TAG, "Couldn't show activiation UI; ActivityNotFoundException: " + e);
+        }
+    }
+}
diff --git a/tests/src/com/android/phone/tests/SendInstantTextTestService.java b/tests/src/com/android/phone/tests/SendInstantTextTestService.java
new file mode 100644
index 0000000..c7ad2f7
--- /dev/null
+++ b/tests/src/com/android/phone/tests/SendInstantTextTestService.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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.phone.tests;
+
+import android.app.IntentService;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ * Service which receives instant text responses from in-call UI and shows the message using
+ * {@link Toast}.
+ */
+public class SendInstantTextTestService extends IntentService {
+    private static final String TAG = SendInstantTextTestService.class.getSimpleName();
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            showMessageWithToast((Intent) msg.obj);
+        }
+    };
+
+    public SendInstantTextTestService() {
+        super("send_instant_text_test_service");
+    }
+
+    @Override
+    protected void onHandleIntent(Intent intent) {
+        String action = intent.getAction();
+        Uri uri = intent.getData();
+        String message = intent.getStringExtra(Intent.EXTRA_TEXT);
+        Log.i(TAG, "Received instant response message. action=" + action
+                + ", uri=" + uri + ", message=\"" + message + "\"");
+        // Phone app uses Toast to show confirmation, which overlaps with this message.
+        // Let's delay showing this one for 5sec.
+        mHandler.sendMessageDelayed(Message.obtain(mHandler, 0, intent), 5 * 1000);
+    }
+
+    private void showMessageWithToast(Intent intent) {
+        Uri uri = intent.getData();
+        String message = intent.getStringExtra(Intent.EXTRA_TEXT);
+        String toastText = getString(R.string.instant_text_back_content, message, uri.toString());
+        Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();
+    }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/phone/unit/CnapTest.java b/tests/src/com/android/phone/unit/CnapTest.java
new file mode 100644
index 0000000..7161ba8
--- /dev/null
+++ b/tests/src/com/android/phone/unit/CnapTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+// Need to be in this package to access package methods.
+package com.android.phone;
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import com.android.internal.telephony.CallerInfo;
+import com.android.phone.PhoneUtils;
+import static com.android.internal.telephony.PhoneConstants.PRESENTATION_ALLOWED;
+import static com.android.internal.telephony.PhoneConstants.PRESENTATION_PAYPHONE;
+import static com.android.internal.telephony.PhoneConstants.PRESENTATION_RESTRICTED;
+import static com.android.internal.telephony.PhoneConstants.PRESENTATION_UNKNOWN;
+
+// Test suite for the Caller Name Presentation (CNAP) handling.
+// See AndroidManifest.xml how to run these tests.
+public class CnapTest extends AndroidTestCase {
+    private static final String TAG = "CnapTest";
+    private Context mContext;
+    private CallerInfo mCallerInfo;
+    // TODO: This string should be loaded from the phone package and
+    // not hardcoded.
+    private String mUnknown = "Unknown";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getContext();
+        mCallerInfo = new CallerInfo();
+    }
+
+    // Checks the cnap 'ABSENT NUMBER' is mapped to the unknown presentation.
+    @SmallTest
+    public void testAbsentNumberIsMappedToUnknown() throws Exception {
+        String num = modifyForSpecialCnapCases("ABSENT NUMBER", PRESENTATION_ALLOWED);
+        assertIsUnknown(num);
+    }
+
+    // HELPERS
+
+    /**
+     * Checks the number and CallerInfo structure indicate the number
+     * is unknown.
+     */
+    private void assertIsUnknown(String number) {
+        assertEquals(mUnknown, number);
+        assertEquals(PRESENTATION_UNKNOWN, mCallerInfo.numberPresentation);
+        // TODO: cnapName and name presentation should be set to
+        // unknown. At least I cannot see why it shouldn't be the case
+        // assertEquals(mUnknown, mCallerInfo.cnapName);
+        // assertEquals(PRESENTATION_UNKNOWN, mCallerInfo.namePresentation);
+    }
+
+    /**
+     * Shorthand for PhoneUtils.modifyForSpecialCnapCases(mContext, mCallerInfo, ...)
+     */
+    private String modifyForSpecialCnapCases(String number, int presentation) {
+        return PhoneUtils.modifyForSpecialCnapCases(
+            mContext, mCallerInfo, number, presentation);
+    }
+}