Home | History | Annotate | Download | only in btservice
      1 /*
      2  * Copyright (C) 2012 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 
     17 package com.android.bluetooth.btservice;
     18 
     19 import java.util.HashMap;
     20 
     21 import com.android.bluetooth.Utils;
     22 
     23 import android.app.Service;
     24 import android.bluetooth.BluetoothAdapter;
     25 import android.bluetooth.BluetoothDevice;
     26 import android.bluetooth.BluetoothProfile;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.pm.PackageManager;
     30 import android.os.IBinder;
     31 import android.util.Log;
     32 
     33 public abstract class ProfileService extends Service {
     34     private static final boolean DBG = false;
     35     //For Debugging only
     36     private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>();
     37 
     38     public static final String BLUETOOTH_ADMIN_PERM =
     39             android.Manifest.permission.BLUETOOTH_ADMIN;
     40     public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
     41 
     42     public static interface IProfileServiceBinder extends IBinder {
     43         public boolean cleanup();
     44     }
     45     //Profile services will not be automatically restarted.
     46     //They must be explicitly restarted by AdapterService
     47     private static final int PROFILE_SERVICE_MODE=Service.START_NOT_STICKY;
     48     protected String mName;
     49     protected BluetoothAdapter mAdapter;
     50     protected IProfileServiceBinder mBinder;
     51     protected boolean mStartError=false;
     52     private boolean mCleaningUp = false;
     53 
     54     protected String getName() {
     55         return getClass().getSimpleName();
     56     }
     57 
     58     protected boolean isAvailable() {
     59         return !mStartError && !mCleaningUp;
     60     }
     61 
     62     protected abstract IProfileServiceBinder initBinder();
     63     protected abstract boolean start();
     64     protected abstract boolean stop();
     65     protected boolean cleanup() {
     66         return true;
     67     }
     68 
     69     protected ProfileService() {
     70         mName = getName();
     71         if (DBG) {
     72             synchronized (sReferenceCount) {
     73                 Integer refCount = sReferenceCount.get(mName);
     74                 if (refCount==null) {
     75                     refCount = 1;
     76                 } else {
     77                     refCount = refCount+1;
     78                 }
     79                 sReferenceCount.put(mName, refCount);
     80                 if (DBG) log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount);
     81             }
     82         }
     83     }
     84 
     85     protected void finalize() {
     86         if (DBG) {
     87             synchronized (sReferenceCount) {
     88                 Integer refCount = sReferenceCount.get(mName);
     89                 if (refCount!=null) {
     90                     refCount = refCount-1;
     91                 } else {
     92                     refCount = 0;
     93                 }
     94                 sReferenceCount.put(mName, refCount);
     95                 log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount);
     96             }
     97         }
     98     }
     99 
    100     @Override
    101     public void onCreate() {
    102         if (DBG) log("onCreate");
    103         super.onCreate();
    104         mAdapter = BluetoothAdapter.getDefaultAdapter();
    105         mBinder = initBinder();
    106     }
    107 
    108     public int onStartCommand(Intent intent, int flags, int startId) {
    109         if (DBG) log("onStartCommand()");
    110         if (mStartError || mAdapter == null) {
    111             Log.w(mName, "Stopping profile service: device does not have BT");
    112             doStop(intent);
    113             return PROFILE_SERVICE_MODE;
    114         }
    115 
    116         if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) {
    117             Log.e(mName, "Permission denied!");
    118             return PROFILE_SERVICE_MODE;
    119         }
    120 
    121         if (intent == null) {
    122             Log.d(mName, "Restarting profile service...");
    123             return PROFILE_SERVICE_MODE;
    124         } else {
    125             String action = intent.getStringExtra(AdapterService.EXTRA_ACTION);
    126             if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
    127                 int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
    128                 if(state==BluetoothAdapter.STATE_OFF) {
    129                     Log.d(mName, "Received stop request...Stopping profile...");
    130                     doStop(intent);
    131                 } else if (state == BluetoothAdapter.STATE_ON) {
    132                     Log.d(mName, "Received start request. Starting profile...");
    133                     doStart(intent);
    134                 }
    135             }
    136         }
    137         return PROFILE_SERVICE_MODE;
    138     }
    139 
    140     public IBinder onBind(Intent intent) {
    141         if (DBG) log("onBind");
    142         return mBinder;
    143     }
    144 
    145     public boolean onUnbind(Intent intent) {
    146         if (DBG) log("onUnbind");
    147         return super.onUnbind(intent);
    148     }
    149 
    150     @Override
    151     public void onDestroy() {
    152         if (DBG) log("Destroying service.");
    153         if (mCleaningUp) {
    154             if (DBG) log("Cleanup already started... Skipping cleanup()...");
    155         } else {
    156             if (DBG) log("cleanup()");
    157             mCleaningUp = true;
    158             cleanup();
    159             if (mBinder != null) {
    160                 mBinder.cleanup();
    161                 mBinder= null;
    162             }
    163         }
    164         super.onDestroy();
    165         mAdapter = null;
    166     }
    167 
    168     private void doStart(Intent intent) {
    169         //Start service
    170         if (mAdapter == null) {
    171             Log.e(mName, "Error starting profile. BluetoothAdapter is null");
    172         } else {
    173             if (DBG) log("start()");
    174             mStartError = !start();
    175             if (!mStartError) {
    176                 notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON);
    177             } else {
    178                 Log.e(mName, "Error starting profile. BluetoothAdapter is null");
    179             }
    180         }
    181     }
    182 
    183     private void doStop(Intent intent) {
    184         if (stop()) {
    185             if (DBG) log("stop()");
    186             notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF);
    187             stopSelf();
    188         } else {
    189             Log.e(mName, "Unable to stop profile");
    190         }
    191     }
    192 
    193     protected void notifyProfileServiceStateChanged(int state) {
    194         //Notify adapter service
    195         AdapterService sAdapter = AdapterService.getAdapterService();
    196         if (sAdapter!= null) {
    197             sAdapter.onProfileServiceStateChanged(getClass().getName(), state);
    198         }
    199     }
    200 
    201     public void notifyProfileConnectionStateChanged(BluetoothDevice device,
    202             int profileId, int newState, int prevState) {
    203         AdapterService svc = AdapterService.getAdapterService();
    204         if (svc != null) {
    205             svc.onProfileConnectionStateChanged(device, profileId, newState, prevState);
    206         }
    207     }
    208 
    209     protected BluetoothDevice getDevice(byte[] address) {
    210         return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
    211     }
    212 
    213     protected void log(String msg) {
    214         Log.d(mName, msg);
    215     }
    216 }
    217