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; 26b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.content.Intent; 27b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.content.pm.PackageManager; 28b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.os.IBinder; 29b5cc776c9353a203cdde97e62b25f05d9633d14cfredcimport android.util.Log; 30b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 31b5cc776c9353a203cdde97e62b25f05d9633d14cfredcpublic abstract class ProfileService extends Service { 32fd1da115cbf09b7dd9bca3c7d3a4fb816a835dc5Matthew Xie private static final boolean DBG = false; 33abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie private static final String TAG = "BluetoothProfileService"; 34abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie 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(); 6572d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen 66b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean start(); 67b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean stop(); 6872d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen protected void create() {} 6974ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 7074ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 7174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 72b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 7374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected ProfileService() { 74b5cc776c9353a203cdde97e62b25f05d9633d14cfredc mName = getName(); 7574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 7674ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 7774ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 7874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount==null) { 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 1; 8074ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 8174ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount+1; 8274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 8374ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 840f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount); 8574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 86b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 8731ba132491053bc86d419a7d51fc04af3299c076fredc } 8831ba132491053bc86d419a7d51fc04af3299c076fredc 8974ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void finalize() { 9074ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 9174ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 9274ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 9374ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount!=null) { 9474ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount-1; 9574ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 9674ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 0; 9774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 9874ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 9974ae04c73312403e89db0f8e9bd9601d403b4783fredc log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount); 100b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 101b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 102b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 103b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 10474ae04c73312403e89db0f8e9bd9601d403b4783fredc @Override 10574ae04c73312403e89db0f8e9bd9601d403b4783fredc public void onCreate() { 1060f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onCreate"); 10774ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onCreate(); 10874ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = BluetoothAdapter.getDefaultAdapter(); 10974ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder = initBinder(); 11072d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen create(); 11174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 11274ae04c73312403e89db0f8e9bd9601d403b4783fredc 11331ba132491053bc86d419a7d51fc04af3299c076fredc public int onStartCommand(Intent intent, int flags, int startId) { 1140f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onStartCommand()"); 115b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On AdapterService adapterService = AdapterService.getAdapterService(); 116b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On if (adapterService != null) { 117b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On adapterService.addProfile(this); 118b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On } else { 119b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On Log.w(TAG, "Could not add this profile because AdapterService is null."); 120b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On } 121b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On 122b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (mStartError || mAdapter == null) { 123b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.w(mName, "Stopping profile service: device does not have BT"); 12431ba132491053bc86d419a7d51fc04af3299c076fredc doStop(intent); 12531ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 126b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 127b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 128b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) { 129b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Permission denied!"); 13031ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 131b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 132b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 13331ba132491053bc86d419a7d51fc04af3299c076fredc if (intent == null) { 13431ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Restarting profile service..."); 13531ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 13631ba132491053bc86d419a7d51fc04af3299c076fredc } else { 13731ba132491053bc86d419a7d51fc04af3299c076fredc String action = intent.getStringExtra(AdapterService.EXTRA_ACTION); 13831ba132491053bc86d419a7d51fc04af3299c076fredc if (AdapterService.ACTION_SERVICE_STATE_CHANGED.equals(action)) { 13931ba132491053bc86d419a7d51fc04af3299c076fredc int state= intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); 14031ba132491053bc86d419a7d51fc04af3299c076fredc if(state==BluetoothAdapter.STATE_OFF) { 14131ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Received stop request...Stopping profile..."); 14231ba132491053bc86d419a7d51fc04af3299c076fredc doStop(intent); 14331ba132491053bc86d419a7d51fc04af3299c076fredc } else if (state == BluetoothAdapter.STATE_ON) { 14431ba132491053bc86d419a7d51fc04af3299c076fredc Log.d(mName, "Received start request. Starting profile..."); 14531ba132491053bc86d419a7d51fc04af3299c076fredc doStart(intent); 14631ba132491053bc86d419a7d51fc04af3299c076fredc } 147b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 148b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 14931ba132491053bc86d419a7d51fc04af3299c076fredc return PROFILE_SERVICE_MODE; 150b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 151b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 15274ae04c73312403e89db0f8e9bd9601d403b4783fredc public IBinder onBind(Intent intent) { 1530f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onBind"); 15472d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen if (mAdapter != null && mBinder == null) { 15572d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen // initBinder returned null, you can't bind 15672d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen throw new UnsupportedOperationException("Cannot bind to " + mName); 15772d0629dfc5db8ae48a512b47aa384f42b9ed71dMarie Janssen } 15874ae04c73312403e89db0f8e9bd9601d403b4783fredc return mBinder; 15974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16074ae04c73312403e89db0f8e9bd9601d403b4783fredc 16174ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean onUnbind(Intent intent) { 1620f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onUnbind"); 16374ae04c73312403e89db0f8e9bd9601d403b4783fredc return super.onUnbind(intent); 16474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16574ae04c73312403e89db0f8e9bd9601d403b4783fredc 166838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood // for dumpsys support 167838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public void dump(StringBuilder sb) { 168f5f90873574eefe5f50a7b383fcd8fefb961f66cAndre Eisenbach sb.append("\nProfile: " + mName + "\n"); 169838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 170838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 171f7435f2f832ab1faa9ca254143796e9516905c63Ajay Panicker public void dumpProto(BluetoothProto.BluetoothLog proto) { 172f7435f2f832ab1faa9ca254143796e9516905c63Ajay Panicker // Do nothing 173f7435f2f832ab1faa9ca254143796e9516905c63Ajay Panicker } 174f7435f2f832ab1faa9ca254143796e9516905c63Ajay Panicker 175838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood // with indenting for subclasses 176838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public static void println(StringBuilder sb, String s) { 177838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append(" "); 178838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append(s); 179838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append("\n"); 180838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 181838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 182b5cc776c9353a203cdde97e62b25f05d9633d14cfredc @Override 183b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public void onDestroy() { 1840f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("Destroying service."); 185b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On AdapterService adapterService = AdapterService.getAdapterService(); 186b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On if (adapterService != null) adapterService.removeProfile(this); 187a1772b03b58d2821a621b40b7e8d1dba1213a556Andre Eisenbach 18874ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mCleaningUp) { 1890f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("Cleanup already started... Skipping cleanup()..."); 19074ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 1910f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("cleanup()"); 19274ae04c73312403e89db0f8e9bd9601d403b4783fredc mCleaningUp = true; 19374ae04c73312403e89db0f8e9bd9601d403b4783fredc cleanup(); 19474ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mBinder != null) { 19574ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder.cleanup(); 19674ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder= null; 19774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19974ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onDestroy(); 20074ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = null; 20174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 20274ae04c73312403e89db0f8e9bd9601d403b4783fredc 20374ae04c73312403e89db0f8e9bd9601d403b4783fredc private void doStart(Intent intent) { 20474ae04c73312403e89db0f8e9bd9601d403b4783fredc //Start service 20574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mAdapter == null) { 20674ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 20774ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 2080f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("start()"); 20974ae04c73312403e89db0f8e9bd9601d403b4783fredc mStartError = !start(); 21074ae04c73312403e89db0f8e9bd9601d403b4783fredc if (!mStartError) { 21174ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON); 21274ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 21374ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 21474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 21574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 216b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 217b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 21831ba132491053bc86d419a7d51fc04af3299c076fredc private void doStop(Intent intent) { 219b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (stop()) { 2200f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("stop()"); 22174ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF); 222b5cc776c9353a203cdde97e62b25f05d9633d14cfredc stopSelf(); 223b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } else { 224b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Unable to stop profile"); 225b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 226b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 227b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 22874ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void notifyProfileServiceStateChanged(int state) { 229b5cc776c9353a203cdde97e62b25f05d9633d14cfredc //Notify adapter service 230b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On AdapterService adapterService = AdapterService.getAdapterService(); 231b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On if (adapterService != null) { 232b55c6a1f4ce60ad552e9c9a6d06fab6781a4dadbCalvin On adapterService.onProfileServiceStateChanged(getClass().getName(), state); 233b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 234b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 235b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 23674ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothDevice getDevice(byte[] address) { 237f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora if(mAdapter != null){ 238f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); 239f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora } 240f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora return null; 24174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 242b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 243b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected void log(String msg) { 244b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.d(mName, msg); 245b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 246b5cc776c9353a203cdde97e62b25f05d9633d14cfredc} 247