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