• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.tradefed.util;
17 
18 import com.android.tradefed.build.IBuildInfo;
19 import com.android.tradefed.build.IDeviceBuildInfo;
20 import com.android.tradefed.targetprep.AltDirBehavior;
21 
22 import java.io.File;
23 import java.io.IOException;
24 import java.net.URL;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
28 
29 /**
30  * A helper class for operations related to tests zip generated by Android build system
31  */
32 public class BuildTestsZipUtils {
33 
34     /**
35      * Resolve the actual apk path based on testing artifact information inside build info.
36      *
37      * @param buildInfo build artifact information
38      * @param apkFileName filename of the apk to install
39      * @param altDirs alternative search paths, in addition to path inside {@code buildInfo}
40      * @param altDirBehavior how alternative search paths should be used against path inside
41      *        {@code buildInfo}: as fallback, or as override; if unspecified, fallback will be used
42      * @param lookupInResource if the file should be looked up in test harness resources as a final
43      *        fallback mechanism
44      * @param deviceSigningKey
45      * @return a {@link File} representing the physical apk file on host or {@code null} if the
46      *     file does not exist.
47      */
getApkFile(IBuildInfo buildInfo, String apkFileName, List<File> altDirs, AltDirBehavior altDirBehavior, boolean lookupInResource, String deviceSigningKey)48     public static File getApkFile(IBuildInfo buildInfo, String apkFileName,
49             List<File> altDirs, AltDirBehavior altDirBehavior,
50             boolean lookupInResource, String deviceSigningKey) throws IOException {
51         String apkBase = apkFileName.split("\\.")[0];
52 
53         List<File> dirs = new ArrayList<>();
54         if (altDirs != null) {
55             for (File dir : altDirs) {
56                 dirs.add(dir);
57                 // Files in tests zip file will be in DATA/app/,
58                 // DATA/app/apk_name or DATA/priv-app/apk_name
59                 dirs.add(FileUtil.getFileForPath(dir, "DATA", "app"));
60                 dirs.add(FileUtil.getFileForPath(dir, "DATA", "app", apkBase));
61                 dirs.add(FileUtil.getFileForPath(dir, "DATA", "priv-app", apkBase));
62                 // Files in out dir will be in data/app/apk_name
63                 dirs.add(FileUtil.getFileForPath(dir, "data", "app", apkBase));
64             }
65         }
66         // reverse the order so ones provided via command line last can be searched first
67         Collections.reverse(dirs);
68 
69         List<File> expandedTestDirs = new ArrayList<>();
70         if (buildInfo != null && buildInfo instanceof IDeviceBuildInfo) {
71             File testsDir = ((IDeviceBuildInfo) buildInfo).getTestsDir();
72             if (testsDir != null && testsDir.exists()) {
73                 expandedTestDirs.add(FileUtil.getFileForPath(testsDir, "DATA", "app"));
74                 expandedTestDirs.add(FileUtil.getFileForPath(testsDir, "DATA", "app", apkBase));
75                 expandedTestDirs.add(
76                         FileUtil.getFileForPath(testsDir, "DATA", "priv-app", apkBase));
77                 expandedTestDirs.add(FileUtil.getFileForPath(testsDir, apkBase));
78 
79                 // Files in testcases directory imported from env. variable can have a folder
80                 // hierarchy, so we search for folder.
81                 File testcasesSubDir = FileUtil.findFile(testsDir, apkBase);
82                 if (testcasesSubDir != null) {
83                     expandedTestDirs.add(testcasesSubDir);
84                 }
85             }
86         }
87         if (altDirBehavior == null) {
88             altDirBehavior = AltDirBehavior.FALLBACK;
89         }
90         if (altDirBehavior == AltDirBehavior.FALLBACK) {
91             // alt dirs are appended after build artifact dirs
92             expandedTestDirs.addAll(dirs);
93             dirs = expandedTestDirs;
94         } else if (altDirBehavior == AltDirBehavior.OVERRIDE) {
95             dirs.addAll(expandedTestDirs);
96         } else {
97             throw new IOException("Missing handler for alt-dir-behavior: " + altDirBehavior);
98         }
99         if (dirs.isEmpty() && !lookupInResource) {
100             throw new IOException(
101                     "Provided buildInfo does not contain a valid tests directory and no " +
102                     "fallback options were provided");
103         }
104 
105         for (File dir : dirs) {
106             // Recursively search each folder
107             File testAppFile = FileUtil.findFile(dir, apkFileName);
108             if (testAppFile != null && testAppFile.exists()) {
109                 return testAppFile;
110             }
111         }
112         if (lookupInResource) {
113             List<String> resourceLookup = new ArrayList<>();
114             if (deviceSigningKey != null) {
115                 resourceLookup.add(String.format("/apks/%s-%s.apk", apkBase, deviceSigningKey));
116             }
117             resourceLookup.add(String.format("/apks/%s", apkFileName));
118             File apkTempFile = FileUtil.createTempFile(apkFileName, ".apk");
119             URL apkUrl = null;
120             for (String path :  resourceLookup) {
121                 apkUrl = BuildTestsZipUtils.class.getResource(path);
122                 if (apkUrl != null) {
123                     break;
124                 }
125             }
126             if (apkUrl != null) {
127                 FileUtil.writeToFile(apkUrl.openStream(), apkTempFile);
128                 // since we don't know when the file would be no longer needed, we set the file to
129                 // be deleted on VM termination
130                 apkTempFile.deleteOnExit();
131                 return apkTempFile;
132             }
133             // If we couldn't find a resource, we delete the tmp file
134             FileUtil.deleteFile(apkTempFile);
135         }
136         return null;
137     }
138 }
139