blob: fc38c4e5f991e8be3517c8e7b76122cce2afaa51 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* 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.android.cts.dexmetadata;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build.VERSION_CODES;
import android.util.ArrayMap;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.ApiLevelUtil;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Device-side test for verifying dex metadata installs.
*/
@RunWith(AndroidJUnit4.class)
public class InstallDexMetadataTest {
private static final String sApkFileExtension = ".apk";
private static final String sDexMetadataFileExtension = ".dm";
private static String sSplitAppPackage = "com.android.cts.dexmetadata.splitapp";
private boolean mShouldRunTest;
private String mBaseCodePath;
private String[] mSplitCodePaths;
private ArrayMap<String, String> mDexMetadataMap;
/**
* Decide if we need to run the test.
*/
@Before
public void setUp() throws Exception {
mShouldRunTest = (ApiLevelUtil.isAtLeast(VERSION_CODES.P)
|| ApiLevelUtil.codenameEquals("P"));
if (mShouldRunTest) {
ApplicationInfo info = getAppInfo(sSplitAppPackage);
mBaseCodePath = info.sourceDir;
mSplitCodePaths = info.splitSourceDirs;
mDexMetadataMap = buildPackageApkToDexMetadataMap(info);
}
Assume.assumeTrue("Skip DexMetadata tests on releases before P.", mShouldRunTest);
}
/**
* Verify that we installed the .dm files for base (no split install).
*/
@Test
public void testDmForBase() throws Exception {
assertNull(mSplitCodePaths);
assertEquals(1, mDexMetadataMap.size());
assertTrue(mDexMetadataMap.containsKey(mBaseCodePath));
}
/**
* Verify that we installed the .dm files for base and split.
*/
@Test
public void testDmForBaseAndSplit() throws Exception {
assertNotNull(mSplitCodePaths);
assertEquals(1 + mSplitCodePaths.length, mDexMetadataMap.size());
assertTrue(mDexMetadataMap.containsKey(mBaseCodePath));
for (String split : mSplitCodePaths) {
assertTrue(mDexMetadataMap.containsKey(split));
}
}
/**
* Verify that we installed the .dm files for base but not for split.
*/
@Test
public void testDmForBaseButNoSplit() throws Exception {
assertNotNull(mSplitCodePaths);
assertEquals(1, mDexMetadataMap.size());
assertTrue(mDexMetadataMap.containsKey(mBaseCodePath));
}
/**
* Verify that we installed the .dm files for split but not for base.
*/
@Test
public void testDmForSplitButNoBase() throws Exception {
assertNotNull(mSplitCodePaths);
assertEquals(mSplitCodePaths.length, mDexMetadataMap.size());
for (String split : mSplitCodePaths) {
assertTrue(mDexMetadataMap.containsKey(split));
}
}
/**
* Verify that we did not install .dm files.
*/
@Test
public void testNoDm() throws Exception {
assertTrue(mDexMetadataMap.isEmpty());
}
private ApplicationInfo getAppInfo(String pkg) {
final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
final PackageManager pm = context.getPackageManager();
android.content.pm.PackageInfo packageInfo;
try {
packageInfo = pm.getPackageInfo(pkg, 0);
return packageInfo.applicationInfo;
} catch (PackageManager.NameNotFoundException e) {
fail("NameNotFoundException");
}
return null;
}
private static String getDexMetadataFromApk(String codePath) {
return codePath.substring(0, codePath.length() - sApkFileExtension.length())
+ sDexMetadataFileExtension;
}
private static ArrayMap<String, String> buildPackageApkToDexMetadataMap(ApplicationInfo info) {
List<String> codePaths = new ArrayList<>();
codePaths.add(info.sourceDir);
if (info.splitSourceDirs != null) {
codePaths.addAll(Arrays.asList(info.splitSourceDirs));
}
ArrayMap<String, String> result = new ArrayMap<>();
for (String codePath : codePaths) {
String dexMetadataPath = getDexMetadataFromApk(codePath);
if (Files.exists(Paths.get(dexMetadataPath))) {
result.put(codePath, dexMetadataPath);
}
}
return result;
}
}