DefaultPhoneNotifier.java revision d2c79d28884203ad4f13ebdf443b3899d56b93d6
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.notifyCallStateUsingSubId(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        long subId = sender.getSubId();
120        Rlog.d(LOG_TAG, "nofityServiceState: mRegistry=" + mRegistry + " ss=" + ss
121                + " sender=" + sender);
122        if (ss == null) {
123            ss = new ServiceState();
124            ss.setStateOutOfService();
125        }
126        try {
127            if (mRegistry != null) {
128                mRegistry.notifyServiceStateUsingSubId(subId, ss);
129            }
130        } catch (RemoteException ex) {
131            // system process is dead
132        }
133    }
134
135    @Override
136    public void notifySignalStrength(Phone sender) {
137        long subId = sender.getSubId();
138        Rlog.d(LOG_TAG, "notifySignalStrength: mRegistry=" + mRegistry
139                + " ss=" + sender.getSignalStrength() + " sender=" + sender);
140        try {
141            if (mRegistry != null) {
142                mRegistry.notifySignalStrengthUsingSubId(subId, sender.getSignalStrength());
143            }
144        } catch (RemoteException ex) {
145            // system process is dead
146        }
147    }
148
149    @Override
150    public void notifyMessageWaitingChanged(Phone sender) {
151        long subId = sender.getSubId();
152        try {
153            if (mRegistry != null) {
154                mRegistry.notifyMessageWaitingChangedUsingSubId(subId,
155                        sender.getMessageWaitingIndicator());
156            }
157        } catch (RemoteException ex) {
158            // system process is dead
159        }
160    }
161
162    @Override
163    public void notifyCallForwardingChanged(Phone sender) {
164        long subId = sender.getSubId();
165        try {
166            if (mRegistry != null) {
167                mRegistry.notifyCallForwardingChangedUsingSubId(subId,
168                        sender.getCallForwardingIndicator());
169            }
170        } catch (RemoteException ex) {
171            // system process is dead
172        }
173    }
174
175    @Override
176    public void notifyDataActivity(Phone sender) {
177        long subId = sender.getSubId();
178        try {
179            if (mRegistry != null) {
180                mRegistry.notifyDataActivityUsingSubId(subId,
181                        convertDataActivityState(sender.getDataActivityState()));
182            }
183        } catch (RemoteException ex) {
184            // system process is dead
185        }
186    }
187
188    @Override
189    public void notifyDataConnection(Phone sender, String reason, String apnType,
190            PhoneConstants.DataState state) {
191        doNotifyDataConnection(sender, reason, apnType, state);
192    }
193
194    private void doNotifyDataConnection(Phone sender, String reason, String apnType,
195            PhoneConstants.DataState state) {
196        long subId = sender.getSubId();
197        long dds = SubscriptionManager.getDefaultDataSubId();
198        if (DBG) log("subId = " + subId + ", DDS = " + dds);
199
200        // TODO
201        // use apnType as the key to which connection we're talking about.
202        // pass apnType back up to fetch particular for this one.
203        TelephonyManager telephony = TelephonyManager.getDefault();
204        LinkProperties linkProperties = null;
205        NetworkCapabilities networkCapabilities = null;
206        boolean roaming = false;
207
208        if (state == PhoneConstants.DataState.CONNECTED) {
209            linkProperties = sender.getLinkProperties(apnType);
210            networkCapabilities = sender.getNetworkCapabilities(apnType);
211        }
212        ServiceState ss = sender.getServiceState();
213        if (ss != null) roaming = ss.getRoaming();
214
215        try {
216            if (mRegistry != null) {
217                mRegistry.notifyDataConnectionUsingSubId(subId,
218                    convertDataState(state),
219                    sender.isDataConnectivityPossible(apnType), reason,
220                    sender.getActiveApnHost(apnType),
221                    apnType,
222                    linkProperties,
223                    networkCapabilities,
224                    ((telephony!=null) ? telephony.getNetworkType() :
225                    TelephonyManager.NETWORK_TYPE_UNKNOWN),
226                    roaming);
227            }
228        } catch (RemoteException ex) {
229            // system process is dead
230        }
231    }
232
233    @Override
234    public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) {
235        long subId = sender.getSubId();
236        try {
237            if (mRegistry != null) {
238                mRegistry.notifyDataConnectionFailedUsingSubId(subId, reason, apnType);
239            }
240        } catch (RemoteException ex) {
241            // system process is dead
242        }
243    }
244
245    @Override
246    public void notifyCellLocation(Phone sender) {
247        long subId = sender.getSubId();
248        Bundle data = new Bundle();
249        sender.getCellLocation().fillInNotifierBundle(data);
250        try {
251            if (mRegistry != null) {
252                mRegistry.notifyCellLocationUsingSubId(subId, data);
253            }
254        } catch (RemoteException ex) {
255            // system process is dead
256        }
257    }
258
259    @Override
260    public void notifyCellInfo(Phone sender, List<CellInfo> cellInfo) {
261        long subId = sender.getSubId();
262        try {
263            if (mRegistry != null) {
264                mRegistry.notifyCellInfoUsingSubId(subId, cellInfo);
265            }
266        } catch (RemoteException ex) {
267
268        }
269    }
270
271    @Override
272    public void notifyDataConnectionRealTimeInfo(Phone sender,
273                                                 DataConnectionRealTimeInfo dcRtInfo) {
274        try {
275            mRegistry.notifyDataConnectionRealTimeInfo(dcRtInfo);
276        } catch (RemoteException ex) {
277
278        }
279    }
280
281    @Override
282    public void notifyOtaspChanged(Phone sender, int otaspMode) {
283        // FIXME: subId?
284        try {
285            if (mRegistry != null) {
286                mRegistry.notifyOtaspChanged(otaspMode);
287            }
288        } catch (RemoteException ex) {
289            // system process is dead
290        }
291    }
292
293    public void notifyPreciseCallState(Phone sender) {
294        // FIXME: subId?
295        Call ringingCall = sender.getRingingCall();
296        Call foregroundCall = sender.getForegroundCall();
297        Call backgroundCall = sender.getBackgroundCall();
298        if (ringingCall != null && foregroundCall != null && backgroundCall != null) {
299            try {
300                mRegistry.notifyPreciseCallState(
301                        convertPreciseCallState(ringingCall.getState()),
302                        convertPreciseCallState(foregroundCall.getState()),
303                        convertPreciseCallState(backgroundCall.getState()));
304            } catch (RemoteException ex) {
305                // system process is dead
306            }
307        }
308    }
309
310    public void notifyDisconnectCause(int cause, int preciseCause) {
311        // FIXME: subId?
312        try {
313            mRegistry.notifyDisconnectCause(cause, preciseCause);
314        } catch (RemoteException ex) {
315            // system process is dead
316        }
317    }
318
319    public void notifyPreciseDataConnectionFailed(Phone sender, String reason, String apnType,
320            String apn, String failCause) {
321        // FIXME: subId?
322        try {
323            mRegistry.notifyPreciseDataConnectionFailed(reason, apnType, apn, failCause);
324        } catch (RemoteException ex) {
325            // system process is dead
326        }
327    }
328
329    @Override
330    public void notifyVoLteServiceStateChanged(Phone sender, VoLteServiceState lteState) {
331        // FIXME: subID
332        try {
333            mRegistry.notifyVoLteServiceStateChanged(lteState);
334        } catch (RemoteException ex) {
335            // system process is dead
336        }
337    }
338
339    /**
340     * Convert the {@link PhoneConstants.State} enum into the TelephonyManager.CALL_STATE_*
341     * constants for the public API.
342     */
343    public static int convertCallState(PhoneConstants.State state) {
344        switch (state) {
345            case RINGING:
346                return TelephonyManager.CALL_STATE_RINGING;
347            case OFFHOOK:
348                return TelephonyManager.CALL_STATE_OFFHOOK;
349            default:
350                return TelephonyManager.CALL_STATE_IDLE;
351        }
352    }
353
354    /**
355     * Convert the TelephonyManager.CALL_STATE_* constants into the
356     * {@link PhoneConstants.State} enum for the public API.
357     */
358    public static PhoneConstants.State convertCallState(int state) {
359        switch (state) {
360            case TelephonyManager.CALL_STATE_RINGING:
361                return PhoneConstants.State.RINGING;
362            case TelephonyManager.CALL_STATE_OFFHOOK:
363                return PhoneConstants.State.OFFHOOK;
364            default:
365                return PhoneConstants.State.IDLE;
366        }
367    }
368
369    /**
370     * Convert the {@link PhoneConstants.DataState} enum into the TelephonyManager.DATA_* constants
371     * for the public API.
372     */
373    public static int convertDataState(PhoneConstants.DataState state) {
374        switch (state) {
375            case CONNECTING:
376                return TelephonyManager.DATA_CONNECTING;
377            case CONNECTED:
378                return TelephonyManager.DATA_CONNECTED;
379            case SUSPENDED:
380                return TelephonyManager.DATA_SUSPENDED;
381            default:
382                return TelephonyManager.DATA_DISCONNECTED;
383        }
384    }
385
386    /**
387     * Convert the TelephonyManager.DATA_* constants into {@link PhoneConstants.DataState} enum
388     * for the public API.
389     */
390    public static PhoneConstants.DataState convertDataState(int state) {
391        switch (state) {
392            case TelephonyManager.DATA_CONNECTING:
393                return PhoneConstants.DataState.CONNECTING;
394            case TelephonyManager.DATA_CONNECTED:
395                return PhoneConstants.DataState.CONNECTED;
396            case TelephonyManager.DATA_SUSPENDED:
397                return PhoneConstants.DataState.SUSPENDED;
398            default:
399                return PhoneConstants.DataState.DISCONNECTED;
400        }
401    }
402
403    /**
404     * Convert the {@link Phone.DataActivityState} enum into the TelephonyManager.DATA_* constants
405     * for the public API.
406     */
407    public static int convertDataActivityState(Phone.DataActivityState state) {
408        switch (state) {
409            case DATAIN:
410                return TelephonyManager.DATA_ACTIVITY_IN;
411            case DATAOUT:
412                return TelephonyManager.DATA_ACTIVITY_OUT;
413            case DATAINANDOUT:
414                return TelephonyManager.DATA_ACTIVITY_INOUT;
415            case DORMANT:
416                return TelephonyManager.DATA_ACTIVITY_DORMANT;
417            default:
418                return TelephonyManager.DATA_ACTIVITY_NONE;
419        }
420    }
421
422    /**
423     * Convert the TelephonyManager.DATA_* constants into the {@link Phone.DataActivityState} enum
424     * for the public API.
425     */
426    public static Phone.DataActivityState convertDataActivityState(int state) {
427        switch (state) {
428            case TelephonyManager.DATA_ACTIVITY_IN:
429                return Phone.DataActivityState.DATAIN;
430            case TelephonyManager.DATA_ACTIVITY_OUT:
431                return Phone.DataActivityState.DATAOUT;
432            case TelephonyManager.DATA_ACTIVITY_INOUT:
433                return Phone.DataActivityState.DATAINANDOUT;
434            case TelephonyManager.DATA_ACTIVITY_DORMANT:
435                return Phone.DataActivityState.DORMANT;
436            default:
437                return Phone.DataActivityState.NONE;
438        }
439    }
440
441    /**
442     * Convert the {@link State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
443     * for the public API.
444     */
445    public static int convertPreciseCallState(Call.State state) {
446        switch (state) {
447            case ACTIVE:
448                return PreciseCallState.PRECISE_CALL_STATE_ACTIVE;
449            case HOLDING:
450                return PreciseCallState.PRECISE_CALL_STATE_HOLDING;
451            case DIALING:
452                return PreciseCallState.PRECISE_CALL_STATE_DIALING;
453            case ALERTING:
454                return PreciseCallState.PRECISE_CALL_STATE_ALERTING;
455            case INCOMING:
456                return PreciseCallState.PRECISE_CALL_STATE_INCOMING;
457            case WAITING:
458                return PreciseCallState.PRECISE_CALL_STATE_WAITING;
459            case DISCONNECTED:
460                return PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED;
461            case DISCONNECTING:
462                return PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING;
463            default:
464                return PreciseCallState.PRECISE_CALL_STATE_IDLE;
465        }
466    }
467
468    /**
469     * Convert the Call.State.* constants into the {@link State} enum
470     * for the public API.
471     */
472    public static Call.State convertPreciseCallState(int state) {
473        switch (state) {
474            case PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
475                return Call.State.ACTIVE;
476            case PreciseCallState.PRECISE_CALL_STATE_HOLDING:
477                return Call.State.HOLDING;
478            case PreciseCallState.PRECISE_CALL_STATE_DIALING:
479                return Call.State.DIALING;
480            case PreciseCallState.PRECISE_CALL_STATE_ALERTING:
481                return Call.State.ALERTING;
482            case PreciseCallState.PRECISE_CALL_STATE_INCOMING:
483                return Call.State.INCOMING;
484            case PreciseCallState.PRECISE_CALL_STATE_WAITING:
485                return Call.State.WAITING;
486            case PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED:
487                return Call.State.DISCONNECTED;
488            case PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING:
489                return Call.State.DISCONNECTING;
490            default:
491                return Call.State.IDLE;
492        }
493    }
494
495    public interface IDataStateChangedCallback {
496        void onDataStateChanged(long subId, String state, String reason, String apnName,
497            String apnType, boolean unavailable);
498    }
499
500    private void log(String s) {
501        Rlog.d(LOG_TAG, s);
502    }
503}
504