OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.webapk.shell_apk; | 5 package org.chromium.webapk.shell_apk; |
6 | 6 |
7 import android.app.Service; | 7 import android.app.Service; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.content.SharedPreferences; | |
11 import android.content.pm.PackageInfo; | |
12 import android.content.pm.PackageManager; | |
10 import android.os.IBinder; | 13 import android.os.IBinder; |
11 import android.util.Log; | 14 import android.util.Log; |
12 | 15 |
13 import org.chromium.webapk.lib.common.WebApkUtils; | 16 import org.chromium.webapk.lib.common.WebApkUtils; |
14 | 17 |
15 import java.io.File; | 18 import java.io.File; |
16 import java.lang.reflect.Constructor; | 19 import java.lang.reflect.Constructor; |
20 import java.util.Scanner; | |
17 | 21 |
18 /** | 22 /** |
19 * Shell class for services provided by WebAPK to Chrome. Extracts code with imp lementation of | 23 * Shell class for services provided by WebAPK to Chrome. Extracts code with imp lementation of |
20 * services from .dex file in Chrome APK. | 24 * services from .dex file in Chrome APK. |
21 */ | 25 */ |
22 public class WebApkServiceFactory extends Service { | 26 public class WebApkServiceFactory extends Service { |
23 private static final String TAG = "cr_WebApkServiceFactory"; | 27 private static final String TAG = "cr_WebApkServiceFactory"; |
24 | 28 |
25 /** | 29 /** |
26 * Name of the class with IBinder API implementation. | 30 * Name of the class with IBinder API implementation. |
27 */ | 31 */ |
28 private static final String WEBAPK_SERVICE_IMPL_CLASS_NAME = | 32 private static final String WEBAPK_SERVICE_IMPL_CLASS_NAME = |
29 "org.chromium.webapk.lib.runtime_library.WebApkServiceImpl"; | 33 "org.chromium.webapk.lib.runtime_library.WebApkServiceImpl"; |
30 | 34 |
35 /** | |
36 * Name of the shared preferences file. | |
37 */ | |
38 private static final String PREF_FILE_NAME = "WEBAPK_PREFS"; | |
Xi Han
2016/05/26 21:40:23
I am not sure whether use "WEBAPK_PREFS" or "webap
| |
39 | |
40 /** | |
41 * Name of the shared preference for Chrome's version code. | |
42 */ | |
43 private static final String REMOTE_VERSION_CODE_PREF = | |
44 "org.chromium.webapk.shell_apk.version_code"; | |
45 | |
46 /** | |
47 * Name of the shared preference for the version number of the dynamically l oaded dex. | |
48 */ | |
49 private static final String RUNTIME_DEX_VERSION_PREF = | |
50 "org.chromium.webapk.shell_apk.dex_version"; | |
51 | |
31 /* | 52 /* |
32 * ClassLoader for loading {@link WEBAPK_SERVICE_IMPL_CLASS_NAME}. Static so that all | 53 * ClassLoader for loading {@link WEBAPK_SERVICE_IMPL_CLASS_NAME}. Static so that all |
33 * {@link WebApkServiceFactory} service instatiations use the same ClassLoad er during the app's | 54 * {@link WebApkServiceFactory} service instatiations use the same ClassLoad er during the app's |
34 * lifetime. | 55 * lifetime. |
35 */ | 56 */ |
36 private static ClassLoader sClassLoader; | 57 private static ClassLoader sClassLoader; |
37 | 58 |
38 @Override | 59 @Override |
39 public IBinder onBind(Intent intent) { | 60 public IBinder onBind(Intent intent) { |
40 ClassLoader webApkClassLoader = getClassLoaderInstance(this); | 61 ClassLoader webApkClassLoader = getClassLoaderInstance(this); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 * @param context WebAPK's context. | 95 * @param context WebAPK's context. |
75 * @return The ClassLoader. | 96 * @return The ClassLoader. |
76 */ | 97 */ |
77 private static ClassLoader createClassLoader(Context context) { | 98 private static ClassLoader createClassLoader(Context context) { |
78 Context remoteContext = WebApkUtils.getHostBrowserContext(context); | 99 Context remoteContext = WebApkUtils.getHostBrowserContext(context); |
79 if (remoteContext == null) { | 100 if (remoteContext == null) { |
80 Log.w(TAG, "Failed to get remote context."); | 101 Log.w(TAG, "Failed to get remote context."); |
81 return null; | 102 return null; |
82 } | 103 } |
83 | 104 |
105 SharedPreferences preferences = context.getSharedPreferences(PREF_FILE_N AME, MODE_PRIVATE); | |
106 | |
107 int runtimeDexVersion = preferences.getInt(RUNTIME_DEX_VERSION_PREF, -1) ; | |
108 int newRuntimeDexVersion = checkForNewRuntimeDexVersion(preferences, rem oteContext); | |
109 if (newRuntimeDexVersion == -1) { | |
110 newRuntimeDexVersion = runtimeDexVersion; | |
111 } | |
84 File localDexDir = context.getDir("dex", Context.MODE_PRIVATE); | 112 File localDexDir = context.getDir("dex", Context.MODE_PRIVATE); |
113 if (newRuntimeDexVersion != runtimeDexVersion) { | |
114 Log.w(TAG, "Delete cached dex files."); | |
115 DexLoader.deleteCachedDexes(localDexDir); | |
116 } | |
117 | |
118 String dexAssetName = WebApkUtils.getRuntimeDexName(newRuntimeDexVersion ); | |
85 File remoteDexFile = | 119 File remoteDexFile = |
86 new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), "web _apk.dex"); | 120 new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), dexA ssetName); |
87 return DexLoader.load(remoteContext, "web_apk.dex", WEBAPK_SERVICE_IMPL_ CLASS_NAME, | 121 return DexLoader.load(remoteContext, dexAssetName, WEBAPK_SERVICE_IMPL_C LASS_NAME, |
88 remoteDexFile, localDexDir); | 122 remoteDexFile, localDexDir); |
89 } | 123 } |
124 | |
125 /** | |
126 * Checks if there is a new "runtime dex" version number. If there is a new version number, | |
127 * updates SharedPreferences. | |
128 * @param preferences WebAPK's SharedPreferences. | |
129 * @param remoteContext | |
130 * @return The new "runtime dex" version number. -1 if there is no new versi on number. | |
131 */ | |
132 private static int checkForNewRuntimeDexVersion( | |
133 SharedPreferences preferences, Context remoteContext) { | |
134 // The "runtime dex" version only changes when {@link remoteContext}'s A PK version code | |
135 // changes. Checking the APK's version code is less expensive than readi ng from the APK's | |
136 // assets. | |
137 PackageInfo remotePackageInfo = null; | |
138 try { | |
139 remotePackageInfo = remoteContext.getPackageManager().getPackageInfo ( | |
140 remoteContext.getPackageName(), 0); | |
141 } catch (PackageManager.NameNotFoundException e) { | |
142 Log.e(TAG, "Failed to get remote package info."); | |
143 return -1; | |
144 } | |
145 | |
146 int cachedRemoteVersionCode = preferences.getInt(REMOTE_VERSION_CODE_PRE F, -1); | |
147 if (cachedRemoteVersionCode == remotePackageInfo.versionCode) { | |
148 return -1; | |
149 } | |
150 | |
151 int runtimeDexVersion = readAssetContentsToInt(remoteContext, "web_apk_d ex_version.txt"); | |
Xi Han
2016/05/26 21:40:23
webapk_dex_version.txt.
| |
152 SharedPreferences.Editor editor = preferences.edit(); | |
153 editor.putInt(REMOTE_VERSION_CODE_PREF, remotePackageInfo.versionCode); | |
154 editor.putInt(RUNTIME_DEX_VERSION_PREF, runtimeDexVersion); | |
155 editor.apply(); | |
156 return runtimeDexVersion; | |
157 } | |
158 | |
159 /** | |
160 * Returns the first integer in an asset file's contents. | |
161 * @param context | |
162 * @param assetName The name of the asset. | |
163 * @return The first integer. | |
164 */ | |
165 private static int readAssetContentsToInt(Context context, String assetName) { | |
166 Scanner scanner = null; | |
167 int value = -1; | |
168 try { | |
169 scanner = new Scanner(context.getAssets().open(assetName)); | |
170 value = scanner.nextInt(); | |
171 scanner.close(); | |
172 } catch (Exception e) { | |
173 } finally { | |
174 if (scanner != null) { | |
175 try { | |
176 scanner.close(); | |
177 } catch (Exception e) { | |
178 } | |
179 } | |
180 } | |
181 return value; | |
182 } | |
90 } | 183 } |
OLD | NEW |