From 077b1ebf23a8a7d415e52ed3dc06cb8f05ab3f7e Mon Sep 17 00:00:00 2001 From: Stanislav Baranov Date: Wed, 9 Jan 2019 14:21:36 -0800 Subject: [PATCH] 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. --- .../flutter/app/FlutterActivityDelegate.java | 6 ++- .../android/io/flutter/view/FlutterMain.java | 9 ++++- .../io/flutter/view/ResourceExtractor.java | 31 ++++++---------- .../io/flutter/view/ResourceUpdater.java | 37 +++++++++---------- 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/engine/src/flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/engine/src/flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 2a4c924c50d..429f43ad8ae 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -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 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]); diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java b/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java index 16d1c0ec3e2..9b0edbeed0b 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/FlutterMain.java @@ -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; } /** diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceExtractor.java b/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceExtractor.java index c28749b9e92..cfcae096678 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceExtractor.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceExtractor.java @@ -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; } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceUpdater.java b/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceUpdater.java index 203ae18d052..5fef38f66f1 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceUpdater.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/ResourceUpdater.java @@ -58,12 +58,12 @@ public final class ResourceUpdater { IMMEDIATE } - private static class DownloadTask extends AsyncTask { + private class DownloadTask extends AsyncTask { @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;