1 /*
2  * Copyright (C) 2012 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.monkey;
17 
18 import com.android.tradefed.build.IAppBuildInfo;
19 import com.android.tradefed.build.IBuildInfo;
20 import com.android.tradefed.build.VersionedFile;
21 import com.android.tradefed.config.ConfigurationException;
22 import com.android.tradefed.config.IConfiguration;
23 import com.android.tradefed.config.IConfigurationReceiver;
24 import com.android.tradefed.config.Option;
25 import com.android.tradefed.device.DeviceNotAvailableException;
26 import com.android.tradefed.device.ITestDevice;
27 import com.android.tradefed.targetprep.BaseTargetPreparer;
28 import com.android.tradefed.targetprep.BuildError;
29 import com.android.tradefed.targetprep.ITargetPreparer;
30 import com.android.tradefed.targetprep.TargetSetupError;
31 import com.android.tradefed.util.AaptParser;
32 
33 import org.junit.Assert;
34 
35 /**
36  * A {@link ITargetPreparer} for {@link IAppBuildInfo}, that dynamically determines the app package
37  * name given its apk file. This saves the user from having to manually specify the --package arg
38  * when running monkey.
39  *
40  * <p>Requires that aapt is on current path.
41  */
42 public class AppPkgInjector extends BaseTargetPreparer implements IConfigurationReceiver {
43 
44     @Option(
45             name = "skip-injector",
46             description =
47                     "Set to true if we should skip automatically "
48                             + "adding all package names of installed packages. Default is false.")
49     private boolean mSkipInjecting = false;
50 
51     private IConfiguration mConfig;
52 
53     /** {@inheritDoc} */
54     @Override
setConfiguration(IConfiguration configuration)55     public void setConfiguration(IConfiguration configuration) {
56         mConfig = configuration;
57     }
58 
59     /** {@inheritDoc} */
60     @Override
setUp(ITestDevice device, IBuildInfo buildInfo)61     public void setUp(ITestDevice device, IBuildInfo buildInfo)
62             throws TargetSetupError, BuildError, DeviceNotAvailableException {
63         if (mSkipInjecting) {
64             return;
65         }
66         Assert.assertNotNull(mConfig);
67         Assert.assertTrue(
68                 "provided build is not a IAppBuildInfo", buildInfo instanceof IAppBuildInfo);
69         IAppBuildInfo appBuild = (IAppBuildInfo) buildInfo;
70         for (VersionedFile apkFile : appBuild.getAppPackageFiles()) {
71             AaptParser aapt = AaptParser.parse(apkFile.getFile());
72             if (aapt == null) {
73                 // throw a build error because typically aapt parse errors are issues with the apk
74                 throw new BuildError(
75                         String.format(
76                                 "aapt parse of %s failed", apkFile.getFile().getAbsolutePath()),
77                         device.getDeviceDescriptor());
78             }
79             String pkgName = aapt.getPackageName();
80             if (pkgName == null) {
81                 // this should never happen
82                 throw new TargetSetupError(
83                         String.format(
84                                 "Failed to parse package name from %s",
85                                 apkFile.getFile().getAbsolutePath()),
86                         device.getDeviceDescriptor());
87             }
88             try {
89                 mConfig.injectOptionValue("package", pkgName);
90             } catch (ConfigurationException e) {
91                 throw new TargetSetupError(
92                         "Failed to inject --package option.", e, device.getDeviceDescriptor());
93             }
94         }
95     }
96 }
97