FileDocCategorySizeDatePackage
TelephonyRegistry.javaAPI DocAndroid 1.5 API20093Wed May 06 22:42:00 BST 2009com.android.server

TelephonyRegistry

public class TelephonyRegistry extends ITelephonyRegistry.Stub
Since phone process can be restarted, this class provides a centralized place that applications can register and be called back from.

Fields Summary
private static final String
TAG
private final android.content.Context
mContext
private final ArrayList
mRecords
private final com.android.internal.app.IBatteryStats
mBatteryStats
private int
mCallState
private String
mCallIncomingNumber
private android.telephony.ServiceState
mServiceState
private int
mSignalStrength
private boolean
mMessageWaiting
private boolean
mCallForwarding
private int
mDataActivity
private int
mDataConnectionState
private boolean
mDataConnectionPossible
private String
mDataConnectionReason
private String
mDataConnectionApn
private String
mDataConnectionInterfaceName
private android.os.Bundle
mCellLocation
Constructors Summary
TelephonyRegistry(android.content.Context context)


    // we keep a copy of all of the sate so we can send it out when folks register for it
    //
    // In these calls we call with the lock held.  This is safe becasuse remote
    // calls go through a oneway interface and local calls going through a handler before
    // they get to app code.

      
        CellLocation.getEmpty().fillInNotifierBundle(mCellLocation);
        mContext = context;
        mBatteryStats = BatteryStatsService.getService();
    
Methods Summary
private voidbroadcastCallStateChanged(int state, java.lang.String incomingNumber)

        long ident = Binder.clearCallingIdentity();
        try {
            if (state == TelephonyManager.CALL_STATE_IDLE) {
                mBatteryStats.notePhoneOff();
            } else {
                mBatteryStats.notePhoneOn();
            }
        } catch (RemoteException e) {
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        
        Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        intent.putExtra(Phone.STATE_KEY,
                DefaultPhoneNotifier.convertCallState(state).toString());
        if (!TextUtils.isEmpty(incomingNumber)) {
            intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
        }
        mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
    
private voidbroadcastDataConnectionFailed(java.lang.String reason)

        Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
        intent.putExtra(Phone.FAILURE_REASON_KEY, reason);
        mContext.sendStickyBroadcast(intent);
    
private voidbroadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible, java.lang.String reason, java.lang.String apn, java.lang.String interfaceName)

        // Note: not reporting to the battery stats service here, because the
        // status bar takes care of that after taking into account all of the
        // required info.
        Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
        intent.putExtra(Phone.STATE_KEY, DefaultPhoneNotifier.convertDataState(state).toString());
        if (!isDataConnectivityPossible) {
            intent.putExtra(Phone.NETWORK_UNAVAILABLE_KEY, true);
        }
        if (reason != null) {
            intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
        }
        intent.putExtra(Phone.DATA_APN_KEY, apn);
        intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName);
        mContext.sendStickyBroadcast(intent);
    
private voidbroadcastServiceStateChanged(android.telephony.ServiceState state)

        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
        Bundle data = new Bundle();
        state.fillInNotifierBundle(data);
        intent.putExtras(data);
        mContext.sendStickyBroadcast(intent);
    
private voidbroadcastSignalStrengthChanged(int asu)

        long ident = Binder.clearCallingIdentity();
        try {
            mBatteryStats.notePhoneSignalStrength(asu);
        } catch (RemoteException e) {
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        
        Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
        intent.putExtra(PhoneStateIntentReceiver.INTENT_KEY_ASU, asu);
        mContext.sendStickyBroadcast(intent);
    
private booleancheckPhoneStatePermission(java.lang.String method)

        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        String msg = "Modify Phone State Permission Denial: " + method + " from pid="
                + Binder.getCallingPid()
                + ", uid=" + Binder.getCallingUid();
        Log.w(TAG, msg);
        return false;
    
public voiddump(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)

        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            pw.println("Permission Denial: can't dump telephony.registry from from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid());
            return;
        }
        synchronized (mRecords) {
            final int N = mRecords.size();
            pw.println("last known state:");
            pw.println("  mCallState=" + mCallState);
            pw.println("  mCallIncomingNumber=" + mCallIncomingNumber);
            pw.println("  mServiceState=" + mServiceState);
            pw.println("  mSignalStrength=" + mSignalStrength);
            pw.println("  mMessageWaiting=" + mMessageWaiting);
            pw.println("  mCallForwarding=" + mCallForwarding);
            pw.println("  mDataActivity=" + mDataActivity);
            pw.println("  mDataConnectionState=" + mDataConnectionState);
            pw.println("  mDataConnectionPossible=" + mDataConnectionPossible);
            pw.println("  mDataConnectionReason=" + mDataConnectionReason);
            pw.println("  mDataConnectionApn=" + mDataConnectionApn);
            pw.println("  mDataConnectionInterfaceName=" + mDataConnectionInterfaceName);
            pw.println("  mCellLocation=" + mCellLocation);
            pw.println("registrations: count=" + N);
            for (int i=0; i<N; i++) {
                Record r = mRecords.get(i);
                pw.println("  " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
            }
        }
    
public voidlisten(java.lang.String pkgForDebug, com.android.internal.telephony.IPhoneStateListener callback, int events, boolean notifyNow)

        //Log.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events));
        if (events != 0) {
            // check permissions
            if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
                mContext.enforceCallingOrSelfPermission(
                        android.Manifest.permission.ACCESS_COARSE_LOCATION, null);

            }

            synchronized (mRecords) {
                // register
                Record r = null;
                find_and_add: {
                    IBinder b = callback.asBinder();
                    final int N = mRecords.size();
                    for (int i=0; i<N; i++) {
                        r = mRecords.get(i);
                        if (b == r.binder) {
                            break find_and_add;
                        }
                    }
                    r = new Record();
                    r.binder = b;
                    r.callback = callback;
                    r.pkgForDebug = pkgForDebug;
                    mRecords.add(r);
                }
                int send = events & (events ^ r.events);
                r.events = events;
                if (notifyNow) {
                    if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
                        sendServiceState(r, mServiceState);
                    }
                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
                        try {
                            r.callback.onSignalStrengthChanged(mSignalStrength);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
                        try {
                            r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
                        try {
                            r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
                        sendCellLocation(r, mCellLocation);
                    }
                    if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
                        try {
                            r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
                        try {
                            r.callback.onDataConnectionStateChanged(mDataConnectionState);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
                        try {
                            r.callback.onDataActivity(mDataActivity);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                }
            }
        } else {
            remove(callback.asBinder());
        }
    
public voidnotifyCallForwardingChanged(boolean cfi)

        if (!checkPhoneStatePermission("notifyCallForwardingChanged()")) {
            return;
        }   
        synchronized (mRecords) {
            mCallForwarding = cfi;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
                    try {
                        r.callback.onCallForwardingIndicatorChanged(cfi);
                    } catch (RemoteException ex) {
                        remove(r.binder);
                    }
                }
            }
        }
    
public voidnotifyCallState(int state, java.lang.String incomingNumber)

        if (!checkPhoneStatePermission("notifyCallState()")) {
            return;
        }
        synchronized (mRecords) {
            mCallState = state;
            mCallIncomingNumber = incomingNumber;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
                    try {
                        r.callback.onCallStateChanged(state, incomingNumber);
                    } catch (RemoteException ex) {
                        remove(r.binder);
                    }
                }
            }
        }
        broadcastCallStateChanged(state, incomingNumber);
    
public voidnotifyCellLocation(android.os.Bundle cellLocation)

        if (!checkPhoneStatePermission("notifyCellLocation()")) {
            return;
        } 
        synchronized (mRecords) {
            mCellLocation = cellLocation;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
                    sendCellLocation(r, cellLocation);
                }
            }
        }
    
public voidnotifyDataActivity(int state)

        if (!checkPhoneStatePermission("notifyDataActivity()")) {
            return;
        }   
        synchronized (mRecords) {
            mDataActivity = state;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
                    try {
                        r.callback.onDataActivity(state);
                    } catch (RemoteException ex) {
                        remove(r.binder);
                    }
                }
            }
        }
    
public voidnotifyDataConnection(int state, boolean isDataConnectivityPissible, java.lang.String reason, java.lang.String apn, java.lang.String interfaceName)

        if (!checkPhoneStatePermission("notifyDataConnection()")) {
            return;
        }   
        synchronized (mRecords) {
            mDataConnectionState = state;
            mDataConnectionPossible = isDataConnectivityPissible;
            mDataConnectionReason = reason;
            mDataConnectionApn = apn;
            mDataConnectionInterfaceName = interfaceName;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
                    try {
                        r.callback.onDataConnectionStateChanged(state);
                    } catch (RemoteException ex) {
                        remove(r.binder);
                    }
                }
            }
        }
        broadcastDataConnectionStateChanged(state, isDataConnectivityPissible,
                reason, apn, interfaceName);
    
public voidnotifyDataConnectionFailed(java.lang.String reason)

        if (!checkPhoneStatePermission("notifyDataConnectionFailed()")) {
            return;
        }   
        /*
         * This is commented out because there is on onDataConnectionFailed callback
         * on PhoneStateListener.  There should be.
        synchronized (mRecords) {
            mDataConnectionFailedReason = reason;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
                    // XXX
                }
            }
        }
        */
        broadcastDataConnectionFailed(reason);
    
public voidnotifyMessageWaitingChanged(boolean mwi)

        if (!checkPhoneStatePermission("notifyMessageWaitingChanged()")) {
            return;
        }      
        synchronized (mRecords) {
            mMessageWaiting = mwi;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
                    try {
                        r.callback.onMessageWaitingIndicatorChanged(mwi);
                    } catch (RemoteException ex) {
                        remove(r.binder);
                    }
                }
            }
        }
    
public voidnotifyServiceState(android.telephony.ServiceState state)

        if (!checkPhoneStatePermission("notifyServiceState()")) {
            return;
        }      
        synchronized (mRecords) {
            mServiceState = state;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
                    sendServiceState(r, state);
                }
            }
        }
        broadcastServiceStateChanged(state);
    
public voidnotifySignalStrength(int signalStrengthASU)

        if (!checkPhoneStatePermission("notifySignalStrength()")) {
            return;
        }      
        synchronized (mRecords) {
            mSignalStrength = signalStrengthASU;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
                    try {
                        r.callback.onSignalStrengthChanged(signalStrengthASU);
                    } catch (RemoteException ex) {
                        remove(r.binder);
                    }
                }
            }
        }
        broadcastSignalStrengthChanged(signalStrengthASU);
    
private voidremove(android.os.IBinder binder)

        synchronized (mRecords) {
            final int N = mRecords.size();
            for (int i=0; i<N; i++) {
                if (mRecords.get(i).binder == binder) {
                    mRecords.remove(i);
                    return;
                }
            }
        }
    
public voidsendCellLocation(com.android.server.TelephonyRegistry$Record r, android.os.Bundle cellLocation)

        try {
            r.callback.onCellLocationChanged(new Bundle(cellLocation));
        } catch (RemoteException ex) {
            remove(r.binder);
        }
    
public voidsendServiceState(com.android.server.TelephonyRegistry$Record r, android.telephony.ServiceState state)

        try {
            r.callback.onServiceStateChanged(new ServiceState(state));
        } catch (RemoteException ex) {
            remove(r.binder);
        }