103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby/* 203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * Copyright (C) 2014 The Android Open Source Project 303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * 403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * Licensed under the Apache License, Version 2.0 (the "License"); 503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * you may not use this file except in compliance with the License. 603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * You may obtain a copy of the License at 703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * 803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * http://www.apache.org/licenses/LICENSE-2.0 903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * 1003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * Unless required by applicable law or agreed to in writing, software 1103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * distributed under the License is distributed on an "AS IS" BASIS, 1203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * See the License for the specific language governing permissions and 1403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * limitations under the License. 1503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby */ 1603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 1703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambypackage com.android.omadm.service; 1803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 1903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.app.Service; 2003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.content.Context; 2103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.content.Intent; 2203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.net.ConnectivityManager; 2303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.net.Network; 2403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.net.NetworkCapabilities; 2503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.net.NetworkInfo; 2603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.net.NetworkRequest; 2703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.os.IBinder; 2803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambyimport android.util.Log; 2903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 3003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby/** 3103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * This service monitors the data connection and call state and brings up the FOTA APN when 3203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * started by an {@link DMIntent#ACTION_START_DATA_CONNECTION_SERVICE} intent. 3303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * 3403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * TODO: handle operators which disallow OMA DM sessions over Wi-Fi. 3503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * TODO: handle mobile data disabled and roaming disabled cases. 3603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby */ 3703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hambypublic class DMDataConnectionService extends Service { 3803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private static final String TAG = "DMDataConnectionService"; 396ec26491263e8266749279ce76ca2787eccb1d98Amit Mahajan private static final boolean DBG = true; 4003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 4103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private ConnectivityManager mConnectivityManager; 4203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 4303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** Start ID of current network request. */ 4403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private int mCurrentStartId; 4503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 4603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** The active NetworkCallback for the FOTA APN, or null. */ 4703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private ConnectivityManager.NetworkCallback mCellNetworkCallback; 4803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 4903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** The active NetworkCallback for WiFi or Ethernet, or null. */ 5003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private ConnectivityManager.NetworkCallback mWiFiNetworkCallback; 5103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 5203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** The active FOTA APN network, or null. */ 5303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private Network mActiveCellNetwork; 5403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 5503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** The active WiFi or Ethernet network, or null. */ 5603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private Network mActiveWiFiNetwork; 5703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 5803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** Wait for 120 seconds after requesting the desired network types. */ 5903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private static final int WAIT_FOR_NETWORK_TIMEOUT_MS = 120 * 1000; 6003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 6103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 6203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public void onCreate() { 6303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("onCreate()"); 6403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 6503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 6603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 6703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 6803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public void onDestroy() { 6903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("onDestroy()"); 7003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 7103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mCurrentStartId = 0; 7203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 7303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mCellNetworkCallback != null) { 7403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mConnectivityManager.unregisterNetworkCallback(mCellNetworkCallback); 7503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("unregistered cell network callback"); 7603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mCellNetworkCallback = null; 7703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 7803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 7903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mWiFiNetworkCallback != null) { 8003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mConnectivityManager.unregisterNetworkCallback(mWiFiNetworkCallback); 8103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("unregistered WiFi network callback"); 8203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mWiFiNetworkCallback = null; 8303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 8426ced6b6a3801ecb1cb6da6816a62ae88c47ba5dJunda Liu // Unbind from any network. 8526ced6b6a3801ecb1cb6da6816a62ae88c47ba5dJunda Liu ConnectivityManager.setProcessDefaultNetwork(null); 8603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 8703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 8803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private boolean isWifiConnected() { 8903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby NetworkInfo ni = mConnectivityManager.getActiveNetworkInfo(); 9003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby return ni != null && ni.isConnected() 9103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby && (ni.getType() == ConnectivityManager.TYPE_WIFI 9203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby || ni.getType() == ConnectivityManager.TYPE_ETHERNET); 9303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 9403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 9503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby /** 9603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * Request route using FOTA APN on the cell network and/or Wi-Fi or Ethernet transport. 9703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby * @param wifiOrEthernet true if Wi-Fi transport type is allowed; false for mobile data only 9803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby */ 9903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private void requestNetworks(boolean wifiOrEthernet) { 10003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (wifiOrEthernet && isWifiConnected()) { 10103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("requesting WiFi or Ethernet network transport"); 10203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby NetworkRequest request = new NetworkRequest.Builder() 10303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 10403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET).build(); 10503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 10603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mWiFiNetworkCallback = new WiFiCallback(); 10703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mConnectivityManager.requestNetwork(request, mWiFiNetworkCallback, 10803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby WAIT_FOR_NETWORK_TIMEOUT_MS); 10903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 11003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("requesting cell network with FOTA capability"); 11103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby NetworkRequest request = new NetworkRequest.Builder() 11203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA).build(); 11303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 11403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mCellNetworkCallback = new CellCallback(); 11503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mConnectivityManager.requestNetwork(request, mCellNetworkCallback, 11603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby WAIT_FOR_NETWORK_TIMEOUT_MS); 11703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 11803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 11903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 12003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 12103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public int onStartCommand(Intent intent, int flags, int startId) { 12203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("onStartCommand: startID " + startId); 12303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 12403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (intent != null) { 12503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby String action = intent.getAction(); 12603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DMIntent.ACTION_START_DATA_CONNECTION_SERVICE.equals(action)) { 12703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby int lastStartId = mCurrentStartId; 12803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mCurrentStartId = startId; 12903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 13003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (lastStartId == 0) { 13103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby requestNetworks(true); // request FOTA APN or Wi-Fi/Ethernet networks 13203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 13303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 13403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("unexpected intent: " + action); 13503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby stopSelf(startId); 13603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 13703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 13803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("unexpected null intent"); 13903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby stopSelf(startId); 14003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 14103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby return Service.START_REDELIVER_INTENT; 14203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 14303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 14403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private void sendDataConnectionReady() { 14503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby Intent intent = new Intent(this, DMIntentReceiver.class); 14603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby intent.setAction(DMIntent.ACTION_DATA_CONNECTION_READY); 14703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby sendBroadcast(intent); 14803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 14903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 15003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby // Callback for FOTA APN of cellular network. 15103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private class CellCallback extends ConnectivityManager.NetworkCallback { 15203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 15303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public void onAvailable(Network network) { 15403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mCurrentStartId != 0) { 15503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("CellCallback.onAvailable() for network: " + network); 15603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mActiveCellNetwork = network; 15703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mActiveWiFiNetwork == null) { 15803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("calling setProcessDefaultNetwork() for cell network"); 15903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby ConnectivityManager.setProcessDefaultNetwork(network); 16003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 16103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby sendDataConnectionReady(); 16203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 16303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("CellCallback: ignoring onAvailable() after service quit"); 16403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 16503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 16603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 16703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 16803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public void onUnavailable() { 16903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mCurrentStartId != 0) { 17003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("CellCallback.onUnavailable() called (timeout)"); 17103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mActiveCellNetwork = null; 17203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mActiveWiFiNetwork == null) { 17303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("clearing setProcessDefaultNetwork() binding"); 17403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby ConnectivityManager.setProcessDefaultNetwork(null); 17503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 17603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 17703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("CellCallback: ignoring onUnavailable() after service quit"); 17803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 17903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 18003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 18103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 18203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby // Callback for WiFi connectivity. 18303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private class WiFiCallback extends ConnectivityManager.NetworkCallback { 18403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 18503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public void onAvailable(Network network) { 18603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mCurrentStartId != 0) { 18703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("WiFiCallback.onAvailable() for network: " + network); 18803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mActiveWiFiNetwork = network; 18903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby ConnectivityManager.setProcessDefaultNetwork(network); 19003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby sendDataConnectionReady(); 19103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 19203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("WiFiCallback: ignoring onAvailable() after service quit"); 19303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 19403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 19503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 19603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 19703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public void onUnavailable() { 19803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mCurrentStartId != 0) { 19903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("WiFi.onUnavailable() called (timeout)"); 20003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby mActiveWiFiNetwork = null; 20103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (mActiveCellNetwork == null) { 20203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) logd("clearing setProcessDefaultNetwork() binding"); 20303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby ConnectivityManager.setProcessDefaultNetwork(null); 20403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby requestNetworks(false); // request FOTA APN only 20503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 20603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } else { 20703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby if (DBG) loge("WiFiCallback: ignoring onUnavailable() after service quit"); 20803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 20903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 21003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 21103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 21203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby @Override 21303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby public IBinder onBind(Intent intent) { 21403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby return null; 21503cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 21603cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 21703cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private static void logd(String msg) { 21803cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby Log.d(TAG, msg); 21903cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 22003cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby 22103cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby private static void loge(String msg) { 22203cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby Log.e(TAG, msg); 22303cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby } 22403cb0f61d4b623eaa435035791df27a74cf3b5ecJake Hamby} 225