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