blob: a7a0c682d93a763395387a3964d83f6529fa4c9e [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
Wink Savillefd2d0132010-10-28 14:22:26 -0700106 private int mOtaspMode;
107
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700108 static final int PHONE_STATE_PERMISSION_MASK =
109 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
110 PhoneStateListener.LISTEN_CALL_STATE |
111 PhoneStateListener.LISTEN_DATA_ACTIVITY |
112 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
113 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
114
Wink Savillee9b06d72009-05-18 21:47:50 -0700115 // we keep a copy of all of the state so we can send it out when folks
116 // register for it
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 //
Wink Savillee9b06d72009-05-18 21:47:50 -0700118 // In these calls we call with the lock held. This is safe becasuse remote
119 // calls go through a oneway interface and local calls going through a
120 // handler before they get to app code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
122 TelephonyRegistry(Context context) {
David 'Digit' Turner4ef8ec32009-09-25 11:33:24 -0700123 CellLocation location = CellLocation.getEmpty();
124
125 // Note that location can be null for non-phone builds like
126 // like the generic one.
127 if (location != null) {
128 location.fillInNotifierBundle(mCellLocation);
129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 mContext = context;
131 mBatteryStats = BatteryStatsService.getService();
Robert Greenwalt02648a42010-05-18 10:52:51 -0700132 mConnectedApns = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 }
134
135 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
136 boolean notifyNow) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800137 // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
Wink Savillee9b06d72009-05-18 21:47:50 -0700138 // Integer.toHexString(events));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 if (events != 0) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700140 /* Checks permission and throws Security exception */
141 checkListenerPermission(events);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142
143 synchronized (mRecords) {
144 // register
145 Record r = null;
146 find_and_add: {
147 IBinder b = callback.asBinder();
148 final int N = mRecords.size();
Wink Savillee9b06d72009-05-18 21:47:50 -0700149 for (int i = 0; i < N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 r = mRecords.get(i);
151 if (b == r.binder) {
152 break find_and_add;
153 }
154 }
155 r = new Record();
156 r.binder = b;
157 r.callback = callback;
158 r.pkgForDebug = pkgForDebug;
159 mRecords.add(r);
160 }
161 int send = events & (events ^ r.events);
162 r.events = events;
163 if (notifyNow) {
164 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400165 try {
166 r.callback.onServiceStateChanged(new ServiceState(mServiceState));
167 } catch (RemoteException ex) {
168 remove(r.binder);
169 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 }
171 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
172 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700173 int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
174 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
175 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 } catch (RemoteException ex) {
177 remove(r.binder);
178 }
179 }
180 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
181 try {
182 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
183 } catch (RemoteException ex) {
184 remove(r.binder);
185 }
186 }
187 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
188 try {
189 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
190 } catch (RemoteException ex) {
191 remove(r.binder);
192 }
193 }
194 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400195 try {
196 r.callback.onCellLocationChanged(new Bundle(mCellLocation));
197 } catch (RemoteException ex) {
198 remove(r.binder);
199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 }
201 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
202 try {
203 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
204 } catch (RemoteException ex) {
205 remove(r.binder);
206 }
207 }
208 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
209 try {
Robert Greenwalt98e0b142009-10-08 21:15:52 -0700210 r.callback.onDataConnectionStateChanged(mDataConnectionState,
211 mDataConnectionNetworkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 } catch (RemoteException ex) {
213 remove(r.binder);
214 }
215 }
216 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
217 try {
218 r.callback.onDataActivity(mDataActivity);
219 } catch (RemoteException ex) {
220 remove(r.binder);
221 }
222 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700223 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
224 try {
225 r.callback.onSignalStrengthsChanged(mSignalStrength);
226 } catch (RemoteException ex) {
227 remove(r.binder);
228 }
229 }
Wink Savillefd2d0132010-10-28 14:22:26 -0700230 if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
231 try {
232 r.callback.onOtaspChanged(mOtaspMode);
233 } catch (RemoteException ex) {
234 remove(r.binder);
235 }
236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 }
238 }
239 } else {
240 remove(callback.asBinder());
241 }
242 }
243
244 private void remove(IBinder binder) {
245 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700246 final int recordCount = mRecords.size();
247 for (int i = 0; i < recordCount; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 if (mRecords.get(i).binder == binder) {
249 mRecords.remove(i);
250 return;
251 }
252 }
253 }
254 }
255
256 public void notifyCallState(int state, String incomingNumber) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700257 if (!checkNotifyPermission("notifyCallState()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700258 return;
259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 synchronized (mRecords) {
261 mCallState = state;
262 mCallIncomingNumber = incomingNumber;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700263 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
265 try {
266 r.callback.onCallStateChanged(state, incomingNumber);
267 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400268 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 }
270 }
271 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400272 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 }
274 broadcastCallStateChanged(state, incomingNumber);
275 }
276
277 public void notifyServiceState(ServiceState state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700278 if (!checkNotifyPermission("notifyServiceState()")){
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700279 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700280 }
Joe Onorato431bb222010-10-18 19:13:23 -0400281 Slog.i(TAG, "notifyServiceState: " + state);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 synchronized (mRecords) {
283 mServiceState = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700284 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400286 try {
287 r.callback.onServiceStateChanged(new ServiceState(state));
288 } catch (RemoteException ex) {
289 mRemoveList.add(r.binder);
290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 }
292 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400293 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 }
295 broadcastServiceStateChanged(state);
296 }
297
Wink Savillee9b06d72009-05-18 21:47:50 -0700298 public void notifySignalStrength(SignalStrength signalStrength) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700299 if (!checkNotifyPermission("notifySignalStrength()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700300 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700301 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700303 mSignalStrength = signalStrength;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700304 for (Record r : mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700305 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400306 try {
307 r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
308 } catch (RemoteException ex) {
309 mRemoveList.add(r.binder);
310 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
313 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700314 int gsmSignalStrength = signalStrength.getGsmSignalStrength();
315 r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
316 : gsmSignalStrength));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400318 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 }
320 }
321 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400322 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700324 broadcastSignalStrengthChanged(signalStrength);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 }
326
327 public void notifyMessageWaitingChanged(boolean mwi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700328 if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
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 mMessageWaiting = mwi;
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_MESSAGE_WAITING_INDICATOR) != 0) {
335 try {
336 r.callback.onMessageWaitingIndicatorChanged(mwi);
337 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400338 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 }
340 }
341 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400342 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 }
344 }
345
346 public void notifyCallForwardingChanged(boolean cfi) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700347 if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
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) {
351 mCallForwarding = cfi;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700352 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
354 try {
355 r.callback.onCallForwardingIndicatorChanged(cfi);
356 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400357 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 }
359 }
360 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400361 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 }
363 }
364
365 public void notifyDataActivity(int state) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700366 if (!checkNotifyPermission("notifyDataActivity()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700367 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 synchronized (mRecords) {
370 mDataActivity = state;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700371 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
373 try {
374 r.callback.onDataActivity(state);
375 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400376 mRemoveList.add(r.binder);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 }
378 }
379 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400380 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 }
382 }
383
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700384 public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700385 String reason, String apn, String apnType, LinkProperties linkProperties,
Wink Savillef61101f2010-09-16 16:36:42 -0700386 LinkCapabilities linkCapabilities, int networkType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700387 if (!checkNotifyPermission("notifyDataConnection()" )) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700388 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700389 }
Joe Onorato431bb222010-10-18 19:13:23 -0400390 Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
391 + isDataConnectivityPossible + " reason=" + reason
Joe Onorato74998472010-10-21 11:38:11 -0400392 + " apn=" + apn + " networkType=" + networkType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 synchronized (mRecords) {
Robert Greenwalt02648a42010-05-18 10:52:51 -0700394 boolean modified = false;
395 if (state == TelephonyManager.DATA_CONNECTED) {
396 if (!mConnectedApns.contains(apnType)) {
397 mConnectedApns.add(apnType);
398 if (mDataConnectionState != state) {
399 mDataConnectionState = state;
400 modified = true;
401 }
402 }
403 } else {
404 mConnectedApns.remove(apnType);
405 if (mConnectedApns.isEmpty()) {
406 mDataConnectionState = state;
407 modified = true;
408 } else {
Robert Greenwalt74d99aa2010-07-14 14:30:34 -0700409 // leave mDataConnectionState as is and
410 // send out the new status for the APN in question.
Robert Greenwalt02648a42010-05-18 10:52:51 -0700411 }
412 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700413 mDataConnectionPossible = isDataConnectivityPossible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 mDataConnectionReason = reason;
Wink Savillef61101f2010-09-16 16:36:42 -0700415 mDataConnectionLinkProperties = linkProperties;
416 mDataConnectionLinkCapabilities = linkCapabilities;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700417 if (mDataConnectionNetworkType != networkType) {
418 mDataConnectionNetworkType = networkType;
419 modified = true;
420 }
421 if (modified) {
422 for (Record r : mRecords) {
423 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
424 try {
425 r.callback.onDataConnectionStateChanged(state, networkType);
426 } catch (RemoteException ex) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400427 mRemoveList.add(r.binder);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 }
430 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400431 handleRemoveListLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 }
433 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700434 broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
Wink Savillef61101f2010-09-16 16:36:42 -0700435 apnType, linkProperties, linkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 }
437
Robert Greenwalt02648a42010-05-18 10:52:51 -0700438 public void notifyDataConnectionFailed(String reason, String apnType) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700439 if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700440 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 /*
Robert Greenwalt02648a42010-05-18 10:52:51 -0700443 * This is commented out because there is no onDataConnectionFailed callback
444 * in PhoneStateListener. There should be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 synchronized (mRecords) {
446 mDataConnectionFailedReason = reason;
447 final int N = mRecords.size();
448 for (int i=N-1; i>=0; i--) {
449 Record r = mRecords.get(i);
450 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
451 // XXX
452 }
453 }
454 }
455 */
Robert Greenwalt02648a42010-05-18 10:52:51 -0700456 broadcastDataConnectionFailed(reason, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458
459 public void notifyCellLocation(Bundle cellLocation) {
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700460 if (!checkNotifyPermission("notifyCellLocation()")) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700461 return;
Wink Savillee9b06d72009-05-18 21:47:50 -0700462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 synchronized (mRecords) {
464 mCellLocation = cellLocation;
Robert Greenwalt02648a42010-05-18 10:52:51 -0700465 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
Joe Onorato163d8d92010-10-21 13:21:20 -0400467 try {
468 r.callback.onCellLocationChanged(new Bundle(cellLocation));
469 } catch (RemoteException ex) {
470 mRemoveList.add(r.binder);
471 }
472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 }
474 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400475 handleRemoveListLocked();
Wink Savillee9b06d72009-05-18 21:47:50 -0700476 }
477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478
Wink Savillefd2d0132010-10-28 14:22:26 -0700479 public void notifyOtaspChanged(int otaspMode) {
480 if (!checkNotifyPermission("notifyOtaspChanged()" )) {
481 return;
482 }
483 synchronized (mRecords) {
484 mOtaspMode = otaspMode;
485 for (Record r : mRecords) {
486 if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
487 try {
488 r.callback.onOtaspChanged(otaspMode);
489 } catch (RemoteException ex) {
490 mRemoveList.add(r.binder);
491 }
492 }
493 }
494 handleRemoveListLocked();
495 }
496 }
497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 @Override
499 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
500 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
501 != PackageManager.PERMISSION_GRANTED) {
502 pw.println("Permission Denial: can't dump telephony.registry from from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700503 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 return;
505 }
506 synchronized (mRecords) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700507 final int recordCount = mRecords.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 pw.println("last known state:");
509 pw.println(" mCallState=" + mCallState);
510 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
511 pw.println(" mServiceState=" + mServiceState);
512 pw.println(" mSignalStrength=" + mSignalStrength);
513 pw.println(" mMessageWaiting=" + mMessageWaiting);
514 pw.println(" mCallForwarding=" + mCallForwarding);
515 pw.println(" mDataActivity=" + mDataActivity);
516 pw.println(" mDataConnectionState=" + mDataConnectionState);
517 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
518 pw.println(" mDataConnectionReason=" + mDataConnectionReason);
519 pw.println(" mDataConnectionApn=" + mDataConnectionApn);
Wink Savillef61101f2010-09-16 16:36:42 -0700520 pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
521 pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 pw.println(" mCellLocation=" + mCellLocation);
Wink Savillee9b06d72009-05-18 21:47:50 -0700523 pw.println("registrations: count=" + recordCount);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700524 for (Record r : mRecords) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
526 }
527 }
528 }
529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 //
531 // the legacy intent broadcasting
532 //
533
534 private void broadcastServiceStateChanged(ServiceState state) {
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700535 long ident = Binder.clearCallingIdentity();
536 try {
Amith Yamasanif37447b2009-10-08 18:28:01 -0700537 mBatteryStats.notePhoneState(state.getState());
Amith Yamasani32dbefd2009-06-19 09:21:17 -0700538 } catch (RemoteException re) {
539 // Can't do much
540 } finally {
541 Binder.restoreCallingIdentity(ident);
542 }
543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800545 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 Bundle data = new Bundle();
547 state.fillInNotifierBundle(data);
548 intent.putExtras(data);
549 mContext.sendStickyBroadcast(intent);
550 }
551
Wink Savillee9b06d72009-05-18 21:47:50 -0700552 private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700553 long ident = Binder.clearCallingIdentity();
554 try {
Wink Savillee9b06d72009-05-18 21:47:50 -0700555 mBatteryStats.notePhoneSignalStrength(signalStrength);
Dianne Hackborn627bba72009-03-24 22:32:56 -0700556 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700557 /* The remote entity disappeared, we can safely ignore the exception. */
Dianne Hackborn627bba72009-03-24 22:32:56 -0700558 } finally {
559 Binder.restoreCallingIdentity(ident);
560 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800563 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700564 Bundle data = new Bundle();
565 signalStrength.fillInNotifierBundle(data);
566 intent.putExtras(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 mContext.sendStickyBroadcast(intent);
568 }
569
570 private void broadcastCallStateChanged(int state, String incomingNumber) {
571 long ident = Binder.clearCallingIdentity();
572 try {
573 if (state == TelephonyManager.CALL_STATE_IDLE) {
574 mBatteryStats.notePhoneOff();
575 } else {
576 mBatteryStats.notePhoneOn();
577 }
578 } catch (RemoteException e) {
Wink Savillee9b06d72009-05-18 21:47:50 -0700579 /* The remote entity disappeared, we can safely ignore the exception. */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 } finally {
581 Binder.restoreCallingIdentity(ident);
582 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800585 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
Wink Savillee9b06d72009-05-18 21:47:50 -0700586 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertCallState(state).toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 if (!TextUtils.isEmpty(incomingNumber)) {
588 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
589 }
590 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
591 }
592
Robert Greenwalt42acef32009-08-12 16:08:25 -0700593 private void broadcastDataConnectionStateChanged(int state,
594 boolean isDataConnectivityPossible,
Wink Savillef61101f2010-09-16 16:36:42 -0700595 String reason, String apn, String apnType, LinkProperties linkProperties,
596 LinkCapabilities linkCapabilities) {
Dianne Hackborn627bba72009-03-24 22:32:56 -0700597 // Note: not reporting to the battery stats service here, because the
598 // status bar takes care of that after taking into account all of the
599 // required info.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800601 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
603 if (!isDataConnectivityPossible) {
604 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
605 }
606 if (reason != null) {
607 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
608 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700609 if (linkProperties != null) {
610 intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties);
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700611 String iface = linkProperties.getInterfaceName();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700612 if (iface != null) {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700613 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700614 }
615 }
Wink Savillef61101f2010-09-16 16:36:42 -0700616 if (linkCapabilities != null) {
617 intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities);
618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 intent.putExtra(Phone.DATA_APN_KEY, apn);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700620 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 mContext.sendStickyBroadcast(intent);
622 }
623
Robert Greenwalt02648a42010-05-18 10:52:51 -0700624 private void broadcastDataConnectionFailed(String reason, String apnType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -0800626 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
Robert Greenwalt02648a42010-05-18 10:52:51 -0700628 intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 mContext.sendStickyBroadcast(intent);
630 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700631
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700632 private boolean checkNotifyPermission(String method) {
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700633 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
634 == PackageManager.PERMISSION_GRANTED) {
635 return true;
636 }
637 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
Wink Savillee9b06d72009-05-18 21:47:50 -0700638 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
Joe Onorato8a9b2202010-02-26 18:56:32 -0800639 Slog.w(TAG, msg);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700640 return false;
641 }
Jaikumar Ganesh45515652009-04-23 15:20:21 -0700642
643 private void checkListenerPermission(int events) {
644 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
645 mContext.enforceCallingOrSelfPermission(
646 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
647
648 }
649
650 if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
651 mContext.enforceCallingOrSelfPermission(
652 android.Manifest.permission.READ_PHONE_STATE, null);
653 }
654 }
Joe Onorato163d8d92010-10-21 13:21:20 -0400655
656 private void handleRemoveListLocked() {
657 if (mRemoveList.size() > 0) {
658 for (IBinder b: mRemoveList) {
659 remove(b);
660 }
661 mRemoveList.clear();
662 }
663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664}