blob: eb14180766b20cd90408345c14b9d50286e316c9 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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;
18
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.PackageManager;
Wink Savillef61101f2010-09-16 16:36:42 -070022import android.net.LinkCapabilities;
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070023import android.net.LinkProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.os.Binder;
25import android.os.Bundle;
26import android.os.IBinder;
27import android.os.RemoteException;
28import android.telephony.CellLocation;
29import android.telephony.PhoneStateListener;
30import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070031import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.telephony.TelephonyManager;
33import android.text.TextUtils;
Joe Onorato8a9b2202010-02-26 18:56:32 -080034import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
36import java.util.ArrayList;
37import java.io.FileDescriptor;
38import java.io.PrintWriter;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070039import java.net.NetworkInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41import com.android.internal.app.IBatteryStats;
42import com.android.internal.telephony.ITelephonyRegistry;
43import com.android.internal.telephony.IPhoneStateListener;
44import com.android.internal.telephony.DefaultPhoneNotifier;
45import com.android.internal.telephony.Phone;
Wink Savillec9330dd2011-01-12 13:37:38 -080046import com.android.internal.telephony.ServiceStateTracker;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import com.android.internal.telephony.TelephonyIntents;
48import com.android.server.am.BatteryStatsService;
49
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050/**
Wink Savillee9b06d72009-05-18 21:47:50 -070051 * Since phone process can be restarted, this class provides a centralized place
52 * that applications can register and be called back from.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 */
54class TelephonyRegistry extends ITelephonyRegistry.Stub {
55 private static final String TAG = "TelephonyRegistry";
56
57 private static class Record {
58 String pkgForDebug;
Wink Savillee9b06d72009-05-18 21:47:50 -070059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 IBinder binder;
Wink Savillee9b06d72009-05-18 21:47:50 -070061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 IPhoneStateListener callback;
Wink Savillee9b06d72009-05-18 21:47:50 -070063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 int events;
65 }
66
67 private final Context mContext;
Wink Savillee9b06d72009-05-18 21:47:50 -070068
Joe Onorato163d8d92010-10-21 13:21:20 -040069 // access should be inside synchronized (mRecords) for these two fields
70 private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
71 private final ArrayList<Record> mRecords = new ArrayList<Record>();
Wink Savillee9b06d72009-05-18 21:47:50 -070072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 private final IBatteryStats mBatteryStats;
74
75 private int mCallState = TelephonyManager.CALL_STATE_IDLE;
Wink Savillee9b06d72009-05-18 21:47:50 -070076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 private String mCallIncomingNumber = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private ServiceState mServiceState = new ServiceState();
Wink Savillee9b06d72009-05-18 21:47:50 -070080
81 private SignalStrength mSignalStrength = new SignalStrength();
82
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 private boolean mMessageWaiting = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 private boolean mCallForwarding = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
Wink Savillee9b06d72009-05-18 21:47:50 -070088
Robert Greenwalt8e7e0a92010-11-09 10:24:40 -080089 private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN;
Wink Savillee9b06d72009-05-18 21:47:50 -070090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 private boolean mDataConnectionPossible = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 private String mDataConnectionReason = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 private String mDataConnectionApn = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070096
Robert Greenwalt02648a42010-05-18 10:52:51 -070097 private ArrayList<String> mConnectedApns;
Robert Greenwalt42acef32009-08-12 16:08:25 -070098
Wink Savillef61101f2010-09-16 16:36:42 -070099 private LinkProperties mDataConnectionLinkProperties;
100
101 private LinkCapabilities mDataConnectionLinkCapabilities;
Wink Savillee9b06d72009-05-18 21:47:50 -0700102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 private Bundle mCellLocation = new Bundle();
104
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700105 private int mDataConnectionNetworkType;
106
Wink Savillec9330dd2011-01-12 13:37:38 -0800107 private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
Wink Savillefd2d0132010-10-28 14:22:26 -0700108
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700109 static final int PHONE_STATE_PERMISSION_MASK =
110 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
111 PhoneStateListener.LISTEN_CALL_STATE |
112 PhoneStateListener.LISTEN_DATA_ACTIVITY |
113 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
114 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
115
Wink Savillee9b06d72009-05-18 21:47:50 -0700116 // we keep a copy of all of the state so we can send it out when folks
117 // register for it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 //
Wink Savillee9b06d72009-05-18 21:47:50 -0700119 // In these calls we call with the lock held. This is safe becasuse remote
120 // calls go through a oneway interface and local calls going through a
121 // handler before they get to app code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122
123 TelephonyRegistry(Context context) {
David 'Digit' Turner4ef8ec32009-09-25 11:33:24 -0700124 CellLocation location = CellLocation.getEmpty();
125
126 // Note that location can be null for non-phone builds like
127 // like the generic one.
128 if (location != null) {
129 location.fillInNotifierBundle(mCellLocation);
130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 mContext = context;
132 mBatteryStats = BatteryStatsService.getService();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700133 mConnectedApns = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 }
135
136 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
137 boolean notifyNow) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800138 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
Wink Savillee9b06d72009-05-18 21:47:50 -0700139 // Integer.toHexString(events));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 if (events != 0) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700141 /* Checks permission and throws Security exception */
142 checkListenerPermission(events);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143
144 synchronized (mRecords) {
145 // register
146 Record r = null;
147 find_and_add: {
148 IBinder b = callback.asBinder();
149 final int N = mRecords.size();
Wink Savillee9b06d72009-05-18 21:47:50 -0700150 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 r = mRecords.get(i);
152 if (b == r.binder) {
153 break find_and_add;
154 }
155 }
156 r = new Record();
157 r.binder = b;
158 r.callback = callback;
159 r.pkgForDebug = pkgForDebug;
160 mRecords.add(r);
161 }
162 int send = events & (events ^ r.events);
163 r.events = events;
164 if (notifyNow) {
165 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400166 try {
167 r.callback.onServiceStateChanged(new ServiceState(mServiceState));
168 } catch (RemoteException ex) {
169 remove(r.binder);
170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 }
172 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
173 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700174 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
175 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
176 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 } catch (RemoteException ex) {
178 remove(r.binder);
179 }
180 }
181 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
182 try {
183 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
184 } catch (RemoteException ex) {
185 remove(r.binder);
186 }
187 }
188 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
189 try {
190 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
191 } catch (RemoteException ex) {
192 remove(r.binder);
193 }
194 }
195 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400196 try {
197 r.callback.onCellLocationChanged(new Bundle(mCellLocation));
198 } catch (RemoteException ex) {
199 remove(r.binder);
200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 }
202 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
203 try {
204 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
205 } catch (RemoteException ex) {
206 remove(r.binder);
207 }
208 }
209 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
210 try {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700211 r.callback.onDataConnectionStateChanged(mDataConnectionState,
212 mDataConnectionNetworkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 } catch (RemoteException ex) {
214 remove(r.binder);
215 }
216 }
217 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
218 try {
219 r.callback.onDataActivity(mDataActivity);
220 } catch (RemoteException ex) {
221 remove(r.binder);
222 }
223 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700224 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
225 try {
226 r.callback.onSignalStrengthsChanged(mSignalStrength);
227 } catch (RemoteException ex) {
228 remove(r.binder);
229 }
230 }
Wink Savillefd2d0132010-10-28 14:22:26 -0700231 if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
232 try {
233 r.callback.onOtaspChanged(mOtaspMode);
234 } catch (RemoteException ex) {
235 remove(r.binder);
236 }
237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 }
239 }
240 } else {
241 remove(callback.asBinder());
242 }
243 }
244
245 private void remove(IBinder binder) {
246 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700247 final int recordCount = mRecords.size();
248 for (int i = 0; i < recordCount; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 if (mRecords.get(i).binder == binder) {
250 mRecords.remove(i);
251 return;
252 }
253 }
254 }
255 }
256
257 public void notifyCallState(int state, String incomingNumber) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700258 if (!checkNotifyPermission("notifyCallState()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700259 return;
260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 synchronized (mRecords) {
262 mCallState = state;
263 mCallIncomingNumber = incomingNumber;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700264 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
266 try {
267 r.callback.onCallStateChanged(state, incomingNumber);
268 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400269 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 }
271 }
272 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400273 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 }
275 broadcastCallStateChanged(state, incomingNumber);
276 }
277
278 public void notifyServiceState(ServiceState state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700279 if (!checkNotifyPermission("notifyServiceState()")){
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700280 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700281 }
Joe Onorato431bb222010-10-18 19:13:23 -0400282 Slog.i(TAG, "notifyServiceState: " + state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 synchronized (mRecords) {
284 mServiceState = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700285 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400287 try {
288 r.callback.onServiceStateChanged(new ServiceState(state));
289 } catch (RemoteException ex) {
290 mRemoveList.add(r.binder);
291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 }
293 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400294 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 }
296 broadcastServiceStateChanged(state);
297 }
298
Wink Savillee9b06d72009-05-18 21:47:50 -0700299 public void notifySignalStrength(SignalStrength signalStrength) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700300 if (!checkNotifyPermission("notifySignalStrength()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700301 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700304 mSignalStrength = signalStrength;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700305 for (Record r : mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700306 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400307 try {
308 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
309 } catch (RemoteException ex) {
310 mRemoveList.add(r.binder);
311 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
314 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700315 int gsmSignalStrength = signalStrength.getGsmSignalStrength();
316 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
317 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400319 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 }
321 }
322 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400323 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700325 broadcastSignalStrengthChanged(signalStrength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 }
327
328 public void notifyMessageWaitingChanged(boolean mwi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700329 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700330 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 synchronized (mRecords) {
333 mMessageWaiting = mwi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700334 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
336 try {
337 r.callback.onMessageWaitingIndicatorChanged(mwi);
338 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400339 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 }
341 }
342 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400343 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 }
345 }
346
347 public void notifyCallForwardingChanged(boolean cfi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700348 if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700349 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 synchronized (mRecords) {
352 mCallForwarding = cfi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700353 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
355 try {
356 r.callback.onCallForwardingIndicatorChanged(cfi);
357 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400358 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 }
360 }
361 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400362 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 }
364 }
365
366 public void notifyDataActivity(int state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700367 if (!checkNotifyPermission("notifyDataActivity()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700368 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 synchronized (mRecords) {
371 mDataActivity = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700372 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
374 try {
375 r.callback.onDataActivity(state);
376 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400377 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 }
379 }
380 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400381 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 }
383 }
384
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700385 public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700386 String reason, String apn, String apnType, LinkProperties linkProperties,
Wink Savillef61101f2010-09-16 16:36:42 -0700387 LinkCapabilities linkCapabilities, int networkType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700388 if (!checkNotifyPermission("notifyDataConnection()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700389 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700390 }
Joe Onorato431bb222010-10-18 19:13:23 -0400391 Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
Wink Saville26f5a382010-11-24 16:44:29 -0800392 + isDataConnectivityPossible + " reason='" + reason
393 + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 synchronized (mRecords) {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700395 boolean modified = false;
396 if (state == TelephonyManager.DATA_CONNECTED) {
397 if (!mConnectedApns.contains(apnType)) {
398 mConnectedApns.add(apnType);
399 if (mDataConnectionState != state) {
400 mDataConnectionState = state;
401 modified = true;
402 }
403 }
404 } else {
Robert Greenwalt8e7e0a92010-11-09 10:24:40 -0800405 if (mConnectedApns.remove(apnType)) {
406 if (mConnectedApns.isEmpty()) {
407 mDataConnectionState = state;
408 modified = true;
409 } else {
410 // leave mDataConnectionState as is and
411 // send out the new status for the APN in question.
412 }
Robert Greenwalt02648a42010-05-18 10:52:51 -0700413 }
414 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700415 mDataConnectionPossible = isDataConnectivityPossible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 mDataConnectionReason = reason;
Wink Savillef61101f2010-09-16 16:36:42 -0700417 mDataConnectionLinkProperties = linkProperties;
418 mDataConnectionLinkCapabilities = linkCapabilities;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700419 if (mDataConnectionNetworkType != networkType) {
420 mDataConnectionNetworkType = networkType;
Robert Greenwalt8e7e0a92010-11-09 10:24:40 -0800421 // need to tell registered listeners about the new network type
Robert Greenwalt02648a42010-05-18 10:52:51 -0700422 modified = true;
423 }
424 if (modified) {
Robert Greenwalt8e7e0a92010-11-09 10:24:40 -0800425 Slog.d(TAG, "onDataConnectionStateChanged(" + state + ", " + networkType + ")");
Robert Greenwalt02648a42010-05-18 10:52:51 -0700426 for (Record r : mRecords) {
427 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
428 try {
429 r.callback.onDataConnectionStateChanged(state, networkType);
430 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400431 mRemoveList.add(r.binder);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 }
434 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400435 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 }
437 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700438 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
Wink Savillef61101f2010-09-16 16:36:42 -0700439 apnType, linkProperties, linkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 }
441
Robert Greenwalt02648a42010-05-18 10:52:51 -0700442 public void notifyDataConnectionFailed(String reason, String apnType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700443 if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700444 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 /*
Robert Greenwalt02648a42010-05-18 10:52:51 -0700447 * This is commented out because there is no onDataConnectionFailed callback
448 * in PhoneStateListener. There should be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 synchronized (mRecords) {
450 mDataConnectionFailedReason = reason;
451 final int N = mRecords.size();
452 for (int i=N-1; i>=0; i--) {
453 Record r = mRecords.get(i);
454 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
455 // XXX
456 }
457 }
458 }
459 */
Robert Greenwalt02648a42010-05-18 10:52:51 -0700460 broadcastDataConnectionFailed(reason, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 }
462
463 public void notifyCellLocation(Bundle cellLocation) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700464 if (!checkNotifyPermission("notifyCellLocation()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700465 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 synchronized (mRecords) {
468 mCellLocation = cellLocation;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700469 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400471 try {
472 r.callback.onCellLocationChanged(new Bundle(cellLocation));
473 } catch (RemoteException ex) {
474 mRemoveList.add(r.binder);
475 }
476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 }
478 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400479 handleRemoveListLocked();
Wink Savillee9b06d72009-05-18 21:47:50 -0700480 }
481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482
Wink Savillefd2d0132010-10-28 14:22:26 -0700483 public void notifyOtaspChanged(int otaspMode) {
484 if (!checkNotifyPermission("notifyOtaspChanged()" )) {
485 return;
486 }
487 synchronized (mRecords) {
488 mOtaspMode = otaspMode;
489 for (Record r : mRecords) {
490 if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
491 try {
492 r.callback.onOtaspChanged(otaspMode);
493 } catch (RemoteException ex) {
494 mRemoveList.add(r.binder);
495 }
496 }
497 }
498 handleRemoveListLocked();
499 }
500 }
501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 @Override
503 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
504 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
505 != PackageManager.PERMISSION_GRANTED) {
506 pw.println("Permission Denial: can't dump telephony.registry from from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700507 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 return;
509 }
510 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700511 final int recordCount = mRecords.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 pw.println("last known state:");
513 pw.println(" mCallState=" + mCallState);
514 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
515 pw.println(" mServiceState=" + mServiceState);
516 pw.println(" mSignalStrength=" + mSignalStrength);
517 pw.println(" mMessageWaiting=" + mMessageWaiting);
518 pw.println(" mCallForwarding=" + mCallForwarding);
519 pw.println(" mDataActivity=" + mDataActivity);
520 pw.println(" mDataConnectionState=" + mDataConnectionState);
521 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
522 pw.println(" mDataConnectionReason=" + mDataConnectionReason);
523 pw.println(" mDataConnectionApn=" + mDataConnectionApn);
Wink Savillef61101f2010-09-16 16:36:42 -0700524 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
525 pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 pw.println(" mCellLocation=" + mCellLocation);
Wink Savillee9b06d72009-05-18 21:47:50 -0700527 pw.println("registrations: count=" + recordCount);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700528 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
530 }
531 }
532 }
533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 //
535 // the legacy intent broadcasting
536 //
537
538 private void broadcastServiceStateChanged(ServiceState state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700539 long ident = Binder.clearCallingIdentity();
540 try {
Amith Yamasanif37447b2009-10-08 18:28:01 -0700541 mBatteryStats.notePhoneState(state.getState());
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700542 } catch (RemoteException re) {
543 // Can't do much
544 } finally {
545 Binder.restoreCallingIdentity(ident);
546 }
547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800549 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 Bundle data = new Bundle();
551 state.fillInNotifierBundle(data);
552 intent.putExtras(data);
553 mContext.sendStickyBroadcast(intent);
554 }
555
Wink Savillee9b06d72009-05-18 21:47:50 -0700556 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700557 long ident = Binder.clearCallingIdentity();
558 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700559 mBatteryStats.notePhoneSignalStrength(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700560 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700561 /* The remote entity disappeared, we can safely ignore the exception. */
Dianne Hackborn627bba72009-03-24 22:32:56 -0700562 } finally {
563 Binder.restoreCallingIdentity(ident);
564 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800567 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700568 Bundle data = new Bundle();
569 signalStrength.fillInNotifierBundle(data);
570 intent.putExtras(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 mContext.sendStickyBroadcast(intent);
572 }
573
574 private void broadcastCallStateChanged(int state, String incomingNumber) {
575 long ident = Binder.clearCallingIdentity();
576 try {
577 if (state == TelephonyManager.CALL_STATE_IDLE) {
578 mBatteryStats.notePhoneOff();
579 } else {
580 mBatteryStats.notePhoneOn();
581 }
582 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700583 /* The remote entity disappeared, we can safely ignore the exception. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 } finally {
585 Binder.restoreCallingIdentity(ident);
586 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800589 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700590 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 if (!TextUtils.isEmpty(incomingNumber)) {
592 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
593 }
594 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
595 }
596
Robert Greenwalt42acef32009-08-12 16:08:25 -0700597 private void broadcastDataConnectionStateChanged(int state,
598 boolean isDataConnectivityPossible,
Wink Savillef61101f2010-09-16 16:36:42 -0700599 String reason, String apn, String apnType, LinkProperties linkProperties,
600 LinkCapabilities linkCapabilities) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700601 // Note: not reporting to the battery stats service here, because the
602 // status bar takes care of that after taking into account all of the
603 // required info.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800604 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800605 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
607 if (!isDataConnectivityPossible) {
608 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
609 }
610 if (reason != null) {
611 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
612 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700613 if (linkProperties != null) {
614 intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties);
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700615 String iface = linkProperties.getInterfaceName();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700616 if (iface != null) {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700617 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700618 }
619 }
Wink Savillef61101f2010-09-16 16:36:42 -0700620 if (linkCapabilities != null) {
621 intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities);
622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 intent.putExtra(Phone.DATA_APN_KEY, apn);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700624 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 mContext.sendStickyBroadcast(intent);
626 }
627
Robert Greenwalt02648a42010-05-18 10:52:51 -0700628 private void broadcastDataConnectionFailed(String reason, String apnType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800630 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700632 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 mContext.sendStickyBroadcast(intent);
634 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700635
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700636 private boolean checkNotifyPermission(String method) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700637 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
638 == PackageManager.PERMISSION_GRANTED) {
639 return true;
640 }
641 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700642 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800643 Slog.w(TAG, msg);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700644 return false;
645 }
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700646
647 private void checkListenerPermission(int events) {
648 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
649 mContext.enforceCallingOrSelfPermission(
650 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
651
652 }
653
654 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
655 mContext.enforceCallingOrSelfPermission(
656 android.Manifest.permission.READ_PHONE_STATE, null);
657 }
658 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400659
660 private void handleRemoveListLocked() {
661 if (mRemoveList.size() > 0) {
662 for (IBinder b: mRemoveList) {
663 remove(b);
664 }
665 mRemoveList.clear();
666 }
667 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668}