100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon/* 200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Copyright (C) 2013 The Android Open Source Project 300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License"); 500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * you may not use this file except in compliance with the License. 600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * You may obtain a copy of the License at 700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * http://www.apache.org/licenses/LICENSE-2.0 900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 1000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Unless required by applicable law or agreed to in writing, software 1100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS, 1200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * See the License for the specific language governing permissions and 1400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * limitations under the License. 1500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon */ 1600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 1700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonpackage com.android.phone; 1800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 19cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordonimport android.app.PendingIntent; 20cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordonimport android.app.PendingIntent.CanceledException; 2100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.BroadcastReceiver; 2200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.Context; 2300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.Intent; 2400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.IntentFilter; 2500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.os.AsyncResult; 2600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.os.Handler; 2700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.os.Message; 2800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.telephony.ServiceState; 2900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.util.Log; 3000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 3100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport com.android.internal.telephony.Phone; 3200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport com.google.common.base.Preconditions; 3300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 3400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon/** 3500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Starts and displays status for Hands Free Activation (HFA). 3600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 3700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * This class operates with Hands Free Activation apps. 3800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * It starts by broadcasting the intent com.android.action.START_HFA. 3900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * An HFA app will pick that up and start the HFA process. 4000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * If it fails it return ERROR_HFA Intent and upon success returns COMPLETE_HFA. 4100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 4200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * If successful, we bounce the radio so that the service picks up the new number. 4300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Once the radio is back on we callback the requestor. 4400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 4500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * If there is an error, we do not bounce the radio but still callback with a failure. 4600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 4700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * TODO(klp): We need system-only permissions for the HFA intents. 4800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon */ 4900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonpublic class HfaLogic { 5000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String TAG = HfaLogic.class.getSimpleName(); 5100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 5200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_START = "com.android.action.START_HFA"; 5300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_ERROR = "com.android.action.ERROR_HFA"; 5400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_CANCEL = "com.android.action.CANCEL_HFA"; 5500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_COMPLETE = "com.android.action.COMPLETE_HFA"; 5600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 5700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final int SERVICE_STATE_CHANGED = 1; 5800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 5900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public static final int NOT_WAITING = 0; 6000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public static final int WAITING_FOR_RADIO_OFF = 1; 6100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public static final int WAITING_FOR_RADIO_ON = 2; 6200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 63cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon public static final int OTASP_UNKNOWN = 0; 64cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon public static final int OTASP_USER_SKIPPED = 1; 65cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon public static final int OTASP_SUCCESS = 2; 66cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon public static final int OTASP_FAILURE = 3; 67cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon 6800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private int mPhoneMonitorState = NOT_WAITING; 6900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private BroadcastReceiver mReceiver; 7000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private HfaLogicCallback mCallback; 71cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon private PendingIntent mResponseIntent; 7200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private Context mContext; 7300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 74fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville private static final int DEFAULT_RETRY_COUNT = 1; 75fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville private int mRetryCount; 76fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville 7700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public interface HfaLogicCallback { 7800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void onSuccess(); 7900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void onError(String errorMsg); 8000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 8100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 82cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon public HfaLogic(Context context, HfaLogicCallback callback, PendingIntent intent) { 8300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mCallback = Preconditions.checkNotNull(callback); 8400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext = Preconditions.checkNotNull(context); 85cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon mResponseIntent = intent; 8600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 8700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 8800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void start() { 89fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "start:"); 90fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville mRetryCount = DEFAULT_RETRY_COUNT; 9100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon startHfaIntentReceiver(); 9200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon startProvisioning(); 9300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 9400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 9500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void startProvisioning() { 96fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "startProvisioning:"); 9700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon sendHfaCommand(ACTION_START); 9800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 9900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 10000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void sendHfaCommand(String action) { 101fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "sendHfaCommand: command=" + action); 10200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext.sendBroadcast(new Intent(action)); 10300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 10400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 10500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onHfaError(String errorMsg) { 106fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "onHfaError: call mCallBack.onError errorMsg=" + errorMsg 107fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville + " mRetryCount=" + mRetryCount); 108fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville mRetryCount -= 1; 109fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville if (mRetryCount >= 0) { 110fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "onHfaError: retry"); 111fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville startProvisioning(); 112fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville } else { 113fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "onHfaError: Declare OTASP_FAILURE"); 114fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville mRetryCount = 0; 115fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville stopHfaIntentReceiver(); 116fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville sendFinalResponse(OTASP_FAILURE, errorMsg); 117fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville mCallback.onError(errorMsg); 118fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville } 11900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 12000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 12100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onHfaSuccess() { 122fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "onHfaSuccess: NOT bouncing radio call onTotalSuccess"); 12300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon stopHfaIntentReceiver(); 124fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville // bounceRadio(); 125fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville onTotalSuccess(); 12600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 12700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 12800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onTotalSuccess() { 129fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville Log.i(TAG, "onTotalSuccess: call mCallBack.onSuccess"); 130cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon sendFinalResponse(OTASP_SUCCESS, null); 13100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mCallback.onSuccess(); 13200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 13300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 13400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void bounceRadio() { 13500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final Phone phone = PhoneGlobals.getInstance().getPhone(); 13600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null); 13700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 13800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mPhoneMonitorState = WAITING_FOR_RADIO_OFF; 13900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.setRadioPower(false); 14000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onServiceStateChange(phone.getServiceState()); 14100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 14200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 14300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onServiceStateChange(ServiceState state) { 14400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final boolean radioIsOff = state.getVoiceRegState() == ServiceState.STATE_POWER_OFF; 14500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final Phone phone = PhoneGlobals.getInstance().getPhone(); 14600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 147cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon Log.i(TAG, "Radio is on: " + !radioIsOff); 14800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 14900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (mPhoneMonitorState == WAITING_FOR_RADIO_OFF) { 15000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (radioIsOff) { 15100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mPhoneMonitorState = WAITING_FOR_RADIO_ON; 15200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.setRadioPower(true); 15300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 15400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } else if (mPhoneMonitorState == WAITING_FOR_RADIO_ON) { 15500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (!radioIsOff) { 15600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mPhoneMonitorState = NOT_WAITING; 15700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.unregisterForServiceStateChanged(mHandler); 15800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 15900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onTotalSuccess(); 16000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 16100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 16200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 16300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 16400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void startHfaIntentReceiver() { 16500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final IntentFilter filter = new IntentFilter(ACTION_COMPLETE); 16600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon filter.addAction(ACTION_ERROR); 16700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 16800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mReceiver = new BroadcastReceiver() { 16900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon @Override 17000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void onReceive(Context context, Intent intent) { 17100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final String action = intent.getAction(); 17200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (action.equals(ACTION_ERROR)) { 17300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onHfaError(intent.getStringExtra("errorCode")); 17400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } else if (action.equals(ACTION_COMPLETE)) { 175cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon Log.i(TAG, "Hfa Successful"); 17600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onHfaSuccess(); 17700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 17800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 17900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon }; 18000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 18100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext.registerReceiver(mReceiver, filter); 18200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 18300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 18400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void stopHfaIntentReceiver() { 18500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (mReceiver != null) { 18600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext.unregisterReceiver(mReceiver); 18700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mReceiver = null; 18800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 18900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 19000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 191cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon private void sendFinalResponse(int responseCode, String errorCode) { 192cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon if (mResponseIntent != null) { 193cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon final Intent extraStuff = new Intent(); 194cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon extraStuff.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE, responseCode); 195cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon 196cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon if (responseCode == OTASP_FAILURE && errorCode != null) { 197cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon extraStuff.putExtra(OtaUtils.EXTRA_OTASP_ERROR_CODE, errorCode); 198cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon } 199cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon 200cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon try { 201cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon Log.i(TAG, "Sending OTASP confirmation with result code: " 202cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon + responseCode); 203cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon mResponseIntent.send(mContext, 0 /* resultCode (not used) */, extraStuff); 204cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon } catch (CanceledException e) { 205cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon Log.e(TAG, "Pending Intent canceled"); 206cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon } 207cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon } 208cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon } 209cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon 21000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private Handler mHandler = new Handler() { 21100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon @Override 21200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void handleMessage(Message msg) { 21300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon switch (msg.what) { 21400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon case SERVICE_STATE_CHANGED: 21500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 21600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onServiceStateChange(state); 21700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon break; 21800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon default: 21900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon break; 22000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 22100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 22200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon }; 22300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 22400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon} 225