am d2ad6183: am 1d154f78: Merge "HFA support in services/Telephony for provisioning CDMA devices." into klp-dev
* commit 'd2ad61832a77694adf80067645244716921c0602':
HFA support in services/Telephony for provisioning CDMA devices.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6ed3dc7..fe71d4c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -513,6 +513,12 @@
android:theme="@style/Theme.Transparent">
</activity>
+ <activity android:name="HfaActivity"
+ android:excludeFromRecents="true"
+ android:launchMode="singleInstance"
+ android:theme="@style/Empty">
+ </activity>
+
<receiver android:name="CallerInfoCacheUpdateReceiver">
<intent-filter>
<action android:name="com.android.phone.UPDATE_CALLER_INFO_CACHE" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 2d3317c..adc54ee 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -125,4 +125,7 @@
<!-- Class name for the default in-call UI Service [DO NOT TRANSLATE] -->
<string name="incall_ui_default_class" translatable="false">com.android.incallui.CallHandlerService</string>
+
+ <!-- CDMA activation goes through HFA [DO NOT TRANSLATE] -->
+ <bool name="config_use_hfa_for_provisioning" translatable="false">false</bool>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1e5122e..f644dda 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -935,7 +935,10 @@
<!-- Message displayed on the OTA activation screen. -->
<string name="ota_touch_activate">A special call needs to be made to activate your phone service.
\n\nAfter pressing \u201CActivate\u201D, listen to the instructions provided to activate your phone.</string>
-
+ <!-- Title shown during Hands Free Activation -->
+ <string name="ota_hfa_activation_title">Activating...</string>
+ <!-- Message shown during the hands free activation screen of the setup wizard. -->
+ <string name="ota_hfa_activation_dialog_message">The phone is activating your mobile data service.\n\nThis can take up to 5 minutes.</string>
<!-- Title of skip activation dialog -->
<string name="ota_skip_activation_dialog_title">Skip activation\?</string>
<!-- Message displayed in skip activation dialog -->
diff --git a/src/com/android/phone/HfaActivity.java b/src/com/android/phone/HfaActivity.java
new file mode 100644
index 0000000..3bc047d
--- /dev/null
+++ b/src/com/android/phone/HfaActivity.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2013 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;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.telephony.ServiceState;
+import android.util.Log;
+
+import com.android.internal.telephony.CallManager;
+import com.android.internal.telephony.Phone;
+import com.google.common.base.Objects;
+import com.google.common.base.Objects.ToStringHelper;
+
+/**
+ * Starts and displays status for Hands Free Activation (HFA).
+ *
+ * This class operates with Hands Free Activation apps.
+ * It starts by broadcasting the intent com.android.action.START_HFA.
+ * An HFA app will pick that up and start the HFA process.
+ * If it fails it return ERROR_HFA Intent and upon success returns COMPLETE_HFA.
+ *
+ * If successful, we bounce the radio so that the service picks up the new number. This is also
+ * necessary for the setup wizard to pick up the successful activation so that it can continue
+ * past the welcome screen. Once the radio is back on we send back the pendingIntent to setup
+ * wizard and destroy the activity.
+ *
+ * If there is an error, we do not bounce the radio but still send the pending intent back to
+ * the wizard (with a failure code).
+ *
+ * The user has an option to skip activation. If that happens, we go back to the setup
+ * wizard.
+ *
+ * TODO(klp): We need system-only permissions for the HFA intents.
+ * TODO(klp): Should be full screen activity instead of dialogs.
+ * TODO(klp): Currently display the error code instead of the error string resource.
+ * TODO(klp): Need to check the system to ensure someone is listening for the intent
+ * before we send it. Should there be a timeout? 5 minutes?
+ */
+public class HfaActivity extends Activity {
+ private static final String TAG = HfaActivity.class.getSimpleName();
+
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+ private static final String ACTION_START = "com.android.action.START_HFA";
+ private static final String ACTION_ERROR = "com.android.action.ERROR_HFA";
+ private static final String ACTION_CANCEL = "com.android.action.CANCEL_HFA";
+ private static final String ACTION_COMPLETE = "com.android.action.COMPLETE_HFA";
+
+ private static final int SERVICE_STATE_CHANGED = 1;
+
+ public static final int OTASP_UNKNOWN = 0;
+ public static final int OTASP_USER_SKIPPED = 1;
+ public static final int OTASP_SUCCESS = 2;
+ public static final int OTASP_FAILURE = 3;
+
+ public static final int NOT_WAITING = 0;
+ public static final int WAITING_FOR_RADIO_OFF = 1;
+ public static final int WAITING_FOR_RADIO_ON = 2;
+
+ private int mPhoneMonitorState = NOT_WAITING;
+ private boolean mCanSkip;
+ private AlertDialog mDialog;
+ private BroadcastReceiver mReceiver;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (VERBOSE) Log.v(TAG, "onCreate");
+
+ startHfaIntentReceiver();
+ startProvisioning();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (VERBOSE) Log.v(TAG, "onDestroy");
+
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ mDialog = null;
+ }
+
+ if (mReceiver != null) {
+ unregisterReceiver(mReceiver);
+ mReceiver = null;
+ }
+ }
+
+ private void startProvisioning() {
+ buildAndShowDialog();
+
+ sendHfaCommand(ACTION_START);
+ }
+
+ private void buildAndShowDialog() {
+ mCanSkip = true;
+
+ mDialog = new AlertDialog.Builder(this)
+ .setTitle(R.string.ota_hfa_activation_title)
+ .setMessage(R.string.ota_hfa_activation_dialog_message)
+ .setPositiveButton(R.string.ota_skip_activation_dialog_skip_label,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface di, int which) {
+ if (mCanSkip) {
+ sendHfaCommand(ACTION_CANCEL);
+ sendResponseToSetupWizard(OTASP_USER_SKIPPED);
+ }
+ }})
+ /*.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface di) {
+ sendResponseToSetupWizard(OTASP_USER_SKIPPED);
+ }})*/
+ .create();
+
+ if (VERBOSE) Log.v(TAG, "showing dialog");
+ mDialog.show();
+ }
+
+ private void sendHfaCommand(String action) {
+ if (VERBOSE) Log.v(TAG, "Sending command: " + action);
+ sendBroadcast(new Intent(action));
+ }
+
+ private void onHfaError(String errorMsg) {
+ mDialog.dismiss();
+
+ AlertDialog errorDialog = new AlertDialog.Builder(this)
+ .setMessage(errorMsg)
+ .setPositiveButton(R.string.ota_skip_activation_dialog_skip_label,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface di, int which) {
+ di.dismiss();
+ sendResponseToSetupWizard(OTASP_USER_SKIPPED);
+ }
+ })
+ .setNegativeButton(R.string.ota_try_again,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface di, int which) {
+ di.dismiss();
+ startProvisioning();
+ }
+ })
+ .create();
+
+ errorDialog.show();
+ }
+
+ private void onHfaSuccess() {
+ // User can no longer skip after success.
+ mCanSkip = false;
+
+ // We need to restart the modem upon successful activation
+ // so that it can acquire a number and ensure setupwizard will
+ // know about this success through phone state changes.
+
+ bounceRadio();
+ }
+
+ private void bounceRadio() {
+ final Phone phone = PhoneGlobals.getInstance().getPhone();
+ phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);
+
+ mPhoneMonitorState = WAITING_FOR_RADIO_OFF;
+ phone.setRadioPower(false);
+ onServiceStateChange(phone.getServiceState());
+ }
+
+ private void onServiceStateChange(ServiceState state) {
+ final boolean radioIsOff = state.getVoiceRegState() == ServiceState.STATE_POWER_OFF;
+ final Phone phone = PhoneGlobals.getInstance().getPhone();
+
+ if (VERBOSE) Log.v(TAG, "Radio is off: " + radioIsOff);
+
+ if (mPhoneMonitorState == WAITING_FOR_RADIO_OFF) {
+ if (radioIsOff) {
+ mPhoneMonitorState = WAITING_FOR_RADIO_ON;
+ phone.setRadioPower(true);
+ }
+ } else if (mPhoneMonitorState == WAITING_FOR_RADIO_ON) {
+ if (!radioIsOff) {
+ mPhoneMonitorState = NOT_WAITING;
+ phone.unregisterForServiceStateChanged(mHandler);
+
+ // We have successfully bounced the radio.
+ // Time to go back to the setup wizard.
+ sendResponseToSetupWizard(OTASP_SUCCESS);
+ }
+ }
+ }
+
+ private void sendResponseToSetupWizard(int responseCode) {
+ final PendingIntent otaResponseIntent = getIntent().getParcelableExtra(
+ OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT);
+
+ final Intent extraStuff = new Intent();
+ extraStuff.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE, responseCode);
+
+ try {
+ if (VERBOSE) Log.v(TAG, "Sending OTASP confirmation with result code: " + responseCode);
+ otaResponseIntent.send(this, 0 /* resultCode (not used) */, extraStuff);
+ } catch (CanceledException e) {
+ Log.e(TAG, "Pending Intent canceled");
+ }
+
+ finish();
+ }
+
+ public void startHfaIntentReceiver() {
+ final IntentFilter filter = new IntentFilter(ACTION_COMPLETE);
+ filter.addAction(ACTION_ERROR);
+
+ mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(ACTION_ERROR)) {
+ onHfaError(intent.getStringExtra("errorCode"));
+ } else if (action.equals(ACTION_COMPLETE)) {
+ if (VERBOSE) Log.v(TAG, "Hfa Successful");
+ onHfaSuccess();
+ }
+ }
+ };
+
+ registerReceiver(mReceiver, filter);
+ }
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case SERVICE_STATE_CHANGED:
+ ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result;
+ onServiceStateChange(state);
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
+}
diff --git a/src/com/android/phone/InCallScreenShowActivation.java b/src/com/android/phone/InCallScreenShowActivation.java
index 243b437..15abb11 100644
--- a/src/com/android/phone/InCallScreenShowActivation.java
+++ b/src/com/android/phone/InCallScreenShowActivation.java
@@ -67,6 +67,14 @@
if (intent.getAction().equals(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING)) {
+ boolean usesHfa = getResources().getBoolean(R.bool.config_use_hfa_for_provisioning);
+ if (usesHfa) {
+ Log.d(LOG_TAG, "Starting Hfa from ACTION_PERFORM_CDMA_PROVISIONING");
+ startHfa();
+ finish();
+ return;
+ }
+
// On voice-capable devices, we perform CDMA provisioning in
// "interactive" mode by directly launching the InCallScreen.
// boolean interactiveMode = PhoneGlobals.sVoiceCapable;
@@ -137,4 +145,21 @@
finish();
}
+
+
+ /**
+ * Starts the HFA provisioning process by bringing up the HFA Activity.
+ */
+ private void startHfa() {
+ final Intent intent = new Intent(this, HfaActivity.class);
+
+ final PendingIntent otaResponseIntent = getIntent().getParcelableExtra(
+ OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT);
+
+ intent.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT, otaResponseIntent);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+ Log.v(LOG_TAG, "Starting hfa activation activity");
+ startActivity(intent);
+ }
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index db06c30..45ffd33 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -1588,4 +1588,5 @@
mBluetoothPhone = null;
}
};
+
}