blob: a33b7c294c695840842fb7f2ce5057a5a5f9be3c [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import com.android.internal.telephony.TelephonyIntents;
47import com.android.server.am.BatteryStatsService;
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049/**
Wink Savillee9b06d72009-05-18 21:47:50 -070050 * Since phone process can be restarted, this class provides a centralized place
51 * that applications can register and be called back from.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 */
53class TelephonyRegistry extends ITelephonyRegistry.Stub {
54 private static final String TAG = "TelephonyRegistry";
55
56 private static class Record {
57 String pkgForDebug;
Wink Savillee9b06d72009-05-18 21:47:50 -070058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 IBinder binder;
Wink Savillee9b06d72009-05-18 21:47:50 -070060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 IPhoneStateListener callback;
Wink Savillee9b06d72009-05-18 21:47:50 -070062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063 int events;
64 }
65
66 private final Context mContext;
Wink Savillee9b06d72009-05-18 21:47:50 -070067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 private final ArrayList<Record> mRecords = new ArrayList();
Wink Savillee9b06d72009-05-18 21:47:50 -070069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070 private final IBatteryStats mBatteryStats;
71
72 private int mCallState = TelephonyManager.CALL_STATE_IDLE;
Wink Savillee9b06d72009-05-18 21:47:50 -070073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 private String mCallIncomingNumber = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 private ServiceState mServiceState = new ServiceState();
Wink Savillee9b06d72009-05-18 21:47:50 -070077
78 private SignalStrength mSignalStrength = new SignalStrength();
79
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 private boolean mMessageWaiting = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 private boolean mCallForwarding = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
Wink Savillee9b06d72009-05-18 21:47:50 -070085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
Wink Savillee9b06d72009-05-18 21:47:50 -070087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 private boolean mDataConnectionPossible = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 private String mDataConnectionReason = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 private String mDataConnectionApn = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070093
Robert Greenwalt02648a42010-05-18 10:52:51 -070094 private ArrayList<String> mConnectedApns;
Robert Greenwalt42acef32009-08-12 16:08:25 -070095
Wink Savillef61101f2010-09-16 16:36:42 -070096 private LinkProperties mDataConnectionLinkProperties;
97
98 private LinkCapabilities mDataConnectionLinkCapabilities;
Wink Savillee9b06d72009-05-18 21:47:50 -070099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 private Bundle mCellLocation = new Bundle();
101
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700102 private int mDataConnectionNetworkType;
103
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700104 static final int PHONE_STATE_PERMISSION_MASK =
105 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
106 PhoneStateListener.LISTEN_CALL_STATE |
107 PhoneStateListener.LISTEN_DATA_ACTIVITY |
108 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
109 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
110
Wink Savillee9b06d72009-05-18 21:47:50 -0700111 // we keep a copy of all of the state so we can send it out when folks
112 // register for it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 //
Wink Savillee9b06d72009-05-18 21:47:50 -0700114 // In these calls we call with the lock held. This is safe becasuse remote
115 // calls go through a oneway interface and local calls going through a
116 // handler before they get to app code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
118 TelephonyRegistry(Context context) {
David 'Digit' Turner4ef8ec32009-09-25 11:33:24 -0700119 CellLocation location = CellLocation.getEmpty();
120
121 // Note that location can be null for non-phone builds like
122 // like the generic one.
123 if (location != null) {
124 location.fillInNotifierBundle(mCellLocation);
125 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 mContext = context;
127 mBatteryStats = BatteryStatsService.getService();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700128 mConnectedApns = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 }
130
131 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
132 boolean notifyNow) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800133 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
Wink Savillee9b06d72009-05-18 21:47:50 -0700134 // Integer.toHexString(events));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 if (events != 0) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700136 /* Checks permission and throws Security exception */
137 checkListenerPermission(events);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138
139 synchronized (mRecords) {
140 // register
141 Record r = null;
142 find_and_add: {
143 IBinder b = callback.asBinder();
144 final int N = mRecords.size();
Wink Savillee9b06d72009-05-18 21:47:50 -0700145 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 r = mRecords.get(i);
147 if (b == r.binder) {
148 break find_and_add;
149 }
150 }
151 r = new Record();
152 r.binder = b;
153 r.callback = callback;
154 r.pkgForDebug = pkgForDebug;
155 mRecords.add(r);
156 }
157 int send = events & (events ^ r.events);
158 r.events = events;
159 if (notifyNow) {
160 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
161 sendServiceState(r, mServiceState);
162 }
163 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
164 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700165 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
166 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
167 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 } catch (RemoteException ex) {
169 remove(r.binder);
170 }
171 }
172 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
173 try {
174 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
175 } catch (RemoteException ex) {
176 remove(r.binder);
177 }
178 }
179 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
180 try {
181 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
182 } catch (RemoteException ex) {
183 remove(r.binder);
184 }
185 }
186 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
187 sendCellLocation(r, mCellLocation);
188 }
189 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
190 try {
191 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
192 } catch (RemoteException ex) {
193 remove(r.binder);
194 }
195 }
196 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
197 try {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700198 r.callback.onDataConnectionStateChanged(mDataConnectionState,
199 mDataConnectionNetworkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 } catch (RemoteException ex) {
201 remove(r.binder);
202 }
203 }
204 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
205 try {
206 r.callback.onDataActivity(mDataActivity);
207 } catch (RemoteException ex) {
208 remove(r.binder);
209 }
210 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700211 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
212 try {
213 r.callback.onSignalStrengthsChanged(mSignalStrength);
214 } catch (RemoteException ex) {
215 remove(r.binder);
216 }
217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 }
219 }
220 } else {
221 remove(callback.asBinder());
222 }
223 }
224
225 private void remove(IBinder binder) {
226 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700227 final int recordCount = mRecords.size();
228 for (int i = 0; i < recordCount; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 if (mRecords.get(i).binder == binder) {
230 mRecords.remove(i);
231 return;
232 }
233 }
234 }
235 }
236
237 public void notifyCallState(int state, String incomingNumber) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700238 if (!checkNotifyPermission("notifyCallState()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700239 return;
240 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700241 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 synchronized (mRecords) {
243 mCallState = state;
244 mCallIncomingNumber = incomingNumber;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700245 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
247 try {
248 r.callback.onCallStateChanged(state, incomingNumber);
249 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700250 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 }
252 }
253 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700254 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 }
256 broadcastCallStateChanged(state, incomingNumber);
257 }
258
259 public void notifyServiceState(ServiceState state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700260 if (!checkNotifyPermission("notifyServiceState()")){
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700261 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 synchronized (mRecords) {
264 mServiceState = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700265 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
267 sendServiceState(r, state);
268 }
269 }
270 }
271 broadcastServiceStateChanged(state);
272 }
273
Wink Savillee9b06d72009-05-18 21:47:50 -0700274 public void notifySignalStrength(SignalStrength signalStrength) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700275 if (!checkNotifyPermission("notifySignalStrength()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700276 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700277 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700278 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700280 mSignalStrength = signalStrength;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700281 for (Record r : mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700282 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
283 sendSignalStrength(r, signalStrength);
284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
286 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700287 int gsmSignalStrength = signalStrength.getGsmSignalStrength();
288 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
289 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700291 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 }
293 }
294 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700295 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700297 broadcastSignalStrengthChanged(signalStrength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 }
299
300 public void notifyMessageWaitingChanged(boolean mwi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700301 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700302 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700303 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700304 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 synchronized (mRecords) {
306 mMessageWaiting = mwi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700307 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
309 try {
310 r.callback.onMessageWaitingIndicatorChanged(mwi);
311 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700312 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 }
314 }
315 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700316 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 }
318 }
319
320 public void notifyCallForwardingChanged(boolean cfi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700321 if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700322 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700323 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700324 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 synchronized (mRecords) {
326 mCallForwarding = cfi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700327 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
329 try {
330 r.callback.onCallForwardingIndicatorChanged(cfi);
331 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700332 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 }
334 }
335 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700336 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 }
338 }
339
340 public void notifyDataActivity(int state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700341 if (!checkNotifyPermission("notifyDataActivity()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700342 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700343 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700344 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 synchronized (mRecords) {
346 mDataActivity = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700347 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
349 try {
350 r.callback.onDataActivity(state);
351 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700352 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
354 }
355 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700356 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 }
358 }
359
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700360 public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700361 String reason, String apn, String apnType, LinkProperties linkProperties,
Wink Savillef61101f2010-09-16 16:36:42 -0700362 LinkCapabilities linkCapabilities, int networkType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700363 if (!checkNotifyPermission("notifyDataConnection()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700364 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 synchronized (mRecords) {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700367 boolean modified = false;
368 if (state == TelephonyManager.DATA_CONNECTED) {
369 if (!mConnectedApns.contains(apnType)) {
370 mConnectedApns.add(apnType);
371 if (mDataConnectionState != state) {
372 mDataConnectionState = state;
373 modified = true;
374 }
375 }
376 } else {
377 mConnectedApns.remove(apnType);
378 if (mConnectedApns.isEmpty()) {
379 mDataConnectionState = state;
380 modified = true;
381 } else {
Robert Greenwalt74d99aa2010-07-14 14:30:34 -0700382 // leave mDataConnectionState as is and
383 // send out the new status for the APN in question.
Robert Greenwalt02648a42010-05-18 10:52:51 -0700384 }
385 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700386 mDataConnectionPossible = isDataConnectivityPossible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 mDataConnectionReason = reason;
Wink Savillef61101f2010-09-16 16:36:42 -0700388 mDataConnectionLinkProperties = linkProperties;
389 mDataConnectionLinkCapabilities = linkCapabilities;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700390 if (mDataConnectionNetworkType != networkType) {
391 mDataConnectionNetworkType = networkType;
392 modified = true;
393 }
394 if (modified) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700395 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700396 for (Record r : mRecords) {
397 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
398 try {
399 r.callback.onDataConnectionStateChanged(state, networkType);
400 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700401 removeList.add(r.binder);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 }
404 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700405 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 }
407 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700408 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
Wink Savillef61101f2010-09-16 16:36:42 -0700409 apnType, linkProperties, linkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 }
411
Robert Greenwalt02648a42010-05-18 10:52:51 -0700412 public void notifyDataConnectionFailed(String reason, String apnType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700413 if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700414 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 /*
Robert Greenwalt02648a42010-05-18 10:52:51 -0700417 * This is commented out because there is no onDataConnectionFailed callback
418 * in PhoneStateListener. There should be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 synchronized (mRecords) {
420 mDataConnectionFailedReason = reason;
421 final int N = mRecords.size();
422 for (int i=N-1; i>=0; i--) {
423 Record r = mRecords.get(i);
424 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
425 // XXX
426 }
427 }
428 }
429 */
Robert Greenwalt02648a42010-05-18 10:52:51 -0700430 broadcastDataConnectionFailed(reason, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 }
432
433 public void notifyCellLocation(Bundle cellLocation) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700434 if (!checkNotifyPermission("notifyCellLocation()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700435 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 synchronized (mRecords) {
438 mCellLocation = cellLocation;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700439 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
441 sendCellLocation(r, cellLocation);
442 }
443 }
444 }
445 }
446
Wink Savillee9b06d72009-05-18 21:47:50 -0700447 /**
448 * Copy the service state object so they can't mess it up in the local calls
449 */
Robert Greenwalt74d99aa2010-07-14 14:30:34 -0700450 private void sendServiceState(Record r, ServiceState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 try {
452 r.callback.onServiceStateChanged(new ServiceState(state));
453 } catch (RemoteException ex) {
454 remove(r.binder);
455 }
456 }
457
Wink Savillee9b06d72009-05-18 21:47:50 -0700458 private void sendCellLocation(Record r, Bundle cellLocation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 try {
460 r.callback.onCellLocationChanged(new Bundle(cellLocation));
461 } catch (RemoteException ex) {
462 remove(r.binder);
463 }
464 }
465
Wink Savillee9b06d72009-05-18 21:47:50 -0700466 private void sendSignalStrength(Record r, SignalStrength signalStrength) {
467 try {
468 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
469 } catch (RemoteException ex) {
470 remove(r.binder);
471 }
472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473
474 @Override
475 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
476 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
477 != PackageManager.PERMISSION_GRANTED) {
478 pw.println("Permission Denial: can't dump telephony.registry from from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700479 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 return;
481 }
482 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700483 final int recordCount = mRecords.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 pw.println("last known state:");
485 pw.println(" mCallState=" + mCallState);
486 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
487 pw.println(" mServiceState=" + mServiceState);
488 pw.println(" mSignalStrength=" + mSignalStrength);
489 pw.println(" mMessageWaiting=" + mMessageWaiting);
490 pw.println(" mCallForwarding=" + mCallForwarding);
491 pw.println(" mDataActivity=" + mDataActivity);
492 pw.println(" mDataConnectionState=" + mDataConnectionState);
493 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
494 pw.println(" mDataConnectionReason=" + mDataConnectionReason);
495 pw.println(" mDataConnectionApn=" + mDataConnectionApn);
Wink Savillef61101f2010-09-16 16:36:42 -0700496 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
497 pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 pw.println(" mCellLocation=" + mCellLocation);
Wink Savillee9b06d72009-05-18 21:47:50 -0700499 pw.println("registrations: count=" + recordCount);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700500 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
502 }
503 }
504 }
505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 //
507 // the legacy intent broadcasting
508 //
509
510 private void broadcastServiceStateChanged(ServiceState state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700511 long ident = Binder.clearCallingIdentity();
512 try {
Amith Yamasanif37447b2009-10-08 18:28:01 -0700513 mBatteryStats.notePhoneState(state.getState());
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700514 } catch (RemoteException re) {
515 // Can't do much
516 } finally {
517 Binder.restoreCallingIdentity(ident);
518 }
519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800521 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 Bundle data = new Bundle();
523 state.fillInNotifierBundle(data);
524 intent.putExtras(data);
525 mContext.sendStickyBroadcast(intent);
526 }
527
Wink Savillee9b06d72009-05-18 21:47:50 -0700528 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700529 long ident = Binder.clearCallingIdentity();
530 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700531 mBatteryStats.notePhoneSignalStrength(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700532 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700533 /* The remote entity disappeared, we can safely ignore the exception. */
Dianne Hackborn627bba72009-03-24 22:32:56 -0700534 } finally {
535 Binder.restoreCallingIdentity(ident);
536 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800539 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700540 Bundle data = new Bundle();
541 signalStrength.fillInNotifierBundle(data);
542 intent.putExtras(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 mContext.sendStickyBroadcast(intent);
544 }
545
546 private void broadcastCallStateChanged(int state, String incomingNumber) {
547 long ident = Binder.clearCallingIdentity();
548 try {
549 if (state == TelephonyManager.CALL_STATE_IDLE) {
550 mBatteryStats.notePhoneOff();
551 } else {
552 mBatteryStats.notePhoneOn();
553 }
554 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700555 /* The remote entity disappeared, we can safely ignore the exception. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 } finally {
557 Binder.restoreCallingIdentity(ident);
558 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800561 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700562 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 if (!TextUtils.isEmpty(incomingNumber)) {
564 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
565 }
566 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
567 }
568
Robert Greenwalt42acef32009-08-12 16:08:25 -0700569 private void broadcastDataConnectionStateChanged(int state,
570 boolean isDataConnectivityPossible,
Wink Savillef61101f2010-09-16 16:36:42 -0700571 String reason, String apn, String apnType, LinkProperties linkProperties,
572 LinkCapabilities linkCapabilities) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700573 // Note: not reporting to the battery stats service here, because the
574 // status bar takes care of that after taking into account all of the
575 // required info.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800577 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
579 if (!isDataConnectivityPossible) {
580 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
581 }
582 if (reason != null) {
583 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
584 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700585 if (linkProperties != null) {
586 intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties);
587 NetworkInterface iface = linkProperties.getInterface();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700588 if (iface != null) {
589 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface.getName());
590 }
591 }
Wink Savillef61101f2010-09-16 16:36:42 -0700592 if (linkCapabilities != null) {
593 intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities);
594 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 intent.putExtra(Phone.DATA_APN_KEY, apn);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700596 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 mContext.sendStickyBroadcast(intent);
598 }
599
Robert Greenwalt02648a42010-05-18 10:52:51 -0700600 private void broadcastDataConnectionFailed(String reason, String apnType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800602 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700604 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 mContext.sendStickyBroadcast(intent);
606 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700607
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700608 private boolean checkNotifyPermission(String method) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700609 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
610 == PackageManager.PERMISSION_GRANTED) {
611 return true;
612 }
613 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700614 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800615 Slog.w(TAG, msg);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700616 return false;
617 }
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700618
619 private void checkListenerPermission(int events) {
620 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
621 mContext.enforceCallingOrSelfPermission(
622 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
623
624 }
625
626 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
627 mContext.enforceCallingOrSelfPermission(
628 android.Manifest.permission.READ_PHONE_STATE, null);
629 }
630 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631}