• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     private static final String TAG = "BluetoothProfileService";
36 
37     //For Debugging only
38     private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>();
39 
40     public static final String BLUETOOTH_ADMIN_PERM =
41             android.Manifest.permission.BLUETOOTH_ADMIN;
42     public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
43     public static final String BLUETOOTH_PRIVILEGED =
44         android.Manifest.permission.BLUETOOTH_PRIVILEGED;
45 
46     public static interface IProfileServiceBinder extends IBinder {
cleanup()47         public boolean cleanup();
48     }
49     //Profile services will not be automatically restarted.
50     //They must be explicitly restarted by AdapterService
51     private static final int PROFILE_SERVICE_MODE=Service.START_NOT_STICKY;
52     protected String mName;
53     protected BluetoothAdapter mAdapter;
54     protected IProfileServiceBinder mBinder;
55     protected boolean mStartError=false;
56     private boolean mCleaningUp = false;
57 
getName()58     protected String getName() {
59         return getClass().getSimpleName();
60     }
61 
isAvailable()62     protected boolean isAvailable() {
63         return !mStartError && !mCleaningUp;
64     }
65 
initBinder()66     protected abstract IProfileServiceBinder initBinder();
start()67     protected abstract boolean start();
stop()68     protected abstract boolean stop();
cleanup()69     protected boolean cleanup() {
70         return true;
71     }
72 
ProfileService()73     protected ProfileService() {
74         mName = getName();
75         if (DBG) {
76             synchronized (sReferenceCount) {
77                 Integer refCount = sReferenceCount.get(mName);
78                 if (refCount==null) {
79                     refCount = 1;
80                 } else {
81                     refCount = refCount+1;
82                 }
83                 sReferenceCount.put(mName, refCount);
84                 if (DBG) log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount);
85             }
86         }
87     }
88 
finalize()89     protected void finalize() {
90         if (DBG) {
91             synchronized (sReferenceCount) {
92                 Integer refCount = sReferenceCount.get(mName);
93                 if (refCount!=null) {
94                     refCount = refCount-1;
95                 } else {
96                     refCount = 0;
97                 }
98                 sReferenceCount.put(mName, refCount);
99                 log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount);
100             }
101         }
102     }
103 
104     @Override
onCreate()105     public void onCreate() {
106         if (DBG) log("onCreate");
107         super.onCreate();
108         mAdapter = BluetoothAdapter.getDefaultAdapter();
109         mBinder = initBinder();
110     }
111 
onStartCommand(Intent intent, int flags, int startId)112     public int onStartCommand(Intent intent, int flags, int startId) {
113         if (DBG) log("onStartCommand()");
114         AdapterService adapterService = AdapterService.getAdapterService();
115         if (adapterService != null) {
116             adapterService.addProfile(this);
117         } else {
118             Log.w(TAG, "Could not add this profile because AdapterService is null.");
119         }
120 
121         if (mStartError || mAdapter == null) {
122             Log.w(mName, "Stopping profile service: device does not have BT");
123             doStop(intent);
124             return PROFILE_SERVICE_MODE;
125         }
126 
127         if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) {
128             Log.e(mName, "Permission denied!");
129             return PROFILE_SERVICE_MODE;
130         }
131 
132         if (intent == null) {
133             Log.d(mName, "Restarting profile service...");
134             return PROFILE_SERVICE_MODE;
135         } else {
136             String action = intent.getStringExtra(AdapterService.EXTRA_ACTION);
137             if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) {
138                 int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
139                 if(state==BluetoothAdapter.STATE_OFF) {
140                     Log.d(mName, "Received stop request...Stopping profile...");
141                     doStop(intent);
142                 } else if (state == BluetoothAdapter.STATE_ON) {
143                     Log.d(mName, "Received start request. Starting profile...");
144                     doStart(intent);
145                 }
146             }
147         }
148         return PROFILE_SERVICE_MODE;
149     }
150 
onBind(Intent intent)151     public IBinder onBind(Intent intent) {
152         if (DBG) log("onBind");
153         return mBinder;
154     }
155 
onUnbind(Intent intent)156     public boolean onUnbind(Intent intent) {
157         if (DBG) log("onUnbind");
158         return super.onUnbind(intent);
159     }
160 
161     // for dumpsys support
dump(StringBuilder sb)162     public void dump(StringBuilder sb) {
163         sb.append("\nProfile: " + mName + "\n");
164     }
165 
dumpProto(BluetoothProto.BluetoothLog proto)166     public void dumpProto(BluetoothProto.BluetoothLog proto) {
167         // Do nothing
168     }
169 
170     // with indenting for subclasses
println(StringBuilder sb, String s)171     public static void println(StringBuilder sb, String s) {
172         sb.append("  ");
173         sb.append(s);
174         sb.append("\n");
175     }
176 
177     @Override
onDestroy()178     public void onDestroy() {
179         if (DBG) log("Destroying service.");
180         AdapterService adapterService = AdapterService.getAdapterService();
181         if (adapterService != null) adapterService.removeProfile(this);
182 
183         if (mCleaningUp) {
184             if (DBG) log("Cleanup already started... Skipping cleanup()...");
185         } else {
186             if (DBG) log("cleanup()");
187             mCleaningUp = true;
188             cleanup();
189             if (mBinder != null) {
190                 mBinder.cleanup();
191                 mBinder= null;
192             }
193         }
194         super.onDestroy();
195         mAdapter = null;
196     }
197 
doStart(Intent intent)198     private void doStart(Intent intent) {
199         //Start service
200         if (mAdapter == null) {
201             Log.e(mName, "Error starting profile. BluetoothAdapter is null");
202         } else {
203             if (DBG) log("start()");
204             mStartError = !start();
205             if (!mStartError) {
206                 notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON);
207             } else {
208                 Log.e(mName, "Error starting profile. BluetoothAdapter is null");
209             }
210         }
211     }
212 
doStop(Intent intent)213     private void doStop(Intent intent) {
214         if (stop()) {
215             if (DBG) log("stop()");
216             notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF);
217             stopSelf();
218         } else {
219             Log.e(mName, "Unable to stop profile");
220         }
221     }
222 
notifyProfileServiceStateChanged(int state)223     protected void notifyProfileServiceStateChanged(int state) {
224         //Notify adapter service
225         AdapterService adapterService = AdapterService.getAdapterService();
226         if (adapterService != null) {
227             adapterService.onProfileServiceStateChanged(getClass().getName(), state);
228         }
229     }
230 
notifyProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState)231     public void notifyProfileConnectionStateChanged(BluetoothDevice device,
232             int profileId, int newState, int prevState) {
233         AdapterService adapterService = AdapterService.getAdapterService();
234         if (adapterService != null) {
235             adapterService.onProfileConnectionStateChanged(device, profileId, newState, prevState);
236         }
237     }
238 
getDevice(byte[] address)239     protected BluetoothDevice getDevice(byte[] address) {
240         if(mAdapter != null){
241             return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
242         }
243         return null;
244     }
245 
log(String msg)246     protected void log(String msg) {
247         Log.d(mName, msg);
248     }
249 }
250