blob: f5b7ca96a9d279208209e678fecbb34301f4d841 [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
Joe Onorato163d8d92010-10-21 13:21:20 -040068 // access should be inside synchronized (mRecords) for these two fields
69 private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
70 private final ArrayList<Record> mRecords = new ArrayList<Record>();
Wink Savillee9b06d72009-05-18 21:47:50 -070071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 private final IBatteryStats mBatteryStats;
73
74 private int mCallState = TelephonyManager.CALL_STATE_IDLE;
Wink Savillee9b06d72009-05-18 21:47:50 -070075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 private String mCallIncomingNumber = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078 private ServiceState mServiceState = new ServiceState();
Wink Savillee9b06d72009-05-18 21:47:50 -070079
80 private SignalStrength mSignalStrength = new SignalStrength();
81
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 private boolean mMessageWaiting = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 private boolean mCallForwarding = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
Wink Savillee9b06d72009-05-18 21:47:50 -070087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
Wink Savillee9b06d72009-05-18 21:47:50 -070089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 private boolean mDataConnectionPossible = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 private String mDataConnectionReason = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 private String mDataConnectionApn = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070095
Robert Greenwalt02648a42010-05-18 10:52:51 -070096 private ArrayList<String> mConnectedApns;
Robert Greenwalt42acef32009-08-12 16:08:25 -070097
Wink Savillef61101f2010-09-16 16:36:42 -070098 private LinkProperties mDataConnectionLinkProperties;
99
100 private LinkCapabilities mDataConnectionLinkCapabilities;
Wink Savillee9b06d72009-05-18 21:47:50 -0700101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 private Bundle mCellLocation = new Bundle();
103
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700104 private int mDataConnectionNetworkType;
105
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700106 static final int PHONE_STATE_PERMISSION_MASK =
107 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
108 PhoneStateListener.LISTEN_CALL_STATE |
109 PhoneStateListener.LISTEN_DATA_ACTIVITY |
110 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
111 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
112
Wink Savillee9b06d72009-05-18 21:47:50 -0700113 // we keep a copy of all of the state so we can send it out when folks
114 // register for it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 //
Wink Savillee9b06d72009-05-18 21:47:50 -0700116 // In these calls we call with the lock held. This is safe becasuse remote
117 // calls go through a oneway interface and local calls going through a
118 // handler before they get to app code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119
120 TelephonyRegistry(Context context) {
David 'Digit' Turner4ef8ec32009-09-25 11:33:24 -0700121 CellLocation location = CellLocation.getEmpty();
122
123 // Note that location can be null for non-phone builds like
124 // like the generic one.
125 if (location != null) {
126 location.fillInNotifierBundle(mCellLocation);
127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 mContext = context;
129 mBatteryStats = BatteryStatsService.getService();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700130 mConnectedApns = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 }
132
133 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
134 boolean notifyNow) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800135 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
Wink Savillee9b06d72009-05-18 21:47:50 -0700136 // Integer.toHexString(events));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 if (events != 0) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700138 /* Checks permission and throws Security exception */
139 checkListenerPermission(events);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141 synchronized (mRecords) {
142 // register
143 Record r = null;
144 find_and_add: {
145 IBinder b = callback.asBinder();
146 final int N = mRecords.size();
Wink Savillee9b06d72009-05-18 21:47:50 -0700147 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 r = mRecords.get(i);
149 if (b == r.binder) {
150 break find_and_add;
151 }
152 }
153 r = new Record();
154 r.binder = b;
155 r.callback = callback;
156 r.pkgForDebug = pkgForDebug;
157 mRecords.add(r);
158 }
159 int send = events & (events ^ r.events);
160 r.events = events;
161 if (notifyNow) {
162 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400163 try {
164 r.callback.onServiceStateChanged(new ServiceState(mServiceState));
165 } catch (RemoteException ex) {
166 remove(r.binder);
167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 }
169 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
170 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700171 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
172 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
173 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 } catch (RemoteException ex) {
175 remove(r.binder);
176 }
177 }
178 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
179 try {
180 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
181 } catch (RemoteException ex) {
182 remove(r.binder);
183 }
184 }
185 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
186 try {
187 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
188 } catch (RemoteException ex) {
189 remove(r.binder);
190 }
191 }
192 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400193 try {
194 r.callback.onCellLocationChanged(new Bundle(mCellLocation));
195 } catch (RemoteException ex) {
196 remove(r.binder);
197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 }
199 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
200 try {
201 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
202 } catch (RemoteException ex) {
203 remove(r.binder);
204 }
205 }
206 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
207 try {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700208 r.callback.onDataConnectionStateChanged(mDataConnectionState,
209 mDataConnectionNetworkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 } catch (RemoteException ex) {
211 remove(r.binder);
212 }
213 }
214 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
215 try {
216 r.callback.onDataActivity(mDataActivity);
217 } catch (RemoteException ex) {
218 remove(r.binder);
219 }
220 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700221 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
222 try {
223 r.callback.onSignalStrengthsChanged(mSignalStrength);
224 } catch (RemoteException ex) {
225 remove(r.binder);
226 }
227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 }
229 }
230 } else {
231 remove(callback.asBinder());
232 }
233 }
234
235 private void remove(IBinder binder) {
236 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700237 final int recordCount = mRecords.size();
238 for (int i = 0; i < recordCount; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 if (mRecords.get(i).binder == binder) {
240 mRecords.remove(i);
241 return;
242 }
243 }
244 }
245 }
246
247 public void notifyCallState(int state, String incomingNumber) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700248 if (!checkNotifyPermission("notifyCallState()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700249 return;
250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 synchronized (mRecords) {
252 mCallState = state;
253 mCallIncomingNumber = incomingNumber;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700254 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
256 try {
257 r.callback.onCallStateChanged(state, incomingNumber);
258 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400259 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 }
261 }
262 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400263 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 }
265 broadcastCallStateChanged(state, incomingNumber);
266 }
267
268 public void notifyServiceState(ServiceState state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700269 if (!checkNotifyPermission("notifyServiceState()")){
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700270 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700271 }
Joe Onorato431bb222010-10-18 19:13:23 -0400272 Slog.i(TAG, "notifyServiceState: " + state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 synchronized (mRecords) {
274 mServiceState = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700275 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400277 try {
278 r.callback.onServiceStateChanged(new ServiceState(state));
279 } catch (RemoteException ex) {
280 mRemoveList.add(r.binder);
281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 }
283 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400284 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 }
286 broadcastServiceStateChanged(state);
287 }
288
Wink Savillee9b06d72009-05-18 21:47:50 -0700289 public void notifySignalStrength(SignalStrength signalStrength) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700290 if (!checkNotifyPermission("notifySignalStrength()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700291 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700292 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700294 mSignalStrength = signalStrength;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700295 for (Record r : mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700296 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400297 try {
298 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
299 } catch (RemoteException ex) {
300 mRemoveList.add(r.binder);
301 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700302 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
304 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700305 int gsmSignalStrength = signalStrength.getGsmSignalStrength();
306 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
307 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400309 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 }
311 }
312 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400313 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700315 broadcastSignalStrengthChanged(signalStrength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
317
318 public void notifyMessageWaitingChanged(boolean mwi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700319 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700320 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700321 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 synchronized (mRecords) {
323 mMessageWaiting = mwi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700324 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
326 try {
327 r.callback.onMessageWaitingIndicatorChanged(mwi);
328 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400329 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
331 }
332 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400333 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 }
335 }
336
337 public void notifyCallForwardingChanged(boolean cfi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700338 if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700339 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 synchronized (mRecords) {
342 mCallForwarding = cfi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700343 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
345 try {
346 r.callback.onCallForwardingIndicatorChanged(cfi);
347 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400348 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 }
350 }
351 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400352 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
354 }
355
356 public void notifyDataActivity(int state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700357 if (!checkNotifyPermission("notifyDataActivity()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700358 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700359 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400360 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 synchronized (mRecords) {
362 mDataActivity = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700363 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
365 try {
366 r.callback.onDataActivity(state);
367 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400368 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 }
370 }
371 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400372 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 }
374 }
375
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700376 public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700377 String reason, String apn, String apnType, LinkProperties linkProperties,
Wink Savillef61101f2010-09-16 16:36:42 -0700378 LinkCapabilities linkCapabilities, int networkType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700379 if (!checkNotifyPermission("notifyDataConnection()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700380 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700381 }
Joe Onorato431bb222010-10-18 19:13:23 -0400382 Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
383 + isDataConnectivityPossible + " reason=" + reason
Joe Onorato74998472010-10-21 11:38:11 -0400384 + " apn=" + apn + " networkType=" + networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 synchronized (mRecords) {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700386 boolean modified = false;
387 if (state == TelephonyManager.DATA_CONNECTED) {
388 if (!mConnectedApns.contains(apnType)) {
389 mConnectedApns.add(apnType);
390 if (mDataConnectionState != state) {
391 mDataConnectionState = state;
392 modified = true;
393 }
394 }
395 } else {
396 mConnectedApns.remove(apnType);
397 if (mConnectedApns.isEmpty()) {
398 mDataConnectionState = state;
399 modified = true;
400 } else {
Robert Greenwalt74d99aa2010-07-14 14:30:34 -0700401 // leave mDataConnectionState as is and
402 // send out the new status for the APN in question.
Robert Greenwalt02648a42010-05-18 10:52:51 -0700403 }
404 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700405 mDataConnectionPossible = isDataConnectivityPossible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 mDataConnectionReason = reason;
Wink Savillef61101f2010-09-16 16:36:42 -0700407 mDataConnectionLinkProperties = linkProperties;
408 mDataConnectionLinkCapabilities = linkCapabilities;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700409 if (mDataConnectionNetworkType != networkType) {
410 mDataConnectionNetworkType = networkType;
411 modified = true;
412 }
413 if (modified) {
414 for (Record r : mRecords) {
415 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
416 try {
417 r.callback.onDataConnectionStateChanged(state, networkType);
418 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400419 mRemoveList.add(r.binder);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400423 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 }
425 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700426 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
Wink Savillef61101f2010-09-16 16:36:42 -0700427 apnType, linkProperties, linkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 }
429
Robert Greenwalt02648a42010-05-18 10:52:51 -0700430 public void notifyDataConnectionFailed(String reason, String apnType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700431 if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700432 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 /*
Robert Greenwalt02648a42010-05-18 10:52:51 -0700435 * This is commented out because there is no onDataConnectionFailed callback
436 * in PhoneStateListener. There should be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 synchronized (mRecords) {
438 mDataConnectionFailedReason = reason;
439 final int N = mRecords.size();
440 for (int i=N-1; i>=0; i--) {
441 Record r = mRecords.get(i);
442 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
443 // XXX
444 }
445 }
446 }
447 */
Robert Greenwalt02648a42010-05-18 10:52:51 -0700448 broadcastDataConnectionFailed(reason, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
450
451 public void notifyCellLocation(Bundle cellLocation) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700452 if (!checkNotifyPermission("notifyCellLocation()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700453 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 synchronized (mRecords) {
456 mCellLocation = cellLocation;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700457 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400459 try {
460 r.callback.onCellLocationChanged(new Bundle(cellLocation));
461 } catch (RemoteException ex) {
462 mRemoveList.add(r.binder);
463 }
464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 }
466 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400467 handleRemoveListLocked();
Wink Savillee9b06d72009-05-18 21:47:50 -0700468 }
469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470
471 @Override
472 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
473 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
474 != PackageManager.PERMISSION_GRANTED) {
475 pw.println("Permission Denial: can't dump telephony.registry from from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700476 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 return;
478 }
479 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700480 final int recordCount = mRecords.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 pw.println("last known state:");
482 pw.println(" mCallState=" + mCallState);
483 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
484 pw.println(" mServiceState=" + mServiceState);
485 pw.println(" mSignalStrength=" + mSignalStrength);
486 pw.println(" mMessageWaiting=" + mMessageWaiting);
487 pw.println(" mCallForwarding=" + mCallForwarding);
488 pw.println(" mDataActivity=" + mDataActivity);
489 pw.println(" mDataConnectionState=" + mDataConnectionState);
490 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
491 pw.println(" mDataConnectionReason=" + mDataConnectionReason);
492 pw.println(" mDataConnectionApn=" + mDataConnectionApn);
Wink Savillef61101f2010-09-16 16:36:42 -0700493 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
494 pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 pw.println(" mCellLocation=" + mCellLocation);
Wink Savillee9b06d72009-05-18 21:47:50 -0700496 pw.println("registrations: count=" + recordCount);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700497 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
499 }
500 }
501 }
502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 //
504 // the legacy intent broadcasting
505 //
506
507 private void broadcastServiceStateChanged(ServiceState state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700508 long ident = Binder.clearCallingIdentity();
509 try {
Amith Yamasanif37447b2009-10-08 18:28:01 -0700510 mBatteryStats.notePhoneState(state.getState());
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700511 } catch (RemoteException re) {
512 // Can't do much
513 } finally {
514 Binder.restoreCallingIdentity(ident);
515 }
516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800518 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 Bundle data = new Bundle();
520 state.fillInNotifierBundle(data);
521 intent.putExtras(data);
522 mContext.sendStickyBroadcast(intent);
523 }
524
Wink Savillee9b06d72009-05-18 21:47:50 -0700525 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700526 long ident = Binder.clearCallingIdentity();
527 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700528 mBatteryStats.notePhoneSignalStrength(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700529 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700530 /* The remote entity disappeared, we can safely ignore the exception. */
Dianne Hackborn627bba72009-03-24 22:32:56 -0700531 } finally {
532 Binder.restoreCallingIdentity(ident);
533 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800536 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700537 Bundle data = new Bundle();
538 signalStrength.fillInNotifierBundle(data);
539 intent.putExtras(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 mContext.sendStickyBroadcast(intent);
541 }
542
543 private void broadcastCallStateChanged(int state, String incomingNumber) {
544 long ident = Binder.clearCallingIdentity();
545 try {
546 if (state == TelephonyManager.CALL_STATE_IDLE) {
547 mBatteryStats.notePhoneOff();
548 } else {
549 mBatteryStats.notePhoneOn();
550 }
551 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700552 /* The remote entity disappeared, we can safely ignore the exception. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 } finally {
554 Binder.restoreCallingIdentity(ident);
555 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800558 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700559 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 if (!TextUtils.isEmpty(incomingNumber)) {
561 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
562 }
563 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
564 }
565
Robert Greenwalt42acef32009-08-12 16:08:25 -0700566 private void broadcastDataConnectionStateChanged(int state,
567 boolean isDataConnectivityPossible,
Wink Savillef61101f2010-09-16 16:36:42 -0700568 String reason, String apn, String apnType, LinkProperties linkProperties,
569 LinkCapabilities linkCapabilities) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700570 // Note: not reporting to the battery stats service here, because the
571 // status bar takes care of that after taking into account all of the
572 // required info.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800574 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
576 if (!isDataConnectivityPossible) {
577 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
578 }
579 if (reason != null) {
580 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
581 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700582 if (linkProperties != null) {
583 intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties);
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700584 String iface = linkProperties.getInterfaceName();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700585 if (iface != null) {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700586 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700587 }
588 }
Wink Savillef61101f2010-09-16 16:36:42 -0700589 if (linkCapabilities != null) {
590 intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities);
591 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 intent.putExtra(Phone.DATA_APN_KEY, apn);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700593 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 mContext.sendStickyBroadcast(intent);
595 }
596
Robert Greenwalt02648a42010-05-18 10:52:51 -0700597 private void broadcastDataConnectionFailed(String reason, String apnType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800599 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700601 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 mContext.sendStickyBroadcast(intent);
603 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700604
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700605 private boolean checkNotifyPermission(String method) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700606 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
607 == PackageManager.PERMISSION_GRANTED) {
608 return true;
609 }
610 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700611 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800612 Slog.w(TAG, msg);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700613 return false;
614 }
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700615
616 private void checkListenerPermission(int events) {
617 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
618 mContext.enforceCallingOrSelfPermission(
619 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
620
621 }
622
623 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
624 mContext.enforceCallingOrSelfPermission(
625 android.Manifest.permission.READ_PHONE_STATE, null);
626 }
627 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400628
629 private void handleRemoveListLocked() {
630 if (mRemoveList.size() > 0) {
631 for (IBinder b: mRemoveList) {
632 remove(b);
633 }
634 mRemoveList.clear();
635 }
636 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637}