Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.phone;
     18 
     19 import android.app.Activity;
     20 import android.app.PendingIntent;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.pm.PackageManager;
     24 import android.content.pm.ResolveInfo;
     25 import android.os.Bundle;
     26 import android.os.SystemProperties;
     27 import android.provider.Settings;
     28 import android.util.Log;
     29 
     30 import com.android.internal.telephony.Phone;
     31 import com.android.internal.telephony.TelephonyCapabilities;
     32 
     33 /**
     34  * Invisible activity that handles the com.android.phone.PERFORM_CDMA_PROVISIONING intent.
     35  * This activity is protected by the android.permission.PERFORM_CDMA_PROVISIONING permission.
     36  *
     37  * We handle the PERFORM_CDMA_PROVISIONING action by launching an OTASP
     38  * call via one of the OtaUtils helper methods: startInteractiveOtasp() on
     39  * regular phones, or startNonInteractiveOtasp() on data-only devices.
     40  *
     41  * TODO: The class name InCallScreenShowActivation is misleading, since
     42  * this activity is totally unrelated to the InCallScreen (which
     43  * implements the in-call UI.)  Let's eventually rename this to something
     44  * like CdmaProvisioningLauncher or CdmaProvisioningHandler...
     45  */
     46 public class InCallScreenShowActivation extends Activity {
     47     private static final String LOG_TAG = "InCallScreenShowActivation";
     48     private static final boolean DBG =
     49             (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
     50 
     51     @Override
     52     protected void onCreate(Bundle icicle) {
     53         super.onCreate(icicle);
     54 
     55         Intent intent = getIntent();
     56         if (DBG) Log.d(LOG_TAG, "onCreate: intent = " + intent);
     57         Bundle extras = intent.getExtras();
     58         if (DBG && (extras != null)) {
     59             Log.d(LOG_TAG, "      - has extras: size = " + extras.size()); // forces an unparcel()
     60             Log.d(LOG_TAG, "      - extras = " + extras);
     61         }
     62 
     63         PhoneGlobals app = PhoneGlobals.getInstance();
     64         Phone phone = app.getPhone();
     65         if (!TelephonyCapabilities.supportsOtasp(phone)) {
     66             Log.w(LOG_TAG, "CDMA Provisioning not supported on this device");
     67             setResult(RESULT_CANCELED);
     68             finish();
     69             return;
     70         }
     71 
     72         if (intent.getAction().equals(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING)) {
     73 
     74             boolean usesHfa = getResources().getBoolean(R.bool.config_use_hfa_for_provisioning);
     75             if (usesHfa) {
     76                 Log.d(LOG_TAG, "Starting Hfa from ACTION_PERFORM_CDMA_PROVISIONING");
     77                 startHfa();
     78                 finish();
     79                 return;
     80             }
     81 
     82             // On voice-capable devices, we perform CDMA provisioning in
     83             // "interactive" mode by directly launching the InCallScreen.
     84             // boolean interactiveMode = PhoneGlobals.sVoiceCapable;
     85             // TODO: Renable interactive mode for device provisioning.
     86             boolean interactiveMode = false;
     87             Log.d(LOG_TAG, "ACTION_PERFORM_CDMA_PROVISIONING (interactiveMode = "
     88                   + interactiveMode + ")...");
     89 
     90             // Testing: this intent extra allows test apps manually
     91             // enable/disable "interactive mode", regardless of whether
     92             // the current device is voice-capable.  This is allowed only
     93             // in userdebug or eng builds.
     94             if (intent.hasExtra(OtaUtils.EXTRA_OVERRIDE_INTERACTIVE_MODE)
     95                     && (SystemProperties.getInt("ro.debuggable", 0) == 1)) {
     96                 interactiveMode =
     97                         intent.getBooleanExtra(OtaUtils.EXTRA_OVERRIDE_INTERACTIVE_MODE, false);
     98                 Log.d(LOG_TAG, "===> MANUALLY OVERRIDING interactiveMode to " + interactiveMode);
     99             }
    100 
    101             // We allow the caller to pass a PendingIntent (as the
    102             // EXTRA_NONINTERACTIVE_OTASP_RESULT_PENDING_INTENT extra)
    103             // which we'll later use to notify them when the OTASP call
    104             // fails or succeeds.
    105             //
    106             // Stash that away here, and we'll fire it off later in
    107             // OtaUtils.sendOtaspResult().
    108             app.cdmaOtaScreenState.otaspResultCodePendingIntent =
    109                         (PendingIntent) intent.getParcelableExtra(
    110                                 OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT);
    111 
    112             if (interactiveMode) {
    113                 // On voice-capable devices, launch an OTASP call and arrange
    114                 // for the in-call UI to come up.  (The InCallScreen will
    115                 // notice that an OTASP call is active, and display the
    116                 // special OTASP UI instead of the usual in-call controls.)
    117 
    118                 if (DBG) Log.d(LOG_TAG, "==> Starting interactive CDMA provisioning...");
    119                 OtaUtils.startInteractiveOtasp(this);
    120 
    121                 // The result we set here is actually irrelevant, since the
    122                 // InCallScreen's "interactive" OTASP sequence never actually
    123                 // finish()es; it ends by directly launching the Home
    124                 // activity.  So our caller won't actually ever get an
    125                 // onActivityResult() call in this case.
    126                 setResult(OtaUtils.RESULT_INTERACTIVE_OTASP_STARTED);
    127             } else {
    128                 // On data-only devices, manually launch the OTASP call
    129                 // *without* displaying any UI.  (Our caller, presumably
    130                 // SetupWizardActivity, is responsible for displaying some
    131                 // sort of progress UI.)
    132 
    133                 if (DBG) Log.d(LOG_TAG, "==> Starting non-interactive CDMA provisioning...");
    134                 int callStatus = OtaUtils.startNonInteractiveOtasp(this);
    135 
    136                 if (callStatus == PhoneUtils.CALL_STATUS_DIALED) {
    137                     if (DBG) Log.d(LOG_TAG, "  ==> successful result from startNonInteractiveOtasp(): "
    138                           + callStatus);
    139                     setResult(OtaUtils.RESULT_NONINTERACTIVE_OTASP_STARTED);
    140                 } else {
    141                     Log.w(LOG_TAG, "Failure code from startNonInteractiveOtasp(): " + callStatus);
    142                     setResult(OtaUtils.RESULT_NONINTERACTIVE_OTASP_FAILED);
    143                 }
    144             }
    145         } else {
    146             Log.e(LOG_TAG, "Unexpected intent action: " + intent);
    147             setResult(RESULT_CANCELED);
    148         }
    149 
    150         finish();
    151     }
    152 
    153     /**
    154      * On devices that provide a phone initialization wizard (such as Google Setup Wizard),
    155      * the wizard displays it's own activation UI. The Hfa activation started by this class
    156      * will show a UI or not depending on the status of the setup wizard. If the setup wizard
    157      * is running, do not show a UI, otherwise show our own UI since setup wizard will not.
    158      *
    159      * The method checks two properties:
    160      * 1. Does the device require a setup wizard (ro.setupwizard.mode == (REQUIRED|OPTIONAL))
    161      * 2. Is device_provisioned set to non-zero--a property that setup wizard sets at completion.
    162      * @return true if wizard is running, false otherwise.
    163      */
    164     private boolean isWizardRunning(Context context) {
    165         Intent intent = new Intent("android.intent.action.DEVICE_INITIALIZATION_WIZARD");
    166         ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent,
    167                 PackageManager.MATCH_DEFAULT_ONLY);
    168         boolean provisioned = Settings.Global.getInt(context.getContentResolver(),
    169                 Settings.Global.DEVICE_PROVISIONED, 0) != 0;
    170         String mode = SystemProperties.get("ro.setupwizard.mode", "REQUIRED");
    171         boolean runningSetupWizard = "REQUIRED".equals(mode) || "OPTIONAL".equals(mode);
    172         if (DBG) {
    173             Log.v(LOG_TAG, "resolvInfo = " + resolveInfo + ", provisioned = " + provisioned
    174                     + ", runningSetupWizard = " + runningSetupWizard);
    175         }
    176         return resolveInfo != null && !provisioned && runningSetupWizard;
    177     }
    178 
    179     /**
    180      * Starts the HFA provisioning process by bringing up the HFA Activity.
    181      */
    182     private void startHfa() {
    183         final Intent intent = new Intent();
    184 
    185         final PendingIntent otaResponseIntent = getIntent().getParcelableExtra(
    186                 OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT);
    187 
    188         final boolean showUi = !isWizardRunning(this);
    189 
    190         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    191 
    192         if (otaResponseIntent != null) {
    193             intent.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE_PENDING_INTENT, otaResponseIntent);
    194         }
    195 
    196         Log.v(LOG_TAG, "Starting hfa activation activity");
    197         if (showUi) {
    198             intent.setClassName(this, HfaActivity.class.getName());
    199             startActivity(intent);
    200         } else {
    201             intent.setClassName(this, HfaService.class.getName());
    202             startService(intent);
    203         }
    204 
    205         setResult(RESULT_OK);
    206     }
    207 }
    208