ProfileService.java revision a08fff0ae81757bdab00ae8865a906c711d5572f
1ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu/* 2ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Copyright (C) 2012 The Android Open Source Project 3ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 4ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Licensed under the Apache License, Version 2.0 (the "License"); 5ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * you may not use this file except in compliance with the License. 6ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * You may obtain a copy of the License at 7ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 8ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * http://www.apache.org/licenses/LICENSE-2.0 9ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * 10ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * Unless required by applicable law or agreed to in writing, software 11ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * distributed under the License is distributed on an "AS IS" BASIS, 12ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * See the License for the specific language governing permissions and 14ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu * limitations under the License. 15ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu */ 16ede67c26e7b2564ea35db6d9b3027a269c150e13Zhihai Xu 17b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpackage com.android.bluetooth.btservice; 18b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 1974ae04c73312403e89db0f8e9bd9601d403b4783fredcimport java.util.HashMap; 2074ae04c73312403e89db0f8e9bd9601d403b4783fredc 2174ae04c73312403e89db0f8e9bd9601d403b4783fredcimport com.android.bluetooth.Utils; 2274ae04c73312403e89db0f8e9bd9601d403b4783fredc 23b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.app.Service; 24b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.bluetooth.BluetoothAdapter; 2574ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.bluetooth.BluetoothDevice; 2674ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.bluetooth.BluetoothProfile; 2774ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.content.Context; 28b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.content.Intent; 29b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.content.pm.PackageManager; 30b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.os.IBinder; 31b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.util.Log; 32b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 33b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpublic abstract class ProfileService extends Service { 34fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie private static final boolean DBG = false; 3574ae04c73312403e89db0f8e9bd9601d403b4783fredc //For Debugging only 3674ae04c73312403e89db0f8e9bd9601d403b4783fredc private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>(); 3774ae04c73312403e89db0f8e9bd9601d403b4783fredc 38b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public static final String BLUETOOTH_ADMIN_PERM = 39b5cc776c9353a203cdde97e62b25f05d9633d14cfredc android.Manifest.permission.BLUETOOTH_ADMIN; 40b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 41a08fff0ae81757bdab00ae8865a906c711d5572fWei Wang public static final String BLUETOOTH_PRIVILEGED = 42a08fff0ae81757bdab00ae8865a906c711d5572fWei Wang android.Manifest.permission.BLUETOOTH_PRIVILEGED; 43b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 4474ae04c73312403e89db0f8e9bd9601d403b4783fredc public static interface IProfileServiceBinder extends IBinder { 4574ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean cleanup(); 4674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 4731ba132491053bc86d419a7d51fc04af3299c076fredc //Profile services will not be automatically restarted. 4831ba132491053bc86d419a7d51fc04af3299c076fredc //They must be explicitly restarted by AdapterService 4931ba132491053bc86d419a7d51fc04af3299c076fredc private static final int PROFILE_SERVICE_MODE=Service.START_NOT_STICKY; 50b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected String mName; 5174ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothAdapter mAdapter; 5274ae04c73312403e89db0f8e9bd9601d403b4783fredc protected IProfileServiceBinder mBinder; 5374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean mStartError=false; 5474ae04c73312403e89db0f8e9bd9601d403b4783fredc private boolean mCleaningUp = false; 55b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 56b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected String getName() { 57b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return getClass().getSimpleName(); 58b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 59b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 6074ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean isAvailable() { 6174ae04c73312403e89db0f8e9bd9601d403b4783fredc return !mStartError && !mCleaningUp; 6274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 6374ae04c73312403e89db0f8e9bd9601d403b4783fredc 6474ae04c73312403e89db0f8e9bd9601d403b4783fredc protected abstract IProfileServiceBinder initBinder(); 65b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean start(); 66b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean stop(); 6774ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 6874ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 6974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 70b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 7174ae04c73312403e89db0f8e9bd9601d403b4783fredc protected ProfileService() { 72b5cc776c9353a203cdde97e62b25f05d9633d14cfredc mName = getName(); 7374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 7474ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 7574ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 7674ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount==null) { 7774ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 1; 7874ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount+1; 8074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 8174ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 820f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount); 8374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 84b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 8531ba132491053bc86d419a7d51fc04af3299c076fredc } 8631ba132491053bc86d419a7d51fc04af3299c076fredc 8774ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void finalize() { 8874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 8974ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 9074ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 9174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount!=null) { 9274ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount-1; 9374ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 9474ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 0; 9574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 9674ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 9774ae04c73312403e89db0f8e9bd9601d403b4783fredc log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount); 98b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 99b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 100b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 101b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 10274ae04c73312403e89db0f8e9bd9601d403b4783fredc @Override 10374ae04c73312403e89db0f8e9bd9601d403b4783fredc public void onCreate() { 1040f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onCreate"); 10574ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onCreate(); 10674ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = BluetoothAdapter.getDefaultAdapter(); 10774ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder = initBinder(); 10874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 10974ae04c73312403e89db0f8e9bd9601d403b4783fredc 11031ba132491053bc86d419a7d51fc04af3299c076fredc public int onStartCommand(Intent intent, int flags, int startId) { 1110f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onStartCommand()"); 112b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (mStartError || mAdapter == null) { 113b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.w(mName, "Stopping profile service: device does not have BT"); 11431ba132491053bc86d419a7d51fc04af3299c076fredc doStop(intent); 11531ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 116b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 117b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 118b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) { 119b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Permission denied!"); 12031ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 121b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 122b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 12331ba132491053bc86d419a7d51fc04af3299c076fredc if (intent == null) { 12431ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Restarting profile service..."); 12531ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 12631ba132491053bc86d419a7d51fc04af3299c076fredc } else { 12731ba132491053bc86d419a7d51fc04af3299c076fredc String action = intent.getStringExtra(AdapterService.EXTRA_ACTION); 12831ba132491053bc86d419a7d51fc04af3299c076fredc if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) { 12931ba132491053bc86d419a7d51fc04af3299c076fredc int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 13031ba132491053bc86d419a7d51fc04af3299c076fredc if(state==BluetoothAdapter.STATE_OFF) { 13131ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Received stop request...Stopping profile..."); 13231ba132491053bc86d419a7d51fc04af3299c076fredc doStop(intent); 13331ba132491053bc86d419a7d51fc04af3299c076fredc } else if (state == BluetoothAdapter.STATE_ON) { 13431ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Received start request. Starting profile..."); 13531ba132491053bc86d419a7d51fc04af3299c076fredc doStart(intent); 13631ba132491053bc86d419a7d51fc04af3299c076fredc } 137b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 138b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 13931ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 140b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 141b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 14274ae04c73312403e89db0f8e9bd9601d403b4783fredc public IBinder onBind(Intent intent) { 1430f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onBind"); 14474ae04c73312403e89db0f8e9bd9601d403b4783fredc return mBinder; 14574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 14674ae04c73312403e89db0f8e9bd9601d403b4783fredc 14774ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean onUnbind(Intent intent) { 1480f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onUnbind"); 14974ae04c73312403e89db0f8e9bd9601d403b4783fredc return super.onUnbind(intent); 15074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 15174ae04c73312403e89db0f8e9bd9601d403b4783fredc 152b5cc776c9353a203cdde97e62b25f05d9633d14cfredc @Override 153b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public void onDestroy() { 1540f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("Destroying service."); 15574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mCleaningUp) { 1560f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("Cleanup already started... Skipping cleanup()..."); 15774ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 1580f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("cleanup()"); 15974ae04c73312403e89db0f8e9bd9601d403b4783fredc mCleaningUp = true; 16074ae04c73312403e89db0f8e9bd9601d403b4783fredc cleanup(); 16174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mBinder != null) { 16274ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder.cleanup(); 16374ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder= null; 16474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16674ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onDestroy(); 16774ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = null; 16874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16974ae04c73312403e89db0f8e9bd9601d403b4783fredc 17074ae04c73312403e89db0f8e9bd9601d403b4783fredc private void doStart(Intent intent) { 17174ae04c73312403e89db0f8e9bd9601d403b4783fredc //Start service 17274ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mAdapter == null) { 17374ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 17474ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 1750f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("start()"); 17674ae04c73312403e89db0f8e9bd9601d403b4783fredc mStartError = !start(); 17774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (!mStartError) { 17874ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON); 17974ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 18074ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 18174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 18274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 183b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 184b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 18531ba132491053bc86d419a7d51fc04af3299c076fredc private void doStop(Intent intent) { 186b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (stop()) { 1870f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("stop()"); 18874ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF); 189b5cc776c9353a203cdde97e62b25f05d9633d14cfredc stopSelf(); 190b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } else { 191b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Unable to stop profile"); 192b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 193b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 194b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 19574ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void notifyProfileServiceStateChanged(int state) { 196b5cc776c9353a203cdde97e62b25f05d9633d14cfredc //Notify adapter service 197b5cc776c9353a203cdde97e62b25f05d9633d14cfredc AdapterService sAdapter = AdapterService.getAdapterService(); 198b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (sAdapter!= null) { 19931ba132491053bc86d419a7d51fc04af3299c076fredc sAdapter.onProfileServiceStateChanged(getClass().getName(), state); 200b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 201b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 202b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 20374ae04c73312403e89db0f8e9bd9601d403b4783fredc public void notifyProfileConnectionStateChanged(BluetoothDevice device, 20474ae04c73312403e89db0f8e9bd9601d403b4783fredc int profileId, int newState, int prevState) { 20574ae04c73312403e89db0f8e9bd9601d403b4783fredc AdapterService svc = AdapterService.getAdapterService(); 20674ae04c73312403e89db0f8e9bd9601d403b4783fredc if (svc != null) { 20774ae04c73312403e89db0f8e9bd9601d403b4783fredc svc.onProfileConnectionStateChanged(device, profileId, newState, prevState); 20874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 20974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 21074ae04c73312403e89db0f8e9bd9601d403b4783fredc 21174ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothDevice getDevice(byte[] address) { 21274ae04c73312403e89db0f8e9bd9601d403b4783fredc return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); 21374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 214b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 215b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected void log(String msg) { 216b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.d(mName, msg); 217b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 218b5cc776c9353a203cdde97e62b25f05d9633d14cfredc} 219