Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Side by Side Diff: webapk/shell_apk/src/org/chromium/webapk/shell_apk/DexLoader.java

Issue 1965583002: Move //webapk to //chrome/android/webapk (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.webapk.shell_apk;
6
7 import android.content.Context;
8 import android.util.Log;
9
10 import dalvik.system.BaseDexClassLoader;
11
12 import java.io.File;
13 import java.io.FileOutputStream;
14 import java.io.InputStream;
15
16 /**
17 * Creates ClassLoader for .dex file in a remote Context's APK.
18 */
19 public class DexLoader {
20 private static final int BUFFER_SIZE = 16 * 1024;
21 private static final String TAG = "cr.DexLoader";
22
23 /**
24 * Creates ClassLoader for .dex file in {@link remoteContext}'s APK.
25 * @param remoteContext The context with the APK with the .dex file.
26 * @param dexName The name of the .dex file in the APK.
27 * @param canaryClassName Name of class in the .dex file. Used for testing t he ClassLoader
28 * before returning it.
29 * @param remoteDexFile Location of already extracted .dex file from APK.
30 * @param localDexDir Writable directory for caching data to speed up future calls to
31 * {@link #load()}.
32 * @return The ClassLoader. Returns null on an error.
33 */
34 public static ClassLoader load(Context remoteContext, String dexName, String canaryClassName,
35 File remoteDexFile, File localDexDir) {
36 File localDexFile = new File(localDexDir, dexName);
37
38 // If {@link localDexFile} exists, technique #2 was previously used to c reate the
39 // ClassLoader. Skip right to the technique which worked last time.
40 if (remoteDexFile != null && remoteDexFile.exists() && !localDexFile.exi sts()) {
41 // Technique #1: At startup, Chrome code extracts the .dex file from its assets and
42 // guesses where DexClassLoader searches for the odex by default and puts the odex
43 // there. Try using the odex from Chrome's data directory.
44 ClassLoader loader = tryCreatingClassLoader(canaryClassName, remoteD exFile, null);
45 if (loader != null) {
46 return loader;
47 }
48 }
49
50 // Technique #2: Extract the .dex file from the remote context's APK. Cr eate a
51 // ClassLoader from the extracted file.
52 if (!localDexFile.exists() || localDexFile.length() == 0) {
53 localDexDir.mkdirs();
54
55 InputStream inputStream;
56 try {
57 inputStream = remoteContext.getAssets().open(dexName);
58 } catch (Exception e) {
59 Log.w(TAG, "Could not extract dex from assets");
60 e.printStackTrace();
61 return null;
62 }
63 copyFromInputStream(inputStream, localDexFile);
64 }
65
66 File localOptimizedDir = new File(localDexDir, "optimized");
67 localOptimizedDir.mkdirs();
68
69 return tryCreatingClassLoader(canaryClassName, localDexFile, localOptimi zedDir);
70 }
71
72 /**
73 * Deletes any files cached by {@link #load()}.
74 * @param localDexDir Cache directory passed to {@link #load()}.
75 */
76 public static void deleteCachedDexes(File localDexDir) {
77 deleteChildren(localDexDir);
78 }
79
80 /**
81 * Deletes all of a directory's children including subdirectories.
82 * @param parentDir Directory whose children should be deleted.
83 */
84 private static void deleteChildren(File parentDir) {
85 if (!parentDir.isDirectory()) {
86 return;
87 }
88
89 File[] files = parentDir.listFiles();
90 if (files != null) {
91 for (File file : files) {
92 deleteChildren(file);
93 if (!file.delete()) {
94 Log.e(TAG, "Could not delete " + file.getPath());
95 }
96 }
97 }
98 }
99
100 /**
101 * Copies an InputStream to a file.
102 * @param inputStream
103 * @param outFile The destination file.
104 */
105 private static void copyFromInputStream(InputStream inputStream, File outFil e) {
106 try (FileOutputStream outputStream = new FileOutputStream(outFile)) {
107 byte[] buffer = new byte[BUFFER_SIZE];
108 int count = 0;
109 while ((count = inputStream.read(buffer, 0, BUFFER_SIZE)) != -1) {
110 outputStream.write(buffer, 0, count);
111 }
112 } catch (Exception e) {
113 } finally {
114 try {
115 inputStream.close();
116 } catch (Exception e) {
117 }
118 }
119 }
120
121 /**
122 * Tries to create ClassLoader with the given .dex file and optimized dex di rectory.
123 * @param canaryClassName Name of class in the .dex file. Used for testing t he ClassLoader
124 * before returning it.
125 * @param dexFile .dex file to create ClassLoader for.
126 * @param optimizedDir Directory for storing the optimized dex file. If null , an OS-defined
127 * path based on {@link dexFile} is used.
128 * @return The ClassLoader. Returns null on an error.
129 */
130 private static ClassLoader tryCreatingClassLoader(
131 String canaryClassName, File dexFile, File optimizedDir) {
132 try {
133 ClassLoader loader = new BaseDexClassLoader(
134 dexFile.getPath(), optimizedDir, null, ClassLoader.getSystem ClassLoader());
135 // Loading {@link canaryClassName} will throw an exception if the .d ex file cannot be
136 // loaded.
137 loader.loadClass(canaryClassName);
138 return loader;
139 } catch (Exception e) {
140 String optimizedDirPath = (optimizedDir == null) ? null : optimizedD ir.getPath();
141 Log.w(TAG, "Could not load dex from " + dexFile.getPath() + " with o ptimized directory "
142 + optimizedDirPath);
143 e.printStackTrace();
144 return null;
145 }
146 }
147 }
OLDNEW
« no previous file with comments | « webapk/shell_apk/res/layout/main.xml ('k') | webapk/shell_apk/src/org/chromium/webapk/shell_apk/MainActivity.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698