1 /*
2  * Copyright (C) 2018 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 
17 package com.android.settingslib.license;
18 
19 import android.content.Context;
20 import android.util.Log;
21 
22 import com.android.settingslib.R;
23 import com.android.settingslib.utils.AsyncLoaderCompat;
24 
25 import java.io.File;
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * LicenseHtmlLoader is a loader which loads a license html file from default license xml files.
31  */
32 public class LicenseHtmlLoaderCompat extends AsyncLoaderCompat<File> {
33     private static final String TAG = "LicenseHtmlLoaderCompat";
34 
35     static final String[] DEFAULT_LICENSE_XML_PATHS = {
36             "/system/etc/NOTICE.xml.gz",
37             "/vendor/etc/NOTICE.xml.gz",
38             "/odm/etc/NOTICE.xml.gz",
39             "/oem/etc/NOTICE.xml.gz",
40             "/product/etc/NOTICE.xml.gz",
41             "/system_ext/etc/NOTICE.xml.gz"};
42     static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";
43 
44     private final Context mContext;
45 
LicenseHtmlLoaderCompat(Context context)46     public LicenseHtmlLoaderCompat(Context context) {
47         super(context);
48         mContext = context;
49     }
50 
51     @Override
loadInBackground()52     public File loadInBackground() {
53         return generateHtmlFromDefaultXmlFiles();
54     }
55 
56     @Override
onDiscardResult(File f)57     protected void onDiscardResult(File f) {
58     }
59 
generateHtmlFromDefaultXmlFiles()60     private File generateHtmlFromDefaultXmlFiles() {
61         final List<File> xmlFiles = getVaildXmlFiles();
62         if (xmlFiles.isEmpty()) {
63             Log.e(TAG, "No notice file exists.");
64             return null;
65         }
66 
67         File cachedHtmlFile = getCachedHtmlFile(mContext);
68         if (!isCachedHtmlFileOutdated(xmlFiles, cachedHtmlFile)
69                 || generateHtmlFile(mContext, xmlFiles, cachedHtmlFile)) {
70             return cachedHtmlFile;
71         }
72 
73         return null;
74     }
75 
getVaildXmlFiles()76     private List<File> getVaildXmlFiles() {
77         final List<File> xmlFiles = new ArrayList();
78         for (final String xmlPath : DEFAULT_LICENSE_XML_PATHS) {
79             File file = new File(xmlPath);
80             if (file.exists() && file.length() != 0) {
81                 xmlFiles.add(file);
82             }
83         }
84         return xmlFiles;
85     }
86 
getCachedHtmlFile(Context context)87     private File getCachedHtmlFile(Context context) {
88         return new File(context.getCacheDir(), NOTICE_HTML_FILE_NAME);
89     }
90 
isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile)91     private boolean isCachedHtmlFileOutdated(List<File> xmlFiles, File cachedHtmlFile) {
92         boolean outdated = true;
93         if (cachedHtmlFile.exists() && cachedHtmlFile.length() != 0) {
94             outdated = false;
95             for (File file : xmlFiles) {
96                 if (cachedHtmlFile.lastModified() < file.lastModified()) {
97                     outdated = true;
98                     break;
99                 }
100             }
101         }
102         return outdated;
103     }
104 
generateHtmlFile(Context context, List<File> xmlFiles, File htmlFile)105     private boolean generateHtmlFile(Context context, List<File> xmlFiles, File htmlFile) {
106         return LicenseHtmlGeneratorFromXml.generateHtml(xmlFiles, htmlFile,
107                 context.getString(R.string.notice_header));
108     }
109 }
110