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.service;
18
19import android.util.Log;
20
21import java.io.File;
22import java.io.FilenameFilter;
23
24class DMSession {
25    private static final String TAG = "DMSession";
26    private static final boolean DBG = DMClientService.DBG;
27
28    private final String mLogPath;
29
30    private int mResultCode;
31
32    private DMHttpConnector mHttpConnector;
33
34    private final DMAlert mDMAlert;
35
36    private final DMClientService mDMClientService;
37
38    private String mLogName;
39
40    private String mServerID;
41
42    public String getLogFileName() {
43        return mLogName;
44    }
45
46    DMSession(DMClientService context) {
47        mLogName = null;
48        mDMClientService = context;
49        mDMAlert = new DMAlert(context);
50        mLogPath = context.getFilesDir().getPath() + "/dm/log/";
51        if (DBG) logd("XXX DMSession mLogPath dir = " + mLogPath);
52    }
53
54    public int startClientSession(String serverID) {
55        prepareLogFile();
56
57        try {
58            mServerID = serverID;
59            mHttpConnector = new DMHttpConnector(this);
60
61            if (DBG) logd("Start client session with server: " + mServerID);
62            mResultCode = NativeDM.startClientSession(mServerID, this);
63
64            logd("startDmSession resultCode: " + mResultCode);
65        } catch (RuntimeException e) {
66            loge("Exception caught starting DM session", e);
67        }
68
69        mHttpConnector.closeSession();
70        mHttpConnector = null;
71        mLogName = null;
72
73        return mResultCode;
74    }
75
76    public int startFotaClientSession(String serverID, String alertStr) {
77        prepareLogFile();
78
79        try {
80            mServerID = serverID;
81            mHttpConnector = new DMHttpConnector(this);
82
83            if (DBG) logd("Start DM session with server: " + mServerID
84                    + " alert string: " + alertStr);
85            mResultCode = NativeDM.startFotaClientSession(serverID, alertStr, this);
86
87            logd("startDmSession resultCode: " + mResultCode);
88        } catch (Exception e) {
89            loge("Exception caught starting DM session", e);
90        }
91
92        mHttpConnector.closeSession();
93        mHttpConnector = null;
94        mLogName = null;
95
96        return mResultCode;
97    }
98
99    public int startLawmoNotifySession(FotaNotifyContext LawmoContext) {
100        prepareLogFile();
101
102        try {
103            mServerID = mDMClientService.getConfigDB().getFotaServerID();
104            mHttpConnector = new DMHttpConnector(this);
105
106            if (DBG) logd("Start LAWMONotify session with server: " + mServerID
107                    + " PkgURI: " + LawmoContext.mPkgURI
108                    + " AlertType: " + LawmoContext.mAlertType
109                    + " Result: " + LawmoContext.mResult);
110            mResultCode = NativeDM.startFotaNotifySession(
111                    LawmoContext.mResult,
112                    LawmoContext.mPkgURI,
113                    LawmoContext.mAlertType,
114                    mServerID,
115                    LawmoContext.mCorrelator,
116                    this);
117            logd("LAWMONotifySession resultCode: " + mResultCode);
118        } catch (Exception e) {
119            loge("Exception caught starting DM session", e);
120        }
121
122        mHttpConnector.closeSession();
123        mHttpConnector = null;
124        mLogName = null;
125
126        return mResultCode;
127    }
128
129    public int startPkg0AlertSession(byte[] data) {
130        DMPkg0Notification notification = new DMPkg0Notification();
131        int ret = NativeDM.parsePkg0(data, notification);
132        if (ret != DMResult.SYNCML_DM_SUCCESS) {
133            if (ret != DMResult.SYNCML_DM_SESSION_AUTH_FAIL) {
134                logd("parsePkg0 return:" + ret);
135                return ret;
136            }
137            if (mDMClientService.getConfigDB().isDmNonceResyncEnabled()) {
138                logd("Nonce resync enabled, ignore as per OMA DM spec.");
139                return ret;
140            }
141        }
142
143        if (DBG) logd("NativeDM.parsePkg0 result: uiMode: " + notification.getUIMode()
144                + " initiator: " + notification.getInitiator()
145                + " sessionId: " + notification.getSessionID()
146                + " serverId: " + notification.getServerID());
147
148        if (notification.getServerID() == null) {
149            return DMResult.SYNCML_DM_SESSION_PARAM_ERR;
150        }
151
152        if (notification.getUIMode() == 3 || notification.getUIMode() == 0) {
153            mDMAlert.setUIMode(mDMClientService.getConfigDB().isDmAlertEnabled());
154        } else {
155            mDMAlert.setUIMode(false);
156        }
157        prepareLogFile();
158
159        mServerID = notification.getServerID();
160        mHttpConnector = new DMHttpConnector(this);
161
162        try {
163            if (notification.getInitiator() == 1) {
164                logd("Start server initiated session");
165                mResultCode = NativeDM.startFotaServerSession(notification.getServerID(),
166                        notification.getSessionID(),
167                        this);
168            } else {
169                logd("Start client initiated session");
170                String alertStr = "org.openmobilealliance.dm.firmwareupdate.userrequest";
171                mResultCode = NativeDM.startFotaClientSession(notification.getServerID(), alertStr,
172                        this);
173            }
174
175            logd("startDmSession resultCode: " + mResultCode);
176
177            if (mResultCode == DMResult.SYNCML_DM_SUCCESS) {
178                mDMClientService.getConfigDB().setFotaServerID(notification.getServerID());
179            }
180        } catch (Exception e) {
181            loge("Exception caught starting DM session", e);
182        }
183
184        mHttpConnector.closeSession();
185        mHttpConnector = null;
186        mLogName = null;
187
188        return mResultCode;
189    }
190
191    public int fotaNotifyDMServer(FotaNotifyContext fotaContext) {
192        prepareLogFile();
193
194        try {
195            mServerID = fotaContext.mServerID;
196            mHttpConnector = new DMHttpConnector(this);
197
198            mResultCode = NativeDM.startFotaNotifySession(
199                    fotaContext.mResult,
200                    fotaContext.mPkgURI,
201                    fotaContext.mAlertType,
202                    fotaContext.mServerID,
203                    fotaContext.mCorrelator,
204                    this);
205            if (DBG) logd("fotaNotifyDMServer resultCode: " + mResultCode);
206        } catch (Exception e) {
207            loge("Exception caught starting DM session", e);
208        }
209
210        mHttpConnector.closeSession();
211        mHttpConnector = null;
212        mLogName = null;
213
214        return mResultCode;
215    }
216
217    public int cancelSession() {
218        NativeDM.cancelSession();       // Just set cancel flag.
219
220        mHttpConnector.closeSession();
221        mHttpConnector = null;
222
223        mDMAlert.cancelSession();
224        return 0;
225    }
226
227    private void prepareLogFile() {
228        File dirs = new File(mLogPath);
229        FilenameFilter filter = new SyncMLFilenameFilter();
230
231        int maxNum = 0;
232        String[] files = dirs.list(filter);
233
234        if(files != null) {
235            for (String f : files) {
236                String digitalStr = f.substring(7, 8);
237                try {
238                    int number = Integer.parseInt(digitalStr);
239                    if (number > maxNum) {
240                        maxNum = number;
241                    }
242
243                } catch (NumberFormatException e) {
244                    loge("NumberFormatException in prepareLogFile()", e);
245                }
246            }
247            maxNum++;
248        }
249
250        if (files == null || maxNum >= 10) {
251            // FIXME: check return value
252            dirs.delete();
253            // FIXME: check return value
254            dirs.mkdirs();
255            maxNum = 1;
256        }
257
258        String num = Integer.toString(maxNum);
259        String logName = "SyncML_" + num + ".txt";
260        mLogName = mLogPath + logName;
261        if (DBG) logd("Log File: " + mLogName);
262    }
263
264    public DMClientService getServiceContext() {
265        return mDMClientService;
266    }
267
268    /**
269     * Get the {@link DMHttpConnector} object for this session. Called from JNI code.
270     *
271     * @return the DMHttpConnector object for this session
272     */
273    public DMHttpConnector getNetConnector() {
274        return mHttpConnector;
275    }
276
277    /**
278     * Get the {@link DMAlert} object for this session. Called from JNI code.
279     *
280     * @return the DMAlert object for this session
281     */
282    public DMAlert getDMAlert() {
283        return mDMAlert;
284    }
285
286    // FIXME: remove if unused?!
287    public String getServerID() {
288        return mServerID;
289    }
290
291    private static class SyncMLFilenameFilter implements FilenameFilter {
292
293        SyncMLFilenameFilter() {
294        }
295
296        @Override
297        public boolean accept(File dir, String name) {
298            return name.endsWith(".txt") && name.startsWith("SyncML_");
299        }
300    }
301
302    private static void logd(String msg) {
303        Log.d(TAG, msg);
304    }
305
306    private static void loge(String msg, Throwable tr) {
307        Log.e(TAG, msg, tr);
308    }
309}
310