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