blob: 34710a184b2f9a303dd8cebd5f968211f5ff9555 [file] [log] [blame]
/*
* 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.
*/
package com.android.phone;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyCapabilities;
/**
* Invisible activity that handles the com.android.phone.PERFORM_CDMA_PROVISIONING intent.
* This activity is protected by the android.permission.PERFORM_CDMA_PROVISIONING permission.
*
* We handle the PERFORM_CDMA_PROVISIONING action by launching an OTASP
* call via one of the OtaUtils helper methods: startInteractiveOtasp() on
* regular phones, or startNonInteractiveOtasp() on data-only devices.
*
* TODO: The class name InCallScreenShowActivation is misleading, since
* this activity is totally unrelated to the InCallScreen (which
* implements the in-call UI.) Let's eventually rename this to something
* like CdmaProvisioningLauncher or CdmaProvisioningHandler...
*/
public class InCallScreenShowActivation extends Activity {
private static final String LOG_TAG = "InCallScreenShowActivation";
private static final boolean DBG =
(PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent intent = getIntent();
if (DBG) Log.d(LOG_TAG, "onCreate: intent = " + intent);
Bundle extras = intent.getExtras();
if (DBG && (extras != null)) {
Log.d(LOG_TAG, " - has extras: size = " + extras.size()); // forces an unparcel()
Log.d(LOG_TAG, " - extras = " + extras);
}
PhoneGlobals app = PhoneGlobals.getInstance();
Phone phone = app.getPhone();
if (!TelephonyCapabilities.supportsOtasp(phone)) {
Log.w(LOG_TAG, "CDMA Provisioning not supported on this device");
setResult(RESULT_CANCELED);
finish();
return;
}
if (intent.getAction().equals(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING)) {
boolean usesHfa = getResources().getBoolean(R.bool.config_use_hfa_for_provisioning);
if (usesHfa) {
Log.i(LOG_TAG, "Starting Hfa from ACTION_PERFORM_CDMA_PROVISIONING");
startHfa();
finish();
return;
}
boolean usesOtasp = getResources().getBoolean(R.bool.config_use_otasp_for_provisioning);
if (usesOtasp) {
// On voice-capable devices, we perform CDMA provisioning in
// "interactive" mode by directly launching the InCallScreen.
// boolean interactiveMode = PhoneGlobals.sVoiceCapable;
// TODO: Renable interactive mode for device provisioning.
boolean interactiveMode = false;
Log.i(LOG_TAG, "ACTION_PERFORM_CDMA_PROVISIONING (interactiveMode = "
+ interactiveMode + ")...");
// Testing: this intent extra allows test apps manually
// enable/disable "interactive mode", regardless of whether
// the current device is voice-capable. This is allowed only
// in userdebug or eng builds.
if (intent.hasExtra(OtaUtils.EXTRA_OVERRIDE_INTERACTIVE_MODE)
&& (SystemProperties.getInt("ro.debuggable", 0) == 1)) {
interactiveMode =
intent.getBooleanExtra(OtaUtils.EXTRA_OVERRIDE_INTERACTIVE_MODE, false);
Log.d(LOG_TAG, "==> MANUALLY OVERRIDING interactiveMode to " + interactiveMode);
}
// We allow the caller to pass a PendingIntent (as the
// EXTRA_NONINTERACTIVE_OTASP_RESULT_PENDING_INTENT extra)
// which we'll later use to notify them when the OTASP call
// fails or succeeds.
//
// Stash that away here, and we'll fire it off later in
// OtaUtils.sendOtaspResult().
app.cdmaOtaScreenState.otaspResultCodePendingIntent =
(PendingIntent) intent.getParcelableExtra(
OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT);
if (interactiveMode) {
// On voice-capable devices, launch an OTASP call and arrange
// for the in-call UI to come up. (The InCallScreen will
// notice that an OTASP call is active, and display the
// special OTASP UI instead of the usual in-call controls.)
if (DBG) Log.d(LOG_TAG, "==> Starting interactive CDMA provisioning...");
OtaUtils.startInteractiveOtasp(this);
// The result we set here is actually irrelevant, since the
// InCallScreen's "interactive" OTASP sequence never actually
// finish()es; it ends by directly launching the Home
// activity. So our caller won't actually ever get an
// onActivityResult() call in this case.
setResult(OtaUtils.RESULT_INTERACTIVE_OTASP_STARTED);
} else {
// On data-only devices, manually launch the OTASP call
// *without* displaying any UI. (Our caller, presumably
// SetupWizardActivity, is responsible for displaying some
// sort of progress UI.)
if (DBG) Log.d(LOG_TAG, "==> Starting non-interactive CDMA provisioning...");
int callStatus = OtaUtils.startNonInteractiveOtasp(this);
if (callStatus == PhoneUtils.CALL_STATUS_DIALED) {
if (DBG) Log.d(LOG_TAG,
" ==> successful result from startNonInteractiveOtasp(): " +
callStatus);
setResult(OtaUtils.RESULT_NONINTERACTIVE_OTASP_STARTED);
} else {
Log.w(LOG_TAG, "Failure code from startNonInteractiveOtasp(): " +
callStatus);
setResult(OtaUtils.RESULT_NONINTERACTIVE_OTASP_FAILED);
}
}
} else {
Log.i(LOG_TAG, "Skipping activation.");
}
} else {
Log.e(LOG_TAG, "Unexpected intent action: " + intent);
setResult(RESULT_CANCELED);
}
finish();
}
/**
* On devices that provide a phone initialization wizard (such as Google Setup Wizard),
* the wizard displays it's own activation UI. The Hfa activation started by this class
* will show a UI or not depending on the status of the setup wizard. If the setup wizard
* is running, do not show a UI, otherwise show our own UI since setup wizard will not.
*
* The method checks two properties:
* 1. Does the device require a setup wizard (ro.setupwizard.mode == (REQUIRED|OPTIONAL))
* 2. Is device_provisioned set to non-zero--a property that setup wizard sets at completion.
* @return true if wizard is running, false otherwise.
*/
private boolean isWizardRunning(Context context) {
Intent intent = new Intent("android.intent.action.DEVICE_INITIALIZATION_WIZARD");
ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean provisioned = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) != 0;
String mode = SystemProperties.get("ro.setupwizard.mode", "REQUIRED");
boolean runningSetupWizard = "REQUIRED".equals(mode) || "OPTIONAL".equals(mode);
if (DBG) {
Log.v(LOG_TAG, "resolvInfo = " + resolveInfo + ", provisioned = " + provisioned
+ ", runningSetupWizard = " + runningSetupWizard);
}
return resolveInfo != null && !provisioned && runningSetupWizard;
}
/**
* Starts the HFA provisioning process by bringing up the HFA Activity.
*/
private void startHfa() {
boolean isWizardRunning = isWizardRunning(this);
// We always run our HFA logic if we're in setup wizard, but if we're outside of setup
// wizard then we have to check a config to see if we should still run HFA.
if (isWizardRunning ||
getResources().getBoolean(R.bool.config_allow_hfa_outside_of_setup_wizard)) {
final Intent intent = new Intent();
final PendingIntent otaResponseIntent = getIntent().getParcelableExtra(
OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT);
final boolean showUi = !isWizardRunning;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (otaResponseIntent != null) {
intent.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT, otaResponseIntent);
}
Log.v(LOG_TAG, "Starting hfa activation activity");
if (showUi) {
intent.setClassName(this, HfaActivity.class.getName());
startActivity(intent);
} else {
intent.setClassName(this, HfaService.class.getName());
startService(intent);
}
}
setResult(RESULT_OK);
}
}