1bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock/*
2bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * Copyright (C) 2013 The Android Open Source Project
3bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock *
4bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * you may not use this file except in compliance with the License.
6bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * You may obtain a copy of the License at
7bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock *
8bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock *
10bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * Unless required by applicable law or agreed to in writing, software
11bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * See the License for the specific language governing permissions and
14bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock * limitations under the License.
15bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock */
16bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
17bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockpackage com.android.server.connectivity;
18bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
19bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.content.BroadcastReceiver;
20bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.content.Context;
21bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.content.Intent;
22bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.content.IntentFilter;
23bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.net.ConnectivityManager;
24bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.os.RemoteException;
25bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.telephony.PhoneStateListener;
26bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.telephony.ServiceState;
27bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.telephony.SignalStrength;
28bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.telephony.TelephonyManager;
29bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport android.util.Log;
30bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
31bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport com.android.internal.app.IBatteryStats;
32bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport com.android.internal.telephony.IccCardConstants;
33bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport com.android.internal.telephony.TelephonyIntents;
34bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockimport com.android.server.am.BatteryStatsService;
35bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
36bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlockpublic class DataConnectionStats extends BroadcastReceiver {
37bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private static final String TAG = "DataConnectionStats";
38bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private static final boolean DEBUG = false;
39bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
40bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private final Context mContext;
41bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private final IBatteryStats mBatteryStats;
42bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
43bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private IccCardConstants.State mSimState = IccCardConstants.State.READY;
44bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private SignalStrength mSignalStrength;
45bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private ServiceState mServiceState;
46bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private int mDataState = TelephonyManager.DATA_DISCONNECTED;
47bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
48bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    public DataConnectionStats(Context context) {
49bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        mContext = context;
50bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        mBatteryStats = BatteryStatsService.getService();
51bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
52bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
53bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    public void startMonitoring() {
54bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        TelephonyManager phone =
55bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
56bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        phone.listen(mPhoneStateListener,
57bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                PhoneStateListener.LISTEN_SERVICE_STATE
58bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock              | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
59bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock              | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
60bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock              | PhoneStateListener.LISTEN_DATA_ACTIVITY);
61bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
62bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        IntentFilter filter = new IntentFilter();
63bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
64bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
65bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
66bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        mContext.registerReceiver(this, filter);
67bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
68bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
69bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    @Override
70bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    public void onReceive(Context context, Intent intent) {
71bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        final String action = intent.getAction();
72bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
73bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            updateSimState(intent);
74bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            notePhoneDataConnectionState();
75bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
76bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
77bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            notePhoneDataConnectionState();
78bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock       }
79bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
80bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
81bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private void notePhoneDataConnectionState() {
82bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        if (mServiceState == null) {
83bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            return;
84bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
85bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        boolean simReadyOrUnknown = mSimState == IccCardConstants.State.READY
86bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                || mSimState == IccCardConstants.State.UNKNOWN;
87bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
88bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                && hasService()
89bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                && mDataState == TelephonyManager.DATA_CONNECTED;
90bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        int networkType = mServiceState.getDataNetworkType();
91bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
92bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                networkType, visible ? "" : "not "));
93bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        try {
94bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mBatteryStats.notePhoneDataConnectionState(networkType, visible);
95bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        } catch (RemoteException e) {
96bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            Log.w(TAG, "Error noting data connection state", e);
97bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
98bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
99bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
100bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private final void updateSimState(Intent intent) {
101bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
102bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
103bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mSimState = IccCardConstants.State.ABSENT;
104bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
105bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mSimState = IccCardConstants.State.READY;
106bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
107bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            final String lockedReason =
108bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
109bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
110bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                mSimState = IccCardConstants.State.PIN_REQUIRED;
111bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
112bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                mSimState = IccCardConstants.State.PUK_REQUIRED;
113bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            } else {
114bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                mSimState = IccCardConstants.State.NETWORK_LOCKED;
115bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            }
116bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        } else {
117bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mSimState = IccCardConstants.State.UNKNOWN;
118bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
119bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
120bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
121bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private boolean isCdma() {
122bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        return mSignalStrength != null && !mSignalStrength.isGsm();
123bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
124bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
125bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private boolean hasService() {
126bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        return mServiceState != null
127bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                && mServiceState.getState() != ServiceState.STATE_OUT_OF_SERVICE
128bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock                && mServiceState.getState() != ServiceState.STATE_POWER_OFF;
129bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    }
130bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
131bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
132bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        @Override
133bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
134bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mSignalStrength = signalStrength;
135bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
136bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
137bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        @Override
138bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        public void onServiceStateChanged(ServiceState state) {
139bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mServiceState = state;
140bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            notePhoneDataConnectionState();
141bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
142bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
143bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        @Override
144bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        public void onDataConnectionStateChanged(int state, int networkType) {
145bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            mDataState = state;
146bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            notePhoneDataConnectionState();
147bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
148bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock
149bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        @Override
150bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        public void onDataActivity(int direction) {
151bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock            notePhoneDataConnectionState();
152bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock        }
153bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock    };
154bf991a8f426921c26e21e54e493781e1d5eb39ffJohn Spurlock}
155