DefaultPhoneNotifier.java revision d1a60dfe521f376e3500946d5371f126dbd36767
1/*
2 * Copyright (C) 2006 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.net.LinkProperties;
20import android.net.NetworkCapabilities;
21import android.os.Bundle;
22import android.os.RemoteException;
23import android.os.ServiceManager;
24import android.telephony.CellInfo;
25import android.telephony.DataConnectionRealTimeInfo;
26import android.telephony.Rlog;
27import android.telephony.VoLteServiceState;
28import android.telephony.ServiceState;
29import android.telephony.SubscriptionManager;
30import android.telephony.TelephonyManager;
31import android.telephony.PreciseCallState;
32import android.telephony.DisconnectCause;
33
34import com.android.internal.telephony.Call;
35import com.android.internal.telephony.CallManager;
36import com.android.internal.telephony.Phone;
37import com.android.internal.telephony.ITelephonyRegistry;
38import com.android.internal.telephony.PhoneConstants;
39
40import java.util.List;
41
42/**
43 * broadcast intents
44 */
45public class DefaultPhoneNotifier implements PhoneNotifier {
46    private static final String LOG_TAG = "DefaultPhoneNotifier";
47    private static final boolean DBG = false; // STOPSHIP if true
48
49    protected ITelephonyRegistry mRegistry;
50
51    /*package*/
52    protected DefaultPhoneNotifier() {
53        mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
54                    "telephony.registry"));
55    }
56
57    @Override
58    public void notifyPhoneState(Phone sender) {
59        Call ringingCall = sender.getRingingCall();
60        long subId = sender.getSubId();
61        String incomingNumber = "";
62        if (ringingCall != null && ringingCall.getEarliestConnection() != null){
63            incomingNumber = ringingCall.getEarliestConnection().getAddress();
64        }
65        try {
66            if (mRegistry != null) {
67                  mRegistry.notifyCallStateForSubscriber(subId,
68                        convertCallState(sender.getState()), incomingNumber);
69            }
70        } catch (RemoteException ex) {
71            // system process is dead
72        }
73        notifyCallStateToTelephonyRegistry(sender);
74    }
75
76    /*
77     *  Suppose, some third party app e.g. FM app registers for a call state changed indication
78     *  through TelephonyManager/PhoneStateListener and an incoming call is received on sub1 or
79     *  sub2. Then ir-respective of sub1/sub2 FM app should be informed of call state
80     *  changed(onCallStateChanged()) indication so that FM app can be paused.
81     *  Hence send consolidated call state information to apps. (i.e. sub1 or sub2 active
82     *  call state,  in priority order RINGING > OFFHOOK > IDLE)
83     */
84    public void notifyCallStateToTelephonyRegistry(Phone sender) {
85        Call ringingCall = null;
86        CallManager cm = CallManager.getInstance();
87        PhoneConstants.State state = sender.getState();
88        String incomingNumber = "";
89        for (Phone phone : cm.getAllPhones()) {
90            if (phone.getState() == PhoneConstants.State.RINGING) {
91                ringingCall = phone.getRingingCall();
92                if (ringingCall != null && ringingCall.getEarliestConnection() != null) {
93                    incomingNumber = ringingCall.getEarliestConnection().getAddress();
94                }
95                sender = phone;
96                state = PhoneConstants.State.RINGING;
97                break;
98            } else if (phone.getState() == PhoneConstants.State.OFFHOOK) {
99                if (state == PhoneConstants.State.IDLE) {
100                    state = PhoneConstants.State.OFFHOOK;
101                    sender = phone;
102                }
103            }
104        }
105        if (DBG) log("notifyCallStateToTelephonyRegistry, subId = " + sender.getSubId()
106                + " state = " + state);
107        try {
108            if (mRegistry != null) {
109                mRegistry.notifyCallState(convertCallState(state), incomingNumber);
110            }
111        } catch (RemoteException ex) {
112            // system process is dead
113        }
114    }
115
116    @Override
117    public void notifyServiceState(Phone sender) {
118        ServiceState ss = sender.getServiceState();
119        int phoneId = sender.getPhoneId();
120        long subId = sender.getSubId();
121
122        Rlog.d(LOG_TAG, "nofityServiceState: mRegistry=" + mRegistry + " ss=" + ss
123                + " sender=" + sender + " phondId=" + phoneId + " subId=" + subId);
124        if (ss == null) {
125            ss = new ServiceState();
126            ss.setStateOutOfService();
127        }
128        try {
129            if (mRegistry != null) {
130                mRegistry.notifyServiceStateForPhoneId(phoneId, subId, ss);
131            }
132        } catch (RemoteException ex) {
133            // system process is dead
134        }
135    }
136
137    @Override
138    public void notifySignalStrength(Phone sender) {
139        long subId = sender.getSubId();
140        Rlog.d(LOG_TAG, "notifySignalStrength: mRegistry=" + mRegistry
141                + " ss=" + sender.getSignalStrength() + " sender=" + sender);
142        try {
143            if (mRegistry != null) {
144                mRegistry.notifySignalStrengthForSubscriber(subId, sender.getSignalStrength());
145            }
146        } catch (RemoteException ex) {
147            // system process is dead
148        }
149    }
150
151    @Override
152    public void notifyMessageWaitingChanged(Phone sender) {
153        int phoneId = sender.getPhoneId();
154        long subId = sender.getSubId();
155
156        try {
157            if (mRegistry != null) {
158                mRegistry.notifyMessageWaitingChangedForPhoneId(phoneId, subId,
159                        sender.getMessageWaitingIndicator());
160            }
161        } catch (RemoteException ex) {
162            // system process is dead
163        }
164    }
165
166    @Override
167    public void notifyCallForwardingChanged(Phone sender) {
168        long subId = sender.getSubId();
169        try {
170            if (mRegistry != null) {
171                mRegistry.notifyCallForwardingChangedForSubscriber(subId,
172                        sender.getCallForwardingIndicator());
173            }
174        } catch (RemoteException ex) {
175            // system process is dead
176        }
177    }
178
179    @Override
180    public void notifyDataActivity(Phone sender) {
181        long subId = sender.getSubId();
182        try {
183            if (mRegistry != null) {
184                mRegistry.notifyDataActivityForSubscriber(subId,
185                        convertDataActivityState(sender.getDataActivityState()));
186            }
187        } catch (RemoteException ex) {
188            // system process is dead
189        }
190    }
191
192    @Override
193    public void notifyDataConnection(Phone sender, String reason, String apnType,
194            PhoneConstants.DataState state) {
195        doNotifyDataConnection(sender, reason, apnType, state);
196    }
197
198    private void doNotifyDataConnection(Phone sender, String reason, String apnType,
199            PhoneConstants.DataState state) {
200        long subId = sender.getSubId();
201        long dds = SubscriptionManager.getDefaultDataSubId();
202        if (DBG) log("subId = " + subId + ", DDS = " + dds);
203
204        // TODO
205        // use apnType as the key to which connection we're talking about.
206        // pass apnType back up to fetch particular for this one.
207        TelephonyManager telephony = TelephonyManager.getDefault();
208        LinkProperties linkProperties = null;
209        NetworkCapabilities networkCapabilities = null;
210        boolean roaming = false;
211
212        if (state == PhoneConstants.DataState.CONNECTED) {
213            linkProperties = sender.getLinkProperties(apnType);
214            networkCapabilities = sender.getNetworkCapabilities(apnType);
215        }
216        ServiceState ss = sender.getServiceState();
217        if (ss != null) roaming = ss.getRoaming();
218
219        try {
220            if (mRegistry != null) {
221                mRegistry.notifyDataConnectionForSubscriber(subId,
222                    convertDataState(state),
223                    sender.isDataConnectivityPossible(apnType), reason,
224                    sender.getActiveApnHost(apnType),
225                    apnType,
226                    linkProperties,
227                    networkCapabilities,
228                    ((telephony!=null) ? telephony.getNetworkType() :
229                    TelephonyManager.NETWORK_TYPE_UNKNOWN),
230                    roaming);
231            }
232        } catch (RemoteException ex) {
233            // system process is dead
234        }
235    }
236
237    @Override
238    public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) {
239        long subId = sender.getSubId();
240        try {
241            if (mRegistry != null) {
242                mRegistry.notifyDataConnectionFailedForSubscriber(subId, reason, apnType);
243            }
244        } catch (RemoteException ex) {
245            // system process is dead
246        }
247    }
248
249    @Override
250    public void notifyCellLocation(Phone sender) {
251        long subId = sender.getSubId();
252        Bundle data = new Bundle();
253        sender.getCellLocation().fillInNotifierBundle(data);
254        try {
255            if (mRegistry != null) {
256                mRegistry.notifyCellLocationForSubscriber(subId, data);
257            }
258        } catch (RemoteException ex) {
259            // system process is dead
260        }
261    }
262
263    @Override
264    public void notifyCellInfo(Phone sender, List<CellInfo> cellInfo) {
265        long subId = sender.getSubId();
266        try {
267            if (mRegistry != null) {
268                mRegistry.notifyCellInfoForSubscriber(subId, cellInfo);
269            }
270        } catch (RemoteException ex) {
271
272        }
273    }
274
275    @Override
276    public void notifyDataConnectionRealTimeInfo(Phone sender,
277                                                 DataConnectionRealTimeInfo dcRtInfo) {
278        try {
279            mRegistry.notifyDataConnectionRealTimeInfo(dcRtInfo);
280        } catch (RemoteException ex) {
281
282        }
283    }
284
285    @Override
286    public void notifyOtaspChanged(Phone sender, int otaspMode) {
287        // FIXME: subId?
288        try {
289            if (mRegistry != null) {
290                mRegistry.notifyOtaspChanged(otaspMode);
291            }
292        } catch (RemoteException ex) {
293            // system process is dead
294        }
295    }
296
297    public void notifyPreciseCallState(Phone sender) {
298        // FIXME: subId?
299        Call ringingCall = sender.getRingingCall();
300        Call foregroundCall = sender.getForegroundCall();
301        Call backgroundCall = sender.getBackgroundCall();
302        if (ringingCall != null && foregroundCall != null && backgroundCall != null) {
303            try {
304                mRegistry.notifyPreciseCallState(
305                        convertPreciseCallState(ringingCall.getState()),
306                        convertPreciseCallState(foregroundCall.getState()),
307                        convertPreciseCallState(backgroundCall.getState()));
308            } catch (RemoteException ex) {
309                // system process is dead
310            }
311        }
312    }
313
314    public void notifyDisconnectCause(int cause, int preciseCause) {
315        // FIXME: subId?
316        try {
317            mRegistry.notifyDisconnectCause(cause, preciseCause);
318        } catch (RemoteException ex) {
319            // system process is dead
320        }
321    }
322
323    public void notifyPreciseDataConnectionFailed(Phone sender, String reason, String apnType,
324            String apn, String failCause) {
325        // FIXME: subId?
326        try {
327            mRegistry.notifyPreciseDataConnectionFailed(reason, apnType, apn, failCause);
328        } catch (RemoteException ex) {
329            // system process is dead
330        }
331    }
332
333    @Override
334    public void notifyVoLteServiceStateChanged(Phone sender, VoLteServiceState lteState) {
335        // FIXME: subID
336        try {
337            mRegistry.notifyVoLteServiceStateChanged(lteState);
338        } catch (RemoteException ex) {
339            // system process is dead
340        }
341    }
342
343    /**
344     * Convert the {@link PhoneConstants.State} enum into the TelephonyManager.CALL_STATE_*
345     * constants for the public API.
346     */
347    public static int convertCallState(PhoneConstants.State state) {
348        switch (state) {
349            case RINGING:
350                return TelephonyManager.CALL_STATE_RINGING;
351            case OFFHOOK:
352                return TelephonyManager.CALL_STATE_OFFHOOK;
353            default:
354                return TelephonyManager.CALL_STATE_IDLE;
355        }
356    }
357
358    /**
359     * Convert the TelephonyManager.CALL_STATE_* constants into the
360     * {@link PhoneConstants.State} enum for the public API.
361     */
362    public static PhoneConstants.State convertCallState(int state) {
363        switch (state) {
364            case TelephonyManager.CALL_STATE_RINGING:
365                return PhoneConstants.State.RINGING;
366            case TelephonyManager.CALL_STATE_OFFHOOK:
367                return PhoneConstants.State.OFFHOOK;
368            default:
369                return PhoneConstants.State.IDLE;
370        }
371    }
372
373    /**
374     * Convert the {@link PhoneConstants.DataState} enum into the TelephonyManager.DATA_* constants
375     * for the public API.
376     */
377    public static int convertDataState(PhoneConstants.DataState state) {
378        switch (state) {
379            case CONNECTING:
380                return TelephonyManager.DATA_CONNECTING;
381            case CONNECTED:
382                return TelephonyManager.DATA_CONNECTED;
383            case SUSPENDED:
384                return TelephonyManager.DATA_SUSPENDED;
385            default:
386                return TelephonyManager.DATA_DISCONNECTED;
387        }
388    }
389
390    /**
391     * Convert the TelephonyManager.DATA_* constants into {@link PhoneConstants.DataState} enum
392     * for the public API.
393     */
394    public static PhoneConstants.DataState convertDataState(int state) {
395        switch (state) {
396            case TelephonyManager.DATA_CONNECTING:
397                return PhoneConstants.DataState.CONNECTING;
398            case TelephonyManager.DATA_CONNECTED:
399                return PhoneConstants.DataState.CONNECTED;
400            case TelephonyManager.DATA_SUSPENDED:
401                return PhoneConstants.DataState.SUSPENDED;
402            default:
403                return PhoneConstants.DataState.DISCONNECTED;
404        }
405    }
406
407    /**
408     * Convert the {@link Phone.DataActivityState} enum into the TelephonyManager.DATA_* constants
409     * for the public API.
410     */
411    public static int convertDataActivityState(Phone.DataActivityState state) {
412        switch (state) {
413            case DATAIN:
414                return TelephonyManager.DATA_ACTIVITY_IN;
415            case DATAOUT:
416                return TelephonyManager.DATA_ACTIVITY_OUT;
417            case DATAINANDOUT:
418                return TelephonyManager.DATA_ACTIVITY_INOUT;
419            case DORMANT:
420                return TelephonyManager.DATA_ACTIVITY_DORMANT;
421            default:
422                return TelephonyManager.DATA_ACTIVITY_NONE;
423        }
424    }
425
426    /**
427     * Convert the TelephonyManager.DATA_* constants into the {@link Phone.DataActivityState} enum
428     * for the public API.
429     */
430    public static Phone.DataActivityState convertDataActivityState(int state) {
431        switch (state) {
432            case TelephonyManager.DATA_ACTIVITY_IN:
433                return Phone.DataActivityState.DATAIN;
434            case TelephonyManager.DATA_ACTIVITY_OUT:
435                return Phone.DataActivityState.DATAOUT;
436            case TelephonyManager.DATA_ACTIVITY_INOUT:
437                return Phone.DataActivityState.DATAINANDOUT;
438            case TelephonyManager.DATA_ACTIVITY_DORMANT:
439                return Phone.DataActivityState.DORMANT;
440            default:
441                return Phone.DataActivityState.NONE;
442        }
443    }
444
445    /**
446     * Convert the {@link State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
447     * for the public API.
448     */
449    public static int convertPreciseCallState(Call.State state) {
450        switch (state) {
451            case ACTIVE:
452                return PreciseCallState.PRECISE_CALL_STATE_ACTIVE;
453            case HOLDING:
454                return PreciseCallState.PRECISE_CALL_STATE_HOLDING;
455            case DIALING:
456                return PreciseCallState.PRECISE_CALL_STATE_DIALING;
457            case ALERTING:
458                return PreciseCallState.PRECISE_CALL_STATE_ALERTING;
459            case INCOMING:
460                return PreciseCallState.PRECISE_CALL_STATE_INCOMING;
461            case WAITING:
462                return PreciseCallState.PRECISE_CALL_STATE_WAITING;
463            case DISCONNECTED:
464                return PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED;
465            case DISCONNECTING:
466                return PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING;
467            default:
468                return PreciseCallState.PRECISE_CALL_STATE_IDLE;
469        }
470    }
471
472    /**
473     * Convert the Call.State.* constants into the {@link State} enum
474     * for the public API.
475     */
476    public static Call.State convertPreciseCallState(int state) {
477        switch (state) {
478            case PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
479                return Call.State.ACTIVE;
480            case PreciseCallState.PRECISE_CALL_STATE_HOLDING:
481                return Call.State.HOLDING;
482            case PreciseCallState.PRECISE_CALL_STATE_DIALING:
483                return Call.State.DIALING;
484            case PreciseCallState.PRECISE_CALL_STATE_ALERTING:
485                return Call.State.ALERTING;
486            case PreciseCallState.PRECISE_CALL_STATE_INCOMING:
487                return Call.State.INCOMING;
488            case PreciseCallState.PRECISE_CALL_STATE_WAITING:
489                return Call.State.WAITING;
490            case PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED:
491                return Call.State.DISCONNECTED;
492            case PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING:
493                return Call.State.DISCONNECTING;
494            default:
495                return Call.State.IDLE;
496        }
497    }
498
499    public interface IDataStateChangedCallback {
500        void onDataStateChanged(long subId, String state, String reason, String apnName,
501            String apnType, boolean unavailable);
502    }
503
504    private void log(String s) {
505        Rlog.d(LOG_TAG, s);
506    }
507}
508