So, hab mal den Source ausgecheckt mittels git.
mac@mac-desktop:~/workspace/android/mydroid$ find . -name 'TelephonyManager.java'
./frameworks/base/telephony/java/android/telephony/TelephonyManager.java
1/*
2 * Copyright (C) 2008 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 android.telephony;
18
19import com.android.internal.telephony.*;
20
21import java.util.ArrayList;
22import java.util.List;
23
24import android.annotation.SdkConstant.SdkConstantType;
25import android.annotation.SdkConstant;
26import android.content.Context;
27import android.os.Bundle;
28import android.os.RemoteException;
29import android.os.ServiceManager;
30import android.os.SystemProperties;
31
32
33/**
34 * Provides access to information about the telephony services on
35 * the device. Applications can use the methods in this class to
36 * determine telephony services and states, as well as to access some
37 * types of subscriber information. Applications can also register
38 * a listener to receive notification of telephony state changes.
39 * <p>
40 * You do not instantiate this class directly; instead, you retrieve
41 * a reference to an instance through
42 * {@link android.content.Context#getSystemService
43 * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
44 * <p>
45 * Note that acess to some telephony information is
46 * permission-protected. Your application cannot access the protected
47 * information unless it has the appropriate permissions declared in
48 * its manifest file. Where permissions apply, they are noted in the
49 * the methods through which you access the protected information.
50 */
51public class TelephonyManager {
52 private static final String TAG = "TelephonyManager";
53
54 private Context mContext;
55 private ITelephonyRegistry mRegistry;
56
57 /** @hide */
58 public TelephonyManager(Context context) {
59 mContext = context;
60 mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
61 "telephony.registry"));
62 }
63
64 /** @hide */
65 private TelephonyManager() {
66 }
67
68 private static TelephonyManager sInstance = new TelephonyManager();
69
70 /** @hide */
71 public static TelephonyManager getDefault() {
72 return sInstance;
73 }
74
75
76 //
77 // Broadcast Intent actions
78 //
79
80 /**
81 * Broadcast intent action indicating that the call state (cellular)
82 * on the device has changed.
83 *
84 * <p>
85 * The {@link #EXTRA_STATE} extra indicates the new call state.
86 * If the new state is RINGING, a second extra
87 * {@link #EXTRA_INCOMING_NUMBER} provides the incoming phone number as
88 * a String.
89 *
90 * <p class="note">
91 * Requires the READ_PHONE_STATE permission.
92 *
93 * <p class="note">
94 * This was a {@link android.content.Context#sendStickyBroadcast sticky}
95 * broadcast in version 1.0, but it is no longer sticky.
96 * Instead, use {@link #getCallState} to synchronously query the current call state.
97 *
98 * @see #EXTRA_STATE
99 * @see #EXTRA_INCOMING_NUMBER
100 * @see #getCallState
101 */
102 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
103 public static final String ACTION_PHONE_STATE_CHANGED =
104 "android.intent.action.PHONE_STATE";
105
106 /**
107 * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
108 * for a String containing the new call state.
109 *
110 * @see #EXTRA_STATE_IDLE
111 * @see #EXTRA_STATE_RINGING
112 * @see #EXTRA_STATE_OFFHOOK
113 *
114 * <p class="note">
115 * Retrieve with
116 * {@link android.content.Intent#getStringExtra(String)}.
117 */
118 public static final String EXTRA_STATE = Phone.STATE_KEY;
119
120 /**
121 * Value used with {@link #EXTRA_STATE} corresponding to
122 * {@link #CALL_STATE_IDLE}.
123 */
124 public static final String EXTRA_STATE_IDLE = Phone.State.IDLE.toString();
125
126 /**
127 * Value used with {@link #EXTRA_STATE} corresponding to
128 * {@link #CALL_STATE_RINGING}.
129 */
130 public static final String EXTRA_STATE_RINGING = Phone.State.RINGING.toString();
131
132 /**
133 * Value used with {@link #EXTRA_STATE} corresponding to
134 * {@link #CALL_STATE_OFFHOOK}.
135 */
136 public static final String EXTRA_STATE_OFFHOOK = Phone.State.OFFHOOK.toString();
137
138 /**
139 * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
140 * for a String containing the incoming phone number.
141 * Only valid when the new call state is RINGING.
142 *
143 * <p class="note">
144 * Retrieve with
145 * {@link android.content.Intent#getStringExtra(String)}.
146 */
147 public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
148
149
150 //
151 //
152 // Device Info
153 //
154 //
155
156 /**
157 * Returns the software version number for the device, for example,
158 * the IMEI/SV for GSM phones.
159 *
160 * <p>Requires Permission:
161 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
162 */
163 public String getDeviceSoftwareVersion() {
164 try {
165 return getSubscriberInfo().getDeviceSvn();
166 } catch (RemoteException ex) {
167 }
168 return null;
169 }
170
171 /**
172 * Returns the unique device ID, for example,the IMEI for GSM
173 * phones.
174 *
175 * <p>Requires Permission:
176 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
177 */
178 public String getDeviceId() {
179 try {
180 return getSubscriberInfo().getDeviceId();
181 } catch (RemoteException ex) {
182 }
183 return null;
184 }
185
186 /**
187 * Returns the current location of the device.
188 *
189 * <p>Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION
190 * ACCESS_COARSE_LOCATION}.
191 */
192 public CellLocation getCellLocation() {
193 try {
194 Bundle bundle = getITelephony().getCellLocation();
195 return CellLocation.newFromBundle(bundle);
196 } catch (RemoteException ex) {
197 }
198 return null;
199 }
200
201 /**
202 * Enables location update notifications. {@link PhoneStateListener#onCellLocationChanged
203 * PhoneStateListener.onCellLocationChanged} will be called on location updates.
204 *
205 * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
206 * CONTROL_LOCATION_UPDATES}
207 *
208 * @hide
209 */
210 public void enableLocationUpdates() {
211 try {
212 getITelephony().enableLocationUpdates();
213 } catch (RemoteException ex) {
214 }
215 }
216
217 /**
218 * Disables location update notifications. {@link PhoneStateListener#onCellLocationChanged
219 * PhoneStateListener.onCellLocationChanged} will be called on location updates.
220 *
221 * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
222 * CONTROL_LOCATION_UPDATES}
223 *
224 * @hide
225 */
226 public void disableLocationUpdates() {
227 try {
228 getITelephony().disableLocationUpdates();
229 } catch (RemoteException ex) {
230 }
231 }
232
233 /**
234 * Returns the neighboring cell information of the device.
235 *
236 * @return List of NeighboringCellInfo or null if info unavailable.
237 *
238 * <p>Requires Permission:
239 * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
240 */
241 public List<NeighboringCellInfo> getNeighboringCellInfo() {
242 try {
243 return getITelephony().getNeighboringCellInfo();
244 } catch (RemoteException ex) {
245 }
246 return null;
247
248 }
249
250 /**
251 * No phone module
252 */
253 public static final int PHONE_TYPE_NONE = 0;
254
255 /**
256 * GSM phone
257 */
258 public static final int PHONE_TYPE_GSM = 1;
259
260 /**
261 * Returns a constant indicating the device phone type.
262 *
263 * @see #PHONE_TYPE_NONE
264 * @see #PHONE_TYPE_GSM
265 */
266 public int getPhoneType() {
267 // in the future, we should really check this
268 return PHONE_TYPE_GSM;
269 }
270
271 //
272 //
273 // Current Network
274 //
275 //
276
277 /**
278 * Returns the alphabetic name of current registered operator.
279 * <p>
280 * Availability: Only when user is registered to a network
281 */
282 public String getNetworkOperatorName() {
283 return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA);
284 }
285
286 /**
287 * Returns the numeric name (MCC+MNC) of current registered operator.
288 * <p>
289 * Availability: Only when user is registered to a network
290 */
291 public String getNetworkOperator() {
292 return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
293 }
294
295 /**
296 * Returns true if the device is considered roaming on the current
297 * network, for GSM purposes.
298 * <p>
299 * Availability: Only when user registered to a network
300 */
301 public boolean isNetworkRoaming() {
302 return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
303 }
304
305 /**
306 * Returns the ISO country code equivilent of the current registered
307 * operator's MCC (Mobile Country Code).
308 * <p>
309 * Availability: Only when user is registered to a network
310 */
311 public String getNetworkCountryIso() {
312 return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);
313 }
314
315 /** Network type is unknown */
316 public static final int NETWORK_TYPE_UNKNOWN = 0;
317 /** Current network is GPRS */
318 public static final int NETWORK_TYPE_GPRS = 1;
319 /** Current network is EDGE */
320 public static final int NETWORK_TYPE_EDGE = 2;
321 /** Current network is UMTS */
322 public static final int NETWORK_TYPE_UMTS = 3;
323
324 /**
325 * Returns a constant indicating the radio technology (network type)
326 * currently in use on the device.
327 * @return the network type
328 *
329 * @see #NETWORK_TYPE_UNKNOWN
330 * @see #NETWORK_TYPE_GPRS
331 * @see #NETWORK_TYPE_EDGE
332 * @see #NETWORK_TYPE_UMTS
333 */
334 public int getNetworkType() {
335 String prop = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE);
336 if ("GPRS".equals(prop)) {
337 return NETWORK_TYPE_GPRS;
338 }
339 else if ("EDGE".equals(prop)) {
340 return NETWORK_TYPE_EDGE;
341 }
342 else if ("UMTS".equals(prop)) {
343 return NETWORK_TYPE_UMTS;
344 }
345 else {
346 return NETWORK_TYPE_UNKNOWN;
347 }
348 }
349
350 /**
351 * Returns a string representation of the radio technology (network type)
352 * currently in use on the device.
353 * @return the name of the radio technology
354 *
355 * @hide pending API council review
356 */
357 public String getNetworkTypeName() {
358 switch (getNetworkType()) {
359 case NETWORK_TYPE_GPRS:
360 return "GPRS";
361 case NETWORK_TYPE_EDGE:
362 return "EDGE";
363 case NETWORK_TYPE_UMTS:
364 return "UMTS";
365 default:
366 return "UNKNOWN";
367 }
368 }
369
370 //
371 //
372 // SIM Card
373 //
374 //
375
376 /** SIM card state: Unknown. Signifies that the SIM is in transition
377 * between states. For example, when the user inputs the SIM pin
378 * under PIN_REQUIRED state, a query for sim status returns
379 * this state before turning to SIM_STATE_READY. */
380 public static final int SIM_STATE_UNKNOWN = 0;
381 /** SIM card state: no SIM card is available in the device */
382 public static final int SIM_STATE_ABSENT = 1;
383 /** SIM card state: Locked: requires the user's SIM PIN to unlock */
384 public static final int SIM_STATE_PIN_REQUIRED = 2;
385 /** SIM card state: Locked: requires the user's SIM PUK to unlock */
386 public static final int SIM_STATE_PUK_REQUIRED = 3;
387 /** SIM card state: Locked: requries a network PIN to unlock */
388 public static final int SIM_STATE_NETWORK_LOCKED = 4;
389 /** SIM card state: Ready */
390 public static final int SIM_STATE_READY = 5;
391
392 /**
393 * Returns a constant indicating the state of the
394 * device SIM card.
395 *
396 * @see #SIM_STATE_UNKNOWN
397 * @see #SIM_STATE_ABSENT
398 * @see #SIM_STATE_PIN_REQUIRED
399 * @see #SIM_STATE_PUK_REQUIRED
400 * @see #SIM_STATE_NETWORK_LOCKED
401 * @see #SIM_STATE_READY
402 */
403 public int getSimState() {
404 String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE);
405 if ("ABSENT".equals(prop)) {
406 return SIM_STATE_ABSENT;
407 }
408 else if ("PIN_REQUIRED".equals(prop)) {
409 return SIM_STATE_PIN_REQUIRED;
410 }
411 else if ("PUK_REQUIRED".equals(prop)) {
412 return SIM_STATE_PUK_REQUIRED;
413 }
414 else if ("NETWORK_LOCKED".equals(prop)) {
415 return SIM_STATE_NETWORK_LOCKED;
416 }
417 else if ("READY".equals(prop)) {
418 return SIM_STATE_READY;
419 }
420 else {
421 return SIM_STATE_UNKNOWN;
422 }
423 }
424
425 /**
426 * Returns the MCC+MNC (mobile country code + mobile network code) of the
427 * provider of the SIM. 5 or 6 decimal digits.
428 * <p>
429 * Availability: SIM state must be {@link #SIM_STATE_READY}
430 *
431 * @see #getSimState
432 */
433 public String getSimOperator() {
434 return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC);
435 }
436
437 /**
438 * Returns the Service Provider Name (SPN).
439 * <p>
440 * Availability: SIM state must be {@link #SIM_STATE_READY}
441 *
442 * @see #getSimState
443 */
444 public String getSimOperatorName() {
445 return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA);
446 }
447
448 /**
449 * Returns the ISO country code equivalent for the SIM provider's country code.
450 */
451 public String getSimCountryIso() {
452 return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ISO_COUNTRY);
453 }
454
455 /**
456 * Returns the serial number of the SIM, if applicable.
457 * <p>
458 * Requires Permission:
459 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
460 */
461 public String getSimSerialNumber() {
462 try {
463 return getSubscriberInfo().getSimSerialNumber();
464 } catch (RemoteException ex) {
465 }
466 return null;
467 }
468
469 //
470 //
471 // Subscriber Info
472 //
473 //
474
475 /**
476 * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
477 * <p>
478 * Requires Permission:
479 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
480 */
481 public String getSubscriberId() {
482 try {
483 return getSubscriberInfo().getSubscriberId();
484 } catch (RemoteException ex) {
485 }
486 return null;
487 }
488
489 /**
490 * Returns the phone number string for line 1, for example, the MSISDN
491 * for a GSM phone.
492 * <p>
493 * Requires Permission:
494 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
495 */
496 public String getLine1Number() {
497 try {
498 return getSubscriberInfo().getLine1Number();
499 } catch (RemoteException ex) {
500 }
501 return null;
502 }
503
504 /**
505 * Returns the alphabetic identifier associated with the line 1 number.
506 * <p>
507 * Requires Permission:
508 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
509 * @hide
510 * nobody seems to call this.
511 */
512 public String getLine1AlphaTag() {
513 try {
514 return getSubscriberInfo().getLine1AlphaTag();
515 } catch (RemoteException ex) {
516 }
517 return null;
518 }
519
520 /**
521 * Returns the voice mail number.
522 * <p>
523 * Requires Permission:
524 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
525 */
526 public String getVoiceMailNumber() {
527 try {
528 return getSubscriberInfo().getVoiceMailNumber();
529 } catch (RemoteException ex) {
530 }
531 return null;
532 }
533
534 /**
535 * Retrieves the alphabetic identifier associated with the voice
536 * mail number.
537 * <p>
538 * Requires Permission:
539 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
540 */
541 public String getVoiceMailAlphaTag() {
542 try {
543 return getSubscriberInfo().getVoiceMailAlphaTag();
544 } catch (RemoteException ex) {
545 }
546 return null;
547 }
548
549 private IPhoneSubInfo getSubscriberInfo() {
550 // get it each time because that process crashes a lot
551 return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
552 }
553
554
555 /** Device call state: No activity. */
556 public static final int CALL_STATE_IDLE = 0;
557 /** Device call state: Ringing. A new call arrived and is
558 * ringing or waiting. In the latter case, another call is
559 * already active. */
560 public static final int CALL_STATE_RINGING = 1;
561 /** Device call state: Off-hook. At least one call exists
562 * that is dialing, active, or on hold, and no calls are ringing
563 * or waiting. */
564 public static final int CALL_STATE_OFFHOOK = 2;
565
566 /**
567 * Returns a constant indicating the call state (cellular) on the device.
568 */
569 public int getCallState() {
570 try {
571 return getITelephony().getCallState();
572 } catch (RemoteException ex) {
573 // the phone process is restarting.
574 return CALL_STATE_IDLE;
575 }
576 }
577
578 /** Data connection activity: No traffic. */
579 public static final int DATA_ACTIVITY_NONE = 0x00000000;
580 /** Data connection activity: Currently receiving IP PPP traffic. */
581 public static final int DATA_ACTIVITY_IN = 0x00000001;
582 /** Data connection activity: Currently sending IP PPP traffic. */
583 public static final int DATA_ACTIVITY_OUT = 0x00000002;
584 /** Data connection activity: Currently both sending and receiving
585 * IP PPP traffic. */
586 public static final int DATA_ACTIVITY_INOUT = DATA_ACTIVITY_IN | DATA_ACTIVITY_OUT;
587
588 /**
589 * Returns a constant indicating the type of activity on a data connection
590 * (cellular).
591 *
592 * @see #DATA_ACTIVITY_NONE
593 * @see #DATA_ACTIVITY_IN
594 * @see #DATA_ACTIVITY_OUT
595 * @see #DATA_ACTIVITY_INOUT
596 */
597 public int getDataActivity() {
598 try {
599 return getITelephony().getDataActivity();
600 } catch (RemoteException ex) {
601 // the phone process is restarting.
602 return DATA_ACTIVITY_NONE;
603 }
604 }
605
606 /** Data connection state: Disconnected. IP traffic not available. */
607 public static final int DATA_DISCONNECTED = 0;
608 /** Data connection state: Currently setting up a data connection. */
609 public static final int DATA_CONNECTING = 1;
610 /** Data connection state: Connected. IP traffic should be available. */
611 public static final int DATA_CONNECTED = 2;
612 /** Data connection state: Suspended. The connection is up, but IP
613 * traffic is temporarily unavailable. For example, in a 2G network,
614 * data activity may be suspended when a voice call arrives. */
615 public static final int DATA_SUSPENDED = 3;
616
617 /**
618 * Returns a constant indicating the current data connection state
619 * (cellular).
620 *
621 * @see #DATA_DISCONNECTED
622 * @see #DATA_CONNECTING
623 * @see #DATA_CONNECTED
624 * @see #DATA_SUSPENDED
625 */
626 public int getDataState() {
627 try {
628 return getITelephony().getDataState();
629 } catch (RemoteException ex) {
630 // the phone process is restarting.
631 return DATA_DISCONNECTED;
632 }
633 }
634
635 private ITelephony getITelephony() {
636 return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
637 }
638
639 //
640 //
641 // PhoneStateListener
642 //
643 //
644
645 /**
646 * Registers a listener object to receive notification of changes
647 * in specified telephony states.
648 * <p>
649 * To register a listener, pass a {@link PhoneStateListener}
650 * and specify at least one telephony state of interest in
651 * the events argument.
652 *
653 * At registration, and when a specified telephony state
654 * changes, the telephony manager invokes the appropriate
655 * callback method on the listener object and passes the
656 * current (udpated) values.
657 * <p>
658 * To unregister a listener, pass the listener object and set the
659 * events argument to
660 * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
661 *
662 * @param listener The {@link PhoneStateListener} object to register
663 * (or unregister)
664 * @param events The telephony state(s) of interest to the listener,
665 * as a bitwise-OR combination of {@link PhoneStateListener}
666 * LISTEN_ flags.
667 */
668 public void listen(PhoneStateListener listener, int events) {
669 String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
670 try {
671 Boolean notifyNow = (getITelephony() != null);
672 mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
673 } catch (RemoteException ex) {
674 // system process dead
675 }
676 }
677}
Die mRegistry scheint interresant zu sein:
mac@mac-desktop:~/workspace/android/mydroid$ find . -name 'ITelephonyRegistry.aidl'
./frameworks/base/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aid
l
1/*
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.internal.telephony;
18
19import android.content.Intent;
20import android.os.Bundle;
21import android.telephony.ServiceState;
22import com.android.internal.telephony.IPhoneStateListener;
23
24interface ITelephonyRegistry {
25 void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
26
27 void notifyCallState(int state, String incomingNumber);
28 void notifyServiceState(in ServiceState state);
29 void notifySignalStrength(int signalStrengthASU);
30 void notifyMessageWaitingChanged(boolean mwi);
31 void notifyCallForwardingChanged(boolean cfi);
32 void notifyDataActivity(int state);
33 void notifyDataConnection(int state, boolean isDataConnectivityPossible,
34 String reason, String apn, String interfaceName);
35 void notifyDataConnectionFailed(String reason);
36 void notifyCellLocation(in Bundle cellLocation);
37}
Das AIDL ist nur der Stub, wo ist jetzt die Impl. davon ?
Sollte wohl ebenfalls so heissen, nur mit .java.
Bingo:
mac@mac-desktop:~/workspace/android/mydroid$ find . -name 'TelephonyRegistry.java'
./frameworks/base/services/java/com/android/server/TelephonyRegistry.java
1/*
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;
29import android.telephony.TelephonyManager;
30import android.text.TextUtils;
31import android.util.Log;
32
33import java.util.ArrayList;
34import java.io.FileDescriptor;
35import java.io.PrintWriter;
36
37import com.android.internal.app.IBatteryStats;
38import com.android.internal.telephony.ITelephonyRegistry;
39import com.android.internal.telephony.IPhoneStateListener;
40import com.android.internal.telephony.DefaultPhoneNotifier;
41import com.android.internal.telephony.Phone;
42import com.android.internal.telephony.PhoneStateIntentReceiver;
43import com.android.internal.telephony.TelephonyIntents;
44import com.android.server.am.BatteryStatsService;
45
46
47/**
48 * Since phone process can be restarted, this class provides a centralized
49 * place that applications can register and be called back from.
50 */
51class TelephonyRegistry extends ITelephonyRegistry.Stub {
52 private static final String TAG = "TelephonyRegistry";
53
54 private static class Record {
55 String pkgForDebug;
56 IBinder binder;
57 IPhoneStateListener callback;
58 int events;
59 }
60
61 private final Context mContext;
62 private final ArrayList<Record> mRecords = new ArrayList();
63 private final IBatteryStats mBatteryStats;
64
65 private int mCallState = TelephonyManager.CALL_STATE_IDLE;
66 private String mCallIncomingNumber = "";
67 private ServiceState mServiceState = new ServiceState();
68 private int mSignalStrength = -1;
69 private boolean mMessageWaiting = false;
70 private boolean mCallForwarding = false;
71 private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
72 private int mDataConnectionState = TelephonyManager.DATA_CONNECTED;
73 private boolean mDataConnectionPossible = false;
74 private String mDataConnectionReason = "";
75 private String mDataConnectionApn = "";
76 private String mDataConnectionInterfaceName = "";
77 private Bundle mCellLocation = new Bundle();
78
79 // we keep a copy of all of the sate so we can send it out when folks register for it
80 //
81 // In these calls we call with the lock held. This is safe becasuse remote
82 // calls go through a oneway interface and local calls going through a handler before
83 // they get to app code.
84
85 TelephonyRegistry(Context context) {
86 CellLocation.getEmpty().fillInNotifierBundle(mCellLocation);
87 mContext = context;
88 mBatteryStats = BatteryStatsService.getService();
89 }
90
91 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
92 boolean notifyNow) {
93 //Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events));
94 if (events != 0) {
95 // check permissions
96 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
97 mContext.enforceCallingOrSelfPermission(
98 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
99
100 }
101
102 synchronized (mRecords) {
103 // register
104 Record r = null;
105 find_and_add: {
106 IBinder b = callback.asBinder();
107 final int N = mRecords.size();
108 for (int i=0; i<N; i++) {
109 r = mRecords.get(i);
110 if (b == r.binder) {
111 break find_and_add;
112 }
113 }
114 r = new Record();
115 r.binder = b;
116 r.callback = callback;
117 r.pkgForDebug = pkgForDebug;
118 mRecords.add(r);
119 }
120 int send = events & (events ^ r.events);
121 r.events = events;
122 if (notifyNow) {
123 if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
124 sendServiceState(r, mServiceState);
125 }
126 if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
127 try {
128 r.callback.onSignalStrengthChanged(mSignalStrength);
129 } catch (RemoteException ex) {
130 remove(r.binder);
131 }
132 }
133 if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
134 try {
135 r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
136 } catch (RemoteException ex) {
137 remove(r.binder);
138 }
139 }
140 if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
141 try {
142 r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
143 } catch (RemoteException ex) {
144 remove(r.binder);
145 }
146 }
147 if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
148 sendCellLocation(r, mCellLocation);
149 }
150 if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
151 try {
152 r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
153 } catch (RemoteException ex) {
154 remove(r.binder);
155 }
156 }
157 if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
158 try {
159 r.callback.onDataConnectionStateChanged(mDataConnectionState);
160 } catch (RemoteException ex) {
161 remove(r.binder);
162 }
163 }
164 if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
165 try {
166 r.callback.onDataActivity(mDataActivity);
167 } catch (RemoteException ex) {
168 remove(r.binder);
169 }
170 }
171 }
172 }
173 } else {
174 remove(callback.asBinder());
175 }
176 }
177
178 private void remove(IBinder binder) {
179 synchronized (mRecords) {
180 final int N = mRecords.size();
181 for (int i=0; i<N; i++) {
182 if (mRecords.get(i).binder == binder) {
183 mRecords.remove(i);
184 return;
185 }
186 }
187 }
188 }
189
190 public void notifyCallState(int state, String incomingNumber) {
191 if (!checkPhoneStatePermission("notifyCallState()")) {
192 return;
193 }
194 synchronized (mRecords) {
195 mCallState = state;
196 mCallIncomingNumber = incomingNumber;
197 final int N = mRecords.size();
198 for (int i=N-1; i>=0; i--) {
199 Record r = mRecords.get(i);
200 if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
201 try {
202 r.callback.onCallStateChanged(state, incomingNumber);
203 } catch (RemoteException ex) {
204 remove(r.binder);
205 }
206 }
207 }
208 }
209 broadcastCallStateChanged(state, incomingNumber);
210 }
211
212 public void notifyServiceState(ServiceState state) {
213 if (!checkPhoneStatePermission("notifyServiceState()")) {
214 return;
215 }
216 synchronized (mRecords) {
217 mServiceState = state;
218 final int N = mRecords.size();
219 for (int i=N-1; i>=0; i--) {
220 Record r = mRecords.get(i);
221 if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
222 sendServiceState(r, state);
223 }
224 }
225 }
226 broadcastServiceStateChanged(state);
227 }
228
229 public void notifySignalStrength(int signalStrengthASU) {
230 if (!checkPhoneStatePermission("notifySignalStrength()")) {
231 return;
232 }
233 synchronized (mRecords) {
234 mSignalStrength = signalStrengthASU;
235 final int N = mRecords.size();
236 for (int i=N-1; i>=0; i--) {
237 Record r = mRecords.get(i);
238 if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
239 try {
240 r.callback.onSignalStrengthChanged(signalStrengthASU);
241 } catch (RemoteException ex) {
242 remove(r.binder);
243 }
244 }
245 }
246 }
247 broadcastSignalStrengthChanged(signalStrengthASU);
248 }
249
250 public void notifyMessageWaitingChanged(boolean mwi) {
251 if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
252 return;
253 }
254 synchronized (mRecords) {
255 mMessageWaiting = mwi;
256 final int N = mRecords.size();
257 for (int i=N-1; i>=0; i--) {
258 Record r = mRecords.get(i);
259 if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
260 try {
261 r.callback.onMessageWaitingIndicatorChanged(mwi);
262 } catch (RemoteException ex) {
263 remove(r.binder);
264 }
265 }
266 }
267 }
268 }
269
270 public void notifyCallForwardingChanged(boolean cfi) {
271 if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
272 return;
273 }
274 synchronized (mRecords) {
275 mCallForwarding = cfi;
276 final int N = mRecords.size();
277 for (int i=N-1; i>=0; i--) {
278 Record r = mRecords.get(i);
279 if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
280 try {
281 r.callback.onCallForwardingIndicatorChanged(cfi);
282 } catch (RemoteException ex) {
283 remove(r.binder);
284 }
285 }
286 }
287 }
288 }
289
290 public void notifyDataActivity(int state) {
291 if (!checkPhoneStatePermission("notifyDataActivity()")) {
292 return;
293 }
294 synchronized (mRecords) {
295 mDataActivity = state;
296 final int N = mRecords.size();
297 for (int i=N-1; i>=0; i--) {
298 Record r = mRecords.get(i);
299 if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
300 try {
301 r.callback.onDataActivity(state);
302 } catch (RemoteException ex) {
303 remove(r.binder);
304 }
305 }
306 }
307 }
308 }
309
310 public void notifyDataConnection(int state, boolean isDataConnectivityPissible,
311 String reason, String apn, String interfaceName) {
312 if (!checkPhoneStatePermission("notifyDataConnection()")) {
313 return;
314 }
315 synchronized (mRecords) {
316 mDataConnectionState = state;
317 mDataConnectionPossible = isDataConnectivityPissible;
318 mDataConnectionReason = reason;
319 mDataConnectionApn = apn;
320 mDataConnectionInterfaceName = interfaceName;
321 final int N = mRecords.size();
322 for (int i=N-1; i>=0; i--) {
323 Record r = mRecords.get(i);
324 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
325 try {
326 r.callback.onDataConnectionStateChanged(state);
327 } catch (RemoteException ex) {
328 remove(r.binder);
329 }
330 }
331 }
332 }
333 broadcastDataConnectionStateChanged(state, isDataConnectivityPissible,
334 reason, apn, interfaceName);
335 }
336
337 public void notifyDataConnectionFailed(String reason) {
338 if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
339 return;
340 }
341 /*
342 * This is commented out because there is on onDataConnectionFailed callback
343 * on PhoneStateListener. There should be.
344 synchronized (mRecords) {
345 mDataConnectionFailedReason = reason;
346 final int N = mRecords.size();
347 for (int i=N-1; i>=0; i--) {
348 Record r = mRecords.get(i);
349 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
350 // XXX
351 }
352 }
353 }
354 */
355 broadcastDataConnectionFailed(reason);
356 }
357
358 public void notifyCellLocation(Bundle cellLocation) {
359 if (!checkPhoneStatePermission("notifyCellLocation()")) {
360 return;
361 }
362 synchronized (mRecords) {
363 mCellLocation = cellLocation;
364 final int N = mRecords.size();
365 for (int i=N-1; i>=0; i--) {
366 Record r = mRecords.get(i);
367 if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
368 sendCellLocation(r, cellLocation);
369 }
370 }
371 }
372 }
373
374 //
375 // the new callback broadcasting
376 //
377 // copy the service state object so they can't mess it up in the local calls
378 //
379 public void sendServiceState(Record r, ServiceState state) {
380 try {
381 r.callback.onServiceStateChanged(new ServiceState(state));
382 } catch (RemoteException ex) {
383 remove(r.binder);
384 }
385 }
386
387 public void sendCellLocation(Record r, Bundle cellLocation) {
388 try {
389 r.callback.onCellLocationChanged(new Bundle(cellLocation));
390 } catch (RemoteException ex) {
391 remove(r.binder);
392 }
393 }
394
395
396 @Override
397 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
398 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
399 != PackageManager.PERMISSION_GRANTED) {
400 pw.println("Permission Denial: can't dump telephony.registry from from pid="
401 + Binder.getCallingPid()
402 + ", uid=" + Binder.getCallingUid());
403 return;
404 }
405 synchronized (mRecords) {
406 final int N = mRecords.size();
407 pw.println("last known state:");
408 pw.println(" mCallState=" + mCallState);
409 pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
410 pw.println(" mServiceState=" + mServiceState);
411 pw.println(" mSignalStrength=" + mSignalStrength);
412 pw.println(" mMessageWaiting=" + mMessageWaiting);
413 pw.println(" mCallForwarding=" + mCallForwarding);
414 pw.println(" mDataActivity=" + mDataActivity);
415 pw.println(" mDataConnectionState=" + mDataConnectionState);
416 pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
417 pw.println(" mDataConnectionReason=" + mDataConnectionReason);
418 pw.println(" mDataConnectionApn=" + mDataConnectionApn);
419 pw.println(" mDataConnectionInterfaceName=" + mDataConnectionInterfaceName);
420 pw.println(" mCellLocation=" + mCellLocation);
421 pw.println("registrations: count=" + N);
422 for (int i=0; i<N; i++) {
423 Record r = mRecords.get(i);
424 pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
425 }
426 }
427 }
428
429
430 //
431 // the legacy intent broadcasting
432 //
433
434 private void broadcastServiceStateChanged(ServiceState state) {
435 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
436 Bundle data = new Bundle();
437 state.fillInNotifierBundle(data);
438 intent.putExtras(data);
439 mContext.sendStickyBroadcast(intent);
440 }
441
442 private void broadcastSignalStrengthChanged(int asu) {
443 long ident = Binder.clearCallingIdentity();
444 try {
445 mBatteryStats.notePhoneSignalStrength(asu);
446 } catch (RemoteException e) {
447 } finally {
448 Binder.restoreCallingIdentity(ident);
449 }
450
451 Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
452 intent.putExtra(PhoneStateIntentReceiver.INTENT_KEY_ASU, asu);
453 mContext.sendStickyBroadcast(intent);
454 }
455
456 private void broadcastCallStateChanged(int state, String incomingNumber) {
457 long ident = Binder.clearCallingIdentity();
458 try {
459 if (state == TelephonyManager.CALL_STATE_IDLE) {
460 mBatteryStats.notePhoneOff();
461 } else {
462 mBatteryStats.notePhoneOn();
463 }
464 } catch (RemoteException e) {
465 } finally {
466 Binder.restoreCallingIdentity(ident);
467 }
468
469 Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
470 intent.putExtra(Phone.STATE_KEY,
471 DefaultPhoneNotifier.convertCallState(state).toString());
472 if (!TextUtils.isEmpty(incomingNumber)) {
473 intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
474 }
475 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
476 }
477
478 private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible,
479 String reason, String apn, String interfaceName) {
480 // Note: not reporting to the battery stats service here, because the
481 // status bar takes care of that after taking into account all of the
482 // required info.
483 Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
484 intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
485 if (!isDataConnectivityPossible) {
486 intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
487 }
488 if (reason != null) {
489 intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
490 }
491 intent.putExtra(Phone.DATA_APN_KEY, apn);
492 intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName);
493 mContext.sendStickyBroadcast(intent);
494 }
495
496 private void broadcastDataConnectionFailed(String reason) {
497 Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
498 intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
499 mContext.sendStickyBroadcast(intent);
500 }
501
502 private boolean checkPhoneStatePermission(String method) {
503 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
504 == PackageManager.PERMISSION_GRANTED) {
505 return true;
506 }
507 String msg = "Modify Phone State Permission Denial: " + method + " from pid="
508 + Binder.getCallingPid()
509 + ", uid=" + Binder.getCallingUid();
510 Log.w(TAG, msg);
511 return false;
512 }
513}
Die CallbackHandler liegen wohl in:
1private final ArrayList<Record> mRecords = new ArrayList();
Sieht momentan nicht danach aus als ob hier ein Ansatzpunkt zu finden wäre das auszulesen ...
- Mac
Windmate HD, See you @ IO 14 , Worked on Wundercar, Glass V3, LG G Watch, Moto 360, Android TV