blob: 7fd37cfceb5229ee0abe363a073d87443c79b14d [file] [log] [blame]
Santos Cordon00d7a432013-09-17 14:07:14 -07001/*
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}