1af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville/* 2af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * Copyright (C) 2009 The Android Open Source Project 3af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * 4af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 5af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * you may not use this file except in compliance with the License. 6af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * You may obtain a copy of the License at 7af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * 8af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 9af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * 10af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * Unless required by applicable law or agreed to in writing, software 11af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 12af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * See the License for the specific language governing permissions and 14af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * limitations under the License. 15af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville */ 16af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 17af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savillepackage com.android.phone; 18af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 19af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savilleimport android.content.BroadcastReceiver; 20af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savilleimport android.content.Context; 21af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savilleimport android.content.Intent; 22839b14d460986608fe577f89f789de854dc85b58Jim Millerimport android.content.pm.PackageManager; 23839b14d460986608fe577f89f789de854dc85b58Jim Millerimport android.content.pm.ResolveInfo; 24ff536c7c948593910f19a6476ef4bc218104c5a2Meng Huimport android.os.AsyncResult; 25f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Bermanimport android.os.Handler; 26f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Bermanimport android.os.Message; 27af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savilleimport android.os.SystemProperties; 28839b14d460986608fe577f89f789de854dc85b58Jim Millerimport android.provider.Settings; 293e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Savilleimport android.telephony.PhoneStateListener; 30ff536c7c948593910f19a6476ef4bc218104c5a2Meng Huimport android.telephony.ServiceState; 313e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Savilleimport android.telephony.TelephonyManager; 32ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 33ff536c7c948593910f19a6476ef4bc218104c5a2Meng Huimport com.android.internal.telephony.Phone; 34ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 35af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savilleimport android.util.Log; 36af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 37af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville/* 38839b14d460986608fe577f89f789de854dc85b58Jim Miller * Handles OTA Start procedure at phone power up. At phone power up, if phone is not OTA 39839b14d460986608fe577f89f789de854dc85b58Jim Miller * provisioned (check MIN value of the Phone) and 'device_provisioned' is not set, 40af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * OTA Activation screen is shown that helps user activate the phone 41af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville */ 42af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savillepublic class OtaStartupReceiver extends BroadcastReceiver { 43839b14d460986608fe577f89f789de854dc85b58Jim Miller private static final String TAG = "OtaStartupReceiver"; 44c3098c14cb1c0444d61ba1b6d0b81175e93bbd75David Brown private static final boolean DBG = true; 45839b14d460986608fe577f89f789de854dc85b58Jim Miller private static final int MIN_READY = 10; 46ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu private static final int SERVICE_STATE_CHANGED = 11; 47f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman private Context mContext; 48af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 493e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville /** 503e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville * For debug purposes we're listening for otaspChanged events as 513e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville * this may be be used in the future for deciding if OTASP is 523e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville * necessary. 533e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville */ 543e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville private int mOtaspMode = -1; 553e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville private boolean mPhoneStateListenerRegistered = false; 563e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 573e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville @Override 583e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville public void onOtaspChanged(int otaspMode) { 593e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville mOtaspMode = otaspMode; 603e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville Log.v(TAG, "onOtaspChanged: mOtaspMode=" + mOtaspMode); 613e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } 623e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville }; 633e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville 643e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville 65839b14d460986608fe577f89f789de854dc85b58Jim Miller private Handler mHandler = new Handler() { 66f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman @Override 67f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman public void handleMessage(Message msg) { 68f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman switch (msg.what) { 69ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu case MIN_READY: 70ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu Log.v(TAG, "Attempting OtaActivation from handler, mOtaspMode=" + mOtaspMode); 71ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 72ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu break; 73ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu case SERVICE_STATE_CHANGED: { 74ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 75ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (DBG) Log.d(TAG, "onServiceStateChanged()... new state = " + state); 76ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 77ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // Possible service states: 78ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_IN_SERVICE // Normal operation 79ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_OUT_OF_SERVICE // Still searching for an operator to register to, 80ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // // or no radio signal 81ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_EMERGENCY_ONLY // Phone is locked; only emergency numbers are allowed 82ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_POWER_OFF // Radio is explicitly powered off (airplane mode) 83ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 84ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // Once we reach STATE_IN_SERVICE 85ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // it's finally OK to start OTA provisioning 86ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (state.getState() == ServiceState.STATE_IN_SERVICE) { 87ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (DBG) Log.d(TAG, "call OtaUtils.maybeDoOtaCall after network is available"); 88ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu Phone phone = PhoneApp.getPhone(); 89ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu phone.unregisterForServiceStateChanged(this); 90ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 91ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu } 92ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu break; 93ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu } 94f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 95ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 96f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 97f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman }; 98af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 993e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville @Override 100f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman public void onReceive(Context context, Intent intent) { 101f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman mContext = context; 1023e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) { 1033e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville Log.v(TAG, "onReceive: intent action=" + intent.getAction() + 1043e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville " mOtaspMode=" + mOtaspMode); 1053e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } 106af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 107d3a8a3a138614071a7a8020e1579048c411abd78Wink Saville if (!TelephonyCapabilities.supportsOtasp(PhoneApp.getPhone())) { 108d3a8a3a138614071a7a8020e1579048c411abd78Wink Saville if (DBG) Log.d(TAG, "OTASP not supported, nothing to do."); 109f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman return; 110f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 111f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman 1123e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (mPhoneStateListenerRegistered == false) { 1133e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) Log.d(TAG, "Register our PhoneStateListener"); 1143e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService( 1153e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville Context.TELEPHONY_SERVICE); 1163e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_OTASP_CHANGED); 1173e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville mPhoneStateListenerRegistered = true; 1183e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } else { 1193e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) Log.d(TAG, "PhoneStateListener already registered"); 1203e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } 1213e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville 122839b14d460986608fe577f89f789de854dc85b58Jim Miller if (shouldPostpone(context)) { 123d3a8a3a138614071a7a8020e1579048c411abd78Wink Saville if (DBG) Log.d(TAG, "Postponing OTASP until wizard runs"); 124f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman return; 125f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 126f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman 127ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // Delay OTA provisioning if network is not available yet 128ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu PhoneApp app = PhoneApp.getInstance(); 129ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu Phone phone = PhoneApp.getPhone(); 130ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (app.mCM.getServiceState() != ServiceState.STATE_IN_SERVICE) { 131ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (DBG) Log.w(TAG, "Network is not ready. Registering to receive notification."); 132ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null); 133ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu return; 134ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu } 135ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 136839b14d460986608fe577f89f789de854dc85b58Jim Miller // The following depends on the phone process being persistent. Normally we can't 137839b14d460986608fe577f89f789de854dc85b58Jim Miller // expect a BroadcastReceiver to persist after returning from this function but it does 138839b14d460986608fe577f89f789de854dc85b58Jim Miller // because the phone activity is persistent. 1393e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) Log.d(TAG, "call OtaUtils.maybeDoOtaCall"); 140839b14d460986608fe577f89f789de854dc85b58Jim Miller OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 141af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville } 142839b14d460986608fe577f89f789de854dc85b58Jim Miller 143839b14d460986608fe577f89f789de854dc85b58Jim Miller /** 144839b14d460986608fe577f89f789de854dc85b58Jim Miller * On devices that provide a phone initialization wizard (such as Google Setup Wizard), we 145839b14d460986608fe577f89f789de854dc85b58Jim Miller * allow delaying CDMA OTA setup so it can be done in a single wizard. The wizard is responsible 146839b14d460986608fe577f89f789de854dc85b58Jim Miller * for (1) disabling itself once it has been run and/or (2) setting the 'device_provisioned' 147839b14d460986608fe577f89f789de854dc85b58Jim Miller * flag to something non-zero and (3) calling the OTA Setup with the action below. 148839b14d460986608fe577f89f789de854dc85b58Jim Miller * 149839b14d460986608fe577f89f789de854dc85b58Jim Miller * NB: Typical phone initialization wizards will install themselves as the homescreen 150839b14d460986608fe577f89f789de854dc85b58Jim Miller * (category "android.intent.category.HOME") with a priority higher than the default. 151839b14d460986608fe577f89f789de854dc85b58Jim Miller * The wizard should set 'device_provisioned' when it completes, disable itself with the 152839b14d460986608fe577f89f789de854dc85b58Jim Miller * PackageManager.setComponentEnabledSetting() and then start home screen. 153839b14d460986608fe577f89f789de854dc85b58Jim Miller * 154839b14d460986608fe577f89f789de854dc85b58Jim Miller * @return true if setup will be handled by wizard, false if it should be done now. 155839b14d460986608fe577f89f789de854dc85b58Jim Miller */ 156839b14d460986608fe577f89f789de854dc85b58Jim Miller private boolean shouldPostpone(Context context) { 157839b14d460986608fe577f89f789de854dc85b58Jim Miller Intent intent = new Intent("android.intent.action.DEVICE_INITIALIZATION_WIZARD"); 158839b14d460986608fe577f89f789de854dc85b58Jim Miller ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, 159839b14d460986608fe577f89f789de854dc85b58Jim Miller PackageManager.MATCH_DEFAULT_ONLY); 160839b14d460986608fe577f89f789de854dc85b58Jim Miller boolean provisioned = Settings.Secure.getInt(context.getContentResolver(), 161839b14d460986608fe577f89f789de854dc85b58Jim Miller Settings.Secure.DEVICE_PROVISIONED, 0) != 0; 162839b14d460986608fe577f89f789de854dc85b58Jim Miller String mode = SystemProperties.get("ro.setupwizard.mode", "REQUIRED"); 163839b14d460986608fe577f89f789de854dc85b58Jim Miller boolean runningSetupWizard = "REQUIRED".equals(mode) || "OPTIONAL".equals(mode); 164839b14d460986608fe577f89f789de854dc85b58Jim Miller if (DBG) { 165839b14d460986608fe577f89f789de854dc85b58Jim Miller Log.v(TAG, "resolvInfo = " + resolveInfo + ", provisioned = " + provisioned 166839b14d460986608fe577f89f789de854dc85b58Jim Miller + ", runningSetupWizard = " + runningSetupWizard); 167839b14d460986608fe577f89f789de854dc85b58Jim Miller } 168839b14d460986608fe577f89f789de854dc85b58Jim Miller return resolveInfo != null && !provisioned && runningSetupWizard; 169af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville } 170af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville} 171