10217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan/* 20217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * Copyright (C) 2017 The Android Open Source Project 30217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * 40217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * Licensed under the Apache License, Version 2.0 (the "License"); 50217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * you may not use this file except in compliance with the License. 60217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * You may obtain a copy of the License at 70217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * 80217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * http://www.apache.org/licenses/LICENSE-2.0 90217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * 100217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * Unless required by applicable law or agreed to in writing, software 110217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * distributed under the License is distributed on an "AS IS" BASIS, 120217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * See the License for the specific language governing permissions and 140217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * limitations under the License. 150217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan */ 160217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 170217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanpackage com.android.car.messenger; 180217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 190217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.app.Service; 200217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.bluetooth.BluetoothAdapter; 210217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.bluetooth.BluetoothDevice; 220217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.bluetooth.BluetoothMapClient; 230217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.bluetooth.BluetoothProfile; 240217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.content.BroadcastReceiver; 250217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.content.Context; 260217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.content.Intent; 270217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.content.IntentFilter; 2860060c1692a932c32d5449443c477a53d5112884roger xueimport android.os.Binder; 290217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.os.IBinder; 300217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.util.Log; 310217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanimport android.widget.Toast; 320217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 330217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan/** 340217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * Background started service that hosts messaging components. 350217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * <p> 360217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * The MapConnector manages connecting to the BT MAP service and the MapMessageMonitor listens for 370217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * new incoming messages and publishes notifications. Actions in the notifications trigger command 380217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * intents to this service (e.g. auto-reply, play message). 390217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * <p> 400217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan * This service and its helper components run entirely in the main thread. 410217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan */ 420217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathanpublic class MessengerService extends Service { 430217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String TAG = "MessengerService"; 440217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); 450217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 460217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Used to start this service at boot-complete. Takes no arguments. 470217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String ACTION_START = "com.android.car.messenger.ACTION_START"; 480217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Used to auto-reply to messages from a sender (invoked from Notification). 490217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String ACTION_AUTO_REPLY = "com.android.car.messenger.ACTION_AUTO_REPLY"; 500217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Used to play-out messages from a sender (invoked from Notification). 510217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String ACTION_PLAY_MESSAGES = "com.android.car.messenger.ACTION_PLAY_MESSAGES"; 524a5024d82db356bc7c6e0848c80f4f0d7e213a0eSrinivas Visvanathan // Used to stop further audio notifications from the conversation. 534a5024d82db356bc7c6e0848c80f4f0d7e213a0eSrinivas Visvanathan static final String ACTION_MUTE_CONVERSATION = 544a5024d82db356bc7c6e0848c80f4f0d7e213a0eSrinivas Visvanathan "com.android.car.messenger.ACTION_MUTE_CONVERSATION"; 551d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue // Used to resume further audio notifications from the conversation. 561d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue static final String ACTION_UNMUTE_CONVERSATION = 571d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue "com.android.car.messenger.ACTION_UNMUTE_CONVERSATION"; 580217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Used to clear notification state when user dismisses notification. 590217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String ACTION_CLEAR_NOTIFICATION_STATE = 600217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan "com.android.car.messenger.ACTION_CLEAR_NOTIFICATION_STATE"; 610217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Used to stop current play-out (invoked from Notification). 620217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String ACTION_STOP_PLAYOUT = "com.android.car.messenger.ACTION_STOP_PLAYOUT"; 630217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 640217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Common extra for ACTION_AUTO_REPLY and ACTION_PLAY_MESSAGES. 650217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan static final String EXTRA_SENDER_KEY = "com.android.car.messenger.EXTRA_SENDER_KEY"; 660217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 67dc905655368f1847bd63e823804ce611086cc487Lujiang Xue static final String EXTRA_REPLY_MESSAGE = "com.android.car.messenger.EXTRA_REPLY_MESSAGE"; 68dc905655368f1847bd63e823804ce611086cc487Lujiang Xue 6960060c1692a932c32d5449443c477a53d5112884roger xue // Used to notify that this service started to play out the messages. 7060060c1692a932c32d5449443c477a53d5112884roger xue static final String ACTION_PLAY_MESSAGES_STARTED = 7160060c1692a932c32d5449443c477a53d5112884roger xue "com.android.car.messenger.ACTION_PLAY_MESSAGES_STARTED"; 7260060c1692a932c32d5449443c477a53d5112884roger xue 7360060c1692a932c32d5449443c477a53d5112884roger xue // Used to notify that this service finished playing out the messages. 7460060c1692a932c32d5449443c477a53d5112884roger xue static final String ACTION_PLAY_MESSAGES_STOPPED = 7560060c1692a932c32d5449443c477a53d5112884roger xue "com.android.car.messenger.ACTION_PLAY_MESSAGES_STOPPED"; 7660060c1692a932c32d5449443c477a53d5112884roger xue 770217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private MapMessageMonitor mMessageMonitor; 780217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private MapDeviceMonitor mDeviceMonitor; 790217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private BluetoothMapClient mMapClient; 8060060c1692a932c32d5449443c477a53d5112884roger xue private final IBinder mBinder = new LocalBinder(); 8160060c1692a932c32d5449443c477a53d5112884roger xue 8260060c1692a932c32d5449443c477a53d5112884roger xue public class LocalBinder extends Binder { 8360060c1692a932c32d5449443c477a53d5112884roger xue MessengerService getService() { 8460060c1692a932c32d5449443c477a53d5112884roger xue return MessengerService.this; 8560060c1692a932c32d5449443c477a53d5112884roger xue } 8660060c1692a932c32d5449443c477a53d5112884roger xue } 870217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 880217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 890217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public void onCreate() { 900217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (DBG) { 910217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "onCreate"); 920217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 930217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 940217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor = new MapMessageMonitor(this); 950217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mDeviceMonitor = new MapDeviceMonitor(); 960217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan connectToMap(); 970217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 980217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 990217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private void connectToMap() { 1000217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (DBG) { 1010217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "Connecting to MAP service"); 1020217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1030217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 1040217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (adapter == null) { 1050217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // This *should* never happen. Unless there's some severe internal error? 1060217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.wtf(TAG, "BluetoothAdapter is null! Internal error?"); 1070217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return; 1080217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1090217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 1100217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (!adapter.getProfileProxy(this, mMapServiceListener, BluetoothProfile.MAP_CLIENT)) { 1110217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // This *should* never happen. Unless arguments passed are incorrect somehow... 1120217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.wtf(TAG, "Unable to get MAP profile! Possible programmer error?"); 1130217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return; 1140217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1150217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1160217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 1170217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 1180217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public int onStartCommand(Intent intent, int flags, int startId) { 1190217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (DBG) { 1206f316f0069b6b8f162fd67b0b042a6c3676227d9Srinivas Visvanathan Log.d(TAG, "Handling intent: " + intent); 1210217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1220217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 1230217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Service will be restarted even if its killed/dies. It will never stop itself. 1240217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // It may be restarted with null intent or one of the other intents e.g. REPLY, PLAY etc. 1250217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan final int result = START_STICKY; 1260217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 1270217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (intent == null || ACTION_START.equals(intent.getAction())) { 1280217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // These are NO-OP's since they're just used to bring up this service. 1290217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return result; 1300217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1310217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 1320217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (!hasRequiredArgs(intent)) { 1330217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return result; 1340217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1350217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan switch (intent.getAction()) { 1360217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_AUTO_REPLY: 13722bc7d8f0b1a18737e951ff3352c089670cc7ab3Srinivas Visvanathan boolean success; 1380217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (mMapClient != null) { 13922bc7d8f0b1a18737e951ff3352c089670cc7ab3Srinivas Visvanathan success = mMessageMonitor.sendAutoReply( 140dc905655368f1847bd63e823804ce611086cc487Lujiang Xue intent.getParcelableExtra(EXTRA_SENDER_KEY), 141dc905655368f1847bd63e823804ce611086cc487Lujiang Xue mMapClient, 142dc905655368f1847bd63e823804ce611086cc487Lujiang Xue intent.getStringExtra(EXTRA_REPLY_MESSAGE)); 1430217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } else { 1440217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.e(TAG, "Unable to send reply; MAP profile disconnected!"); 14522bc7d8f0b1a18737e951ff3352c089670cc7ab3Srinivas Visvanathan success = false; 1460217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 14722bc7d8f0b1a18737e951ff3352c089670cc7ab3Srinivas Visvanathan if (!success) { 1480217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Toast.makeText(this, R.string.auto_reply_failed_message, Toast.LENGTH_SHORT) 1490217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan .show(); 1500217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1510217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan break; 1520217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_PLAY_MESSAGES: 1530217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor.playMessages(intent.getParcelableExtra(EXTRA_SENDER_KEY)); 1540217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan break; 1554a5024d82db356bc7c6e0848c80f4f0d7e213a0eSrinivas Visvanathan case ACTION_MUTE_CONVERSATION: 1561d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue mMessageMonitor.toggleMuteConversation( 1571d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue intent.getParcelableExtra(EXTRA_SENDER_KEY), true); 1581d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue break; 1591d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue case ACTION_UNMUTE_CONVERSATION: 1601d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue mMessageMonitor.toggleMuteConversation( 1611d3c7eb3eb086dcb452f492867e30121535a9465Lujiang Xue intent.getParcelableExtra(EXTRA_SENDER_KEY), false); 1624a5024d82db356bc7c6e0848c80f4f0d7e213a0eSrinivas Visvanathan break; 1630217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_STOP_PLAYOUT: 1640217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor.stopPlayout(); 1650217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan break; 1660217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_CLEAR_NOTIFICATION_STATE: 1670217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor.clearNotificationState(intent.getParcelableExtra(EXTRA_SENDER_KEY)); 1680217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan break; 1690217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan default: 1700217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.e(TAG, "Ignoring unknown intent: " + intent.getAction()); 1710217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1720217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return result; 1730217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1740217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 17560060c1692a932c32d5449443c477a53d5112884roger xue /** 17660060c1692a932c32d5449443c477a53d5112884roger xue * @return {code true} if the service is playing the TTS of the message. 17760060c1692a932c32d5449443c477a53d5112884roger xue */ 17860060c1692a932c32d5449443c477a53d5112884roger xue public boolean isPlaying() { 17960060c1692a932c32d5449443c477a53d5112884roger xue return mMessageMonitor.isPlaying(); 18060060c1692a932c32d5449443c477a53d5112884roger xue } 18160060c1692a932c32d5449443c477a53d5112884roger xue 1820217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private boolean hasRequiredArgs(Intent intent) { 1830217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan switch (intent.getAction()) { 1840217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_AUTO_REPLY: 1850217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_PLAY_MESSAGES: 1864a5024d82db356bc7c6e0848c80f4f0d7e213a0eSrinivas Visvanathan case ACTION_MUTE_CONVERSATION: 1870217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_CLEAR_NOTIFICATION_STATE: 1880217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (!intent.hasExtra(EXTRA_SENDER_KEY)) { 1890217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.w(TAG, "Intent is missing sender-key extra: " + intent.getAction()); 1900217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return false; 1910217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 1920217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return true; 1930217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan case ACTION_STOP_PLAYOUT: 1940217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // No args. 1950217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return true; 1960217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan default: 1970217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // For unknown actions, default to true. We'll report error on these later. 1980217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return true; 1990217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2000217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2010217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2020217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 2030217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public void onDestroy() { 2040217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (DBG) { 2050217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "onDestroy"); 2060217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2070217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (mMapClient != null) { 2080217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMapClient.close(); 2090217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2100217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mDeviceMonitor.cleanup(); 2110217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor.cleanup(); 2120217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2130217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2140217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 2150217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public IBinder onBind(Intent intent) { 21660060c1692a932c32d5449443c477a53d5112884roger xue return mBinder; 2170217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2180217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2190217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // NOTE: These callbacks are invoked on the main thread. 2200217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private final BluetoothProfile.ServiceListener mMapServiceListener = 2210217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan new BluetoothProfile.ServiceListener() { 2220217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 2230217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public void onServiceConnected(int profile, BluetoothProfile proxy) { 2240217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMapClient = (BluetoothMapClient) proxy; 2250217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (MessengerService.DBG) { 2260217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "Connected to MAP service!"); 2270217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2280217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2290217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // Since we're connected, we will received broadcasts for any new messages 2300217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan // in the MapMessageMonitor. 2310217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2320217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2330217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 2340217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public void onServiceDisconnected(int profile) { 2350217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (MessengerService.DBG) { 2360217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "Disconnected from MAP service!"); 2370217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2380217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMapClient = null; 2390217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor.handleMapDisconnect(); 2400217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2410217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan }; 2420217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2430217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan private class MapDeviceMonitor extends BroadcastReceiver { 2440217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan MapDeviceMonitor() { 2450217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (DBG) { 2460217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "Registering Map device monitor"); 2470217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2480217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan IntentFilter intentFilter = new IntentFilter(); 2490217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan intentFilter.addAction(BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED); 2500217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan registerReceiver(this, intentFilter, android.Manifest.permission.BLUETOOTH, null); 2510217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2520217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2530217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan void cleanup() { 2540217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan unregisterReceiver(this); 2550217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2560217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan 2570217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan @Override 2580217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan public void onReceive(Context context, Intent intent) { 2590217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 2600217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan int previousState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, -1); 2610217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 2620217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (state == -1 || previousState == -1 || device == null) { 2630217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.w(TAG, "Skipping broadcast, missing required extra"); 2640217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan return; 2650217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2660217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (previousState == BluetoothProfile.STATE_CONNECTED 2670217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan && state != BluetoothProfile.STATE_CONNECTED) { 2680217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan if (DBG) { 2690217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan Log.d(TAG, "Device losing MAP connection: " + device); 2700217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2710217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan mMessageMonitor.handleDeviceDisconnect(device); 2720217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2730217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2740217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan } 2750217b09b25c8a2cb0408790979eff327aec42d45Srinivas Visvanathan} 276