summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/util/ConnectivityUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/messaging/util/ConnectivityUtil.java')
-rw-r--r--src/com/android/messaging/util/ConnectivityUtil.java247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/com/android/messaging/util/ConnectivityUtil.java b/src/com/android/messaging/util/ConnectivityUtil.java
new file mode 100644
index 0000000..49f6e0a
--- /dev/null
+++ b/src/com/android/messaging/util/ConnectivityUtil.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.messaging.util;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+
+public class ConnectivityUtil {
+ // Assume not connected until informed differently
+ private volatile int mCurrentServiceState = ServiceState.STATE_POWER_OFF;
+
+ private final TelephonyManager mTelephonyManager;
+ private final Context mContext;
+ private final ConnectivityBroadcastReceiver mReceiver;
+ private final ConnectivityManager mConnMgr;
+
+ private ConnectivityListener mListener;
+ private final IntentFilter mIntentFilter;
+
+ public interface ConnectivityListener {
+ public void onConnectivityStateChanged(final Context context, final Intent intent);
+ public void onPhoneStateChanged(final Context context, int serviceState);
+ }
+
+ public ConnectivityUtil(final Context context) {
+ mContext = context;
+ mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mConnMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mReceiver = new ConnectivityBroadcastReceiver();
+ mIntentFilter = new IntentFilter();
+ mIntentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ }
+
+ public int getCurrentServiceState() {
+ return mCurrentServiceState;
+ }
+
+ private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onServiceStateChanged(final ServiceState serviceState) {
+ if (mCurrentServiceState != serviceState.getState()) {
+ mCurrentServiceState = serviceState.getState();
+ onPhoneStateChanged(mCurrentServiceState);
+ }
+ }
+
+ @Override
+ public void onDataConnectionStateChanged(final int state) {
+ mCurrentServiceState = (state == TelephonyManager.DATA_DISCONNECTED) ?
+ ServiceState.STATE_OUT_OF_SERVICE : ServiceState.STATE_IN_SERVICE;
+ }
+ };
+
+ private void onPhoneStateChanged(final int serviceState) {
+ final ConnectivityListener listener = mListener;
+ if (listener != null) {
+ listener.onPhoneStateChanged(mContext, serviceState);
+ }
+ }
+
+ private void onConnectivityChanged(final Context context, final Intent intent) {
+ final ConnectivityListener listener = mListener;
+ if (listener != null) {
+ listener.onConnectivityStateChanged(context, intent);
+ }
+ }
+
+ public void register(final ConnectivityListener listener) {
+ Assert.isTrue(mListener == null || mListener == listener);
+ if (mListener == null) {
+ if (mTelephonyManager != null) {
+ mCurrentServiceState = (PhoneUtils.getDefault().isAirplaneModeOn() ?
+ ServiceState.STATE_POWER_OFF : ServiceState.STATE_IN_SERVICE);
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_SERVICE_STATE);
+ }
+ if (mConnMgr != null) {
+ mContext.registerReceiver(mReceiver, mIntentFilter);
+ }
+ }
+ mListener = listener;
+ }
+
+ public void unregister() {
+ if (mListener != null) {
+ if (mTelephonyManager != null) {
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ mCurrentServiceState = ServiceState.STATE_POWER_OFF;
+ }
+ if (mConnMgr != null) {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+ mListener = null;
+ }
+
+ /**
+ * Connectivity change broadcast receiver. This gets the network connectivity updates.
+ * In case we don't get the active connectivity when we first acquire the network,
+ * this receiver will notify us when it is connected, so to unblock the waiting thread
+ * which is sending the message.
+ */
+ public class ConnectivityBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ if (!intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+ return;
+ }
+
+ onConnectivityChanged(context, intent);
+ }
+ }
+
+ private int mSignalLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+ // We use a separate instance than mPhoneStateListener because the lifetimes are different.
+ private final PhoneStateListener mSignalStrengthListener = new PhoneStateListener() {
+ @Override
+ public void onSignalStrengthsChanged(final SignalStrength signalStrength) {
+ mSignalLevel = getLevel(signalStrength);
+ }
+ };
+
+ public void registerForSignalStrength() {
+ mTelephonyManager.listen(
+ mSignalStrengthListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+ }
+
+ public void unregisterForSignalStrength() {
+ mTelephonyManager.listen(mSignalStrengthListener, PhoneStateListener.LISTEN_NONE);
+ }
+
+ /**
+ * @param subId This is ignored because TelephonyManager does not support it.
+ * @return Signal strength as level 0..4
+ */
+ public int getSignalLevel(final int subId) {
+ return mSignalLevel;
+ }
+
+ private static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+ private static final int SIGNAL_STRENGTH_POOR = 1;
+ private static final int SIGNAL_STRENGTH_MODERATE = 2;
+ private static final int SIGNAL_STRENGTH_GOOD = 3;
+ private static final int SIGNAL_STRENGTH_GREAT = 4;
+
+ private static final int GSM_SIGNAL_STRENGTH_GREAT = 12;
+ private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
+ private static final int GSM_SIGNAL_STRENGTH_MODERATE = 8;
+
+ private static int getLevel(final SignalStrength signalStrength) {
+ if (signalStrength.isGsm()) {
+ // From frameworks/base/telephony/java/android/telephony/CellSignalStrengthGsm.java
+
+ // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+ // asu = 0 (-113dB or less) is very weak
+ // signal, its better to show 0 bars to the user in such cases.
+ // asu = 99 is a special case, where the signal strength is unknown.
+ final int asu = signalStrength.getGsmSignalStrength();
+ if (asu <= 2 || asu == 99) return SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ else if (asu >= GSM_SIGNAL_STRENGTH_GREAT) return SIGNAL_STRENGTH_GREAT;
+ else if (asu >= GSM_SIGNAL_STRENGTH_GOOD) return SIGNAL_STRENGTH_GOOD;
+ else if (asu >= GSM_SIGNAL_STRENGTH_MODERATE) return SIGNAL_STRENGTH_MODERATE;
+ else return SIGNAL_STRENGTH_POOR;
+ } else {
+ // From frameworks/base/telephony/java/android/telephony/CellSignalStrengthCdma.java
+
+ final int cdmaLevel = getCdmaLevel(signalStrength);
+ final int evdoLevel = getEvdoLevel(signalStrength);
+ if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+ /* We don't know evdo, use cdma */
+ return getCdmaLevel(signalStrength);
+ } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+ /* We don't know cdma, use evdo */
+ return getEvdoLevel(signalStrength);
+ } else {
+ /* We know both, use the lowest level */
+ return cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
+ }
+ }
+ }
+
+ /**
+ * Get cdma as level 0..4
+ */
+ private static int getCdmaLevel(final SignalStrength signalStrength) {
+ final int cdmaDbm = signalStrength.getCdmaDbm();
+ final int cdmaEcio = signalStrength.getCdmaEcio();
+ int levelDbm;
+ int levelEcio;
+ if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
+ else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
+ else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
+ else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
+ else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ // Ec/Io are in dB*10
+ if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
+ else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
+ else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
+ else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
+ else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ final int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
+ return level;
+ }
+ /**
+ * Get Evdo as level 0..4
+ */
+ private static int getEvdoLevel(final SignalStrength signalStrength) {
+ final int evdoDbm = signalStrength.getEvdoDbm();
+ final int evdoSnr = signalStrength.getEvdoSnr();
+ int levelEvdoDbm;
+ int levelEvdoSnr;
+ if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
+ else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
+ else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
+ else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
+ else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
+ else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
+ else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
+ else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
+ else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ final int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
+ return level;
+ }
+}