1/*
2 * Copyright (C) 2014 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.omadm.plugin.diagmon;
18
19import android.content.Context;
20import android.telephony.PhoneStateListener;
21import android.telephony.ServiceState;
22import android.telephony.TelephonyManager;
23import android.util.Log;
24
25import com.android.omadm.plugin.DmtBasePlugin;
26import com.android.omadm.plugin.DmtData;
27import com.android.omadm.plugin.DmtPathUtils;
28import com.android.omadm.plugin.DmtPluginNode;
29import com.android.omadm.plugin.ErrorCodes;
30
31import java.lang.reflect.Method;
32import java.util.HashMap;
33import java.util.Map;
34
35public class DiagmonPlugin extends DmtBasePlugin {
36    private static final String TAG = "DiagmonPlugin";
37    private static final boolean DBG = true;
38
39    private String mRootPath;
40
41    private Context mContext;
42
43    private Map<String, DmtData> nodeValues;
44
45    private boolean mHomeRoam = false;
46
47    private RFPhoneStateListener mRFPhoneStateListener;
48
49    public TelephonyManager mTelephonyManager;
50
51    public static final String DIAGMON_ROOT = DmtPathUtils.ROOTNODE;
52
53    public static final String DIAGMON_PATH = "./ManagedObjects/DiagMon";
54
55
56    public DiagmonPlugin(Context ctx) {
57        mContext = ctx;
58
59        mTelephonyManager = (TelephonyManager) mContext
60                .getSystemService(Context.TELEPHONY_SERVICE);
61        mRFPhoneStateListener = new RFPhoneStateListener();
62        mTelephonyManager.listen(mRFPhoneStateListener,
63                PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
64        mTelephonyManager.listen(mRFPhoneStateListener,
65                PhoneStateListener.LISTEN_SERVICE_STATE);
66    }
67
68    @SuppressWarnings("unchecked")
69    public boolean init(String rootPath, Map parameters) {
70        if (DiagmonPlugin.DBG) {
71            Log.i(TAG, "Enter DiagmonPlugin.init");
72        }
73        mRootPath = rootPath;
74        nodeValues = new HashMap<String, DmtData>();
75        String tmpPath = DIAGMON_ROOT;
76        DmtData tmpNodeData = new DmtData("RF", DmtData.NODE);
77        nodeValues.put(tmpPath, tmpNodeData);
78        tmpPath = "RF";
79        tmpNodeData = new DmtData("CurrentSystem|HomeRoam", DmtData.NODE);
80        nodeValues.put(tmpPath, tmpNodeData);
81        tmpPath = "RF/CurrentSystem";
82        tmpNodeData = new DmtData("Data|Voice", DmtData.NODE);
83        nodeValues.put(tmpPath, tmpNodeData);
84        tmpPath = "RF/CurrentSystem/Data";
85        tmpNodeData = new DmtData(null, DmtData.STRING);
86        nodeValues.put(tmpPath, tmpNodeData);
87        tmpPath = "RF/CurrentSystem/Voice";
88        tmpNodeData = new DmtData(null, DmtData.STRING);
89        nodeValues.put(tmpPath, tmpNodeData);
90        tmpPath = "RF/HomeRoam";
91        tmpNodeData = new DmtData(null, DmtData.STRING);
92        nodeValues.put(tmpPath, tmpNodeData);
93
94        return true;
95    }
96
97    //@Override
98    public DmtPluginNode getNode(String path) {
99        DmtPluginNode node = new DmtPluginNode("", new DmtData("abc"));
100        setOperationResult(ErrorCodes.SYNCML_DM_SUCCESS);
101        return node;
102    }
103
104    //@Override
105    public DmtData getNodeValue(String path) {
106        if (DiagmonPlugin.DBG) {
107            Log.i(TAG, "rootPath=" + mRootPath);
108        }
109        if (DiagmonPlugin.DBG) {
110            Log.i(TAG, "path=" + path);
111        }
112        //mContext.enforceCallingPermission("com.android.permission.READ_OMADM_SETTINGS", "Insufficient Permissions");
113
114        DmtData data = null;
115
116        if (path.equals("./ManagedObjects/DiagMon/RF/CurrentSystem/Data")) {
117            if (DiagmonPlugin.DBG) {
118                Log.d(TAG, "Get on CurrentSystem Value");
119            }
120            String mCurrentSystem;
121            try {
122                mCurrentSystem = getCurrentSystem();
123                if (DiagmonPlugin.DBG) {
124                    Log.d(TAG, "Current System Value: " + mCurrentSystem);
125                }
126            } catch (Exception e) {
127                mCurrentSystem = "Unknown";
128                if (DiagmonPlugin.DBG) {
129                    Log.d(TAG, "Get on Current System Value failed");
130                }
131                e.printStackTrace();
132            }
133            data = new DmtData(mCurrentSystem);
134            setOperationResult(ErrorCodes.SYNCML_DM_SUCCESS);
135        } else if (path.equals("./ManagedObjects/DiagMon/RF/CurrentSystem/Voice")) {
136            if (DiagmonPlugin.DBG) {
137                Log.d(TAG, "Get on CurrentSystem Voice Value");
138            }
139            String mCurrentSystemVoice;
140            if (isVoiceCapable(mContext)) {
141                mCurrentSystemVoice = "1xRTT"; //As per VZW (36953) requirement value is 1xRTT
142            } else {
143                mCurrentSystemVoice = "Voice not available";
144            }
145            if (DiagmonPlugin.DBG) {
146                Log.d(TAG, "Current System Voice Value: " + mCurrentSystemVoice);
147            }
148            data = new DmtData(mCurrentSystemVoice);
149            setOperationResult(ErrorCodes.SYNCML_DM_SUCCESS);
150        } else if (path.equals("./ManagedObjects/DiagMon/RF/HomeRoam")) {
151            if (DiagmonPlugin.DBG) {
152                Log.d(TAG, "Get on HomeRoam Value");
153            }
154            String sHomeRoam;
155            try {
156                sHomeRoam = getHomeRoam();
157                if (DiagmonPlugin.DBG) {
158                    Log.d(TAG, "HomeRoam Value: " + sHomeRoam);
159                }
160            } catch (Exception e) {
161                sHomeRoam = "Unknown";
162                if (DiagmonPlugin.DBG) {
163                    Log.d(TAG, "Get on HomeRoam Value failed");
164                }
165                e.printStackTrace();
166            }
167            data = new DmtData(sHomeRoam);
168            setOperationResult(ErrorCodes.SYNCML_DM_SUCCESS);
169        } else {
170            setOperationResult(ErrorCodes.SYNCML_DM_FAIL);
171        }
172
173        return data;
174    }
175
176    @SuppressWarnings("unchecked")
177    //@Override
178    public Map getNodes(String rootPath) {
179        if (DiagmonPlugin.DBG) {
180            Log.d(TAG, "Enter DiagmonPlugin::getNodes()");
181        }
182        Map<String, DmtPluginNode> hMap = new HashMap<String, DmtPluginNode>();
183        DmtPluginNode node;
184
185        Map<String, DmtData> nodes = getNodeMap(DmtPathUtils.toRelativePath(DIAGMON_PATH,
186                mRootPath));
187
188        for (String diagPath : nodes.keySet()) {
189            DmtData data = nodes.get(diagPath);
190            if (diagPath.equals(DIAGMON_ROOT)) {
191                diagPath = "";
192            }
193            if (DiagmonPlugin.DBG) {
194                Log.i(TAG, "put node = '" + diagPath + "'");
195            }
196            node = new DmtPluginNode(diagPath, data);
197            hMap.put(diagPath, node);
198        }
199
200        if (DiagmonPlugin.DBG) {
201            Log.i(TAG, "created the nodes.");
202        }
203        if (DiagmonPlugin.DBG) {
204            Log.d(TAG, "Leave DiagmonPlugin::getNodes()");
205        }
206        return hMap;
207    }
208
209    public Map<String, DmtData> getNodeMap(String rootPath) {
210
211        Map<String, DmtData> nodeMap = new HashMap<String, DmtData>();
212        if (rootPath.equals(DIAGMON_ROOT)) {
213            nodeMap.putAll(nodeValues);
214        } else {
215            for (String key : nodeValues.keySet()) {
216                if (key.startsWith(rootPath)) {
217                    if ((key.substring(rootPath.length(), (rootPath.length() + 1))).equals("/")) {
218                        nodeMap.put(key, nodeValues.get(key));
219                    }
220                }
221            }
222        }
223        return nodeMap;
224    }
225
226    public boolean release() {
227        mTelephonyManager.listen(mRFPhoneStateListener, PhoneStateListener.LISTEN_NONE);
228        return true;
229    }
230
231    private final class RFPhoneStateListener extends PhoneStateListener {
232
233        @Override
234        public void onServiceStateChanged(ServiceState serviceState) {
235            mHomeRoam = serviceState.getRoaming();
236            if (DiagmonPlugin.DBG) {
237                Log.v(TAG, "Service State intent received: " + mHomeRoam);
238            }
239        }
240    }
241
242    private String getCurrentSystem() {
243        int mNetworkType = mTelephonyManager.getNetworkType();
244        if (DiagmonPlugin.DBG) {
245            Log.d(TAG, "Network Type value : " + mNetworkType);
246        }
247        if (mNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN) {
248            return ("Unknown");
249        } else if (mNetworkType == TelephonyManager.NETWORK_TYPE_1xRTT) {
250            return ("1xRTT");
251        } else if (mNetworkType == TelephonyManager.NETWORK_TYPE_EVDO_0
252                || mNetworkType == TelephonyManager.NETWORK_TYPE_EVDO_A) {
253            return ("EVDO");
254        } else if (mNetworkType == TelephonyManager.NETWORK_TYPE_LTE) {
255            return ("LTE");
256        } else if (mNetworkType == TelephonyManager.NETWORK_TYPE_EHRPD) {
257            return ("eHRPD");
258        } else {
259            return ("Unknown");
260        }
261    }
262
263    private String getHomeRoam() {
264        if (mHomeRoam) {
265            return ("Roam");
266        } else {
267            return ("Home");
268        }
269    }
270
271    private static boolean isVoiceCapable(Context context) {
272        TelephonyManager telephonyManager =
273                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
274        if (telephonyManager == null) {
275            return false;
276        }
277        try {
278            Class partypes[] = new Class[0];
279            Method sIsVoiceCapable = TelephonyManager.class.getMethod("isVoiceCapable", partypes);
280            Object arglist[] = new Object[0];
281            Object retobj = sIsVoiceCapable.invoke(telephonyManager, arglist);
282            return (Boolean) retobj;
283        } catch (java.lang.reflect.InvocationTargetException e) {
284            // Failure, must be another device.
285            // Assume that it is voice capable.
286            e.printStackTrace();
287        } catch (IllegalAccessException e) {
288            // Failure, must be an other device.
289            // Assume that it is voice capable.
290            e.printStackTrace();
291        } catch (NoSuchMethodException e) {
292            e.printStackTrace();
293        }
294        return true;
295    }
296}
297