Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(192)

Side by Side Diff: net/android/java/src/org/chromium/net/AndroidCellularSignalStrength.java

Issue 2763853002: Use Android callback API to obtain cellular signal strength (Closed)
Patch Set: comments Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/android/cellular_signal_strength_unittest.cc ('k') | net/nqe/network_quality_estimator.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.net; 5 package org.chromium.net;
6 6
7 import android.Manifest;
8 import android.annotation.TargetApi; 7 import android.annotation.TargetApi;
9 import android.content.Context; 8 import android.content.Context;
10 import android.content.pm.PackageManager;
11 import android.os.Build; 9 import android.os.Build;
12 import android.os.Process; 10 import android.os.Handler;
13 import android.telephony.CellInfo; 11 import android.os.HandlerThread;
14 import android.telephony.CellInfoCdma; 12 import android.telephony.PhoneStateListener;
15 import android.telephony.CellInfoGsm; 13 import android.telephony.SignalStrength;
16 import android.telephony.CellInfoLte;
17 import android.telephony.CellInfoWcdma;
18 import android.telephony.TelephonyManager; 14 import android.telephony.TelephonyManager;
19 15
16 import org.chromium.base.ApplicationState;
17 import org.chromium.base.ApplicationStatus;
20 import org.chromium.base.ContextUtils; 18 import org.chromium.base.ContextUtils;
19 import org.chromium.base.ThreadUtils;
21 import org.chromium.base.annotations.CalledByNative; 20 import org.chromium.base.annotations.CalledByNative;
22 import org.chromium.base.annotations.JNINamespace; 21 import org.chromium.base.annotations.JNINamespace;
23 22
24 import java.util.Iterator; 23 /**
25 import java.util.List; 24 * This class provides the cellular signal strength using the APIs provided by A ndroid. This class
25 * is thread safe.
26 */
27 @JNINamespace("net::android")
28 public class AndroidCellularSignalStrength {
29 // {@link mSignalLevel} is set to volatile since may be accessed across thre ads.
30 private volatile int mSignalLevel = CellularSignalStrengthError.ERROR_NOT_SU PPORTED;
26 31
27 /** 32 private static final AndroidCellularSignalStrength sInstance =
28 * This class interacts with the CellInfo API provided by Android. This class is thread safe. 33 new AndroidCellularSignalStrength();
29 */ 34
30 @JNINamespace("net::android::cellular_signal_strength")
31 public class AndroidCellularSignalStrength {
32 /** 35 /**
33 * @return Signal strength (in dbM) for the currently registered cellular ne twork. Returns 36 * This class listens to the changes in the cellular signal strength level a nd updates {@link
34 * {@link CellularSignalStrengthError#ERROR_NOT_SUPPORTED} if the signal str ength is 37 * mSignalLevel}. {@link CellStateListener} registers as a signal strength o bserver only if the
35 * unavailable or if there are multiple cellular radios on the device. 38 * application has running activities.
36 */ 39 */
37 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 40 private class CellStateListener
38 @CalledByNative 41 extends PhoneStateListener implements ApplicationStatus.ApplicationS tateListener {
39 public static int getSignalStrengthDbm() { 42 private final TelephonyManager mTelephonyManager;
40 List<CellInfo> cellInfos = getRegisteredCellInfo(); 43
41 return cellInfos == null || cellInfos.size() != 1 44 CellStateListener() {
42 ? CellularSignalStrengthError.ERROR_NOT_SUPPORTED 45 ThreadUtils.assertOnBackgroundThread();
43 : getSignalStrengthDbm(cellInfos.get(0)); 46
47 mTelephonyManager =
48 (TelephonyManager) ContextUtils.getApplicationContext().getS ystemService(
49 Context.TELEPHONY_SERVICE);
50
51 if (mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_RE ADY) return;
52
53 ApplicationStatus.registerApplicationStateListener(this);
54 onApplicationStateChange(ApplicationStatus.getStateForApplication()) ;
55 }
56
57 private void register() {
58 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_SIGNAL_STRE NGTHS);
59 }
60
61 private void unregister() {
62 mSignalLevel = CellularSignalStrengthError.ERROR_NOT_SUPPORTED;
63 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
64 }
65
66 @Override
67 @TargetApi(Build.VERSION_CODES.M)
68 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
69 if (ApplicationStatus.getStateForApplication()
70 != ApplicationState.HAS_RUNNING_ACTIVITIES) {
71 return;
72 }
73 mSignalLevel = signalStrength.getLevel();
74 }
75
76 // ApplicationStatus.ApplicationStateListener
77 @Override
78 public void onApplicationStateChange(int newState) {
79 if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) {
80 register();
81 } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
82 unregister();
83 }
84 }
85 }
86
87 private AndroidCellularSignalStrength() {
88 // {@link android.telephony.SignalStrength#getLevel} is only available o n API Level
89 // {@link Build.VERSION_CODES#M} and higher.
90 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
91
92 HandlerThread handlerThread = new HandlerThread("AndroidCellularSignalSt rength");
93 handlerThread.start();
94
95 new Handler(handlerThread.getLooper()).post(new Runnable() {
96 @Override
97 public void run() {
98 new CellStateListener();
99 }
100 });
44 } 101 }
45 102
46 /** 103 /**
47 * @return the signal strength level (between 0 and 4, both inclusive) for t he currently 104 * @return the signal strength level (between 0 and 4, both inclusive) for t he currently
48 * registered cellular network with lower value indicating lower signal stre ngth. Returns 105 * registered cellular network with lower value indicating lower signal stre ngth. Returns
49 * {@link CellularSignalStrengthError#ERROR_NOT_SUPPORTED} if the signal str ength level is 106 * {@link CellularSignalStrengthError#ERROR_NOT_SUPPORTED} if the signal str ength level is
50 * unavailable or if there are multiple cellular radios on the device. 107 * unavailable.
51 */ 108 */
52 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 109 @TargetApi(Build.VERSION_CODES.M)
53 @CalledByNative 110 @CalledByNative
54 public static int getSignalStrengthLevel() { 111 private static int getSignalStrengthLevel() {
55 List<CellInfo> cellInfos = getRegisteredCellInfo(); 112 return sInstance.mSignalLevel;
56 return cellInfos == null || cellInfos.size() != 1
57 ? CellularSignalStrengthError.ERROR_NOT_SUPPORTED
58 : getSignalStrengthLevel(cellInfos.get(0));
59 }
60
61 /**
62 * Returns true if the API for quering the signal strength is available.
63 * {@link android.telephony#CellInfoWcdma} is only available on API Level
64 * {@link Build.VERSION_CODES#JELLY_BEAN_MR2} and higher. Also verifies that appropriate
65 * permissions are already available. This ensures that on Android M and hig her, Chromium will
66 * not request run-time permission from the user when querying for cellular signal strength.
67 * TODO(tbansal): Consider using {@link TelephonyManager#getNeighboringCellI nfo}
68 * for earlier versions of Android.
69 */
70 private static boolean isAPIAvailable() {
71 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) return f alse;
72
73 try {
74 return ContextUtils.getApplicationContext().checkPermission(
75 Manifest.permission.ACCESS_COARSE_LOCATION, Process.m yPid(),
76 Process.myUid())
77 == PackageManager.PERMISSION_GRANTED;
78 } catch (Exception ignored) {
79 // Work around certain platforms where this method sometimes throws a runtime exception.
80 // See crbug.com/663360.
81 }
82 return false;
83 }
84
85 /**
86 * Returns all observed cell information from all radios on the device inclu ding the primary
87 * and neighboring cells. Returns only the information of cells that are reg istered to a
88 * mobile network. May return {@code null}.
89 */
90 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
91 private static List<CellInfo> getRegisteredCellInfo() {
92 if (!isAPIAvailable()) {
93 return null;
94 }
95
96 TelephonyManager telephonyManager =
97 (TelephonyManager) ContextUtils.getApplicationContext().getSyste mService(
98 Context.TELEPHONY_SERVICE);
99 if (telephonyManager == null) {
100 return null;
101 }
102
103 List<CellInfo> cellInfos = telephonyManager.getAllCellInfo();
104 if (cellInfos == null) {
105 return null;
106 }
107
108 Iterator<CellInfo> iter = cellInfos.iterator();
109 while (iter.hasNext()) {
110 if (!iter.next().isRegistered()) {
111 iter.remove();
112 }
113 }
114 return cellInfos;
115 }
116
117 /**
118 * @return Signal strength (in dbM) from {@link cellInfo}. Returns {@link
119 * CellularSignalStrengthError#ERROR_NOT_SUPPORTED} if the signal strength i s unavailable.
120 */
121 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
122 private static int getSignalStrengthDbm(CellInfo cellInfo) {
123 if (cellInfo instanceof CellInfoCdma) {
124 return ((CellInfoCdma) cellInfo).getCellSignalStrength().getDbm();
125 }
126 if (cellInfo instanceof CellInfoGsm) {
127 return ((CellInfoGsm) cellInfo).getCellSignalStrength().getDbm();
128 }
129 if (cellInfo instanceof CellInfoLte) {
130 return ((CellInfoLte) cellInfo).getCellSignalStrength().getDbm();
131 }
132 if (cellInfo instanceof CellInfoWcdma) {
133 return ((CellInfoWcdma) cellInfo).getCellSignalStrength().getDbm();
134 }
135 return CellularSignalStrengthError.ERROR_NOT_SUPPORTED;
136 }
137
138 /**
139 * @return the signal level from {@link cellInfo}. Returns {@link
140 * CellularSignalStrengthError#ERROR_NOT_SUPPORTED} if the signal
141 * level is unavailable with lower value indicating lower signal strength.
142 */
143 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
144 private static int getSignalStrengthLevel(CellInfo cellInfo) {
145 if (cellInfo instanceof CellInfoCdma) {
146 return ((CellInfoCdma) cellInfo).getCellSignalStrength().getLevel();
147 }
148 if (cellInfo instanceof CellInfoGsm) {
149 return ((CellInfoGsm) cellInfo).getCellSignalStrength().getLevel();
150 }
151 if (cellInfo instanceof CellInfoLte) {
152 return ((CellInfoLte) cellInfo).getCellSignalStrength().getLevel();
153 }
154 if (cellInfo instanceof CellInfoWcdma) {
155 return ((CellInfoWcdma) cellInfo).getCellSignalStrength().getLevel() ;
156 }
157 return CellularSignalStrengthError.ERROR_NOT_SUPPORTED;
158 } 113 }
159 } 114 }
OLDNEW
« no previous file with comments | « net/android/cellular_signal_strength_unittest.cc ('k') | net/nqe/network_quality_estimator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698