1 /*
2  * Copyright (C) 2018 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 
17 package com.android.cts.releaseparser;
18 
19 import com.android.cts.releaseparser.ReleaseProto.*;
20 
21 import java.io.File;
22 import java.util.logging.Level;
23 import java.util.logging.Logger;
24 
25 public class ApkParser extends ZipParser {
26     private ApiPackage mExternalApiPackage;
27     private ApiPackage mInternalApiPackage;
28     private AppInfo.Builder mAppInfoBuilder;
29 
ApkParser(File file)30     public ApkParser(File file) {
31         super(file);
32     }
33 
34     @Override
getType()35     public Entry.EntryType getType() {
36         return Entry.EntryType.APK;
37     }
38 
39     @Override
setAdditionalInfo()40     public void setAdditionalInfo() {
41         getFileEntryBuilder().setAppInfo(getAppInfo());
42     }
43 
getExternalApiPackage()44     public ApiPackage getExternalApiPackage() {
45         if (mExternalApiPackage == null) {
46             prase();
47         }
48         return mExternalApiPackage;
49     }
50 
51     // Todo
getTestCaseApiPackage()52     public ApiPackage getTestCaseApiPackage() {
53         if (mInternalApiPackage == null) {
54             prase();
55         }
56         return mInternalApiPackage;
57     }
58 
getAppInfo()59     public AppInfo getAppInfo() {
60         if (mAppInfoBuilder == null) {
61             prase();
62         }
63         return mAppInfoBuilder.build();
64     }
65 
prase()66     private void prase() {
67         // todo parse dependencies
68         processManifest();
69         processDex();
70         processZip();
71         getLogger().log(Level.WARNING, "ToDo,parse dependencies," + getFileName());
72     }
73 
processManifest()74     private void processManifest() {
75         AndroidManifestParser manifestParser = new AndroidManifestParser(getFile());
76         mAppInfoBuilder = manifestParser.getAppInfoBuilder();
77     }
78 
processDex()79     private void processDex() {
80         DexParser dexParser = new DexParser(getFile());
81         dexParser.setPackageName(mAppInfoBuilder.getPackageName());
82         mExternalApiPackage = dexParser.getExternalApiPackage();
83         mAppInfoBuilder.addExternalApiPackages(mExternalApiPackage);
84         mInternalApiPackage = dexParser.getInternalApiPackage();
85         mAppInfoBuilder.addInternalApiPackages(mInternalApiPackage);
86     }
87 
processZip()88     private void processZip() {
89         mAppInfoBuilder.setPackageFileContent(getPackageFileContent());
90     }
91 
92     private static final String USAGE_MESSAGE =
93             "Usage: java -jar releaseparser.jar "
94                     + ApkParser.class.getCanonicalName()
95                     + " [-options <parameter>]...\n"
96                     + "           to prase APK file meta data\n"
97                     + "Options:\n"
98                     + "\t-i PATH\t The file path of the file to be parsed.\n"
99                     + "\t-of PATH\t The file path of the output file instead of printing to System.out.\n"
100                     + "\t-pi \t Parses internal methods and fields too. Output will be large when parsing multiple files in a release.\n"
101                     + "\t-s \t Skips parsing embedded SO files if it takes too long time.\n";
102 
main(String[] args)103     public static void main(String[] args) {
104         try {
105             ArgumentParser argParser = new ArgumentParser(args);
106             String fileName = argParser.getParameterElement("i", 0);
107             String outputFileName = argParser.getParameterElement("of", 0);
108             boolean parseSo = !argParser.containsOption("s");
109             boolean parseInternalApi = argParser.containsOption("pi");
110 
111             File aFile = new File(fileName);
112             ApkParser aParser = new ApkParser(aFile);
113             aParser.setParseSo(parseSo);
114             aParser.setParseInternalApi(parseInternalApi);
115             Entry.Builder fileEntryBuilder = aParser.getFileEntryBuilder();
116             writeTextFormatMessage(outputFileName, fileEntryBuilder.build());
117         } catch (Exception ex) {
118             System.out.println(USAGE_MESSAGE);
119             ex.printStackTrace();
120         }
121     }
122 
getLogger()123     private static Logger getLogger() {
124         return Logger.getLogger(ApkParser.class.getSimpleName());
125     }
126 }
127