From 527fa8f4de0459b807cbaf9d87167caff992267f Mon Sep 17 00:00:00 2001 From: "Torne (Richard Coles)" Date: Fri, 8 Feb 2019 15:11:02 -0500 Subject: [PATCH] Handle WebView assets correctly when multiple APKs are used. Add all splits and shared libraries used by the WebView implementation to the application's asset path, instead of just the base APK. Fix the asset manipulation code path in WebViewFactory to reuse the modern implementation in WebViewDelegate (using appendLibAssetForMainAssetPath) instead of relying on addAssetPathAsSharedLibrary. Add a new variant of appendLibAssetForMainAssetPath which accepts multiple paths at once, to make it more efficient. Bug: 124116212 Test: atest CtsWebkitTestCases Change-Id: Ie55525d78089a4595c5b0b126e4ff1530303afe8 --- core/java/android/app/ResourcesManager.java | 24 ++++++++++++------- core/java/android/webkit/WebViewDelegate.java | 24 +++++++++---------- core/java/android/webkit/WebViewFactory.java | 3 +-- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 2d9fbf9743974..35658fbcb989e 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -1091,6 +1091,16 @@ public class ResourcesManager { */ @UnsupportedAppUsage public void appendLibAssetForMainAssetPath(String assetPath, String libAsset) { + appendLibAssetsForMainAssetPath(assetPath, new String[] { libAsset }); + } + + /** + * Appends the library asset paths to any ResourcesImpl object that contains the main + * assetPath. + * @param assetPath The main asset path for which to add the library asset path. + * @param libAssets The library asset paths to add. + */ + public void appendLibAssetsForMainAssetPath(String assetPath, String[] libAssets) { synchronized (this) { // Record which ResourcesImpl need updating // (and what ResourcesKey they should update to). @@ -1102,15 +1112,13 @@ public class ResourcesManager { final WeakReference weakImplRef = mResourceImpls.valueAt(i); final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null; if (impl != null && Objects.equals(key.mResDir, assetPath)) { - if (!ArrayUtils.contains(key.mLibDirs, libAsset)) { - final int newLibAssetCount = 1 + - (key.mLibDirs != null ? key.mLibDirs.length : 0); - final String[] newLibAssets = new String[newLibAssetCount]; - if (key.mLibDirs != null) { - System.arraycopy(key.mLibDirs, 0, newLibAssets, 0, key.mLibDirs.length); - } - newLibAssets[newLibAssetCount - 1] = libAsset; + String[] newLibAssets = key.mLibDirs; + for (String libAsset : libAssets) { + newLibAssets = + ArrayUtils.appendElement(String.class, newLibAssets, libAsset); + } + if (newLibAssets != key.mLibDirs) { updatedResourceKeys.put(impl, new ResourcesKey( key.mResDir, key.mSplitResDirs, diff --git a/core/java/android/webkit/WebViewDelegate.java b/core/java/android/webkit/WebViewDelegate.java index 3d3d941984480..f5657dff538fc 100644 --- a/core/java/android/webkit/WebViewDelegate.java +++ b/core/java/android/webkit/WebViewDelegate.java @@ -209,19 +209,17 @@ public final class WebViewDelegate { * Adds the WebView asset path to {@link android.content.res.AssetManager}. */ public void addWebViewAssetPath(Context context) { - final String newAssetPath = WebViewFactory.getLoadedPackageInfo().applicationInfo.sourceDir; - + final String[] newAssetPaths = + WebViewFactory.getLoadedPackageInfo().applicationInfo.getAllApkPaths(); final ApplicationInfo appInfo = context.getApplicationInfo(); - final String[] libs = appInfo.sharedLibraryFiles; - if (!ArrayUtils.contains(libs, newAssetPath)) { - // Build the new library asset path list. - final int newLibAssetsCount = 1 + (libs != null ? libs.length : 0); - final String[] newLibAssets = new String[newLibAssetsCount]; - if (libs != null) { - System.arraycopy(libs, 0, newLibAssets, 0, libs.length); - } - newLibAssets[newLibAssetsCount - 1] = newAssetPath; + // Build the new library asset path list. + String[] newLibAssets = appInfo.sharedLibraryFiles; + for (String newAssetPath : newAssetPaths) { + newLibAssets = ArrayUtils.appendElement(String.class, newLibAssets, newAssetPath); + } + + if (newLibAssets != appInfo.sharedLibraryFiles) { // Update the ApplicationInfo object with the new list. // We know this will persist and future Resources created via ResourcesManager // will include the shared library because this ApplicationInfo comes from the @@ -230,8 +228,8 @@ public final class WebViewDelegate { appInfo.sharedLibraryFiles = newLibAssets; // Update existing Resources with the WebView library. - ResourcesManager.getInstance().appendLibAssetForMainAssetPath( - appInfo.getBaseResourcePath(), newAssetPath); + ResourcesManager.getInstance().appendLibAssetsForMainAssetPath( + appInfo.getBaseResourcePath(), newAssetPaths); } } diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 6d88530f29d91..528a6a84c6303 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -448,8 +448,7 @@ public final class WebViewFactory { Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()"); try { - initialApplication.getAssets().addAssetPathAsSharedLibrary( - webViewContext.getApplicationInfo().sourceDir); + new WebViewDelegate().addWebViewAssetPath(initialApplication); ClassLoader clazzLoader = webViewContext.getClassLoader(); Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");