blob: 8fc4d570400f6bd202a2a8edf3662081a26be2f2 [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;
22import android.os.Binder;
23import android.os.Bundle;
24import android.os.IBinder;
25import android.os.RemoteException;
26import android.telephony.CellLocation;
27import android.telephony.PhoneStateListener;
28import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070029import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.telephony.TelephonyManager;
31import android.text.TextUtils;
Joe Onorato8a9b2202010-02-26 18:56:32 -080032import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033
34import java.util.ArrayList;
35import java.io.FileDescriptor;
36import java.io.PrintWriter;
37
38import com.android.internal.app.IBatteryStats;
39import com.android.internal.telephony.ITelephonyRegistry;
40import com.android.internal.telephony.IPhoneStateListener;
41import com.android.internal.telephony.DefaultPhoneNotifier;
42import com.android.internal.telephony.Phone;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import com.android.internal.telephony.TelephonyIntents;
44import com.android.server.am.BatteryStatsService;
45
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046/**
Wink Savillee9b06d72009-05-18 21:47:50 -070047 * Since phone process can be restarted, this class provides a centralized place
48 * that applications can register and be called back from.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 */
50class TelephonyRegistry extends ITelephonyRegistry.Stub {
51 private static final String TAG = "TelephonyRegistry";
52
53 private static class Record {
54 String pkgForDebug;
Wink Savillee9b06d72009-05-18 21:47:50 -070055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 IBinder binder;
Wink Savillee9b06d72009-05-18 21:47:50 -070057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 IPhoneStateListener callback;
Wink Savillee9b06d72009-05-18 21:47:50 -070059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 int events;
61 }
62
63 private final Context mContext;
Wink Savillee9b06d72009-05-18 21:47:50 -070064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 private final ArrayList<Record> mRecords = new ArrayList();
Wink Savillee9b06d72009-05-18 21:47:50 -070066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 private final IBatteryStats mBatteryStats;
68
69 private int mCallState = TelephonyManager.CALL_STATE_IDLE;
Wink Savillee9b06d72009-05-18 21:47:50 -070070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 private String mCallIncomingNumber = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 private ServiceState mServiceState = new ServiceState();
Wink Savillee9b06d72009-05-18 21:47:50 -070074
75 private SignalStrength mSignalStrength = new SignalStrength();
76
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 private boolean mMessageWaiting = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private boolean mCallForwarding = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
Wink Savillee9b06d72009-05-18 21:47:50 -070082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
Wink Savillee9b06d72009-05-18 21:47:50 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 private boolean mDataConnectionPossible = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 private String mDataConnectionReason = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 private String mDataConnectionApn = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070090
Robert Greenwalt02648a42010-05-18 10:52:51 -070091 private ArrayList<String> mConnectedApns;
Robert Greenwalt42acef32009-08-12 16:08:25 -070092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 private String mDataConnectionInterfaceName = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 private Bundle mCellLocation = new Bundle();
96
Robert Greenwalt98e0b142009-10-08 21:15:52 -070097 private int mDataConnectionNetworkType;
98
Jaikumar Ganesh45515652009-04-23 15:20:21 -070099 static final int PHONE_STATE_PERMISSION_MASK =
100 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
101 PhoneStateListener.LISTEN_CALL_STATE |
102 PhoneStateListener.LISTEN_DATA_ACTIVITY |
103 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
104 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
105
Wink Savillee9b06d72009-05-18 21:47:50 -0700106 // we keep a copy of all of the state so we can send it out when folks
107 // register for it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 //
Wink Savillee9b06d72009-05-18 21:47:50 -0700109 // In these calls we call with the lock held. This is safe becasuse remote
110 // calls go through a oneway interface and local calls going through a
111 // handler before they get to app code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
113 TelephonyRegistry(Context context) {
David 'Digit' Turner4ef8ec32009-09-25 11:33:24 -0700114 CellLocation location = CellLocation.getEmpty();
115
116 // Note that location can be null for non-phone builds like
117 // like the generic one.
118 if (location != null) {
119 location.fillInNotifierBundle(mCellLocation);
120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 mContext = context;
122 mBatteryStats = BatteryStatsService.getService();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700123 mConnectedApns = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 }
125
126 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
127 boolean notifyNow) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800128 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
Wink Savillee9b06d72009-05-18 21:47:50 -0700129 // Integer.toHexString(events));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 if (events != 0) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700131 /* Checks permission and throws Security exception */
132 checkListenerPermission(events);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133
134 synchronized (mRecords) {
135 // register
136 Record r = null;
137 find_and_add: {
138 IBinder b = callback.asBinder();
139 final int N = mRecords.size();
Wink Savillee9b06d72009-05-18 21:47:50 -0700140 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 r = mRecords.get(i);
142 if (b == r.binder) {
143 break find_and_add;
144 }
145 }
146 r = new Record();
147 r.binder = b;
148 r.callback = callback;
149 r.pkgForDebug = pkgForDebug;
150 mRecords.add(r);
151 }
152 int send = events & (events ^ r.events);
153 r.events = events;
154 if (notifyNow) {
155 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
156 sendServiceState(r, mServiceState);
157 }
158 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
159 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700160 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
161 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
162 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 } catch (RemoteException ex) {
164 remove(r.binder);
165 }
166 }
167 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
168 try {
169 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
170 } catch (RemoteException ex) {
171 remove(r.binder);
172 }
173 }
174 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
175 try {
176 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
177 } catch (RemoteException ex) {
178 remove(r.binder);
179 }
180 }
181 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
182 sendCellLocation(r, mCellLocation);
183 }
184 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
185 try {
186 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
187 } catch (RemoteException ex) {
188 remove(r.binder);
189 }
190 }
191 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
192 try {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700193 r.callback.onDataConnectionStateChanged(mDataConnectionState,
194 mDataConnectionNetworkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 } catch (RemoteException ex) {
196 remove(r.binder);
197 }
198 }
199 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
200 try {
201 r.callback.onDataActivity(mDataActivity);
202 } catch (RemoteException ex) {
203 remove(r.binder);
204 }
205 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700206 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
207 try {
208 r.callback.onSignalStrengthsChanged(mSignalStrength);
209 } catch (RemoteException ex) {
210 remove(r.binder);
211 }
212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 }
214 }
215 } else {
216 remove(callback.asBinder());
217 }
218 }
219
220 private void remove(IBinder binder) {
221 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700222 final int recordCount = mRecords.size();
223 for (int i = 0; i < recordCount; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 if (mRecords.get(i).binder == binder) {
225 mRecords.remove(i);
226 return;
227 }
228 }
229 }
230 }
231
232 public void notifyCallState(int state, String incomingNumber) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700233 if (!checkNotifyPermission("notifyCallState()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700234 return;
235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 synchronized (mRecords) {
237 mCallState = state;
238 mCallIncomingNumber = incomingNumber;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700239 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
241 try {
242 r.callback.onCallStateChanged(state, incomingNumber);
243 } catch (RemoteException ex) {
244 remove(r.binder);
245 }
246 }
247 }
248 }
249 broadcastCallStateChanged(state, incomingNumber);
250 }
251
252 public void notifyServiceState(ServiceState state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700253 if (!checkNotifyPermission("notifyServiceState()")){
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700254 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 synchronized (mRecords) {
257 mServiceState = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700258 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
260 sendServiceState(r, state);
261 }
262 }
263 }
264 broadcastServiceStateChanged(state);
265 }
266
Wink Savillee9b06d72009-05-18 21:47:50 -0700267 public void notifySignalStrength(SignalStrength signalStrength) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700268 if (!checkNotifyPermission("notifySignalStrength()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700269 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700270 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700272 mSignalStrength = signalStrength;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700273 for (Record r : mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700274 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
275 sendSignalStrength(r, signalStrength);
276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
278 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700279 int gsmSignalStrength = signalStrength.getGsmSignalStrength();
280 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
281 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 } catch (RemoteException ex) {
283 remove(r.binder);
284 }
285 }
286 }
287 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700288 broadcastSignalStrengthChanged(signalStrength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 }
290
291 public void notifyMessageWaitingChanged(boolean mwi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700292 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700293 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700294 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 synchronized (mRecords) {
296 mMessageWaiting = mwi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700297 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
299 try {
300 r.callback.onMessageWaitingIndicatorChanged(mwi);
301 } catch (RemoteException ex) {
302 remove(r.binder);
303 }
304 }
305 }
306 }
307 }
308
309 public void notifyCallForwardingChanged(boolean cfi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700310 if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700311 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 synchronized (mRecords) {
314 mCallForwarding = cfi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700315 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
317 try {
318 r.callback.onCallForwardingIndicatorChanged(cfi);
319 } catch (RemoteException ex) {
320 remove(r.binder);
321 }
322 }
323 }
324 }
325 }
326
327 public void notifyDataActivity(int state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700328 if (!checkNotifyPermission("notifyDataActivity()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700329 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 synchronized (mRecords) {
332 mDataActivity = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700333 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
335 try {
336 r.callback.onDataActivity(state);
337 } catch (RemoteException ex) {
338 remove(r.binder);
339 }
340 }
341 }
342 }
343 }
344
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700345 public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
Robert Greenwalt02648a42010-05-18 10:52:51 -0700346 String reason, String apn, String apnType, String interfaceName, int networkType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700347 if (!checkNotifyPermission("notifyDataConnection()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700348 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700349 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 synchronized (mRecords) {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700351 boolean modified = false;
352 if (state == TelephonyManager.DATA_CONNECTED) {
353 if (!mConnectedApns.contains(apnType)) {
354 mConnectedApns.add(apnType);
355 if (mDataConnectionState != state) {
356 mDataConnectionState = state;
357 modified = true;
358 }
359 }
360 } else {
361 mConnectedApns.remove(apnType);
362 if (mConnectedApns.isEmpty()) {
363 mDataConnectionState = state;
364 modified = true;
365 } else {
366 // we're still connected, so send that out if we send anything.
367 state = mDataConnectionState;
368 }
369 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700370 mDataConnectionPossible = isDataConnectivityPossible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 mDataConnectionReason = reason;
372 mDataConnectionApn = apn;
373 mDataConnectionInterfaceName = interfaceName;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700374 if (mDataConnectionNetworkType != networkType) {
375 mDataConnectionNetworkType = networkType;
376 modified = true;
377 }
378 if (modified) {
379 for (Record r : mRecords) {
380 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
381 try {
382 r.callback.onDataConnectionStateChanged(state, networkType);
383 } catch (RemoteException ex) {
384 remove(r.binder);
385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 }
387 }
388 }
389 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700390 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
Robert Greenwalt02648a42010-05-18 10:52:51 -0700391 apnType, interfaceName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 }
393
Robert Greenwalt02648a42010-05-18 10:52:51 -0700394 public void notifyDataConnectionFailed(String reason, String apnType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700395 if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700396 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 /*
Robert Greenwalt02648a42010-05-18 10:52:51 -0700399 * This is commented out because there is no onDataConnectionFailed callback
400 * in PhoneStateListener. There should be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 synchronized (mRecords) {
402 mDataConnectionFailedReason = reason;
403 final int N = mRecords.size();
404 for (int i=N-1; i>=0; i--) {
405 Record r = mRecords.get(i);
406 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
407 // XXX
408 }
409 }
410 }
411 */
Robert Greenwalt02648a42010-05-18 10:52:51 -0700412 broadcastDataConnectionFailed(reason, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 }
414
415 public void notifyCellLocation(Bundle cellLocation) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700416 if (!checkNotifyPermission("notifyCellLocation()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700417 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 synchronized (mRecords) {
420 mCellLocation = cellLocation;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700421 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
423 sendCellLocation(r, cellLocation);
424 }
425 }
426 }
427 }
428
Wink Savillee9b06d72009-05-18 21:47:50 -0700429 /**
430 * Copy the service state object so they can't mess it up in the local calls
431 */
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700432 public void sendServiceState(Record r, ServiceState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 try {
434 r.callback.onServiceStateChanged(new ServiceState(state));
435 } catch (RemoteException ex) {
436 remove(r.binder);
437 }
438 }
439
Wink Savillee9b06d72009-05-18 21:47:50 -0700440 private void sendCellLocation(Record r, Bundle cellLocation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 try {
442 r.callback.onCellLocationChanged(new Bundle(cellLocation));
443 } catch (RemoteException ex) {
444 remove(r.binder);
445 }
446 }
447
Wink Savillee9b06d72009-05-18 21:47:50 -0700448 private void sendSignalStrength(Record r, SignalStrength signalStrength) {
449 try {
450 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
451 } catch (RemoteException ex) {
452 remove(r.binder);
453 }
454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455
456 @Override
457 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
458 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
459 != PackageManager.PERMISSION_GRANTED) {
460 pw.println("Permission Denial: can't dump telephony.registry from from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700461 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 return;
463 }
464 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700465 final int recordCount = mRecords.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 pw.println("last known state:");
467 pw.println(" mCallState=" + mCallState);
468 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
469 pw.println(" mServiceState=" + mServiceState);
470 pw.println(" mSignalStrength=" + mSignalStrength);
471 pw.println(" mMessageWaiting=" + mMessageWaiting);
472 pw.println(" mCallForwarding=" + mCallForwarding);
473 pw.println(" mDataActivity=" + mDataActivity);
474 pw.println(" mDataConnectionState=" + mDataConnectionState);
475 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
476 pw.println(" mDataConnectionReason=" + mDataConnectionReason);
477 pw.println(" mDataConnectionApn=" + mDataConnectionApn);
478 pw.println(" mDataConnectionInterfaceName=" + mDataConnectionInterfaceName);
479 pw.println(" mCellLocation=" + mCellLocation);
Wink Savillee9b06d72009-05-18 21:47:50 -0700480 pw.println("registrations: count=" + recordCount);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700481 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
483 }
484 }
485 }
486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 //
488 // the legacy intent broadcasting
489 //
490
491 private void broadcastServiceStateChanged(ServiceState state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700492 long ident = Binder.clearCallingIdentity();
493 try {
Amith Yamasanif37447b2009-10-08 18:28:01 -0700494 mBatteryStats.notePhoneState(state.getState());
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700495 } catch (RemoteException re) {
496 // Can't do much
497 } finally {
498 Binder.restoreCallingIdentity(ident);
499 }
500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800502 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 Bundle data = new Bundle();
504 state.fillInNotifierBundle(data);
505 intent.putExtras(data);
506 mContext.sendStickyBroadcast(intent);
507 }
508
Wink Savillee9b06d72009-05-18 21:47:50 -0700509 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700510 long ident = Binder.clearCallingIdentity();
511 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700512 mBatteryStats.notePhoneSignalStrength(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700513 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700514 /* The remote entity disappeared, we can safely ignore the exception. */
Dianne Hackborn627bba72009-03-24 22:32:56 -0700515 } finally {
516 Binder.restoreCallingIdentity(ident);
517 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800520 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700521 Bundle data = new Bundle();
522 signalStrength.fillInNotifierBundle(data);
523 intent.putExtras(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 mContext.sendStickyBroadcast(intent);
525 }
526
527 private void broadcastCallStateChanged(int state, String incomingNumber) {
528 long ident = Binder.clearCallingIdentity();
529 try {
530 if (state == TelephonyManager.CALL_STATE_IDLE) {
531 mBatteryStats.notePhoneOff();
532 } else {
533 mBatteryStats.notePhoneOn();
534 }
535 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700536 /* The remote entity disappeared, we can safely ignore the exception. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 } finally {
538 Binder.restoreCallingIdentity(ident);
539 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800542 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700543 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 if (!TextUtils.isEmpty(incomingNumber)) {
545 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
546 }
547 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
548 }
549
Robert Greenwalt42acef32009-08-12 16:08:25 -0700550 private void broadcastDataConnectionStateChanged(int state,
551 boolean isDataConnectivityPossible,
Robert Greenwalt02648a42010-05-18 10:52:51 -0700552 String reason, String apn, String apnType, String interfaceName) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700553 // Note: not reporting to the battery stats service here, because the
554 // status bar takes care of that after taking into account all of the
555 // required info.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800557 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
559 if (!isDataConnectivityPossible) {
560 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
561 }
562 if (reason != null) {
563 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
564 }
565 intent.putExtra(Phone.DATA_APN_KEY, apn);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700566 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName);
568 mContext.sendStickyBroadcast(intent);
569 }
570
Robert Greenwalt02648a42010-05-18 10:52:51 -0700571 private void broadcastDataConnectionFailed(String reason, String apnType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800573 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700575 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 mContext.sendStickyBroadcast(intent);
577 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700578
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700579 private boolean checkNotifyPermission(String method) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700580 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
581 == PackageManager.PERMISSION_GRANTED) {
582 return true;
583 }
584 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700585 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800586 Slog.w(TAG, msg);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700587 return false;
588 }
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700589
590 private void checkListenerPermission(int events) {
591 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
592 mContext.enforceCallingOrSelfPermission(
593 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
594
595 }
596
597 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
598 mContext.enforceCallingOrSelfPermission(
599 android.Manifest.permission.READ_PHONE_STATE, null);
600 }
601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602}