未验证 提交 d48de7a3 编写于 作者: S Stanislav Baranov 提交者: GitHub

Support for binary decompression of dynamic patches. (#7777)

上级 713fe130
...@@ -42,7 +42,7 @@ fi ...@@ -42,7 +42,7 @@ fi
echo "Checking license count in licenses_flutter..." echo "Checking license count in licenses_flutter..."
actualLicenseCount=`tail -n 1 flutter/ci/licenses_golden/licenses_flutter | tr -dc '0-9'` actualLicenseCount=`tail -n 1 flutter/ci/licenses_golden/licenses_flutter | tr -dc '0-9'`
expectedLicenseCount=2 # When changing this number: Update the error message below as well describing all expected license types. expectedLicenseCount=3 # When changing this number: Update the error message below as well describing all expected license types.
if [ "$actualLicenseCount" -ne "$expectedLicenseCount" ] if [ "$actualLicenseCount" -ne "$expectedLicenseCount" ]
then then
......
...@@ -691,6 +691,40 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ...@@ -691,6 +691,40 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
==================================================================================================== ====================================================================================================
====================================================================================================
LIBRARY: engine
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/util/BSDiff.java + ../../../flutter/LICENSE
TYPE: LicenseType.bsd
FILE: ../../../flutter/shell/platform/android/io/flutter/util/BSDiff.java
----------------------------------------------------------------------------------------------------
Copyright 2003-2005 Colin Percival. All rights reserved.
Copyright 2013 The Flutter Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
====================================================================================================
==================================================================================================== ====================================================================================================
LIBRARY: txt LIBRARY: txt
ORIGIN: ../../../flutter/third_party/txt/LICENSE ORIGIN: ../../../flutter/third_party/txt/LICENSE
...@@ -977,4 +1011,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ...@@ -977,4 +1011,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
==================================================================================================== ====================================================================================================
Total license count: 2 Total license count: 3
...@@ -149,6 +149,7 @@ java_library("flutter_shell_java") { ...@@ -149,6 +149,7 @@ java_library("flutter_shell_java") {
"io/flutter/plugin/platform/PlatformViewsController.java", "io/flutter/plugin/platform/PlatformViewsController.java",
"io/flutter/plugin/platform/SingleViewPresentation.java", "io/flutter/plugin/platform/SingleViewPresentation.java",
"io/flutter/plugin/platform/VirtualDisplayController.java", "io/flutter/plugin/platform/VirtualDisplayController.java",
"io/flutter/util/BSDiff.java",
"io/flutter/util/PathUtils.java", "io/flutter/util/PathUtils.java",
"io/flutter/util/Preconditions.java", "io/flutter/util/Preconditions.java",
"io/flutter/util/Predicate.java", "io/flutter/util/Predicate.java",
......
// Copyright 2003-2005 Colin Percival. All rights reserved.
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.util;
import java.io.*;
import java.util.zip.GZIPInputStream;
/**
* This is a Java port of algorithm from Flutter framework bsdiff.dart.
* Note that this port uses 32-bit ints, which limits data size to 2GB.
**/
public abstract class BSDiff {
public static byte[] bspatch(byte[] olddata, byte[] diffdata) throws IOException {
InputStream in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
DataInputStream header = new DataInputStream(in);
byte[] magic = new byte[8];
header.read(magic);
if (!new String(magic).equals("BZDIFF40")) {
throw new IOException("Invalid magic");
}
int ctrllen = (int) header.readLong();
int datalen = (int) header.readLong();
int newsize = (int) header.readLong();
header.close();
in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
in.skip(32);
DataInputStream cpf = new DataInputStream(new GZIPInputStream(in));
in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
in.skip(32 + ctrllen);
InputStream dpf = new GZIPInputStream(in);
in = new ByteArrayInputStream(diffdata, 0, diffdata.length);
in.skip(32 + ctrllen + datalen);
InputStream epf = new GZIPInputStream(in);
byte[] newdata = new byte[newsize];
int oldpos = 0;
int newpos = 0;
while (newpos < newsize) {
int[] ctrl = new int[3];
for (int i = 0; i <= 2; i++) {
ctrl[i] = (int) cpf.readLong();
}
if (newpos + ctrl[0] > newsize) {
throw new IOException("Invalid ctrl[0]");
}
read(dpf, newdata, newpos, ctrl[0]);
for (int i = 0; i < ctrl[0]; i++) {
if ((oldpos + i >= 0) && (oldpos + i < olddata.length)) {
newdata[newpos + i] += olddata[oldpos + i];
}
}
newpos += ctrl[0];
oldpos += ctrl[0];
if (newpos + ctrl[1] > newsize) {
throw new IOException("Invalid ctrl[0]");
}
read(epf, newdata, newpos, ctrl[1]);
newpos += ctrl[1];
oldpos += ctrl[2];
}
cpf.close();
dpf.close();
epf.close();
return newdata;
}
private static void read(InputStream in, byte[] buf, int off, int len) throws IOException {
for (int i, n = 0; n < len; n += i) {
if ((i = in.read(buf, off + n, len - n)) < 0) {
throw new IOException("Unexpected EOF");
}
}
}
}
...@@ -11,6 +11,7 @@ import android.content.res.AssetManager; ...@@ -11,6 +11,7 @@ import android.content.res.AssetManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
import io.flutter.util.BSDiff;
import io.flutter.util.PathUtils; import io.flutter.util.PathUtils;
import org.json.JSONObject; import org.json.JSONObject;
...@@ -19,6 +20,7 @@ import java.util.Collection; ...@@ -19,6 +20,7 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
...@@ -29,8 +31,6 @@ class ResourceExtractor { ...@@ -29,8 +31,6 @@ class ResourceExtractor {
private static final String TAG = "ResourceExtractor"; private static final String TAG = "ResourceExtractor";
private static final String TIMESTAMP_PREFIX = "res_timestamp-"; private static final String TIMESTAMP_PREFIX = "res_timestamp-";
private static final int BUFFER_SIZE = 16 * 1024;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
static long getVersionCode(PackageInfo packageInfo) { static long getVersionCode(PackageInfo packageInfo) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
...@@ -177,7 +177,6 @@ class ResourceExtractor { ...@@ -177,7 +177,6 @@ class ResourceExtractor {
private boolean extractAPK(File dataDir) { private boolean extractAPK(File dataDir) {
final AssetManager manager = mContext.getResources().getAssets(); final AssetManager manager = mContext.getResources().getAssets();
byte[] buffer = null;
for (String asset : mResources) { for (String asset : mResources) {
try { try {
final File output = new File(dataDir, asset); final File output = new File(dataDir, asset);
...@@ -190,19 +189,11 @@ class ResourceExtractor { ...@@ -190,19 +189,11 @@ class ResourceExtractor {
try (InputStream is = manager.open(asset); try (InputStream is = manager.open(asset);
OutputStream os = new FileOutputStream(output)) { OutputStream os = new FileOutputStream(output)) {
if (buffer == null) { copy(is, os);
buffer = new byte[BUFFER_SIZE];
}
int count = 0;
while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) {
os.write(buffer, 0, count);
}
os.flush();
Log.i(TAG, "Extracted baseline resource " + asset);
} }
Log.i(TAG, "Extracted baseline resource " + asset);
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
continue; continue;
...@@ -219,6 +210,8 @@ class ResourceExtractor { ...@@ -219,6 +210,8 @@ class ResourceExtractor {
/// Returns true if successfully unpacked update resources or if there is no update, /// Returns true if successfully unpacked update resources or if there is no update,
/// otherwise deletes all resources and returns false. /// otherwise deletes all resources and returns false.
private boolean extractUpdate(File dataDir) { private boolean extractUpdate(File dataDir) {
final AssetManager manager = mContext.getResources().getAssets();
ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater(); ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater();
if (resourceUpdater == null) { if (resourceUpdater == null) {
return true; return true;
...@@ -245,11 +238,15 @@ class ResourceExtractor { ...@@ -245,11 +238,15 @@ class ResourceExtractor {
return false; return false;
} }
byte[] buffer = null;
for (String asset : mResources) { for (String asset : mResources) {
boolean useDiff = false;
ZipEntry entry = zipFile.getEntry(asset); ZipEntry entry = zipFile.getEntry(asset);
if (entry == null) { if (entry == null) {
continue; useDiff = true;
entry = zipFile.getEntry(asset + ".bzdiff40");
if (entry == null) {
continue;
}
} }
final File output = new File(dataDir, asset); final File output = new File(dataDir, asset);
...@@ -260,18 +257,29 @@ class ResourceExtractor { ...@@ -260,18 +257,29 @@ class ResourceExtractor {
output.getParentFile().mkdirs(); output.getParentFile().mkdirs();
} }
try (InputStream is = zipFile.getInputStream(entry); try {
OutputStream os = new FileOutputStream(output)) { if (useDiff) {
if (buffer == null) { ByteArrayOutputStream diff = new ByteArrayOutputStream();
buffer = new byte[BUFFER_SIZE]; try (InputStream is = zipFile.getInputStream(entry)) {
} copy(is, diff);
}
ByteArrayOutputStream orig = new ByteArrayOutputStream();
try (InputStream is = manager.open(asset)) {
copy(is, orig);
}
try (OutputStream os = new FileOutputStream(output)) {
os.write(BSDiff.bspatch(orig.toByteArray(), diff.toByteArray()));
}
int count = 0; } else {
while ((count = is.read(buffer, 0, BUFFER_SIZE)) != -1) { try (InputStream is = zipFile.getInputStream(entry);
os.write(buffer, 0, count); OutputStream os = new FileOutputStream(output)) {
copy(is, os);
}
} }
os.flush();
Log.i(TAG, "Extracted override resource " + asset); Log.i(TAG, "Extracted override resource " + asset);
} catch (FileNotFoundException fnfe) { } catch (FileNotFoundException fnfe) {
...@@ -339,4 +347,11 @@ class ResourceExtractor { ...@@ -339,4 +347,11 @@ class ResourceExtractor {
return null; return null;
} }
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[16 * 1024];
for (int i; (i = in.read(buf)) >= 0; ) {
out.write(buf, 0, i);
}
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册