Refactor dynamic patching to use clearer naming and structure. (flutter/engine#7426)

This is a no-op change, except for fixing a bug where download task
reference wasn't cleared after download was completed.

This change also removes call to output stream flush(), which is not
necessary according to Java spec.

The rest of the change deals with requiring the code to work directly
with ResourceUpdater object instead of having FlutterMain be a facade
that forwards some of ResourceUpdater's methods. This simplifies the
other (more essential) upcoming changes that will be landing in the
followings few PRs.
This commit is contained in:
Stanislav Baranov 2019-01-09 14:21:36 -08:00 committed by GitHub
parent 1bdc80b8d6
commit 077b1ebf23
4 changed files with 41 additions and 42 deletions

View File

@ -33,6 +33,7 @@ import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterRunArguments;
import io.flutter.view.FlutterView;
import java.io.File;
import java.util.ArrayList;
/**
@ -343,8 +344,9 @@ public final class FlutterActivityDelegate
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
ArrayList<String> bundlePaths = new ArrayList<>();
if (FlutterMain.getUpdateInstallationPath() != null) {
bundlePaths.add(FlutterMain.getUpdateInstallationPath());
if (FlutterMain.getResourceUpdater() != null) {
File patchFile = FlutterMain.getResourceUpdater().getPatch();
bundlePaths.add(patchFile.getPath());
}
bundlePaths.add(appBundlePath);
args.bundlePaths = bundlePaths.toArray(new String[0]);

View File

@ -360,8 +360,13 @@ public class FlutterMain {
return appBundle.exists() ? appBundle.getPath() : null;
}
public static String getUpdateInstallationPath() {
return sResourceUpdater == null ? null : sResourceUpdater.getUpdateInstallationPath();
/**
* Returns the main internal interface for the dynamic patching subsystem.
*
* If this is null, it means that dynamic patching is disabled in this app.
*/
public static ResourceUpdater getResourceUpdater() {
return sResourceUpdater;
}
/**

View File

@ -123,17 +123,6 @@ class ResourceExtractor {
}
}
boolean filesMatch() {
JSONObject updateManifest = readUpdateManifest();
if (!validateUpdateManifest(updateManifest)) {
updateManifest = null;
}
final File dataDir = new File(PathUtils.getDataDirectory(mContext));
final String timestamp = checkTimestamp(dataDir, updateManifest);
return (timestamp == null);
}
private String[] getExistingTimestamps(File dataDir) {
return dataDir.list(new FilenameFilter() {
@Override
@ -160,7 +149,6 @@ class ResourceExtractor {
}
}
/// Returns true if successfully unpacked APK resources,
/// otherwise deletes all resources and returns false.
private boolean extractAPK(File dataDir) {
@ -208,11 +196,12 @@ class ResourceExtractor {
/// Returns true if successfully unpacked update resources or if there is no update,
/// otherwise deletes all resources and returns false.
private boolean extractUpdate(File dataDir) {
if (FlutterMain.getUpdateInstallationPath() == null) {
ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater();
if (resourceUpdater == null) {
return true;
}
final File updateFile = new File(FlutterMain.getUpdateInstallationPath());
File updateFile = resourceUpdater.getPatch();
if (!updateFile.exists()) {
return true;
}
@ -298,11 +287,14 @@ class ResourceExtractor {
if (!buildNumber.equals(Long.toString(getVersionCode(packageInfo)))) {
Log.w(TAG, "Outdated update file for " + getVersionCode(packageInfo));
} else {
final File updateFile = new File(FlutterMain.getUpdateInstallationPath());
ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater();
assert resourceUpdater != null;
File patchFile = resourceUpdater.getPatch();
assert patchFile.exists();
if (patchNumber != null) {
expectedTimestamp += "-" + patchNumber + "-" + updateFile.lastModified();
expectedTimestamp += "-" + patchNumber + "-" + patchFile.lastModified();
} else {
expectedTimestamp += "-" + updateFile.lastModified();
expectedTimestamp += "-" + patchFile.lastModified();
}
}
}
@ -365,11 +357,12 @@ class ResourceExtractor {
/// Returns null if no update manifest is found.
private JSONObject readUpdateManifest() {
if (FlutterMain.getUpdateInstallationPath() == null) {
ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater();
if (resourceUpdater == null) {
return null;
}
File updateFile = new File(FlutterMain.getUpdateInstallationPath());
File updateFile = resourceUpdater.getPatch();
if (!updateFile.exists()) {
return null;
}

View File

@ -58,12 +58,12 @@ public final class ResourceUpdater {
IMMEDIATE
}
private static class DownloadTask extends AsyncTask<String, String, Void> {
private class DownloadTask extends AsyncTask<String, String, Void> {
@Override
protected Void doInBackground(String... args) {
protected Void doInBackground(String... unused) {
try {
URL unresolvedURL = new URL(args[0]);
File localFile = new File(args[1]);
URL unresolvedURL = new URL(buildUpdateDownloadURL());
File localFile = getPatch();
long startMillis = new Date().getTime();
Log.i(TAG, "Checking for updates at " + unresolvedURL);
@ -71,10 +71,10 @@ public final class ResourceUpdater {
HttpURLConnection connection =
(HttpURLConnection)unresolvedURL.openConnection();
long lastModified = localFile.lastModified();
if (lastModified != 0) {
Log.i(TAG, "Active update timestamp " + lastModified);
connection.setIfModifiedSince(lastModified);
long lastDownloadTime = localFile.lastModified();
if (lastDownloadTime != 0) {
Log.i(TAG, "Active update timestamp " + lastDownloadTime);
connection.setIfModifiedSince(lastDownloadTime);
}
try (InputStream input = connection.getInputStream()) {
@ -108,7 +108,6 @@ public final class ResourceUpdater {
long totalMillis = new Date().getTime() - startMillis;
Log.i(TAG, "Update downloaded in " + totalMillis / 100 / 10. + "s");
output.flush();
return null;
}
}
@ -127,7 +126,7 @@ public final class ResourceUpdater {
this.context = context;
}
public String getAPKVersion() {
private String getAPKVersion() {
try {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
@ -138,11 +137,11 @@ public final class ResourceUpdater {
}
}
public String getUpdateInstallationPath() {
return context.getFilesDir().toString() + "/patch.zip";
public File getPatch() {
return new File(context.getFilesDir().toString() + "/patch.zip");
}
public String buildUpdateDownloadURL() {
private String buildUpdateDownloadURL() {
Bundle metaData;
try {
metaData = context.getPackageManager().getApplicationInfo(
@ -168,7 +167,7 @@ public final class ResourceUpdater {
return uri.normalize().toString();
}
public DownloadMode getDownloadMode() {
DownloadMode getDownloadMode() {
Bundle metaData;
try {
metaData = context.getPackageManager().getApplicationInfo(
@ -195,7 +194,7 @@ public final class ResourceUpdater {
}
}
public InstallMode getInstallMode() {
InstallMode getInstallMode() {
Bundle metaData;
try {
metaData = context.getPackageManager().getApplicationInfo(
@ -222,21 +221,21 @@ public final class ResourceUpdater {
}
}
public void startUpdateDownloadOnce() {
void startUpdateDownloadOnce() {
if (downloadTask != null ) {
return;
}
downloadTask = new DownloadTask();
downloadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
buildUpdateDownloadURL(), getUpdateInstallationPath());
downloadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void waitForDownloadCompletion() {
void waitForDownloadCompletion() {
if (downloadTask == null) {
return;
}
try {
downloadTask.get();
downloadTask = null;
} catch (CancellationException e) {
Log.w(TAG, "Download cancelled: " + e.getMessage());
return;