ProfileService.java revision fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5
1b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpackage com.android.bluetooth.btservice; 2b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 374ae04c73312403e89db0f8e9bd9601d403b4783fredcimport java.util.HashMap; 474ae04c73312403e89db0f8e9bd9601d403b4783fredc 574ae04c73312403e89db0f8e9bd9601d403b4783fredcimport com.android.bluetooth.Utils; 674ae04c73312403e89db0f8e9bd9601d403b4783fredc 7b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.app.Service; 8b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.bluetooth.BluetoothAdapter; 974ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.bluetooth.BluetoothDevice; 1074ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.bluetooth.BluetoothProfile; 1174ae04c73312403e89db0f8e9bd9601d403b4783fredcimport android.content.Context; 12b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.content.Intent; 13b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.content.pm.PackageManager; 14b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.os.IBinder; 15b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.util.Log; 16b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 17b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpublic abstract class ProfileService extends Service { 18fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie private static final boolean DBG = false; 1974ae04c73312403e89db0f8e9bd9601d403b4783fredc //For Debugging only 2074ae04c73312403e89db0f8e9bd9601d403b4783fredc private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>(); 2174ae04c73312403e89db0f8e9bd9601d403b4783fredc 22b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public static final String BLUETOOTH_ADMIN_PERM = 23b5cc776c9353a203cdde97e62b25f05d9633d14cfredc android.Manifest.permission.BLUETOOTH_ADMIN; 24b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 25b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 2674ae04c73312403e89db0f8e9bd9601d403b4783fredc public static interface IProfileServiceBinder extends IBinder { 2774ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean cleanup(); 2874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 2931ba132491053bc86d419a7d51fc04af3299c076fredc //Profile services will not be automatically restarted. 3031ba132491053bc86d419a7d51fc04af3299c076fredc //They must be explicitly restarted by AdapterService 3131ba132491053bc86d419a7d51fc04af3299c076fredc private static final int PROFILE_SERVICE_MODE=Service.START_NOT_STICKY; 32b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected String mName; 3374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothAdapter mAdapter; 3474ae04c73312403e89db0f8e9bd9601d403b4783fredc protected IProfileServiceBinder mBinder; 3574ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean mStartError=false; 3674ae04c73312403e89db0f8e9bd9601d403b4783fredc private boolean mCleaningUp = false; 37b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 38b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected String getName() { 39b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return getClass().getSimpleName(); 40b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 41b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 4274ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean isAvailable() { 4374ae04c73312403e89db0f8e9bd9601d403b4783fredc return !mStartError && !mCleaningUp; 4474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 4574ae04c73312403e89db0f8e9bd9601d403b4783fredc 4674ae04c73312403e89db0f8e9bd9601d403b4783fredc protected abstract IProfileServiceBinder initBinder(); 47b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean start(); 48b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean stop(); 4974ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 5074ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 5174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 52b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 5374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected ProfileService() { 54b5cc776c9353a203cdde97e62b25f05d9633d14cfredc mName = getName(); 5574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 5674ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 5774ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 5874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount==null) { 5974ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 1; 6074ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 6174ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount+1; 6274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 6374ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 6474ae04c73312403e89db0f8e9bd9601d403b4783fredc log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount); 6574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 66b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 6731ba132491053bc86d419a7d51fc04af3299c076fredc } 6831ba132491053bc86d419a7d51fc04af3299c076fredc 6974ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void finalize() { 7074ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 7174ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 7274ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 7374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount!=null) { 7474ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount-1; 7574ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 7674ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 0; 7774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 7874ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount); 80b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 81b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 82b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 83b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 8474ae04c73312403e89db0f8e9bd9601d403b4783fredc @Override 8574ae04c73312403e89db0f8e9bd9601d403b4783fredc public void onCreate() { 8674ae04c73312403e89db0f8e9bd9601d403b4783fredc log("onCreate"); 8774ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onCreate(); 8874ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = BluetoothAdapter.getDefaultAdapter(); 8974ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder = initBinder(); 9074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 9174ae04c73312403e89db0f8e9bd9601d403b4783fredc 9231ba132491053bc86d419a7d51fc04af3299c076fredc public int onStartCommand(Intent intent, int flags, int startId) { 9331ba132491053bc86d419a7d51fc04af3299c076fredc log("onStartCommand()"); 94b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (mStartError || mAdapter == null) { 95b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.w(mName, "Stopping profile service: device does not have BT"); 9631ba132491053bc86d419a7d51fc04af3299c076fredc doStop(intent); 9731ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 98b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 99b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 100b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) { 101b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Permission denied!"); 10231ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 103b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 104b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 10531ba132491053bc86d419a7d51fc04af3299c076fredc if (intent == null) { 10631ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Restarting profile service..."); 10731ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 10831ba132491053bc86d419a7d51fc04af3299c076fredc } else { 10931ba132491053bc86d419a7d51fc04af3299c076fredc String action = intent.getStringExtra(AdapterService.EXTRA_ACTION); 11031ba132491053bc86d419a7d51fc04af3299c076fredc if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) { 11131ba132491053bc86d419a7d51fc04af3299c076fredc int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 11231ba132491053bc86d419a7d51fc04af3299c076fredc if(state==BluetoothAdapter.STATE_OFF) { 11331ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Received stop request...Stopping profile..."); 11431ba132491053bc86d419a7d51fc04af3299c076fredc doStop(intent); 11531ba132491053bc86d419a7d51fc04af3299c076fredc } else if (state == BluetoothAdapter.STATE_ON) { 11631ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Received start request. Starting profile..."); 11731ba132491053bc86d419a7d51fc04af3299c076fredc doStart(intent); 11831ba132491053bc86d419a7d51fc04af3299c076fredc } 119b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 120b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 12131ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 122b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 123b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 12474ae04c73312403e89db0f8e9bd9601d403b4783fredc public IBinder onBind(Intent intent) { 12574ae04c73312403e89db0f8e9bd9601d403b4783fredc log("onBind"); 12674ae04c73312403e89db0f8e9bd9601d403b4783fredc return mBinder; 12774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 12874ae04c73312403e89db0f8e9bd9601d403b4783fredc 12974ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean onUnbind(Intent intent) { 13074ae04c73312403e89db0f8e9bd9601d403b4783fredc log("onUnbind"); 13174ae04c73312403e89db0f8e9bd9601d403b4783fredc return super.onUnbind(intent); 13274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 13374ae04c73312403e89db0f8e9bd9601d403b4783fredc 134b5cc776c9353a203cdde97e62b25f05d9633d14cfredc @Override 135b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public void onDestroy() { 136b5cc776c9353a203cdde97e62b25f05d9633d14cfredc log("Destroying service."); 13774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mCleaningUp) { 13874ae04c73312403e89db0f8e9bd9601d403b4783fredc log("Cleanup already started... Skipping cleanup()..."); 13974ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 14074ae04c73312403e89db0f8e9bd9601d403b4783fredc log("cleanup()"); 14174ae04c73312403e89db0f8e9bd9601d403b4783fredc mCleaningUp = true; 14274ae04c73312403e89db0f8e9bd9601d403b4783fredc cleanup(); 14374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mBinder != null) { 14474ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder.cleanup(); 14574ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder= null; 14674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 14774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 14874ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onDestroy(); 14974ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = null; 15074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 15174ae04c73312403e89db0f8e9bd9601d403b4783fredc 15274ae04c73312403e89db0f8e9bd9601d403b4783fredc private void doStart(Intent intent) { 15374ae04c73312403e89db0f8e9bd9601d403b4783fredc //Start service 15474ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mAdapter == null) { 15574ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 15674ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 15774ae04c73312403e89db0f8e9bd9601d403b4783fredc log("start()"); 15874ae04c73312403e89db0f8e9bd9601d403b4783fredc mStartError = !start(); 15974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (!mStartError) { 16074ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON); 16174ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 16274ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 16374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 165b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 166b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 16731ba132491053bc86d419a7d51fc04af3299c076fredc private void doStop(Intent intent) { 168b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (stop()) { 16974ae04c73312403e89db0f8e9bd9601d403b4783fredc log("stop()"); 17074ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF); 171b5cc776c9353a203cdde97e62b25f05d9633d14cfredc stopSelf(); 172b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } else { 173b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Unable to stop profile"); 174b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 175b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 176b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 17774ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void notifyProfileServiceStateChanged(int state) { 178b5cc776c9353a203cdde97e62b25f05d9633d14cfredc //Notify adapter service 179b5cc776c9353a203cdde97e62b25f05d9633d14cfredc AdapterService sAdapter = AdapterService.getAdapterService(); 180b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (sAdapter!= null) { 18131ba132491053bc86d419a7d51fc04af3299c076fredc sAdapter.onProfileServiceStateChanged(getClass().getName(), state); 182b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 183b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 184b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 18574ae04c73312403e89db0f8e9bd9601d403b4783fredc public void notifyProfileConnectionStateChanged(BluetoothDevice device, 18674ae04c73312403e89db0f8e9bd9601d403b4783fredc int profileId, int newState, int prevState) { 18774ae04c73312403e89db0f8e9bd9601d403b4783fredc AdapterService svc = AdapterService.getAdapterService(); 18874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (svc != null) { 18974ae04c73312403e89db0f8e9bd9601d403b4783fredc svc.onProfileConnectionStateChanged(device, profileId, newState, prevState); 19074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19274ae04c73312403e89db0f8e9bd9601d403b4783fredc 19374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothDevice getDevice(byte[] address) { 19474ae04c73312403e89db0f8e9bd9601d403b4783fredc return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); 19574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 196b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 197b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected void log(String msg) { 198b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.d(mName, msg); 199b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 200b5cc776c9353a203cdde97e62b25f05d9633d14cfredc} 201