• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 android.content.pm.cts;
18 
19 import static android.content.pm.PackageInfo.INSTALL_LOCATION_AUTO;
20 import static android.content.pm.PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
21 import static android.content.pm.PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
22 import static android.content.pm.PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
23 import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
24 import static android.content.pm.PackageInstaller.SessionParams.MODE_INHERIT_EXISTING;
25 import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_RESTORE;
26 import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP;
27 import static android.content.pm.PackageManager.INSTALL_REASON_POLICY;
28 import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN;
29 import static android.content.pm.PackageManager.INSTALL_REASON_USER;
30 import static android.content.pm.PackageManager.INSTALL_SCENARIO_BULK;
31 import static android.content.pm.PackageManager.INSTALL_SCENARIO_BULK_SECONDARY;
32 import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT;
33 import static android.content.pm.PackageManager.INSTALL_SCENARIO_FAST;
34 
35 import static com.google.common.truth.Truth.assertThat;
36 
37 import static org.junit.Assert.fail;
38 
39 import android.content.pm.Flags;
40 import android.content.pm.PackageInstaller;
41 import android.content.pm.PackageInstaller.SessionInfo;
42 import android.content.pm.PackageInstaller.SessionParams;
43 import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
44 import android.graphics.Bitmap;
45 import android.net.Uri;
46 import android.platform.test.annotations.AppModeFull;
47 import android.util.Log;
48 
49 import androidx.test.InstrumentationRegistry;
50 
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Rule;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 import org.junit.runners.Parameterized;
57 
58 import java.util.ArrayList;
59 import java.util.Collection;
60 import java.util.List;
61 import java.util.function.Consumer;
62 
63 @RunWith(Parameterized.class)
64 @AppModeFull // TODO(Instant) Figure out which APIs should work.
65 public class InstallSessionParamsUnitTest {
66     private static final String LOG_TAG = InstallSessionParamsUnitTest.class.getSimpleName();
67     private static Optional UNSET = new Optional(false, null);
68 
69     @Rule
70     public AbandonAllPackageSessionsRule mAbandonSessionsRule = new AbandonAllPackageSessionsRule();
71 
72     @Parameterized.Parameter(0)
73     public Optional<Integer> mode;
74     @Parameterized.Parameter(1)
75     public Optional<Integer> installLocation;
76     @Parameterized.Parameter(2)
77     public Optional<Integer> size;
78     @Parameterized.Parameter(3)
79     public Optional<String> appPackageName;
80     @Parameterized.Parameter(4)
81     public Optional<Bitmap> appIcon;
82     @Parameterized.Parameter(5)
83     public Optional<String> appLabel;
84     @Parameterized.Parameter(6)
85     public Optional<Uri> originatingUri;
86     @Parameterized.Parameter(7)
87     public Optional<Integer> originatingUid;
88     @Parameterized.Parameter(8)
89     public Optional<Uri> referredUri;
90     @Parameterized.Parameter(9)
91     public Optional<Integer> installReason;
92     @Parameterized.Parameter(10)
93     public Optional<Integer> installScenario;
94     @Parameterized.Parameter(11)
95     public Optional<Integer> packageSource;
96     @Parameterized.Parameter(12)
97     public Optional<Boolean> enableAutoDependencyInstall;
98     @Parameterized.Parameter(13)
99     public boolean expectFailure;
100 
101     private PackageInstaller mInstaller = InstrumentationRegistry.getInstrumentation()
102             .getTargetContext()
103             .getPackageManager()
104             .getPackageInstaller();
105 
106     /**
107      * Generate test-parameters where all params are the same, but one param cycles through all
108      * values.
109      */
getSingleParameterChangingTests( Object[][][] allParameterValues, int changingParameterIndex, Object[] changingParameterValues, boolean expectFailure)110     private static ArrayList<Object[]> getSingleParameterChangingTests(
111             Object[][][] allParameterValues, int changingParameterIndex,
112             Object[] changingParameterValues, boolean expectFailure) {
113         ArrayList<Object[]> params = new ArrayList<>();
114 
115         for (Object changingParameterValue : changingParameterValues) {
116             ArrayList<Object> singleTestParams = new ArrayList<>();
117 
118             // parameterIndex is the index of the parameter (0 = mode, ...)
119             for (int parameterIndex = 0; parameterIndex < allParameterValues.length;
120                     parameterIndex++) {
121                 Object[][] parameterValues = allParameterValues[parameterIndex];
122 
123                 if (parameterIndex == changingParameterIndex) {
124                     if (changingParameterValue == UNSET) {
125                         // No need to wrap UNSET again
126                         singleTestParams.add(UNSET);
127                     } else {
128                         singleTestParams.add(Optional.of(changingParameterValue));
129                     }
130                 } else {
131                     singleTestParams.add(Optional.of(parameterValues[0][0]));
132                 }
133             }
134             singleTestParams.add(expectFailure);
135             params.add(singleTestParams.toArray());
136         }
137 
138         return params;
139     }
140 
141     /**
142      * Generate test-parameters for all tests.
143      */
144     @Parameterized.Parameters
getParameters()145     public static Collection<Object[]> getParameters() {
146         // {{{valid parameters}, {invalid parameters}}}
147         Object[][][] allParameterValues = {
148          /*mode*/
149                 {{MODE_FULL_INSTALL, MODE_INHERIT_EXISTING}, {0xfff}},
150          /*installLocation*/
151                 {{INSTALL_LOCATION_UNSPECIFIED, INSTALL_LOCATION_AUTO,
152                         INSTALL_LOCATION_INTERNAL_ONLY, INSTALL_LOCATION_PREFER_EXTERNAL,
153                         /* parame is not verified */ 0xfff}, {}},
154          /*size*/
155                 {{1, 8092, Integer.MAX_VALUE, /* param is not verified */ -1, 0}, {}},
156          /*appPackageName*/
157                 {{"a.package.name", null, /* param is not verified */ "android"}, {}},
158          /*appIcon*/
159                 {{null, Bitmap.createBitmap(42, 42, Bitmap.Config.ARGB_8888)}, {}},
160          /*appLabel*/
161                 {{"A label", null}, {}},
162          /*originatingUri*/
163                 {{Uri.parse("android.com"), null}, {}},
164          /*originatingUid*/
165                 {{-1, 0, 1}, {}},
166          /*referredUri*/
167                 {{Uri.parse("android.com"), null}, {}},
168          /*installReason*/
169                 {{INSTALL_REASON_UNKNOWN, INSTALL_REASON_POLICY, INSTALL_REASON_DEVICE_RESTORE,
170                         INSTALL_REASON_DEVICE_SETUP, INSTALL_REASON_USER,
171                         /* parame is not verified */ 0xfff}, {}},
172          /*installScenario*/
173                 {{INSTALL_SCENARIO_DEFAULT, INSTALL_SCENARIO_FAST, INSTALL_SCENARIO_BULK,
174                         INSTALL_SCENARIO_BULK_SECONDARY}, {}},
175          /*packageSource*/
176                 {{PackageInstaller.PACKAGE_SOURCE_UNSPECIFIED,
177                         PackageInstaller.PACKAGE_SOURCE_OTHER,
178                         PackageInstaller.PACKAGE_SOURCE_STORE,
179                         PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE,
180                         PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE}, {}},
181          /*enableAutoDependencyInstall*/
182                 {{true, false}, {}}
183         };
184 
185         ArrayList<Object[]> allTestParams = new ArrayList<>();
186 
187         // changingParameterIndex is the index the parameter that changes (0 = mode ...)
188         for (int changingParameterIndex = 0; changingParameterIndex < allParameterValues.length;
189                 changingParameterIndex++) {
190             // Allowed values
191             allTestParams.addAll(getSingleParameterChangingTests(allParameterValues,
192                     changingParameterIndex, allParameterValues[changingParameterIndex][0], false));
193 
194             // Value unset (mode param cannot be unset)
195             if (changingParameterIndex != 0) {
196                 Object[] unset = {UNSET};
197                 allTestParams.addAll(getSingleParameterChangingTests(allParameterValues,
198                         changingParameterIndex, unset, false));
199             }
200 
201             // Illegal values
202             allTestParams.addAll(getSingleParameterChangingTests(allParameterValues,
203                     changingParameterIndex, allParameterValues[changingParameterIndex][1], true));
204         }
205 
206         return allTestParams;
207     }
208 
209     /**
210      * Get the sessionInfo if this package owns the session.
211      *
212      * @param sessionId The id of the session
213      *
214      * @return The {@link PackageInstaller.SessionInfo} object, or {@code null} if session is not
215      * owned by the this package.
216      */
getSessionInfo(int sessionId)217     private SessionInfo getSessionInfo(int sessionId) {
218         List<SessionInfo> mySessionInfos = mInstaller.getMySessions();
219 
220         for (SessionInfo sessionInfo : mySessionInfos) {
221             if (sessionInfo.getSessionId() == sessionId) {
222                 return sessionInfo;
223             }
224         }
225 
226         return null;
227     }
228 
229     @Before
onBefore()230     public void onBefore() throws Exception {
231         PackageManagerShellCommandInstallTest.setSystemProperty(
232                 "debug.pm.install_skip_size_check_for_maxint", "1");
233     }
234 
235     @After
onAfter()236     public void onAfter() throws Exception {
237         // Set the test override to invalid.
238         PackageManagerShellCommandInstallTest.setSystemProperty(
239                 "debug.pm.install_skip_size_check_for_maxint", "invalid");
240     }
241 
242     @Test
checkSessionParams()243     public void checkSessionParams() throws Exception {
244         Log.i(LOG_TAG, "mode=" + mode + " installLocation=" + installLocation + " size=" + size
245                 + " appPackageName=" + appPackageName + " appIcon=" + appIcon + " appLabel="
246                 + appLabel + " originatingUri=" + originatingUri + " originatingUid="
247                 + originatingUid + " referredUri=" + referredUri + " installReason=" + installReason
248                 + " installScenario=" + installScenario + " expectFailure=" + expectFailure);
249 
250         SessionParams params = new SessionParams(mode.get());
251         installLocation.ifPresent(params::setInstallLocation);
252         size.ifPresent(params::setSize);
253         appPackageName.ifPresent(params::setAppPackageName);
254         appIcon.ifPresent(params::setAppIcon);
255         appLabel.ifPresent(params::setAppLabel);
256         originatingUri.ifPresent(params::setOriginatingUri);
257         originatingUid.ifPresent(params::setOriginatingUid);
258         referredUri.ifPresent(params::setReferrerUri);
259         installReason.ifPresent(params::setInstallReason);
260         installScenario.ifPresent(params::setInstallScenario);
261         packageSource.ifPresent(params::setPackageSource);
262         if (Flags.sdkDependencyInstaller()) {
263             // Verify that auto install of dependencies is enabled by default.
264             assertThat(params.isAutoInstallDependenciesEnabled).isTrue();
265             enableAutoDependencyInstall.ifPresent(params::setAutoInstallDependenciesEnabled);
266         }
267 
268         int sessionId;
269         try {
270             sessionId = mInstaller.createSession(params);
271 
272             if (expectFailure) {
273                 fail("Creating session did not fail");
274             }
275         } catch (Exception e) {
276             if (expectFailure) {
277                 return;
278             }
279 
280             throw e;
281         }
282 
283         SessionInfo info = getSessionInfo(sessionId);
284 
285         assertThat(info.getMode()).isEqualTo(mode.get());
286         packageSource.ifPresent(i -> assertThat(info.getPackageSource()).isEqualTo(i));
287         installLocation.ifPresent(i -> assertThat(info.getInstallLocation()).isEqualTo(i));
288         size.ifPresent(i -> assertThat(info.getSize()).isEqualTo(i));
289         appPackageName.ifPresent(s -> assertThat(info.getAppPackageName()).isEqualTo(s));
290 
291         if (appIcon.isPresent()) {
292             if (appIcon.get() == null) {
293                 assertThat(info.getAppIcon()).isNull();
294             } else {
295                 assertThat(appIcon.get().sameAs(info.getAppIcon())).isTrue();
296             }
297         }
298 
299         appLabel.ifPresent(s -> assertThat(info.getAppLabel()).isEqualTo(s));
300         originatingUri.ifPresent(uri -> assertThat(info.getOriginatingUri()).isEqualTo(uri));
301         originatingUid.ifPresent(i -> assertThat(info.getOriginatingUid()).isEqualTo(i));
302         referredUri.ifPresent(uri -> assertThat(info.getReferrerUri()).isEqualTo(uri));
303         installReason.ifPresent(i -> assertThat(info.getInstallReason()).isEqualTo(i));
304         if (Flags.sdkDependencyInstaller()) {
305             enableAutoDependencyInstall.ifPresent(
306                     i -> assertThat(info.isAutoInstallDependenciesEnabled()).isEqualTo(i));
307         }
308     }
309 
310     /** Similar to java.util.Optional but distinguishing between null and unset */
311     private static class Optional<T> {
312         private final boolean mIsSet;
313         private final T mValue;
314 
Optional(boolean isSet, T value)315         Optional(boolean isSet, T value) {
316             mIsSet = isSet;
317             mValue = value;
318         }
319 
of(T value)320         static <T> Optional of(T value) {
321             return new Optional(true, value);
322         }
323 
get()324         T get() {
325             if (!mIsSet) {
326                 throw new IllegalStateException(this + " is not set");
327             }
328             return mValue;
329         }
330 
toString()331         public String toString() {
332             if (!mIsSet) {
333                 return "unset";
334             } else if (mValue == null) {
335                 return "null";
336             } else {
337                 return mValue.toString();
338             }
339         }
340 
isPresent()341         boolean isPresent() {
342             return mIsSet;
343         }
344 
ifPresent(Consumer<T> consumer)345         void ifPresent(Consumer<T> consumer) {
346             if (mIsSet) {
347                 consumer.accept(mValue);
348             }
349         }
350     }
351 }
352