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.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ResolveInfo; 24 import android.os.AsyncResult; 25 import android.os.Handler; 26 import android.os.Message; 27 import android.os.SystemProperties; 28 import android.provider.Settings; 29 import android.telephony.PhoneStateListener; 30 import android.telephony.ServiceState; 31 import android.telephony.TelephonyManager; 32 33 import com.android.internal.telephony.Phone; 34 import com.android.internal.telephony.ServiceStateTracker; 35 import com.android.internal.telephony.TelephonyCapabilities; 36 37 import android.util.Log; 38 39 /* 40 * Handles OTA Start procedure at phone power up. At phone power up, if phone is not OTA 41 * provisioned (check MIN value of the Phone) and 'device_provisioned' is not set, 42 * OTA Activation screen is shown that helps user activate the phone 43 */ 44 public class OtaStartupReceiver extends BroadcastReceiver { 45 private static final String TAG = "OtaStartupReceiver"; 46 private static final boolean DBG = false; 47 private static final int MIN_READY = 10; 48 private static final int SERVICE_STATE_CHANGED = 11; 49 private Context mContext; 50 51 private int mOtaspMode = -1; 52 private boolean mPhoneStateListenerRegistered = false; 53 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 54 @Override 55 public void onOtaspChanged(int otaspMode) { 56 if (mOtaspMode == otaspMode) { 57 return; 58 } 59 mOtaspMode = otaspMode; 60 Log.v(TAG, "onOtaspChanged: mOtaspMode=" + mOtaspMode); 61 62 if (otaspMode == ServiceStateTracker.OTASP_NEEDED) { 63 Log.i(TAG, "OTASP is needed - performing CDMA provisioning"); 64 final Intent intent = new Intent(OtaUtils.ACTION_PERFORM_CDMA_PROVISIONING); 65 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 66 mContext.startActivity(intent); 67 } 68 } 69 }; 70 71 72 private Handler mHandler = new Handler() { 73 @Override 74 public void handleMessage(Message msg) { 75 switch (msg.what) { 76 case MIN_READY: 77 Log.v(TAG, "Attempting OtaActivation from handler, mOtaspMode=" + mOtaspMode); 78 OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 79 break; 80 case SERVICE_STATE_CHANGED: { 81 ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 82 if (DBG) Log.d(TAG, "onServiceStateChanged()... new state = " + state); 83 84 // Possible service states: 85 // - STATE_IN_SERVICE // Normal operation 86 // - STATE_OUT_OF_SERVICE // Still searching for an operator to register to, 87 // // or no radio signal 88 // - STATE_EMERGENCY_ONLY // Phone is locked; only emergency numbers are allowed 89 // - STATE_POWER_OFF // Radio is explicitly powered off (airplane mode) 90 91 // Once we reach STATE_IN_SERVICE 92 // it's finally OK to start OTA provisioning 93 if (state.getState() == ServiceState.STATE_IN_SERVICE) { 94 if (DBG) Log.d(TAG, "call OtaUtils.maybeDoOtaCall after network is available"); 95 Phone phone = PhoneGlobals.getPhone(); 96 phone.unregisterForServiceStateChanged(this); 97 OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 98 } 99 break; 100 } 101 } 102 103 } 104 }; 105 106 @Override onReceive(Context context, Intent intent)107 public void onReceive(Context context, Intent intent) { 108 mContext = context; 109 if (DBG) { 110 Log.v(TAG, "onReceive: intent action=" + intent.getAction() + 111 " mOtaspMode=" + mOtaspMode); 112 } 113 114 PhoneGlobals globals = PhoneGlobals.getInstanceIfPrimary(); 115 if (globals == null) { 116 if (DBG) Log.d(TAG, "Not primary user, nothing to do."); 117 return; 118 } 119 120 if (mPhoneStateListenerRegistered == false) { 121 if (DBG) Log.d(TAG, "Register our PhoneStateListener"); 122 TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService( 123 Context.TELEPHONY_SERVICE); 124 telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_OTASP_CHANGED); 125 mPhoneStateListenerRegistered = true; 126 } else { 127 if (DBG) Log.d(TAG, "PhoneStateListener already registered"); 128 } 129 130 if (!TelephonyCapabilities.supportsOtasp(PhoneGlobals.getPhone())) { 131 if (DBG) Log.d(TAG, "OTASP not supported, nothing to do."); 132 return; 133 } 134 135 if (shouldPostpone(context)) { 136 if (DBG) Log.d(TAG, "Postponing OTASP until wizard runs"); 137 return; 138 } 139 140 // Delay OTA provisioning if network is not available yet 141 PhoneGlobals app = PhoneGlobals.getInstance(); 142 Phone phone = PhoneGlobals.getPhone(); 143 if (app.mCM.getServiceState() != ServiceState.STATE_IN_SERVICE) { 144 if (DBG) Log.w(TAG, "Network is not ready. Registering to receive notification."); 145 phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null); 146 return; 147 } 148 149 // The following depends on the phone process being persistent. Normally we can't 150 // expect a BroadcastReceiver to persist after returning from this function but it does 151 // because the phone activity is persistent. 152 if (DBG) Log.d(TAG, "call OtaUtils.maybeDoOtaCall"); 153 OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 154 } 155 156 /** 157 * On devices that provide a phone initialization wizard (such as Google Setup Wizard), we 158 * allow delaying CDMA OTA setup so it can be done in a single wizard. The wizard is responsible 159 * for (1) disabling itself once it has been run and/or (2) setting the 'device_provisioned' 160 * flag to something non-zero and (3) calling the OTA Setup with the action below. 161 * 162 * NB: Typical phone initialization wizards will install themselves as the homescreen 163 * (category "android.intent.category.HOME") with a priority higher than the default. 164 * The wizard should set 'device_provisioned' when it completes, disable itself with the 165 * PackageManager.setComponentEnabledSetting() and then start home screen. 166 * 167 * @return true if setup will be handled by wizard, false if it should be done now. 168 */ shouldPostpone(Context context)169 private boolean shouldPostpone(Context context) { 170 Intent intent = new Intent("android.intent.action.DEVICE_INITIALIZATION_WIZARD"); 171 ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, 172 PackageManager.MATCH_DEFAULT_ONLY); 173 boolean provisioned = Settings.Global.getInt(context.getContentResolver(), 174 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 175 String mode = SystemProperties.get("ro.setupwizard.mode", "REQUIRED"); 176 boolean runningSetupWizard = "REQUIRED".equals(mode) || "OPTIONAL".equals(mode); 177 if (DBG) { 178 Log.v(TAG, "resolvInfo = " + resolveInfo + ", provisioned = " + provisioned 179 + ", runningSetupWizard = " + runningSetupWizard); 180 } 181 return resolveInfo != null && !provisioned && runningSetupWizard; 182 } 183 } 184