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; 34f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawaimport com.android.internal.telephony.TelephonyCapabilities; 35ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 36af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savilleimport android.util.Log; 37af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 38af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville/* 39839b14d460986608fe577f89f789de854dc85b58Jim Miller * Handles OTA Start procedure at phone power up. At phone power up, if phone is not OTA 40839b14d460986608fe577f89f789de854dc85b58Jim Miller * provisioned (check MIN value of the Phone) and 'device_provisioned' is not set, 41af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville * OTA Activation screen is shown that helps user activate the phone 42af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville */ 43af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Savillepublic class OtaStartupReceiver extends BroadcastReceiver { 44839b14d460986608fe577f89f789de854dc85b58Jim Miller private static final String TAG = "OtaStartupReceiver"; 45c49d1c9004f3151d1cc5f31d6fc617bfc9603267Daisuke Miyakawa private static final boolean DBG = false; 46839b14d460986608fe577f89f789de854dc85b58Jim Miller private static final int MIN_READY = 10; 47ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu private static final int SERVICE_STATE_CHANGED = 11; 48f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman private Context mContext; 49af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 503e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville /** 513e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville * For debug purposes we're listening for otaspChanged events as 523e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville * this may be be used in the future for deciding if OTASP is 533e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville * necessary. 543e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville */ 553e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville private int mOtaspMode = -1; 563e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville private boolean mPhoneStateListenerRegistered = false; 573e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 583e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville @Override 593e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville public void onOtaspChanged(int otaspMode) { 603e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville mOtaspMode = otaspMode; 613e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville Log.v(TAG, "onOtaspChanged: mOtaspMode=" + mOtaspMode); 623e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } 633e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville }; 643e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville 653e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville 66839b14d460986608fe577f89f789de854dc85b58Jim Miller private Handler mHandler = new Handler() { 67f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman @Override 68f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman public void handleMessage(Message msg) { 69f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman switch (msg.what) { 70ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu case MIN_READY: 71ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu Log.v(TAG, "Attempting OtaActivation from handler, mOtaspMode=" + mOtaspMode); 72ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 73ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu break; 74ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu case SERVICE_STATE_CHANGED: { 75ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 76ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (DBG) Log.d(TAG, "onServiceStateChanged()... new state = " + state); 77ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 78ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // Possible service states: 79ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_IN_SERVICE // Normal operation 80ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_OUT_OF_SERVICE // Still searching for an operator to register to, 81ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // // or no radio signal 82ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_EMERGENCY_ONLY // Phone is locked; only emergency numbers are allowed 83ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // - STATE_POWER_OFF // Radio is explicitly powered off (airplane mode) 84ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 85ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // Once we reach STATE_IN_SERVICE 86ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // it's finally OK to start OTA provisioning 87ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (state.getState() == ServiceState.STATE_IN_SERVICE) { 88ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (DBG) Log.d(TAG, "call OtaUtils.maybeDoOtaCall after network is available"); 89a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn Phone phone = PhoneGlobals.getPhone(); 90ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu phone.unregisterForServiceStateChanged(this); 91ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 92ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu } 93ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu break; 94ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu } 95f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 96ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 97f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 98f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman }; 99af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 1003e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville @Override 101f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman public void onReceive(Context context, Intent intent) { 102f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman mContext = context; 1033e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) { 1043e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville Log.v(TAG, "onReceive: intent action=" + intent.getAction() + 1053e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville " mOtaspMode=" + mOtaspMode); 1063e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } 107af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville 108a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn PhoneGlobals globals = PhoneGlobals.getInstanceIfPrimary(); 109a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn if (globals == null) { 110a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn if (DBG) Log.d(TAG, "Not primary user, nothing to do."); 111a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn return; 112a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn } 113a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn 114a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn if (!TelephonyCapabilities.supportsOtasp(PhoneGlobals.getPhone())) { 115d3a8a3a138614071a7a8020e1579048c411abd78Wink Saville if (DBG) Log.d(TAG, "OTASP not supported, nothing to do."); 116f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman return; 117f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 118f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman 1193e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (mPhoneStateListenerRegistered == false) { 1203e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) Log.d(TAG, "Register our PhoneStateListener"); 1213e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService( 1223e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville Context.TELEPHONY_SERVICE); 1233e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_OTASP_CHANGED); 1243e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville mPhoneStateListenerRegistered = true; 1253e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } else { 1263e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) Log.d(TAG, "PhoneStateListener already registered"); 1273e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville } 1283e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville 129839b14d460986608fe577f89f789de854dc85b58Jim Miller if (shouldPostpone(context)) { 130d3a8a3a138614071a7a8020e1579048c411abd78Wink Saville if (DBG) Log.d(TAG, "Postponing OTASP until wizard runs"); 131f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman return; 132f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman } 133f70a0e98ae18491cbd52ce8f6c4e613d4a9afd94Paul Berman 134ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu // Delay OTA provisioning if network is not available yet 135a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn PhoneGlobals app = PhoneGlobals.getInstance(); 136a1a9601840e50e18ff8ca4be9b888e592287577bDianne Hackborn Phone phone = PhoneGlobals.getPhone(); 137ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (app.mCM.getServiceState() != ServiceState.STATE_IN_SERVICE) { 138ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu if (DBG) Log.w(TAG, "Network is not ready. Registering to receive notification."); 139ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null); 140ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu return; 141ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu } 142ff536c7c948593910f19a6476ef4bc218104c5a2Meng Hu 143839b14d460986608fe577f89f789de854dc85b58Jim Miller // The following depends on the phone process being persistent. Normally we can't 144839b14d460986608fe577f89f789de854dc85b58Jim Miller // expect a BroadcastReceiver to persist after returning from this function but it does 145839b14d460986608fe577f89f789de854dc85b58Jim Miller // because the phone activity is persistent. 1463e651fd2b8bc3b43ad2af296e6c720363a3af900Wink Saville if (DBG) Log.d(TAG, "call OtaUtils.maybeDoOtaCall"); 147839b14d460986608fe577f89f789de854dc85b58Jim Miller OtaUtils.maybeDoOtaCall(mContext, mHandler, MIN_READY); 148af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville } 149f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa 150839b14d460986608fe577f89f789de854dc85b58Jim Miller /** 151f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa * On devices that provide a phone initialization wizard (such as Google Setup Wizard), we 152839b14d460986608fe577f89f789de854dc85b58Jim Miller * allow delaying CDMA OTA setup so it can be done in a single wizard. The wizard is responsible 153f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa * for (1) disabling itself once it has been run and/or (2) setting the 'device_provisioned' 154839b14d460986608fe577f89f789de854dc85b58Jim Miller * flag to something non-zero and (3) calling the OTA Setup with the action below. 155f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa * 156839b14d460986608fe577f89f789de854dc85b58Jim Miller * NB: Typical phone initialization wizards will install themselves as the homescreen 157f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa * (category "android.intent.category.HOME") with a priority higher than the default. 158839b14d460986608fe577f89f789de854dc85b58Jim Miller * The wizard should set 'device_provisioned' when it completes, disable itself with the 159839b14d460986608fe577f89f789de854dc85b58Jim Miller * PackageManager.setComponentEnabledSetting() and then start home screen. 160f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa * 161839b14d460986608fe577f89f789de854dc85b58Jim Miller * @return true if setup will be handled by wizard, false if it should be done now. 162839b14d460986608fe577f89f789de854dc85b58Jim Miller */ 163839b14d460986608fe577f89f789de854dc85b58Jim Miller private boolean shouldPostpone(Context context) { 164839b14d460986608fe577f89f789de854dc85b58Jim Miller Intent intent = new Intent("android.intent.action.DEVICE_INITIALIZATION_WIZARD"); 165f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, 166839b14d460986608fe577f89f789de854dc85b58Jim Miller PackageManager.MATCH_DEFAULT_ONLY); 16725add64b1b5553207de50ee993375f4188eacb75Jeff Brown boolean provisioned = Settings.Global.getInt(context.getContentResolver(), 16825add64b1b5553207de50ee993375f4188eacb75Jeff Brown Settings.Global.DEVICE_PROVISIONED, 0) != 0; 169839b14d460986608fe577f89f789de854dc85b58Jim Miller String mode = SystemProperties.get("ro.setupwizard.mode", "REQUIRED"); 170839b14d460986608fe577f89f789de854dc85b58Jim Miller boolean runningSetupWizard = "REQUIRED".equals(mode) || "OPTIONAL".equals(mode); 171839b14d460986608fe577f89f789de854dc85b58Jim Miller if (DBG) { 172f8a9fbe31969b4f97ea03d233684efc117888879Daisuke Miyakawa Log.v(TAG, "resolvInfo = " + resolveInfo + ", provisioned = " + provisioned 173839b14d460986608fe577f89f789de854dc85b58Jim Miller + ", runningSetupWizard = " + runningSetupWizard); 174839b14d460986608fe577f89f789de854dc85b58Jim Miller } 175839b14d460986608fe577f89f789de854dc85b58Jim Miller return resolveInfo != null && !provisioned && runningSetupWizard; 176af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville } 177af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville} 178