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
74d6883697c932aa7e9d15e34275dcd3a5df8df071Santos Cordon    // No retry at the moment. Increase later if necessary.
75d6883697c932aa7e9d15e34275dcd3a5df8df071Santos Cordon    private static final int DEFAULT_RETRY_COUNT = 0;
76fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville    private int mRetryCount;
77fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville
7800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    public interface HfaLogicCallback {
7900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        public void onSuccess();
8000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        public void onError(String errorMsg);
8100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
8200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
83cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon    public HfaLogic(Context context, HfaLogicCallback callback, PendingIntent intent) {
8400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mCallback = Preconditions.checkNotNull(callback);
8500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mContext = Preconditions.checkNotNull(context);
86cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon        mResponseIntent = intent;
8700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
8800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
8900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    public void start() {
90fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        Log.i(TAG, "start:");
91fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        mRetryCount = DEFAULT_RETRY_COUNT;
9200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        startHfaIntentReceiver();
9300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        startProvisioning();
9400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
9500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
9600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void startProvisioning() {
97fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        Log.i(TAG, "startProvisioning:");
9800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        sendHfaCommand(ACTION_START);
9900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
10000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
10100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void sendHfaCommand(String action) {
102fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        Log.i(TAG, "sendHfaCommand: command=" + action);
10300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mContext.sendBroadcast(new Intent(action));
10400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
10500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
10600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void onHfaError(String errorMsg) {
107fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        Log.i(TAG, "onHfaError: call mCallBack.onError errorMsg=" + errorMsg
108fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville                + " mRetryCount=" + mRetryCount);
109fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        mRetryCount -= 1;
110fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        if (mRetryCount >= 0) {
111fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            Log.i(TAG, "onHfaError: retry");
112fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            startProvisioning();
113fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        } else {
114fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            Log.i(TAG, "onHfaError: Declare OTASP_FAILURE");
115fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            mRetryCount = 0;
116fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            stopHfaIntentReceiver();
117fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            sendFinalResponse(OTASP_FAILURE, errorMsg);
118fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville            mCallback.onError(errorMsg);
119fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        }
12000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
12100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
12200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void onHfaSuccess() {
123fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        Log.i(TAG, "onHfaSuccess: NOT bouncing radio call onTotalSuccess");
12400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        stopHfaIntentReceiver();
125fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        // bounceRadio();
126fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        onTotalSuccess();
12700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
12800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
12900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void onTotalSuccess() {
130fc57843ecd4eae238d193c9c3e68c0176c17d99dWink Saville        Log.i(TAG, "onTotalSuccess: call mCallBack.onSuccess");
131cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon        sendFinalResponse(OTASP_SUCCESS, null);
13200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mCallback.onSuccess();
13300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
13400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
13500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void bounceRadio() {
13600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        final Phone phone = PhoneGlobals.getInstance().getPhone();
13700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);
13800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
13900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mPhoneMonitorState = WAITING_FOR_RADIO_OFF;
14000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        phone.setRadioPower(false);
14100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        onServiceStateChange(phone.getServiceState());
14200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
14300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
14400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void onServiceStateChange(ServiceState state) {
14500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        final boolean radioIsOff = state.getVoiceRegState() == ServiceState.STATE_POWER_OFF;
14600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        final Phone phone = PhoneGlobals.getInstance().getPhone();
14700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
148cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon        Log.i(TAG, "Radio is on: " + !radioIsOff);
14900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
15000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        if (mPhoneMonitorState == WAITING_FOR_RADIO_OFF) {
15100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            if (radioIsOff) {
15200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                mPhoneMonitorState = WAITING_FOR_RADIO_ON;
15300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                phone.setRadioPower(true);
15400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            }
15500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        } else if (mPhoneMonitorState == WAITING_FOR_RADIO_ON) {
15600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            if (!radioIsOff) {
15700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                mPhoneMonitorState = NOT_WAITING;
15800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                phone.unregisterForServiceStateChanged(mHandler);
15900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
16000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                onTotalSuccess();
16100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            }
16200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        }
16300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
16400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
16500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void startHfaIntentReceiver() {
16600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        final IntentFilter filter = new IntentFilter(ACTION_COMPLETE);
16700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        filter.addAction(ACTION_ERROR);
16800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
16900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mReceiver = new BroadcastReceiver() {
17000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            @Override
17100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            public void onReceive(Context context, Intent intent) {
17200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                final String action = intent.getAction();
17300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                if (action.equals(ACTION_ERROR)) {
17400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                    onHfaError(intent.getStringExtra("errorCode"));
17500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                } else if (action.equals(ACTION_COMPLETE)) {
176cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon                    Log.i(TAG, "Hfa Successful");
17700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                    onHfaSuccess();
17800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                }
17900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            }
18000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        };
18100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
18200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        mContext.registerReceiver(mReceiver, filter);
18300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
18400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
18500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private void stopHfaIntentReceiver() {
18600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        if (mReceiver != null) {
18700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            mContext.unregisterReceiver(mReceiver);
18800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            mReceiver = null;
18900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        }
19000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    }
19100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
192cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon    private void sendFinalResponse(int responseCode, String errorCode) {
193cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon        if (mResponseIntent != null) {
194cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            final Intent extraStuff = new Intent();
195cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            extraStuff.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE, responseCode);
196cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon
197cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            if (responseCode == OTASP_FAILURE && errorCode != null) {
198cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon                extraStuff.putExtra(OtaUtils.EXTRA_OTASP_ERROR_CODE, errorCode);
199cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            }
200cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon
201cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            try {
202cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon                Log.i(TAG, "Sending OTASP confirmation with result code: "
203cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon                        + responseCode);
204cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon                mResponseIntent.send(mContext, 0 /* resultCode (not used) */, extraStuff);
205cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            } catch (CanceledException e) {
206cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon                Log.e(TAG, "Pending Intent canceled");
207cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon            }
208cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon        }
209cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon    }
210cd76f8b160e0e4b2e5ccf34c0c5e1e58a0bb8b72Santos Cordon
21100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    private Handler mHandler = new Handler() {
21200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        @Override
21300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        public void handleMessage(Message msg) {
21400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            switch (msg.what) {
21500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                case SERVICE_STATE_CHANGED:
21600d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                    ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result;
21700d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                    onServiceStateChange(state);
21800d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                    break;
21900d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                default:
22000d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon                    break;
22100d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon            }
22200d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon        }
22300d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon    };
22400d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon
22500d7a430ac98cd65b7ae3afca5fa9509f1480edaSantos Cordon}
226