PageRenderTime 103ms CodeModel.GetById 12ms app.highlight 83ms RepoModel.GetById 2ms app.codeStats 0ms

/services/java/com/android/server/TelephonyRegistry.java

https://github.com/aizuzi/platform_frameworks_base
Java | 956 lines | 824 code | 89 blank | 43 comment | 164 complexity | 73f264e8125d482545289b6534106329 MD5 | raw file
  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.app.ActivityManager;
 20import android.content.BroadcastReceiver;
 21import android.content.Context;
 22import android.content.Intent;
 23import android.content.IntentFilter;
 24import android.content.pm.PackageManager;
 25import android.net.LinkCapabilities;
 26import android.net.LinkProperties;
 27import android.os.Binder;
 28import android.os.Bundle;
 29import android.os.Handler;
 30import android.os.IBinder;
 31import android.os.Message;
 32import android.os.RemoteException;
 33import android.os.UserHandle;
 34import android.telephony.CellLocation;
 35import android.telephony.PhoneStateListener;
 36import android.telephony.ServiceState;
 37import android.telephony.SignalStrength;
 38import android.telephony.CellInfo;
 39import android.telephony.TelephonyManager;
 40import android.telephony.DisconnectCause;
 41import android.telephony.PreciseCallState;
 42import android.telephony.PreciseDataConnectionState;
 43import android.telephony.PreciseDisconnectCause;
 44import android.text.TextUtils;
 45import android.util.Slog;
 46
 47import java.util.ArrayList;
 48import java.util.List;
 49import java.io.FileDescriptor;
 50import java.io.PrintWriter;
 51
 52import com.android.internal.app.IBatteryStats;
 53import com.android.internal.telephony.ITelephonyRegistry;
 54import com.android.internal.telephony.IPhoneStateListener;
 55import com.android.internal.telephony.DefaultPhoneNotifier;
 56import com.android.internal.telephony.PhoneConstants;
 57import com.android.internal.telephony.ServiceStateTracker;
 58import com.android.internal.telephony.TelephonyIntents;
 59import com.android.server.am.BatteryStatsService;
 60
 61/**
 62 * Since phone process can be restarted, this class provides a centralized place
 63 * that applications can register and be called back from.
 64 */
 65class TelephonyRegistry extends ITelephonyRegistry.Stub {
 66    private static final String TAG = "TelephonyRegistry";
 67    private static final boolean DBG = false;
 68    private static final boolean DBG_LOC = false;
 69
 70    private static class Record {
 71        String pkgForDebug;
 72
 73        IBinder binder;
 74
 75        IPhoneStateListener callback;
 76
 77        int callerUid;
 78
 79        int events;
 80
 81        @Override
 82        public String toString() {
 83            return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid +
 84                    " events=" + Integer.toHexString(events) + "}";
 85        }
 86    }
 87
 88    private final Context mContext;
 89
 90    // access should be inside synchronized (mRecords) for these two fields
 91    private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>();
 92    private final ArrayList<Record> mRecords = new ArrayList<Record>();
 93
 94    private final IBatteryStats mBatteryStats;
 95
 96    private int mCallState = TelephonyManager.CALL_STATE_IDLE;
 97
 98    private String mCallIncomingNumber = "";
 99
100    private ServiceState mServiceState = new ServiceState();
101
102    private SignalStrength mSignalStrength = new SignalStrength();
103
104    private boolean mMessageWaiting = false;
105
106    private boolean mCallForwarding = false;
107
108    private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
109
110    private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN;
111
112    private boolean mDataConnectionPossible = false;
113
114    private String mDataConnectionReason = "";
115
116    private String mDataConnectionApn = "";
117
118    private ArrayList<String> mConnectedApns;
119
120    private LinkProperties mDataConnectionLinkProperties;
121
122    private LinkCapabilities mDataConnectionLinkCapabilities;
123
124    private Bundle mCellLocation = new Bundle();
125
126    private int mDataConnectionNetworkType;
127
128    private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
129
130    private List<CellInfo> mCellInfo = null;
131
132    private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
133
134    private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
135
136    private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
137
138    private PreciseCallState mPreciseCallState = new PreciseCallState();
139
140    private PreciseDataConnectionState mPreciseDataConnectionState =
141                new PreciseDataConnectionState();
142
143    static final int PHONE_STATE_PERMISSION_MASK =
144                PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
145                PhoneStateListener.LISTEN_CALL_STATE |
146                PhoneStateListener.LISTEN_DATA_ACTIVITY |
147                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
148                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
149
150    static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
151                PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
152                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
153
154    private static final int MSG_USER_SWITCHED = 1;
155
156    private final Handler mHandler = new Handler() {
157        @Override
158        public void handleMessage(Message msg) {
159            switch (msg.what) {
160                case MSG_USER_SWITCHED: {
161                    if (DBG) Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
162                    TelephonyRegistry.this.notifyCellLocation(mCellLocation);
163                    break;
164                }
165            }
166        }
167    };
168
169    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
170        @Override
171        public void onReceive(Context context, Intent intent) {
172            String action = intent.getAction();
173            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
174                mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
175                       intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
176            }
177        }
178    };
179
180    // we keep a copy of all of the state so we can send it out when folks
181    // register for it
182    //
183    // In these calls we call with the lock held. This is safe becasuse remote
184    // calls go through a oneway interface and local calls going through a
185    // handler before they get to app code.
186
187    TelephonyRegistry(Context context) {
188        CellLocation  location = CellLocation.getEmpty();
189
190        // Note that location can be null for non-phone builds like
191        // like the generic one.
192        if (location != null) {
193            location.fillInNotifierBundle(mCellLocation);
194        }
195        mContext = context;
196        mBatteryStats = BatteryStatsService.getService();
197        mConnectedApns = new ArrayList<String>();
198    }
199
200    public void systemRunning() {
201        // Watch for interesting updates
202        final IntentFilter filter = new IntentFilter();
203        filter.addAction(Intent.ACTION_USER_SWITCHED);
204        filter.addAction(Intent.ACTION_USER_REMOVED);
205        mContext.registerReceiver(mBroadcastReceiver, filter);
206    }
207
208    @Override
209    public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
210            boolean notifyNow) {
211        int callerUid = UserHandle.getCallingUserId();
212        int myUid = UserHandle.myUserId();
213        if (DBG) {
214            Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
215                + " myUid=" + myUid
216                + " callerUid=" + callerUid);
217        }
218        if (events != 0) {
219            /* Checks permission and throws Security exception */
220            checkListenerPermission(events);
221
222            synchronized (mRecords) {
223                // register
224                Record r = null;
225                find_and_add: {
226                    IBinder b = callback.asBinder();
227                    final int N = mRecords.size();
228                    for (int i = 0; i < N; i++) {
229                        r = mRecords.get(i);
230                        if (b == r.binder) {
231                            break find_and_add;
232                        }
233                    }
234                    r = new Record();
235                    r.binder = b;
236                    r.callback = callback;
237                    r.pkgForDebug = pkgForDebug;
238                    r.callerUid = callerUid;
239                    mRecords.add(r);
240                    if (DBG) Slog.i(TAG, "listen: add new record=" + r);
241                }
242                int send = events & (events ^ r.events);
243                r.events = events;
244                if (notifyNow) {
245                    if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
246                        try {
247                            r.callback.onServiceStateChanged(new ServiceState(mServiceState));
248                        } catch (RemoteException ex) {
249                            remove(r.binder);
250                        }
251                    }
252                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
253                        try {
254                            int gsmSignalStrength = mSignalStrength.getGsmSignalStrength();
255                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
256                                    : gsmSignalStrength));
257                        } catch (RemoteException ex) {
258                            remove(r.binder);
259                        }
260                    }
261                    if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
262                        try {
263                            r.callback.onMessageWaitingIndicatorChanged(mMessageWaiting);
264                        } catch (RemoteException ex) {
265                            remove(r.binder);
266                        }
267                    }
268                    if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
269                        try {
270                            r.callback.onCallForwardingIndicatorChanged(mCallForwarding);
271                        } catch (RemoteException ex) {
272                            remove(r.binder);
273                        }
274                    }
275                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
276                        try {
277                            if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + mCellLocation);
278                            r.callback.onCellLocationChanged(new Bundle(mCellLocation));
279                        } catch (RemoteException ex) {
280                            remove(r.binder);
281                        }
282                    }
283                    if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
284                        try {
285                            r.callback.onCallStateChanged(mCallState, mCallIncomingNumber);
286                        } catch (RemoteException ex) {
287                            remove(r.binder);
288                        }
289                    }
290                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
291                        try {
292                            r.callback.onDataConnectionStateChanged(mDataConnectionState,
293                                mDataConnectionNetworkType);
294                        } catch (RemoteException ex) {
295                            remove(r.binder);
296                        }
297                    }
298                    if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
299                        try {
300                            r.callback.onDataActivity(mDataActivity);
301                        } catch (RemoteException ex) {
302                            remove(r.binder);
303                        }
304                    }
305                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
306                        try {
307                            r.callback.onSignalStrengthsChanged(mSignalStrength);
308                        } catch (RemoteException ex) {
309                            remove(r.binder);
310                        }
311                    }
312                    if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
313                        try {
314                            r.callback.onOtaspChanged(mOtaspMode);
315                        } catch (RemoteException ex) {
316                            remove(r.binder);
317                        }
318                    }
319                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
320                        try {
321                            if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo=" + mCellInfo);
322                            r.callback.onCellInfoChanged(mCellInfo);
323                        } catch (RemoteException ex) {
324                            remove(r.binder);
325                        }
326                    }
327                    if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
328                        try {
329                            r.callback.onPreciseCallStateChanged(mPreciseCallState);
330                        } catch (RemoteException ex) {
331                            remove(r.binder);
332                        }
333                    }
334                    if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
335                        try {
336                            r.callback.onPreciseDataConnectionStateChanged(
337                                    mPreciseDataConnectionState);
338                        } catch (RemoteException ex) {
339                            remove(r.binder);
340                        }
341                    }
342                }
343            }
344        } else {
345            remove(callback.asBinder());
346        }
347    }
348
349    private void remove(IBinder binder) {
350        synchronized (mRecords) {
351            final int recordCount = mRecords.size();
352            for (int i = 0; i < recordCount; i++) {
353                if (mRecords.get(i).binder == binder) {
354                    mRecords.remove(i);
355                    return;
356                }
357            }
358        }
359    }
360
361    public void notifyCallState(int state, String incomingNumber) {
362        if (!checkNotifyPermission("notifyCallState()")) {
363            return;
364        }
365        synchronized (mRecords) {
366            mCallState = state;
367            mCallIncomingNumber = incomingNumber;
368            for (Record r : mRecords) {
369                if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
370                    try {
371                        r.callback.onCallStateChanged(state, incomingNumber);
372                    } catch (RemoteException ex) {
373                        mRemoveList.add(r.binder);
374                    }
375                }
376            }
377            handleRemoveListLocked();
378        }
379        broadcastCallStateChanged(state, incomingNumber);
380    }
381
382    public void notifyServiceState(ServiceState state) {
383        if (!checkNotifyPermission("notifyServiceState()")){
384            return;
385        }
386        synchronized (mRecords) {
387            mServiceState = state;
388            for (Record r : mRecords) {
389                if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
390                    try {
391                        r.callback.onServiceStateChanged(new ServiceState(state));
392                    } catch (RemoteException ex) {
393                        mRemoveList.add(r.binder);
394                    }
395                }
396            }
397            handleRemoveListLocked();
398        }
399        broadcastServiceStateChanged(state);
400    }
401
402    public void notifySignalStrength(SignalStrength signalStrength) {
403        if (!checkNotifyPermission("notifySignalStrength()")) {
404            return;
405        }
406        synchronized (mRecords) {
407            mSignalStrength = signalStrength;
408            for (Record r : mRecords) {
409                if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
410                    try {
411                        r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
412                    } catch (RemoteException ex) {
413                        mRemoveList.add(r.binder);
414                    }
415                }
416                if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
417                    try {
418                        int gsmSignalStrength = signalStrength.getGsmSignalStrength();
419                        r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
420                                : gsmSignalStrength));
421                    } catch (RemoteException ex) {
422                        mRemoveList.add(r.binder);
423                    }
424                }
425            }
426            handleRemoveListLocked();
427        }
428        broadcastSignalStrengthChanged(signalStrength);
429    }
430
431    public void notifyCellInfo(List<CellInfo> cellInfo) {
432        if (!checkNotifyPermission("notifyCellInfo()")) {
433            return;
434        }
435
436        synchronized (mRecords) {
437            mCellInfo = cellInfo;
438            for (Record r : mRecords) {
439                if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
440                    try {
441                        if (DBG_LOC) {
442                            Slog.d(TAG, "notifyCellInfo: mCellInfo=" + mCellInfo + " r=" + r);
443                        }
444                        r.callback.onCellInfoChanged(cellInfo);
445                    } catch (RemoteException ex) {
446                        mRemoveList.add(r.binder);
447                    }
448                }
449            }
450            handleRemoveListLocked();
451        }
452    }
453
454    public void notifyMessageWaitingChanged(boolean mwi) {
455        if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
456            return;
457        }
458        synchronized (mRecords) {
459            mMessageWaiting = mwi;
460            for (Record r : mRecords) {
461                if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
462                    try {
463                        r.callback.onMessageWaitingIndicatorChanged(mwi);
464                    } catch (RemoteException ex) {
465                        mRemoveList.add(r.binder);
466                    }
467                }
468            }
469            handleRemoveListLocked();
470        }
471    }
472
473    public void notifyCallForwardingChanged(boolean cfi) {
474        if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
475            return;
476        }
477        synchronized (mRecords) {
478            mCallForwarding = cfi;
479            for (Record r : mRecords) {
480                if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
481                    try {
482                        r.callback.onCallForwardingIndicatorChanged(cfi);
483                    } catch (RemoteException ex) {
484                        mRemoveList.add(r.binder);
485                    }
486                }
487            }
488            handleRemoveListLocked();
489        }
490    }
491
492    public void notifyDataActivity(int state) {
493        if (!checkNotifyPermission("notifyDataActivity()" )) {
494            return;
495        }
496        synchronized (mRecords) {
497            mDataActivity = state;
498            for (Record r : mRecords) {
499                if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
500                    try {
501                        r.callback.onDataActivity(state);
502                    } catch (RemoteException ex) {
503                        mRemoveList.add(r.binder);
504                    }
505                }
506            }
507            handleRemoveListLocked();
508        }
509    }
510
511    public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
512            String reason, String apn, String apnType, LinkProperties linkProperties,
513            LinkCapabilities linkCapabilities, int networkType, boolean roaming) {
514        if (!checkNotifyPermission("notifyDataConnection()" )) {
515            return;
516        }
517        if (DBG) {
518            Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
519                + isDataConnectivityPossible + " reason='" + reason
520                + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
521                + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords);
522        }
523        synchronized (mRecords) {
524            boolean modified = false;
525            if (state == TelephonyManager.DATA_CONNECTED) {
526                if (!mConnectedApns.contains(apnType)) {
527                    mConnectedApns.add(apnType);
528                    if (mDataConnectionState != state) {
529                        mDataConnectionState = state;
530                        modified = true;
531                    }
532                }
533            } else {
534                if (mConnectedApns.remove(apnType)) {
535                    if (mConnectedApns.isEmpty()) {
536                        mDataConnectionState = state;
537                        modified = true;
538                    } else {
539                        // leave mDataConnectionState as is and
540                        // send out the new status for the APN in question.
541                    }
542                }
543            }
544            mDataConnectionPossible = isDataConnectivityPossible;
545            mDataConnectionReason = reason;
546            mDataConnectionLinkProperties = linkProperties;
547            mDataConnectionLinkCapabilities = linkCapabilities;
548            if (mDataConnectionNetworkType != networkType) {
549                mDataConnectionNetworkType = networkType;
550                // need to tell registered listeners about the new network type
551                modified = true;
552            }
553            if (modified) {
554                if (DBG) {
555                    Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState
556                        + ", " + mDataConnectionNetworkType + ")");
557                }
558                for (Record r : mRecords) {
559                    if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
560                        try {
561                            r.callback.onDataConnectionStateChanged(mDataConnectionState,
562                                    mDataConnectionNetworkType);
563                        } catch (RemoteException ex) {
564                            mRemoveList.add(r.binder);
565                        }
566                    }
567                }
568                handleRemoveListLocked();
569            }
570            mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
571                    apnType, apn, reason, linkProperties, "");
572            for (Record r : mRecords) {
573                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
574                    try {
575                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
576                    } catch (RemoteException ex) {
577                        mRemoveList.add(r.binder);
578                    }
579                }
580            }
581            handleRemoveListLocked();
582        }
583        broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
584                apnType, linkProperties, linkCapabilities, roaming);
585        broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
586                linkProperties, "");
587    }
588
589    public void notifyDataConnectionFailed(String reason, String apnType) {
590        if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
591            return;
592        }
593        synchronized (mRecords) {
594            mPreciseDataConnectionState = new PreciseDataConnectionState(
595                    TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
596                    apnType, "", reason, null, "");
597            for (Record r : mRecords) {
598                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
599                    try {
600                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
601                    } catch (RemoteException ex) {
602                        mRemoveList.add(r.binder);
603                    }
604                }
605            }
606            handleRemoveListLocked();
607        }
608        broadcastDataConnectionFailed(reason, apnType);
609        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
610                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
611    }
612
613    public void notifyCellLocation(Bundle cellLocation) {
614        if (!checkNotifyPermission("notifyCellLocation()")) {
615            return;
616        }
617        synchronized (mRecords) {
618            mCellLocation = cellLocation;
619            for (Record r : mRecords) {
620                if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
621                    try {
622                        if (DBG_LOC) {
623                            Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation
624                                    + " r=" + r);
625                        }
626                        r.callback.onCellLocationChanged(new Bundle(cellLocation));
627                    } catch (RemoteException ex) {
628                        mRemoveList.add(r.binder);
629                    }
630
631                }
632            }
633            handleRemoveListLocked();
634        }
635    }
636
637    public void notifyOtaspChanged(int otaspMode) {
638        if (!checkNotifyPermission("notifyOtaspChanged()" )) {
639            return;
640        }
641        synchronized (mRecords) {
642            mOtaspMode = otaspMode;
643            for (Record r : mRecords) {
644                if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) {
645                    try {
646                        r.callback.onOtaspChanged(otaspMode);
647                    } catch (RemoteException ex) {
648                        mRemoveList.add(r.binder);
649                    }
650                }
651            }
652            handleRemoveListLocked();
653        }
654    }
655
656    public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
657            int backgroundCallState) {
658        if (!checkNotifyPermission("notifyPreciseCallState()")) {
659            return;
660        }
661        synchronized (mRecords) {
662            mRingingCallState = ringingCallState;
663            mForegroundCallState = foregroundCallState;
664            mBackgroundCallState = backgroundCallState;
665            mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
666                    backgroundCallState,
667                    DisconnectCause.NOT_VALID,
668                    PreciseDisconnectCause.NOT_VALID);
669            for (Record r : mRecords) {
670                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
671                    try {
672                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
673                    } catch (RemoteException ex) {
674                        mRemoveList.add(r.binder);
675                    }
676                }
677            }
678            handleRemoveListLocked();
679        }
680        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
681                DisconnectCause.NOT_VALID,
682                PreciseDisconnectCause.NOT_VALID);
683    }
684
685    public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
686        if (!checkNotifyPermission("notifyDisconnectCause()")) {
687            return;
688        }
689        synchronized (mRecords) {
690            mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
691                    mBackgroundCallState, disconnectCause, preciseDisconnectCause);
692            for (Record r : mRecords) {
693                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
694                    try {
695                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
696                    } catch (RemoteException ex) {
697                        mRemoveList.add(r.binder);
698                    }
699                }
700            }
701            handleRemoveListLocked();
702        }
703        broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
704                mBackgroundCallState, disconnectCause, preciseDisconnectCause);
705    }
706
707    public void notifyPreciseDataConnectionFailed(String reason, String apnType,
708            String apn, String failCause) {
709        if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
710            return;
711        }
712        synchronized (mRecords) {
713            mPreciseDataConnectionState = new PreciseDataConnectionState(
714                    TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
715                    apnType, apn, reason, null, failCause);
716            for (Record r : mRecords) {
717                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
718                    try {
719                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
720                    } catch (RemoteException ex) {
721                        mRemoveList.add(r.binder);
722                    }
723                }
724            }
725            handleRemoveListLocked();
726        }
727        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
728                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
729    }
730
731    @Override
732    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
733        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
734                != PackageManager.PERMISSION_GRANTED) {
735            pw.println("Permission Denial: can't dump telephony.registry from from pid="
736                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
737            return;
738        }
739        synchronized (mRecords) {
740            final int recordCount = mRecords.size();
741            pw.println("last known state:");
742            pw.println("  mCallState=" + mCallState);
743            pw.println("  mCallIncomingNumber=" + mCallIncomingNumber);
744            pw.println("  mServiceState=" + mServiceState);
745            pw.println("  mSignalStrength=" + mSignalStrength);
746            pw.println("  mMessageWaiting=" + mMessageWaiting);
747            pw.println("  mCallForwarding=" + mCallForwarding);
748            pw.println("  mDataActivity=" + mDataActivity);
749            pw.println("  mDataConnectionState=" + mDataConnectionState);
750            pw.println("  mDataConnectionPossible=" + mDataConnectionPossible);
751            pw.println("  mDataConnectionReason=" + mDataConnectionReason);
752            pw.println("  mDataConnectionApn=" + mDataConnectionApn);
753            pw.println("  mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
754            pw.println("  mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
755            pw.println("  mCellLocation=" + mCellLocation);
756            pw.println("  mCellInfo=" + mCellInfo);
757            pw.println("registrations: count=" + recordCount);
758            for (Record r : mRecords) {
759                pw.println("  " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
760            }
761        }
762    }
763
764    //
765    // the legacy intent broadcasting
766    //
767
768    private void broadcastServiceStateChanged(ServiceState state) {
769        long ident = Binder.clearCallingIdentity();
770        try {
771            mBatteryStats.notePhoneState(state.getState());
772        } catch (RemoteException re) {
773            // Can't do much
774        } finally {
775            Binder.restoreCallingIdentity(ident);
776        }
777
778        Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
779        Bundle data = new Bundle();
780        state.fillInNotifierBundle(data);
781        intent.putExtras(data);
782        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
783    }
784
785    private void broadcastSignalStrengthChanged(SignalStrength signalStrength) {
786        long ident = Binder.clearCallingIdentity();
787        try {
788            mBatteryStats.notePhoneSignalStrength(signalStrength);
789        } catch (RemoteException e) {
790            /* The remote entity disappeared, we can safely ignore the exception. */
791        } finally {
792            Binder.restoreCallingIdentity(ident);
793        }
794
795        Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
796        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
797        Bundle data = new Bundle();
798        signalStrength.fillInNotifierBundle(data);
799        intent.putExtras(data);
800        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
801    }
802
803    private void broadcastCallStateChanged(int state, String incomingNumber) {
804        long ident = Binder.clearCallingIdentity();
805        try {
806            if (state == TelephonyManager.CALL_STATE_IDLE) {
807                mBatteryStats.notePhoneOff();
808            } else {
809                mBatteryStats.notePhoneOn();
810            }
811        } catch (RemoteException e) {
812            /* The remote entity disappeared, we can safely ignore the exception. */
813        } finally {
814            Binder.restoreCallingIdentity(ident);
815        }
816
817        Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
818        intent.putExtra(PhoneConstants.STATE_KEY,
819                DefaultPhoneNotifier.convertCallState(state).toString());
820        if (!TextUtils.isEmpty(incomingNumber)) {
821            intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
822        }
823        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
824                android.Manifest.permission.READ_PHONE_STATE);
825    }
826
827    private void broadcastDataConnectionStateChanged(int state,
828            boolean isDataConnectivityPossible,
829            String reason, String apn, String apnType, LinkProperties linkProperties,
830            LinkCapabilities linkCapabilities, boolean roaming) {
831        // Note: not reporting to the battery stats service here, because the
832        // status bar takes care of that after taking into account all of the
833        // required info.
834        Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
835        intent.putExtra(PhoneConstants.STATE_KEY,
836                DefaultPhoneNotifier.convertDataState(state).toString());
837        if (!isDataConnectivityPossible) {
838            intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true);
839        }
840        if (reason != null) {
841            intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
842        }
843        if (linkProperties != null) {
844            intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
845            String iface = linkProperties.getInterfaceName();
846            if (iface != null) {
847                intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface);
848            }
849        }
850        if (linkCapabilities != null) {
851            intent.putExtra(PhoneConstants.DATA_LINK_CAPABILITIES_KEY, linkCapabilities);
852        }
853        if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true);
854
855        intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
856        intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
857        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
858    }
859
860    private void broadcastDataConnectionFailed(String reason, String apnType) {
861        Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
862        intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason);
863        intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
864        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
865    }
866
867    private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
868            int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
869        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
870        intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
871        intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
872        intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
873        intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
874        intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
875        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
876                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
877    }
878
879    private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
880            String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) {
881        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
882        intent.putExtra(PhoneConstants.STATE_KEY, state);
883        intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
884        if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
885        if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
886        if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
887        if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
888        if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
889
890        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
891                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
892    }
893
894    private boolean checkNotifyPermission(String method) {
895        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
896                == PackageManager.PERMISSION_GRANTED) {
897            return true;
898        }
899        String msg = "Modify Phone State Permission Denial: " + method + " from pid="
900                + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid();
901        if (DBG) Slog.w(TAG, msg);
902        return false;
903    }
904
905    private void checkListenerPermission(int events) {
906        if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
907            mContext.enforceCallingOrSelfPermission(
908                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
909
910        }
911
912        if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
913            mContext.enforceCallingOrSelfPermission(
914                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
915
916        }
917
918        if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
919            mContext.enforceCallingOrSelfPermission(
920                    android.Manifest.permission.READ_PHONE_STATE, null);
921        }
922
923        if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
924            mContext.enforceCallingOrSelfPermission(
925                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
926
927        }
928    }
929
930    private void handleRemoveListLocked() {
931        if (mRemoveList.size() > 0) {
932            for (IBinder b: mRemoveList) {
933                remove(b);
934            }
935            mRemoveList.clear();
936        }
937    }
938
939    private boolean validateEventsAndUserLocked(Record r, int events) {
940        int foregroundUser;
941        long callingIdentity = Binder.clearCallingIdentity();
942        boolean valid = false;
943        try {
944            foregroundUser = ActivityManager.getCurrentUser();
945            valid = r.callerUid ==  foregroundUser && (r.events & events) != 0;
946            if (DBG | DBG_LOC) {
947                Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid
948                        + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
949                        + " r.events=" + r.events + " events=" + events);
950            }
951        } finally {
952            Binder.restoreCallingIdentity(callingIdentity);
953        }
954        return valid;
955    }
956}