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

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: java singleton Created 3 years, 6 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.NonThreadSafe;
20 import org.chromium.base.ThreadUtils;
21 import org.chromium.base.annotations.CalledByNative; 21 import org.chromium.base.annotations.CalledByNative;
22 import org.chromium.base.annotations.JNINamespace; 22 import org.chromium.base.annotations.JNINamespace;
23 23 import org.chromium.base.annotations.SuppressFBWarnings;
24 import java.util.Iterator;
25 import java.util.List;
26 24
27 /** 25 /**
28 * This class interacts with the CellInfo API provided by Android. This class is thread safe. 26 * This class provides the cellular signal strength using the APIs provided by A ndroid. This class
27 * is thread safe.
29 */ 28 */
30 @JNINamespace("net::android::cellular_signal_strength") 29 @JNINamespace("net::android")
31 public class AndroidCellularSignalStrength { 30 public class AndroidCellularSignalStrength {
31 // {@link mSignalLevel} is set to volatile since may be accessed across thre ads.
32 private volatile int mSignalLevel = CellularSignalStrengthError.ERROR_NOT_SU PPORTED;
33
34 @SuppressFBWarnings("URF_UNREAD_FIELD")
35 private CellStateListener mCellStateListener;
36
37 // {@link mHandlerThread} is the thread on which {@link mCellStateListener} listens to the
38 // changes in the cellular signal strength.
39 private HandlerThread mHandlerThread;
pauljensen 2017/06/22 13:32:14 mHandlerThread should be a local not a member vari
tbansal1 2017/06/22 23:17:52 Done.
40
41 private static AndroidCellularSignalStrength sInstance;
42
43 private static volatile NonThreadSafe sThreadCheck;
44
32 /** 45 /**
33 * @return Signal strength (in dbM) for the currently registered cellular ne twork. Returns 46 * 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 47 * 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. 48 * application has running activities.
36 */ 49 */
37 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 50 private class CellStateListener
38 @CalledByNative 51 extends PhoneStateListener implements ApplicationStatus.ApplicationS tateListener {
39 public static int getSignalStrengthDbm() { 52 private final TelephonyManager mTelephonyManager;
40 List<CellInfo> cellInfos = getRegisteredCellInfo(); 53
41 return cellInfos == null || cellInfos.size() != 1 54 CellStateListener() {
42 ? CellularSignalStrengthError.ERROR_NOT_SUPPORTED 55 ThreadUtils.assertOnBackgroundThread();
43 : getSignalStrengthDbm(cellInfos.get(0)); 56
57 mTelephonyManager =
58 (TelephonyManager) ContextUtils.getApplicationContext().getS ystemService(
59 Context.TELEPHONY_SERVICE);
60
61 if (mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_RE ADY) return;
62
63 ApplicationStatus.registerApplicationStateListener(this);
64 onApplicationStateChange(ApplicationStatus.getStateForApplication()) ;
65 }
66
67 private void register() {
pauljensen 2017/06/22 13:32:14 I think you want to initialize mSignalLevel to ERR
tbansal1 2017/06/22 23:17:52 Done.
68 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_SIGNAL_STRE NGTHS);
69 }
70
71 private void unregister() {
72 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
73 }
74
75 @Override
76 @TargetApi(Build.VERSION_CODES.M)
77 public void onSignalStrengthsChanged(SignalStrength signalStrength) {
78 mSignalLevel = signalStrength.getLevel();
79 }
80
81 // ApplicationStatus.ApplicationStateListener
82 @Override
83 public void onApplicationStateChange(int newState) {
84 if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) {
85 register();
86 } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
87 unregister();
88 }
89 }
90 }
91
92 // Suppress FindBugs warning about unsynchronized initializing of the static field. The warning
93 // does not apply since {@link sInstance} is accessed on a single thread, wh ich is enforced
94 // using {@link sThreadCheck}.
95 @SuppressFBWarnings("LI_LAZY_INIT_STATIC")
96 private static AndroidCellularSignalStrength getInstance() {
97 if (sInstance == null) sInstance = new AndroidCellularSignalStrength();
98 return sInstance;
99 }
100
101 private AndroidCellularSignalStrength() {
102 if (!isAPIAvailable(ContextUtils.getApplicationContext())) return;
103
104 mHandlerThread = new HandlerThread("AndroidCellularSignalStrength");
105 mHandlerThread.start();
106
107 new Handler(mHandlerThread.getLooper()).post(new Runnable() {
108 @Override
109 public void run() {
110 mCellStateListener = new CellStateListener();
111 }
112 });
44 } 113 }
45 114
46 /** 115 /**
47 * @return the signal strength level (between 0 and 4, both inclusive) for t he currently 116 * @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 117 * 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 118 * {@link CellularSignalStrengthError#ERROR_NOT_SUPPORTED} if the signal str ength level is
50 * unavailable or if there are multiple cellular radios on the device. 119 * unavailable. Must be called on the same thread.
51 */ 120 */
52 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 121 @TargetApi(Build.VERSION_CODES.M)
53 @CalledByNative 122 @CalledByNative
54 public static int getSignalStrengthLevel() { 123 private static int getSignalStrengthLevel() {
55 List<CellInfo> cellInfos = getRegisteredCellInfo(); 124 if (sThreadCheck == null) {
56 return cellInfos == null || cellInfos.size() != 1 125 sThreadCheck = new NonThreadSafe();
57 ? CellularSignalStrengthError.ERROR_NOT_SUPPORTED 126 }
pauljensen 2017/06/22 13:32:14 This is racy and also I don't see any reason to re
tbansal1 2017/06/22 23:17:52 Done.
58 : getSignalStrengthLevel(cellInfos.get(0)); 127 assert sThreadCheck.calledOnValidThread();
128 return getInstance().mSignalLevel;
59 } 129 }
60 130
61 /** 131 /**
62 * Returns true if the API for quering the signal strength is available. 132 * Returns true if the API for quering the signal strength is available.
63 * {@link android.telephony#CellInfoWcdma} is only available on API Level 133 * {@link android.telephony.SignalStrength#getLevel} is only available on AP I Level
64 * {@link Build.VERSION_CODES#JELLY_BEAN_MR2} and higher. Also verifies that appropriate 134 * {@link Build.VERSION_CODES#M} and higher.
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 */ 135 */
90 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 136 private static boolean isAPIAvailable(Context context) {
91 private static List<CellInfo> getRegisteredCellInfo() { 137 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
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 } 138 }
159 } 139 }
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