blob: 0a90a4cde285f5b8e083dec68c9c9b574e382b4a [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;
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070022import android.net.LinkProperties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.os.Binder;
24import android.os.Bundle;
25import android.os.IBinder;
26import android.os.RemoteException;
27import android.telephony.CellLocation;
28import android.telephony.PhoneStateListener;
29import android.telephony.ServiceState;
Wink Savillee9b06d72009-05-18 21:47:50 -070030import android.telephony.SignalStrength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.telephony.TelephonyManager;
32import android.text.TextUtils;
Joe Onorato8a9b2202010-02-26 18:56:32 -080033import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
35import java.util.ArrayList;
36import java.io.FileDescriptor;
37import java.io.PrintWriter;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070038import java.net.NetworkInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
40import com.android.internal.app.IBatteryStats;
41import com.android.internal.telephony.ITelephonyRegistry;
42import com.android.internal.telephony.IPhoneStateListener;
43import com.android.internal.telephony.DefaultPhoneNotifier;
44import com.android.internal.telephony.Phone;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import com.android.internal.telephony.TelephonyIntents;
46import com.android.server.am.BatteryStatsService;
47
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048/**
Wink Savillee9b06d72009-05-18 21:47:50 -070049 * Since phone process can be restarted, this class provides a centralized place
50 * that applications can register and be called back from.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 */
52class TelephonyRegistry extends ITelephonyRegistry.Stub {
53 private static final String TAG = "TelephonyRegistry";
54
55 private static class Record {
56 String pkgForDebug;
Wink Savillee9b06d72009-05-18 21:47:50 -070057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 IBinder binder;
Wink Savillee9b06d72009-05-18 21:47:50 -070059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060 IPhoneStateListener callback;
Wink Savillee9b06d72009-05-18 21:47:50 -070061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 int events;
63 }
64
65 private final Context mContext;
Wink Savillee9b06d72009-05-18 21:47:50 -070066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 private final ArrayList<Record> mRecords = new ArrayList();
Wink Savillee9b06d72009-05-18 21:47:50 -070068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 private final IBatteryStats mBatteryStats;
70
71 private int mCallState = TelephonyManager.CALL_STATE_IDLE;
Wink Savillee9b06d72009-05-18 21:47:50 -070072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 private String mCallIncomingNumber = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 private ServiceState mServiceState = new ServiceState();
Wink Savillee9b06d72009-05-18 21:47:50 -070076
77 private SignalStrength mSignalStrength = new SignalStrength();
78
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private boolean mMessageWaiting = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 private boolean mCallForwarding = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
Wink Savillee9b06d72009-05-18 21:47:50 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
Wink Savillee9b06d72009-05-18 21:47:50 -070086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 private boolean mDataConnectionPossible = false;
Wink Savillee9b06d72009-05-18 21:47:50 -070088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 private String mDataConnectionReason = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 private String mDataConnectionApn = "";
Wink Savillee9b06d72009-05-18 21:47:50 -070092
Robert Greenwalt02648a42010-05-18 10:52:51 -070093 private ArrayList<String> mConnectedApns;
Robert Greenwalt42acef32009-08-12 16:08:25 -070094
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070095 private LinkProperties mDataConnectionProperties;
Wink Savillee9b06d72009-05-18 21:47:50 -070096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private Bundle mCellLocation = new Bundle();
98
Robert Greenwalt98e0b142009-10-08 21:15:52 -070099 private int mDataConnectionNetworkType;
100
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700101 static final int PHONE_STATE_PERMISSION_MASK =
102 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
103 PhoneStateListener.LISTEN_CALL_STATE |
104 PhoneStateListener.LISTEN_DATA_ACTIVITY |
105 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
106 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
107
Wink Savillee9b06d72009-05-18 21:47:50 -0700108 // we keep a copy of all of the state so we can send it out when folks
109 // register for it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 //
Wink Savillee9b06d72009-05-18 21:47:50 -0700111 // In these calls we call with the lock held. This is safe becasuse remote
112 // calls go through a oneway interface and local calls going through a
113 // handler before they get to app code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114
115 TelephonyRegistry(Context context) {
David 'Digit' Turner4ef8ec32009-09-25 11:33:24 -0700116 CellLocation location = CellLocation.getEmpty();
117
118 // Note that location can be null for non-phone builds like
119 // like the generic one.
120 if (location != null) {
121 location.fillInNotifierBundle(mCellLocation);
122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 mContext = context;
124 mBatteryStats = BatteryStatsService.getService();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700125 mConnectedApns = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 }
127
128 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
129 boolean notifyNow) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800130 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
Wink Savillee9b06d72009-05-18 21:47:50 -0700131 // Integer.toHexString(events));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 if (events != 0) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700133 /* Checks permission and throws Security exception */
134 checkListenerPermission(events);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135
136 synchronized (mRecords) {
137 // register
138 Record r = null;
139 find_and_add: {
140 IBinder b = callback.asBinder();
141 final int N = mRecords.size();
Wink Savillee9b06d72009-05-18 21:47:50 -0700142 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 r = mRecords.get(i);
144 if (b == r.binder) {
145 break find_and_add;
146 }
147 }
148 r = new Record();
149 r.binder = b;
150 r.callback = callback;
151 r.pkgForDebug = pkgForDebug;
152 mRecords.add(r);
153 }
154 int send = events & (events ^ r.events);
155 r.events = events;
156 if (notifyNow) {
157 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
158 sendServiceState(r, mServiceState);
159 }
160 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
161 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700162 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
163 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
164 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 } catch (RemoteException ex) {
166 remove(r.binder);
167 }
168 }
169 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
170 try {
171 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
172 } catch (RemoteException ex) {
173 remove(r.binder);
174 }
175 }
176 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
177 try {
178 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
179 } catch (RemoteException ex) {
180 remove(r.binder);
181 }
182 }
183 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
184 sendCellLocation(r, mCellLocation);
185 }
186 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
187 try {
188 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
189 } catch (RemoteException ex) {
190 remove(r.binder);
191 }
192 }
193 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
194 try {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700195 r.callback.onDataConnectionStateChanged(mDataConnectionState,
196 mDataConnectionNetworkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 } catch (RemoteException ex) {
198 remove(r.binder);
199 }
200 }
201 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
202 try {
203 r.callback.onDataActivity(mDataActivity);
204 } catch (RemoteException ex) {
205 remove(r.binder);
206 }
207 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700208 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
209 try {
210 r.callback.onSignalStrengthsChanged(mSignalStrength);
211 } catch (RemoteException ex) {
212 remove(r.binder);
213 }
214 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 }
216 }
217 } else {
218 remove(callback.asBinder());
219 }
220 }
221
222 private void remove(IBinder binder) {
223 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700224 final int recordCount = mRecords.size();
225 for (int i = 0; i < recordCount; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 if (mRecords.get(i).binder == binder) {
227 mRecords.remove(i);
228 return;
229 }
230 }
231 }
232 }
233
234 public void notifyCallState(int state, String incomingNumber) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700235 if (!checkNotifyPermission("notifyCallState()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700236 return;
237 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700238 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 synchronized (mRecords) {
240 mCallState = state;
241 mCallIncomingNumber = incomingNumber;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700242 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
244 try {
245 r.callback.onCallStateChanged(state, incomingNumber);
246 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700247 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 }
249 }
250 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700251 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 }
253 broadcastCallStateChanged(state, incomingNumber);
254 }
255
256 public void notifyServiceState(ServiceState state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700257 if (!checkNotifyPermission("notifyServiceState()")){
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700258 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 synchronized (mRecords) {
261 mServiceState = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700262 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
264 sendServiceState(r, state);
265 }
266 }
267 }
268 broadcastServiceStateChanged(state);
269 }
270
Wink Savillee9b06d72009-05-18 21:47:50 -0700271 public void notifySignalStrength(SignalStrength signalStrength) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700272 if (!checkNotifyPermission("notifySignalStrength()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700273 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700274 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700275 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700277 mSignalStrength = signalStrength;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700278 for (Record r : mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700279 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
280 sendSignalStrength(r, signalStrength);
281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
283 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700284 int gsmSignalStrength = signalStrength.getGsmSignalStrength();
285 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
286 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700288 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 }
290 }
291 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700292 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700294 broadcastSignalStrengthChanged(signalStrength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 }
296
297 public void notifyMessageWaitingChanged(boolean mwi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700298 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700299 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700300 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700301 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 synchronized (mRecords) {
303 mMessageWaiting = mwi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700304 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
306 try {
307 r.callback.onMessageWaitingIndicatorChanged(mwi);
308 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700309 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 }
311 }
312 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700313 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 }
315 }
316
317 public void notifyCallForwardingChanged(boolean cfi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700318 if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700319 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700320 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700321 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 synchronized (mRecords) {
323 mCallForwarding = cfi;
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_CALL_FORWARDING_INDICATOR) != 0) {
326 try {
327 r.callback.onCallForwardingIndicatorChanged(cfi);
328 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700329 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
331 }
332 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700333 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 }
335 }
336
337 public void notifyDataActivity(int state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700338 if (!checkNotifyPermission("notifyDataActivity()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700339 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700340 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700341 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 synchronized (mRecords) {
343 mDataActivity = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700344 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
346 try {
347 r.callback.onDataActivity(state);
348 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700349 removeList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
351 }
352 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700353 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 }
355 }
356
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700357 public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700358 String reason, String apn, String apnType, LinkProperties linkProperties,
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700359 int networkType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700360 if (!checkNotifyPermission("notifyDataConnection()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700361 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 synchronized (mRecords) {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700364 boolean modified = false;
365 if (state == TelephonyManager.DATA_CONNECTED) {
366 if (!mConnectedApns.contains(apnType)) {
367 mConnectedApns.add(apnType);
368 if (mDataConnectionState != state) {
369 mDataConnectionState = state;
370 modified = true;
371 }
372 }
373 } else {
374 mConnectedApns.remove(apnType);
375 if (mConnectedApns.isEmpty()) {
376 mDataConnectionState = state;
377 modified = true;
378 } else {
Robert Greenwalt74d99aa2010-07-14 14:30:34 -0700379 // leave mDataConnectionState as is and
380 // send out the new status for the APN in question.
Robert Greenwalt02648a42010-05-18 10:52:51 -0700381 }
382 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700383 mDataConnectionPossible = isDataConnectivityPossible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 mDataConnectionReason = reason;
385 mDataConnectionApn = apn;
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700386 mDataConnectionProperties = linkProperties;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700387 if (mDataConnectionNetworkType != networkType) {
388 mDataConnectionNetworkType = networkType;
389 modified = true;
390 }
391 if (modified) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700392 ArrayList<IBinder> removeList = new ArrayList<IBinder>();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700393 for (Record r : mRecords) {
394 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
395 try {
396 r.callback.onDataConnectionStateChanged(state, networkType);
397 } catch (RemoteException ex) {
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700398 removeList.add(r.binder);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 }
401 }
Robert Greenwalt1d15dd72010-06-21 12:15:26 -0700402 for (IBinder b : removeList) remove(b);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 }
404 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700405 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700406 apnType, linkProperties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 }
408
Robert Greenwalt02648a42010-05-18 10:52:51 -0700409 public void notifyDataConnectionFailed(String reason, String apnType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700410 if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700411 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 /*
Robert Greenwalt02648a42010-05-18 10:52:51 -0700414 * This is commented out because there is no onDataConnectionFailed callback
415 * in PhoneStateListener. There should be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 synchronized (mRecords) {
417 mDataConnectionFailedReason = reason;
418 final int N = mRecords.size();
419 for (int i=N-1; i>=0; i--) {
420 Record r = mRecords.get(i);
421 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
422 // XXX
423 }
424 }
425 }
426 */
Robert Greenwalt02648a42010-05-18 10:52:51 -0700427 broadcastDataConnectionFailed(reason, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 }
429
430 public void notifyCellLocation(Bundle cellLocation) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700431 if (!checkNotifyPermission("notifyCellLocation()")) {
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 synchronized (mRecords) {
435 mCellLocation = cellLocation;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700436 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
438 sendCellLocation(r, cellLocation);
439 }
440 }
441 }
442 }
443
Wink Savillee9b06d72009-05-18 21:47:50 -0700444 /**
445 * Copy the service state object so they can't mess it up in the local calls
446 */
Robert Greenwalt74d99aa2010-07-14 14:30:34 -0700447 private void sendServiceState(Record r, ServiceState state) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 try {
449 r.callback.onServiceStateChanged(new ServiceState(state));
450 } catch (RemoteException ex) {
451 remove(r.binder);
452 }
453 }
454
Wink Savillee9b06d72009-05-18 21:47:50 -0700455 private void sendCellLocation(Record r, Bundle cellLocation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 try {
457 r.callback.onCellLocationChanged(new Bundle(cellLocation));
458 } catch (RemoteException ex) {
459 remove(r.binder);
460 }
461 }
462
Wink Savillee9b06d72009-05-18 21:47:50 -0700463 private void sendSignalStrength(Record r, SignalStrength signalStrength) {
464 try {
465 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
466 } catch (RemoteException ex) {
467 remove(r.binder);
468 }
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);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700493 pw.println(" mDataConnectionProperties=" + mDataConnectionProperties);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 pw.println(" mCellLocation=" + mCellLocation);
Wink Savillee9b06d72009-05-18 21:47:50 -0700495 pw.println("registrations: count=" + recordCount);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700496 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
498 }
499 }
500 }
501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800502 //
503 // the legacy intent broadcasting
504 //
505
506 private void broadcastServiceStateChanged(ServiceState state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700507 long ident = Binder.clearCallingIdentity();
508 try {
Amith Yamasanif37447b2009-10-08 18:28:01 -0700509 mBatteryStats.notePhoneState(state.getState());
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700510 } catch (RemoteException re) {
511 // Can't do much
512 } finally {
513 Binder.restoreCallingIdentity(ident);
514 }
515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800517 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 Bundle data = new Bundle();
519 state.fillInNotifierBundle(data);
520 intent.putExtras(data);
521 mContext.sendStickyBroadcast(intent);
522 }
523
Wink Savillee9b06d72009-05-18 21:47:50 -0700524 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700525 long ident = Binder.clearCallingIdentity();
526 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700527 mBatteryStats.notePhoneSignalStrength(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700528 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700529 /* The remote entity disappeared, we can safely ignore the exception. */
Dianne Hackborn627bba72009-03-24 22:32:56 -0700530 } finally {
531 Binder.restoreCallingIdentity(ident);
532 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800535 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700536 Bundle data = new Bundle();
537 signalStrength.fillInNotifierBundle(data);
538 intent.putExtras(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 mContext.sendStickyBroadcast(intent);
540 }
541
542 private void broadcastCallStateChanged(int state, String incomingNumber) {
543 long ident = Binder.clearCallingIdentity();
544 try {
545 if (state == TelephonyManager.CALL_STATE_IDLE) {
546 mBatteryStats.notePhoneOff();
547 } else {
548 mBatteryStats.notePhoneOn();
549 }
550 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700551 /* The remote entity disappeared, we can safely ignore the exception. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 } finally {
553 Binder.restoreCallingIdentity(ident);
554 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800557 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700558 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 if (!TextUtils.isEmpty(incomingNumber)) {
560 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
561 }
562 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
563 }
564
Robert Greenwalt42acef32009-08-12 16:08:25 -0700565 private void broadcastDataConnectionStateChanged(int state,
566 boolean isDataConnectivityPossible,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700567 String reason, String apn, String apnType, LinkProperties linkProperties) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700568 // Note: not reporting to the battery stats service here, because the
569 // status bar takes care of that after taking into account all of the
570 // required info.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800572 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
574 if (!isDataConnectivityPossible) {
575 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
576 }
577 if (reason != null) {
578 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
579 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700580 if (linkProperties != null) {
581 intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties);
582 NetworkInterface iface = linkProperties.getInterface();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700583 if (iface != null) {
584 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface.getName());
585 }
586 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 intent.putExtra(Phone.DATA_APN_KEY, apn);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700588 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 mContext.sendStickyBroadcast(intent);
590 }
591
Robert Greenwalt02648a42010-05-18 10:52:51 -0700592 private void broadcastDataConnectionFailed(String reason, String apnType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800594 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
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 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700599
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700600 private boolean checkNotifyPermission(String method) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700601 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
602 == PackageManager.PERMISSION_GRANTED) {
603 return true;
604 }
605 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700606 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800607 Slog.w(TAG, msg);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700608 return false;
609 }
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700610
611 private void checkListenerPermission(int events) {
612 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
613 mContext.enforceCallingOrSelfPermission(
614 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
615
616 }
617
618 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
619 mContext.enforceCallingOrSelfPermission(
620 android.Manifest.permission.READ_PHONE_STATE, null);
621 }
622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623}