/* * Copyright 2014-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.android.support.exopackage; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import android.content.Context; import android.util.Log; /** * Loads pre-dexed jars installed by the exopackage installer into our ClassLoader. * <p> * See http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html for an * explanation of how an app can load pre-dexed libraries. This class goes a step further and then * hacks the system class loader so these can be referenced by default. This logic has to run * before any class that references the code in these dexes is loaded. */ public class ExopackageDexLoader { private static final String TAG = "ExopackageDexLoader"; private ExopackageDexLoader() {} /** * Load JARs installed by Buck's Exopackage installer and add them to * the Application ClassLoader. * * @param context The application context. */ @SuppressWarnings("PMD.CollapsibleIfStatements") public static void loadExopackageJars(Context context) { File containingDirectory = new File( "/data/local/tmp/exopackage/" + context.getPackageName() + "/secondary-dex"); List<File> dexJars = new ArrayList<>(); Set<String> expectedOdexSet = new HashSet<>(); File[] files = containingDirectory.listFiles(); if (files != null) { for (File file : files) { if (file.getName().equals("metadata.txt")) { continue; } if (!file.getName().endsWith(".dex.jar")) { Log.w(TAG, "Skipping unexpected file in exopackage directory: " + file.getName()); continue; } dexJars.add(file); expectedOdexSet.add(file.getName().replaceFirst("\\.jar$", ".dex")); } } File dexOptDir = context.getDir("exopackage_dex_opt", Context.MODE_PRIVATE); SystemClassLoaderAdder.installDexJars(context.getClassLoader(), dexOptDir, dexJars); File[] odexes = dexOptDir.listFiles(); if (odexes != null) { for (File odex : odexes) { if (!expectedOdexSet.contains(odex.getName())) { if (!odex.delete()) { Log.w(TAG, "Failed to delete stale odex: " + odex.getAbsolutePath()); } } } } } }