HfaLogic.java revision 00d7a430ac98cd65b7ae3afca5fa9509f1480eda
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 1900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.BroadcastReceiver; 2000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.Context; 2100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.Intent; 2200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.content.IntentFilter; 2300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.os.AsyncResult; 2400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.os.Handler; 2500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.os.Message; 2600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.telephony.ServiceState; 2700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport android.util.Log; 2800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 2900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport com.android.internal.telephony.Phone; 3000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonimport com.google.common.base.Preconditions; 3100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 3200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon/** 3300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Starts and displays status for Hands Free Activation (HFA). 3400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 3500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * This class operates with Hands Free Activation apps. 3600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * It starts by broadcasting the intent com.android.action.START_HFA. 3700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * An HFA app will pick that up and start the HFA process. 3800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * If it fails it return ERROR_HFA Intent and upon success returns COMPLETE_HFA. 3900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 4000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * If successful, we bounce the radio so that the service picks up the new number. 4100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * Once the radio is back on we callback the requestor. 4200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 4300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * If there is an error, we do not bounce the radio but still callback with a failure. 4400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * 4500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon * TODO(klp): We need system-only permissions for the HFA intents. 4600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon */ 4700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordonpublic class HfaLogic { 4800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String TAG = HfaLogic.class.getSimpleName(); 4900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 5000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 5100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_START = "com.android.action.START_HFA"; 5200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_ERROR = "com.android.action.ERROR_HFA"; 5300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_CANCEL = "com.android.action.CANCEL_HFA"; 5400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final String ACTION_COMPLETE = "com.android.action.COMPLETE_HFA"; 5500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 5600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private static final int SERVICE_STATE_CHANGED = 1; 5700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 5800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public static final int NOT_WAITING = 0; 5900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public static final int WAITING_FOR_RADIO_OFF = 1; 6000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public static final int WAITING_FOR_RADIO_ON = 2; 6100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 6200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private int mPhoneMonitorState = NOT_WAITING; 6300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private BroadcastReceiver mReceiver; 6400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private HfaLogicCallback mCallback; 6500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private Context mContext; 6600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 6700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public interface HfaLogicCallback { 6800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void onSuccess(); 6900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void onError(String errorMsg); 7000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 7100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 7200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public HfaLogic(Context context, HfaLogicCallback callback) { 7300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mCallback = Preconditions.checkNotNull(callback); 7400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext = Preconditions.checkNotNull(context); 7500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 7600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 7700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void start() { 7800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon Log.i(TAG, "Start Hfa Provisioning."); 7900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon startHfaIntentReceiver(); 8000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon startProvisioning(); 8100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 8200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 8300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void startProvisioning() { 8400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon sendHfaCommand(ACTION_START); 8500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 8600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 8700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void sendHfaCommand(String action) { 8800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (VERBOSE) Log.v(TAG, "Sending command: " + action); 8900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext.sendBroadcast(new Intent(action)); 9000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 9100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 9200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onHfaError(String errorMsg) { 9300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon stopHfaIntentReceiver(); 9400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mCallback.onError(errorMsg); 9500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 9600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 9700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onHfaSuccess() { 9800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon stopHfaIntentReceiver(); 9900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon bounceRadio(); 10000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 10100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 10200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onTotalSuccess() { 10300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mCallback.onSuccess(); 10400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 10500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 10600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void bounceRadio() { 10700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final Phone phone = PhoneGlobals.getInstance().getPhone(); 10800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null); 10900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 11000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mPhoneMonitorState = WAITING_FOR_RADIO_OFF; 11100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.setRadioPower(false); 11200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onServiceStateChange(phone.getServiceState()); 11300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 11400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 11500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void onServiceStateChange(ServiceState state) { 11600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final boolean radioIsOff = state.getVoiceRegState() == ServiceState.STATE_POWER_OFF; 11700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final Phone phone = PhoneGlobals.getInstance().getPhone(); 11800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 11900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (VERBOSE) Log.v(TAG, "Radio is on: " + !radioIsOff); 12000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 12100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (mPhoneMonitorState == WAITING_FOR_RADIO_OFF) { 12200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (radioIsOff) { 12300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mPhoneMonitorState = WAITING_FOR_RADIO_ON; 12400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.setRadioPower(true); 12500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 12600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } else if (mPhoneMonitorState == WAITING_FOR_RADIO_ON) { 12700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (!radioIsOff) { 12800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mPhoneMonitorState = NOT_WAITING; 12900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon phone.unregisterForServiceStateChanged(mHandler); 13000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 13100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onTotalSuccess(); 13200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 13300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 13400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 13500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 13600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void startHfaIntentReceiver() { 13700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final IntentFilter filter = new IntentFilter(ACTION_COMPLETE); 13800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon filter.addAction(ACTION_ERROR); 13900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 14000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mReceiver = new BroadcastReceiver() { 14100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon @Override 14200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void onReceive(Context context, Intent intent) { 14300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon final String action = intent.getAction(); 14400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (action.equals(ACTION_ERROR)) { 14500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onHfaError(intent.getStringExtra("errorCode")); 14600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } else if (action.equals(ACTION_COMPLETE)) { 14700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (VERBOSE) Log.v(TAG, "Hfa Successful"); 14800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onHfaSuccess(); 14900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 15000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 15100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon }; 15200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 15300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext.registerReceiver(mReceiver, filter); 15400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 15500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 15600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private void stopHfaIntentReceiver() { 15700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon if (mReceiver != null) { 15800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mContext.unregisterReceiver(mReceiver); 15900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon mReceiver = null; 16000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 16100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 16200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 16300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon private Handler mHandler = new Handler() { 16400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon @Override 16500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon public void handleMessage(Message msg) { 16600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon switch (msg.what) { 16700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon case SERVICE_STATE_CHANGED: 16800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 16900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon onServiceStateChange(state); 17000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon break; 17100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon default: 17200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon break; 17300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 17400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon } 17500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon }; 17600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon 17700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon} 178