HfaLogic.java revision 00d7a430ac98cd65b7ae3afca5fa9509f1480eda
1/* 2 * Copyright (C) 2013 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 17package com.android.phone; 18 19import android.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.os.AsyncResult; 24import android.os.Handler; 25import android.os.Message; 26import android.telephony.ServiceState; 27import android.util.Log; 28 29import com.android.internal.telephony.Phone; 30import com.google.common.base.Preconditions; 31 32/** 33 * Starts and displays status for Hands Free Activation (HFA). 34 * 35 * This class operates with Hands Free Activation apps. 36 * It starts by broadcasting the intent com.android.action.START_HFA. 37 * An HFA app will pick that up and start the HFA process. 38 * If it fails it return ERROR_HFA Intent and upon success returns COMPLETE_HFA. 39 * 40 * If successful, we bounce the radio so that the service picks up the new number. 41 * Once the radio is back on we callback the requestor. 42 * 43 * If there is an error, we do not bounce the radio but still callback with a failure. 44 * 45 * TODO(klp): We need system-only permissions for the HFA intents. 46 */ 47public class HfaLogic { 48 private static final String TAG = HfaLogic.class.getSimpleName(); 49 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 50 51 private static final String ACTION_START = "com.android.action.START_HFA"; 52 private static final String ACTION_ERROR = "com.android.action.ERROR_HFA"; 53 private static final String ACTION_CANCEL = "com.android.action.CANCEL_HFA"; 54 private static final String ACTION_COMPLETE = "com.android.action.COMPLETE_HFA"; 55 56 private static final int SERVICE_STATE_CHANGED = 1; 57 58 public static final int NOT_WAITING = 0; 59 public static final int WAITING_FOR_RADIO_OFF = 1; 60 public static final int WAITING_FOR_RADIO_ON = 2; 61 62 private int mPhoneMonitorState = NOT_WAITING; 63 private BroadcastReceiver mReceiver; 64 private HfaLogicCallback mCallback; 65 private Context mContext; 66 67 public interface HfaLogicCallback { 68 public void onSuccess(); 69 public void onError(String errorMsg); 70 } 71 72 public HfaLogic(Context context, HfaLogicCallback callback) { 73 mCallback = Preconditions.checkNotNull(callback); 74 mContext = Preconditions.checkNotNull(context); 75 } 76 77 public void start() { 78 Log.i(TAG, "Start Hfa Provisioning."); 79 startHfaIntentReceiver(); 80 startProvisioning(); 81 } 82 83 private void startProvisioning() { 84 sendHfaCommand(ACTION_START); 85 } 86 87 private void sendHfaCommand(String action) { 88 if (VERBOSE) Log.v(TAG, "Sending command: " + action); 89 mContext.sendBroadcast(new Intent(action)); 90 } 91 92 private void onHfaError(String errorMsg) { 93 stopHfaIntentReceiver(); 94 mCallback.onError(errorMsg); 95 } 96 97 private void onHfaSuccess() { 98 stopHfaIntentReceiver(); 99 bounceRadio(); 100 } 101 102 private void onTotalSuccess() { 103 mCallback.onSuccess(); 104 } 105 106 private void bounceRadio() { 107 final Phone phone = PhoneGlobals.getInstance().getPhone(); 108 phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null); 109 110 mPhoneMonitorState = WAITING_FOR_RADIO_OFF; 111 phone.setRadioPower(false); 112 onServiceStateChange(phone.getServiceState()); 113 } 114 115 private void onServiceStateChange(ServiceState state) { 116 final boolean radioIsOff = state.getVoiceRegState() == ServiceState.STATE_POWER_OFF; 117 final Phone phone = PhoneGlobals.getInstance().getPhone(); 118 119 if (VERBOSE) Log.v(TAG, "Radio is on: " + !radioIsOff); 120 121 if (mPhoneMonitorState == WAITING_FOR_RADIO_OFF) { 122 if (radioIsOff) { 123 mPhoneMonitorState = WAITING_FOR_RADIO_ON; 124 phone.setRadioPower(true); 125 } 126 } else if (mPhoneMonitorState == WAITING_FOR_RADIO_ON) { 127 if (!radioIsOff) { 128 mPhoneMonitorState = NOT_WAITING; 129 phone.unregisterForServiceStateChanged(mHandler); 130 131 onTotalSuccess(); 132 } 133 } 134 } 135 136 private void startHfaIntentReceiver() { 137 final IntentFilter filter = new IntentFilter(ACTION_COMPLETE); 138 filter.addAction(ACTION_ERROR); 139 140 mReceiver = new BroadcastReceiver() { 141 @Override 142 public void onReceive(Context context, Intent intent) { 143 final String action = intent.getAction(); 144 if (action.equals(ACTION_ERROR)) { 145 onHfaError(intent.getStringExtra("errorCode")); 146 } else if (action.equals(ACTION_COMPLETE)) { 147 if (VERBOSE) Log.v(TAG, "Hfa Successful"); 148 onHfaSuccess(); 149 } 150 } 151 }; 152 153 mContext.registerReceiver(mReceiver, filter); 154 } 155 156 private void stopHfaIntentReceiver() { 157 if (mReceiver != null) { 158 mContext.unregisterReceiver(mReceiver); 159 mReceiver = null; 160 } 161 } 162 163 private Handler mHandler = new Handler() { 164 @Override 165 public void handleMessage(Message msg) { 166 switch (msg.what) { 167 case SERVICE_STATE_CHANGED: 168 ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 169 onServiceStateChange(state); 170 break; 171 default: 172 break; 173 } 174 } 175 }; 176 177} 178