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; 35abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie private static final String TAG = "BluetoothProfileService"; 36abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie 3774ae04c73312403e89db0f8e9bd9601d403b4783fredc //For Debugging only 3874ae04c73312403e89db0f8e9bd9601d403b4783fredc private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>(); 3974ae04c73312403e89db0f8e9bd9601d403b4783fredc 40b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public static final String BLUETOOTH_ADMIN_PERM = 41b5cc776c9353a203cdde97e62b25f05d9633d14cfredc android.Manifest.permission.BLUETOOTH_ADMIN; 42b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; 43a08fff0ae81757bdab00ae8865a906c711d5572fWei Wang public static final String BLUETOOTH_PRIVILEGED = 44a08fff0ae81757bdab00ae8865a906c711d5572fWei Wang android.Manifest.permission.BLUETOOTH_PRIVILEGED; 45b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 4674ae04c73312403e89db0f8e9bd9601d403b4783fredc public static interface IProfileServiceBinder extends IBinder { 4774ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean cleanup(); 4874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 4931ba132491053bc86d419a7d51fc04af3299c076fredc //Profile services will not be automatically restarted. 5031ba132491053bc86d419a7d51fc04af3299c076fredc //They must be explicitly restarted by AdapterService 5131ba132491053bc86d419a7d51fc04af3299c076fredc private static final int PROFILE_SERVICE_MODE=Service.START_NOT_STICKY; 52b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected String mName; 5374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothAdapter mAdapter; 5474ae04c73312403e89db0f8e9bd9601d403b4783fredc protected IProfileServiceBinder mBinder; 5574ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean mStartError=false; 5674ae04c73312403e89db0f8e9bd9601d403b4783fredc private boolean mCleaningUp = false; 57b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 58838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood private AdapterService mAdapterService; 59838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 60b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected String getName() { 61b5cc776c9353a203cdde97e62b25f05d9633d14cfredc return getClass().getSimpleName(); 62b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 63b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 6474ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean isAvailable() { 6574ae04c73312403e89db0f8e9bd9601d403b4783fredc return !mStartError && !mCleaningUp; 6674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 6774ae04c73312403e89db0f8e9bd9601d403b4783fredc 6874ae04c73312403e89db0f8e9bd9601d403b4783fredc protected abstract IProfileServiceBinder initBinder(); 69b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean start(); 70b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected abstract boolean stop(); 7174ae04c73312403e89db0f8e9bd9601d403b4783fredc protected boolean cleanup() { 7274ae04c73312403e89db0f8e9bd9601d403b4783fredc return true; 7374ae04c73312403e89db0f8e9bd9601d403b4783fredc } 74b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 7574ae04c73312403e89db0f8e9bd9601d403b4783fredc protected ProfileService() { 76b5cc776c9353a203cdde97e62b25f05d9633d14cfredc mName = getName(); 7774ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 7874ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 7974ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 8074ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount==null) { 8174ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 1; 8274ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 8374ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount+1; 8474ae04c73312403e89db0f8e9bd9601d403b4783fredc } 8574ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 860f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount); 8774ae04c73312403e89db0f8e9bd9601d403b4783fredc } 88b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 8931ba132491053bc86d419a7d51fc04af3299c076fredc } 9031ba132491053bc86d419a7d51fc04af3299c076fredc 9174ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void finalize() { 9274ae04c73312403e89db0f8e9bd9601d403b4783fredc if (DBG) { 9374ae04c73312403e89db0f8e9bd9601d403b4783fredc synchronized (sReferenceCount) { 9474ae04c73312403e89db0f8e9bd9601d403b4783fredc Integer refCount = sReferenceCount.get(mName); 9574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (refCount!=null) { 9674ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = refCount-1; 9774ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 9874ae04c73312403e89db0f8e9bd9601d403b4783fredc refCount = 0; 9974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 10074ae04c73312403e89db0f8e9bd9601d403b4783fredc sReferenceCount.put(mName, refCount); 10174ae04c73312403e89db0f8e9bd9601d403b4783fredc log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount); 102b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 103b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 104b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 105b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 10674ae04c73312403e89db0f8e9bd9601d403b4783fredc @Override 10774ae04c73312403e89db0f8e9bd9601d403b4783fredc public void onCreate() { 1080f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onCreate"); 10974ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onCreate(); 11074ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = BluetoothAdapter.getDefaultAdapter(); 11174ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder = initBinder(); 112838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood mAdapterService = AdapterService.getAdapterService(); 113abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie if (mAdapterService != null) { 114abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie mAdapterService.addProfile(this); 115abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie } else { 116abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie Log.w(TAG, "onCreate, null mAdapterService"); 117abe1879f779481f9ee1a48b2de343097a6ddcf85Matthew Xie } 11874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 11974ae04c73312403e89db0f8e9bd9601d403b4783fredc 12031ba132491053bc86d419a7d51fc04af3299c076fredc public int onStartCommand(Intent intent, int flags, int startId) { 1210f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onStartCommand()"); 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"); 15474ae04c73312403e89db0f8e9bd9601d403b4783fredc return mBinder; 15574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 15674ae04c73312403e89db0f8e9bd9601d403b4783fredc 15774ae04c73312403e89db0f8e9bd9601d403b4783fredc public boolean onUnbind(Intent intent) { 1580f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("onUnbind"); 15974ae04c73312403e89db0f8e9bd9601d403b4783fredc return super.onUnbind(intent); 16074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 16174ae04c73312403e89db0f8e9bd9601d403b4783fredc 162838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood // for dumpsys support 163838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public void dump(StringBuilder sb) { 164f5f90873574eefe5f50a7b383fcd8fefb961f66cAndre Eisenbach sb.append("\nProfile: " + mName + "\n"); 165838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 166838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 167838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood // with indenting for subclasses 168838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood public static void println(StringBuilder sb, String s) { 169838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append(" "); 170838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append(s); 171838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood sb.append("\n"); 172838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood } 173838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood 174b5cc776c9353a203cdde97e62b25f05d9633d14cfredc @Override 175b5cc776c9353a203cdde97e62b25f05d9633d14cfredc public void onDestroy() { 1760f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("Destroying service."); 177a1772b03b58d2821a621b40b7e8d1dba1213a556Andre Eisenbach if (mAdapterService != null) mAdapterService.removeProfile(this); 178a1772b03b58d2821a621b40b7e8d1dba1213a556Andre Eisenbach 17974ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mCleaningUp) { 1800f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("Cleanup already started... Skipping cleanup()..."); 18174ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 1820f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("cleanup()"); 18374ae04c73312403e89db0f8e9bd9601d403b4783fredc mCleaningUp = true; 18474ae04c73312403e89db0f8e9bd9601d403b4783fredc cleanup(); 18574ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mBinder != null) { 18674ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder.cleanup(); 18774ae04c73312403e89db0f8e9bd9601d403b4783fredc mBinder= null; 18874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 18974ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19074ae04c73312403e89db0f8e9bd9601d403b4783fredc super.onDestroy(); 19174ae04c73312403e89db0f8e9bd9601d403b4783fredc mAdapter = null; 19274ae04c73312403e89db0f8e9bd9601d403b4783fredc } 19374ae04c73312403e89db0f8e9bd9601d403b4783fredc 19474ae04c73312403e89db0f8e9bd9601d403b4783fredc private void doStart(Intent intent) { 19574ae04c73312403e89db0f8e9bd9601d403b4783fredc //Start service 19674ae04c73312403e89db0f8e9bd9601d403b4783fredc if (mAdapter == null) { 19774ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 19874ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 1990f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("start()"); 20074ae04c73312403e89db0f8e9bd9601d403b4783fredc mStartError = !start(); 20174ae04c73312403e89db0f8e9bd9601d403b4783fredc if (!mStartError) { 20274ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON); 20374ae04c73312403e89db0f8e9bd9601d403b4783fredc } else { 20474ae04c73312403e89db0f8e9bd9601d403b4783fredc Log.e(mName, "Error starting profile. BluetoothAdapter is null"); 20574ae04c73312403e89db0f8e9bd9601d403b4783fredc } 20674ae04c73312403e89db0f8e9bd9601d403b4783fredc } 207b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 208b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 20931ba132491053bc86d419a7d51fc04af3299c076fredc private void doStop(Intent intent) { 210b5cc776c9353a203cdde97e62b25f05d9633d14cfredc if (stop()) { 2110f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie if (DBG) log("stop()"); 21274ae04c73312403e89db0f8e9bd9601d403b4783fredc notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF); 213b5cc776c9353a203cdde97e62b25f05d9633d14cfredc stopSelf(); 214b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } else { 215b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.e(mName, "Unable to stop profile"); 216b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 217b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 218b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 21974ae04c73312403e89db0f8e9bd9601d403b4783fredc protected void notifyProfileServiceStateChanged(int state) { 220b5cc776c9353a203cdde97e62b25f05d9633d14cfredc //Notify adapter service 221838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood if (mAdapterService != null) { 222838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood mAdapterService.onProfileServiceStateChanged(getClass().getName(), state); 223b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 224b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 225b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 22674ae04c73312403e89db0f8e9bd9601d403b4783fredc public void notifyProfileConnectionStateChanged(BluetoothDevice device, 22774ae04c73312403e89db0f8e9bd9601d403b4783fredc int profileId, int newState, int prevState) { 228838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood if (mAdapterService != null) { 229838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood mAdapterService.onProfileConnectionStateChanged(device, profileId, newState, prevState); 23074ae04c73312403e89db0f8e9bd9601d403b4783fredc } 23174ae04c73312403e89db0f8e9bd9601d403b4783fredc } 23274ae04c73312403e89db0f8e9bd9601d403b4783fredc 23374ae04c73312403e89db0f8e9bd9601d403b4783fredc protected BluetoothDevice getDevice(byte[] address) { 234f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora if(mAdapter != null){ 235f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); 236f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora } 237f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora return null; 23874ae04c73312403e89db0f8e9bd9601d403b4783fredc } 239b5cc776c9353a203cdde97e62b25f05d9633d14cfredc 240b5cc776c9353a203cdde97e62b25f05d9633d14cfredc protected void log(String msg) { 241b5cc776c9353a203cdde97e62b25f05d9633d14cfredc Log.d(mName, msg); 242b5cc776c9353a203cdde97e62b25f05d9633d14cfredc } 243b5cc776c9353a203cdde97e62b25f05d9633d14cfredc} 244