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.Rlog;
26import android.telephony.VoLteServiceState;
27import android.telephony.ServiceState;
28import android.telephony.SubscriptionManager;
29import android.telephony.TelephonyManager;
30import android.telephony.PreciseCallState;
31import android.telephony.DisconnectCause;
32
33import com.android.internal.telephony.Call;
34import com.android.internal.telephony.CallManager;
35import com.android.internal.telephony.Phone;
36import com.android.internal.telephony.ITelephonyRegistry;
37import com.android.internal.telephony.PhoneConstants;
38
39import java.util.List;
40
41/**
42 * broadcast intents
43 */
44public class DefaultPhoneNotifier implements PhoneNotifier {
45    private static final String LOG_TAG = "DefaultPhoneNotifier";
46    private static final boolean DBG = false; // STOPSHIP if true
47
48    protected ITelephonyRegistry mRegistry;
49
50    public DefaultPhoneNotifier() {
51        mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
52                    "telephony.registry"));
53    }
54
55    @Override
56    public void notifyPhoneState(Phone sender) {
57        Call ringingCall = sender.getRingingCall();
58        int subId = sender.getSubId();
59        int phoneId = sender.getPhoneId();
60        String incomingNumber = "";
61        if (ringingCall != null && ringingCall.getEarliestConnection() != null) {
62            incomingNumber = ringingCall.getEarliestConnection().getAddress();
63        }
64        try {
65            if (mRegistry != null) {
66                  mRegistry.notifyCallStateForPhoneId(phoneId, subId,
67                        convertCallState(sender.getState()), incomingNumber);
68            }
69        } catch (RemoteException ex) {
70            // system process is dead
71        }
72    }
73
74    @Override
75    public void notifyServiceState(Phone sender) {
76        ServiceState ss = sender.getServiceState();
77        int phoneId = sender.getPhoneId();
78        int subId = sender.getSubId();
79
80        Rlog.d(LOG_TAG, "nofityServiceState: mRegistry=" + mRegistry + " ss=" + ss
81                + " sender=" + sender + " phondId=" + phoneId + " subId=" + subId);
82        if (ss == null) {
83            ss = new ServiceState();
84            ss.setStateOutOfService();
85        }
86        try {
87            if (mRegistry != null) {
88                mRegistry.notifyServiceStateForPhoneId(phoneId, subId, ss);
89            }
90        } catch (RemoteException ex) {
91            // system process is dead
92        }
93    }
94
95    @Override
96    public void notifySignalStrength(Phone sender) {
97        int phoneId = sender.getPhoneId();
98        int subId = sender.getSubId();
99        if (DBG) {
100            // too chatty to log constantly
101            Rlog.d(LOG_TAG, "notifySignalStrength: mRegistry=" + mRegistry
102                    + " ss=" + sender.getSignalStrength() + " sender=" + sender);
103        }
104        try {
105            if (mRegistry != null) {
106                mRegistry.notifySignalStrengthForPhoneId(phoneId, subId,
107                        sender.getSignalStrength());
108            }
109        } catch (RemoteException ex) {
110            // system process is dead
111        }
112    }
113
114    @Override
115    public void notifyMessageWaitingChanged(Phone sender) {
116        int phoneId = sender.getPhoneId();
117        int subId = sender.getSubId();
118
119        try {
120            if (mRegistry != null) {
121                mRegistry.notifyMessageWaitingChangedForPhoneId(phoneId, subId,
122                        sender.getMessageWaitingIndicator());
123            }
124        } catch (RemoteException ex) {
125            // system process is dead
126        }
127    }
128
129    @Override
130    public void notifyCallForwardingChanged(Phone sender) {
131        int subId = sender.getSubId();
132        try {
133            if (mRegistry != null) {
134                mRegistry.notifyCallForwardingChangedForSubscriber(subId,
135                        sender.getCallForwardingIndicator());
136            }
137        } catch (RemoteException ex) {
138            // system process is dead
139        }
140    }
141
142    @Override
143    public void notifyDataActivity(Phone sender) {
144        int subId = sender.getSubId();
145        try {
146            if (mRegistry != null) {
147                mRegistry.notifyDataActivityForSubscriber(subId,
148                        convertDataActivityState(sender.getDataActivityState()));
149            }
150        } catch (RemoteException ex) {
151            // system process is dead
152        }
153    }
154
155    @Override
156    public void notifyDataConnection(Phone sender, String reason, String apnType,
157            PhoneConstants.DataState state) {
158        doNotifyDataConnection(sender, reason, apnType, state);
159    }
160
161    private void doNotifyDataConnection(Phone sender, String reason, String apnType,
162            PhoneConstants.DataState state) {
163        int subId = sender.getSubId();
164        long dds = SubscriptionManager.getDefaultDataSubscriptionId();
165        if (DBG) log("subId = " + subId + ", DDS = " + dds);
166
167        // TODO
168        // use apnType as the key to which connection we're talking about.
169        // pass apnType back up to fetch particular for this one.
170        TelephonyManager telephony = TelephonyManager.getDefault();
171        LinkProperties linkProperties = null;
172        NetworkCapabilities networkCapabilities = null;
173        boolean roaming = false;
174
175        if (state == PhoneConstants.DataState.CONNECTED) {
176            linkProperties = sender.getLinkProperties(apnType);
177            networkCapabilities = sender.getNetworkCapabilities(apnType);
178        }
179        ServiceState ss = sender.getServiceState();
180        if (ss != null) roaming = ss.getDataRoaming();
181
182        try {
183            if (mRegistry != null) {
184                mRegistry.notifyDataConnectionForSubscriber(subId,
185                    convertDataState(state),
186                    sender.isDataConnectivityPossible(apnType), reason,
187                    sender.getActiveApnHost(apnType),
188                    apnType,
189                    linkProperties,
190                    networkCapabilities,
191                    ((telephony!=null) ? telephony.getDataNetworkType(subId) :
192                    TelephonyManager.NETWORK_TYPE_UNKNOWN),
193                    roaming);
194            }
195        } catch (RemoteException ex) {
196            // system process is dead
197        }
198    }
199
200    @Override
201    public void notifyDataConnectionFailed(Phone sender, String reason, String apnType) {
202        int subId = sender.getSubId();
203        try {
204            if (mRegistry != null) {
205                mRegistry.notifyDataConnectionFailedForSubscriber(subId, reason, apnType);
206            }
207        } catch (RemoteException ex) {
208            // system process is dead
209        }
210    }
211
212    @Override
213    public void notifyCellLocation(Phone sender) {
214        int subId = sender.getSubId();
215        Bundle data = new Bundle();
216        sender.getCellLocation().fillInNotifierBundle(data);
217        try {
218            if (mRegistry != null) {
219                mRegistry.notifyCellLocationForSubscriber(subId, data);
220            }
221        } catch (RemoteException ex) {
222            // system process is dead
223        }
224    }
225
226    @Override
227    public void notifyCellInfo(Phone sender, List<CellInfo> cellInfo) {
228        int subId = sender.getSubId();
229        try {
230            if (mRegistry != null) {
231                mRegistry.notifyCellInfoForSubscriber(subId, cellInfo);
232            }
233        } catch (RemoteException ex) {
234
235        }
236    }
237
238    @Override
239    public void notifyOtaspChanged(Phone sender, int otaspMode) {
240        // FIXME: subId?
241        try {
242            if (mRegistry != null) {
243                mRegistry.notifyOtaspChanged(otaspMode);
244            }
245        } catch (RemoteException ex) {
246            // system process is dead
247        }
248    }
249
250    public void notifyPreciseCallState(Phone sender) {
251        // FIXME: subId?
252        Call ringingCall = sender.getRingingCall();
253        Call foregroundCall = sender.getForegroundCall();
254        Call backgroundCall = sender.getBackgroundCall();
255        if (ringingCall != null && foregroundCall != null && backgroundCall != null) {
256            try {
257                mRegistry.notifyPreciseCallState(
258                        convertPreciseCallState(ringingCall.getState()),
259                        convertPreciseCallState(foregroundCall.getState()),
260                        convertPreciseCallState(backgroundCall.getState()));
261            } catch (RemoteException ex) {
262                // system process is dead
263            }
264        }
265    }
266
267    public void notifyDisconnectCause(int cause, int preciseCause) {
268        // FIXME: subId?
269        try {
270            mRegistry.notifyDisconnectCause(cause, preciseCause);
271        } catch (RemoteException ex) {
272            // system process is dead
273        }
274    }
275
276    public void notifyPreciseDataConnectionFailed(Phone sender, String reason, String apnType,
277            String apn, String failCause) {
278        // FIXME: subId?
279        try {
280            mRegistry.notifyPreciseDataConnectionFailed(reason, apnType, apn, failCause);
281        } catch (RemoteException ex) {
282            // system process is dead
283        }
284    }
285
286    @Override
287    public void notifyVoLteServiceStateChanged(Phone sender, VoLteServiceState lteState) {
288        // FIXME: subID
289        try {
290            mRegistry.notifyVoLteServiceStateChanged(lteState);
291        } catch (RemoteException ex) {
292            // system process is dead
293        }
294    }
295
296    @Override
297    public void notifyOemHookRawEventForSubscriber(int subId, byte[] rawData) {
298        try {
299            mRegistry.notifyOemHookRawEventForSubscriber(subId, rawData);
300        } catch (RemoteException ex) {
301            // system process is dead
302        }
303    }
304
305    /**
306     * Convert the {@link PhoneConstants.State} enum into the TelephonyManager.CALL_STATE_*
307     * constants for the public API.
308     */
309    public static int convertCallState(PhoneConstants.State state) {
310        switch (state) {
311            case RINGING:
312                return TelephonyManager.CALL_STATE_RINGING;
313            case OFFHOOK:
314                return TelephonyManager.CALL_STATE_OFFHOOK;
315            default:
316                return TelephonyManager.CALL_STATE_IDLE;
317        }
318    }
319
320    /**
321     * Convert the TelephonyManager.CALL_STATE_* constants into the
322     * {@link PhoneConstants.State} enum for the public API.
323     */
324    public static PhoneConstants.State convertCallState(int state) {
325        switch (state) {
326            case TelephonyManager.CALL_STATE_RINGING:
327                return PhoneConstants.State.RINGING;
328            case TelephonyManager.CALL_STATE_OFFHOOK:
329                return PhoneConstants.State.OFFHOOK;
330            default:
331                return PhoneConstants.State.IDLE;
332        }
333    }
334
335    /**
336     * Convert the {@link PhoneConstants.DataState} enum into the TelephonyManager.DATA_* constants
337     * for the public API.
338     */
339    public static int convertDataState(PhoneConstants.DataState state) {
340        switch (state) {
341            case CONNECTING:
342                return TelephonyManager.DATA_CONNECTING;
343            case CONNECTED:
344                return TelephonyManager.DATA_CONNECTED;
345            case SUSPENDED:
346                return TelephonyManager.DATA_SUSPENDED;
347            default:
348                return TelephonyManager.DATA_DISCONNECTED;
349        }
350    }
351
352    /**
353     * Convert the TelephonyManager.DATA_* constants into {@link PhoneConstants.DataState} enum
354     * for the public API.
355     */
356    public static PhoneConstants.DataState convertDataState(int state) {
357        switch (state) {
358            case TelephonyManager.DATA_CONNECTING:
359                return PhoneConstants.DataState.CONNECTING;
360            case TelephonyManager.DATA_CONNECTED:
361                return PhoneConstants.DataState.CONNECTED;
362            case TelephonyManager.DATA_SUSPENDED:
363                return PhoneConstants.DataState.SUSPENDED;
364            default:
365                return PhoneConstants.DataState.DISCONNECTED;
366        }
367    }
368
369    /**
370     * Convert the {@link Phone.DataActivityState} enum into the TelephonyManager.DATA_* constants
371     * for the public API.
372     */
373    public static int convertDataActivityState(Phone.DataActivityState state) {
374        switch (state) {
375            case DATAIN:
376                return TelephonyManager.DATA_ACTIVITY_IN;
377            case DATAOUT:
378                return TelephonyManager.DATA_ACTIVITY_OUT;
379            case DATAINANDOUT:
380                return TelephonyManager.DATA_ACTIVITY_INOUT;
381            case DORMANT:
382                return TelephonyManager.DATA_ACTIVITY_DORMANT;
383            default:
384                return TelephonyManager.DATA_ACTIVITY_NONE;
385        }
386    }
387
388    /**
389     * Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
390     * for the public API.
391     */
392    public static int convertPreciseCallState(Call.State state) {
393        switch (state) {
394            case ACTIVE:
395                return PreciseCallState.PRECISE_CALL_STATE_ACTIVE;
396            case HOLDING:
397                return PreciseCallState.PRECISE_CALL_STATE_HOLDING;
398            case DIALING:
399                return PreciseCallState.PRECISE_CALL_STATE_DIALING;
400            case ALERTING:
401                return PreciseCallState.PRECISE_CALL_STATE_ALERTING;
402            case INCOMING:
403                return PreciseCallState.PRECISE_CALL_STATE_INCOMING;
404            case WAITING:
405                return PreciseCallState.PRECISE_CALL_STATE_WAITING;
406            case DISCONNECTED:
407                return PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED;
408            case DISCONNECTING:
409                return PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING;
410            default:
411                return PreciseCallState.PRECISE_CALL_STATE_IDLE;
412        }
413    }
414
415    private void log(String s) {
416        Rlog.d(LOG_TAG, s);
417    }
418}
419