| Index: chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java
|
| diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java
|
| index d977edbab65e3f1f13d11a26ef47fe2b94dd8f4a..61a43c40ddfba1e91879d261622fc77817cfc16b 100644
|
| --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java
|
| +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java
|
| @@ -7,6 +7,9 @@ package org.chromium.webapk.shell_apk;
|
| import android.app.Service;
|
| import android.content.Context;
|
| import android.content.Intent;
|
| +import android.content.SharedPreferences;
|
| +import android.content.pm.PackageInfo;
|
| +import android.content.pm.PackageManager;
|
| import android.os.Bundle;
|
| import android.os.IBinder;
|
| import android.util.Log;
|
| @@ -15,6 +18,7 @@ import org.chromium.webapk.lib.common.WebApkUtils;
|
|
|
| import java.io.File;
|
| import java.lang.reflect.Constructor;
|
| +import java.util.Scanner;
|
|
|
| /**
|
| * Shell class for services provided by WebAPK to Chrome. Extracts code with implementation of
|
| @@ -29,6 +33,23 @@ public class WebApkServiceFactory extends Service {
|
| private static final String WEBAPK_SERVICE_IMPL_CLASS_NAME =
|
| "org.chromium.webapk.lib.runtime_library.WebApkServiceImpl";
|
|
|
| + /**
|
| + * Name of the shared preferences file.
|
| + */
|
| + private static final String PREF_PACKAGE = "org.chromium.webapk.shell_apk";
|
| +
|
| + /**
|
| + * Name of the shared preference for Chrome's version code.
|
| + */
|
| + private static final String REMOTE_VERSION_CODE_PREF =
|
| + "org.chromium.webapk.shell_apk.version_code";
|
| +
|
| + /**
|
| + * Name of the shared preference for the version number of the dynamically loaded dex.
|
| + */
|
| + private static final String RUNTIME_DEX_VERSION_PREF =
|
| + "org.chromium.webapk.shell_apk.dex_version";
|
| +
|
| private static final String KEY_SMALL_ICON_ID = "small_icon_id";
|
|
|
| /*
|
| @@ -62,7 +83,7 @@ public class WebApkServiceFactory extends Service {
|
| }
|
|
|
| /**
|
| - * Gets / creates ClassLaoder for loading {@link WEBAPK_SERVICE_IMPL_CLASS_NAME}.
|
| + * Gets / creates ClassLoader for loading {@link WEBAPK_SERVICE_IMPL_CLASS_NAME}.
|
| * @param context WebAPK's context.
|
| * @return The ClassLoader.
|
| */
|
| @@ -85,10 +106,82 @@ public class WebApkServiceFactory extends Service {
|
| return null;
|
| }
|
|
|
| + SharedPreferences preferences = context.getSharedPreferences(PREF_PACKAGE, MODE_PRIVATE);
|
| +
|
| + int runtimeDexVersion = preferences.getInt(RUNTIME_DEX_VERSION_PREF, -1);
|
| + int newRuntimeDexVersion = checkForNewRuntimeDexVersion(preferences, remoteContext);
|
| + if (newRuntimeDexVersion == -1) {
|
| + newRuntimeDexVersion = runtimeDexVersion;
|
| + }
|
| File localDexDir = context.getDir("dex", Context.MODE_PRIVATE);
|
| + if (newRuntimeDexVersion != runtimeDexVersion) {
|
| + Log.w(TAG, "Delete cached dex files.");
|
| + DexLoader.deleteCachedDexes(localDexDir);
|
| + }
|
| +
|
| + String dexAssetName = WebApkUtils.getRuntimeDexName(newRuntimeDexVersion);
|
| File remoteDexFile =
|
| - new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), "web_apk.dex");
|
| - return DexLoader.load(remoteContext, "web_apk.dex", WEBAPK_SERVICE_IMPL_CLASS_NAME,
|
| + new File(remoteContext.getDir("dex", Context.MODE_PRIVATE), dexAssetName);
|
| + return DexLoader.load(remoteContext, dexAssetName, WEBAPK_SERVICE_IMPL_CLASS_NAME,
|
| remoteDexFile, localDexDir);
|
| }
|
| +
|
| + /**
|
| + * Checks if there is a new "runtime dex" version number. If there is a new version number,
|
| + * updates SharedPreferences.
|
| + * @param preferences WebAPK's SharedPreferences.
|
| + * @param remoteContext
|
| + * @return The new "runtime dex" version number. -1 if there is no new version number.
|
| + */
|
| + private static int checkForNewRuntimeDexVersion(
|
| + SharedPreferences preferences, Context remoteContext) {
|
| + // The "runtime dex" version only changes when {@link remoteContext}'s APK version code
|
| + // changes. Checking the APK's version code is less expensive than reading from the APK's
|
| + // assets.
|
| + PackageInfo remotePackageInfo = null;
|
| + try {
|
| + remotePackageInfo = remoteContext.getPackageManager().getPackageInfo(
|
| + remoteContext.getPackageName(), 0);
|
| + } catch (PackageManager.NameNotFoundException e) {
|
| + Log.e(TAG, "Failed to get remote package info.");
|
| + return -1;
|
| + }
|
| +
|
| + int cachedRemoteVersionCode = preferences.getInt(REMOTE_VERSION_CODE_PREF, -1);
|
| + if (cachedRemoteVersionCode == remotePackageInfo.versionCode) {
|
| + return -1;
|
| + }
|
| +
|
| + int runtimeDexVersion = readAssetContentsToInt(remoteContext, "webapk_dex_version.txt");
|
| + SharedPreferences.Editor editor = preferences.edit();
|
| + editor.putInt(REMOTE_VERSION_CODE_PREF, remotePackageInfo.versionCode);
|
| + editor.putInt(RUNTIME_DEX_VERSION_PREF, runtimeDexVersion);
|
| + editor.apply();
|
| + return runtimeDexVersion;
|
| + }
|
| +
|
| + /**
|
| + * Returns the first integer in an asset file's contents.
|
| + * @param context
|
| + * @param assetName The name of the asset.
|
| + * @return The first integer.
|
| + */
|
| + private static int readAssetContentsToInt(Context context, String assetName) {
|
| + Scanner scanner = null;
|
| + int value = -1;
|
| + try {
|
| + scanner = new Scanner(context.getAssets().open(assetName));
|
| + value = scanner.nextInt();
|
| + scanner.close();
|
| + } catch (Exception e) {
|
| + } finally {
|
| + if (scanner != null) {
|
| + try {
|
| + scanner.close();
|
| + } catch (Exception e) {
|
| + }
|
| + }
|
| + }
|
| + return value;
|
| + }
|
| }
|
|
|