1 /*
2  * Copyright (C) 2020 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.tests.apex.app;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.Manifest;
22 import android.content.Context;
23 import android.content.pm.ApplicationInfo;
24 import android.content.pm.PackageInfo;
25 import android.content.pm.PackageManager;
26 import android.content.rollback.RollbackInfo;
27 
28 import androidx.test.InstrumentationRegistry;
29 
30 import com.android.cts.install.lib.Install;
31 import com.android.cts.install.lib.InstallUtils;
32 import com.android.cts.install.lib.TestApp;
33 import com.android.cts.rollback.lib.RollbackUtils;
34 
35 import org.junit.After;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.junit.runners.JUnit4;
40 
41 @RunWith(JUnit4.class)
42 public class ApexCompressionTests {
43     private static final String COMPRESSED_APEX_PACKAGE_NAME = "com.android.apex.compressed";
44     private final Context mContext = InstrumentationRegistry.getContext();
45     private final PackageManager mPm = mContext.getPackageManager();
46 
47     private static final TestApp UNCOMPRESSED_APEX_V1 = new TestApp(
48             "TestAppUncompressedApexV1", COMPRESSED_APEX_PACKAGE_NAME, 2, /*isApex*/ true,
49             "com.android.apex.compressed.v1_original.apex");
50     private static final TestApp UNCOMPRESSED_APEX_V2 = new TestApp(
51             "TestAppUncompressedApexV2", COMPRESSED_APEX_PACKAGE_NAME, 2, /*isApex*/ true,
52             "com.android.apex.compressed.v2_original.apex");
53 
54     @Before
adoptShellPermissions()55     public void adoptShellPermissions() {
56         androidx.test.platform.app.InstrumentationRegistry
57                 .getInstrumentation()
58                 .getUiAutomation()
59                 .adoptShellPermissionIdentity(
60                         Manifest.permission.INSTALL_PACKAGES,
61                         Manifest.permission.DELETE_PACKAGES,
62                         Manifest.permission.TEST_MANAGE_ROLLBACKS);
63     }
64 
65     @After
dropShellPermissions()66     public void dropShellPermissions() {
67         androidx.test.platform.app.InstrumentationRegistry
68                 .getInstrumentation()
69                 .getUiAutomation()
70                 .dropShellPermissionIdentity();
71     }
72 
73     @Test
testDecompressedApexIsConsideredFactory()74     public void testDecompressedApexIsConsideredFactory() throws Exception {
75         // Only retrieve active apex package
76         PackageInfo pi = mPm.getPackageInfo(
77                 COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
78         assertThat(pi).isNotNull();
79         assertThat(pi.isApex).isTrue();
80         assertThat(pi.packageName).isEqualTo(COMPRESSED_APEX_PACKAGE_NAME);
81         assertThat(pi.getLongVersionCode()).isEqualTo(1);
82         boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
83         assertThat(isFactoryPackage).isTrue();
84     }
85 
86     @Test
testUnusedDecompressedApexIsCleanedUp_HigherVersion()87     public void testUnusedDecompressedApexIsCleanedUp_HigherVersion() throws Exception {
88         Install.single(UNCOMPRESSED_APEX_V2).setStaged().commit();
89     }
90 
91     @Test
testUnusedDecompressedApexIsCleanedUp_SameVersion()92     public void testUnusedDecompressedApexIsCleanedUp_SameVersion() throws Exception {
93         Install.single(UNCOMPRESSED_APEX_V1).setStaged().commit();
94     }
95 
96 
97     @Test
testCapexToApexSwitch()98     public void testCapexToApexSwitch() throws Exception {
99         // Only retrieve active apex package
100         PackageInfo pi = mPm.getPackageInfo(
101                 COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
102         assertThat(pi).isNotNull();
103         assertThat(pi.isApex).isTrue();
104         assertThat(pi.packageName).isEqualTo(COMPRESSED_APEX_PACKAGE_NAME);
105         assertThat(pi.getLongVersionCode()).isEqualTo(1);
106         boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
107         assertThat(isFactoryPackage).isTrue();
108         assertThat(pi.applicationInfo.sourceDir).startsWith("/system/apex");
109     }
110 
111     @Test
testDecompressedApexVersionAlwaysHasSameVersionAsCapex()112     public void testDecompressedApexVersionAlwaysHasSameVersionAsCapex() throws Exception {
113         // Only retrieve active apex package
114         PackageInfo pi = mPm.getPackageInfo(
115                 COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
116         assertThat(pi).isNotNull();
117         assertThat(pi.isApex).isTrue();
118         assertThat(pi.packageName).isEqualTo(COMPRESSED_APEX_PACKAGE_NAME);
119         assertThat(pi.getLongVersionCode()).isEqualTo(1);
120         boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
121         assertThat(isFactoryPackage).isTrue();
122     }
123 
124     @Test
testCompressedApexCanBeRolledBack_Commit()125     public void testCompressedApexCanBeRolledBack_Commit() throws Exception {
126         // Verify before updating
127         PackageInfo pi = mPm.getPackageInfo(
128                 COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
129         assertThat(pi.getLongVersionCode()).isEqualTo(1);
130         boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
131         assertThat(isFactoryPackage).isTrue();
132         assertThat(pi.applicationInfo.sourceDir).startsWith("/data/apex/decompressed/");
133 
134         Install.single(UNCOMPRESSED_APEX_V2).setStaged().setEnableRollback().commit();
135     }
136 
137     @Test
testCompressedApexCanBeRolledBack_Rollback()138     public void testCompressedApexCanBeRolledBack_Rollback() throws Exception {
139         // Verify before rollback
140         PackageInfo pi = mPm.getPackageInfo(
141                 COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
142         assertThat(pi.getLongVersionCode()).isEqualTo(2);
143         boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
144         assertThat(isFactoryPackage).isFalse();
145         assertThat(pi.applicationInfo.sourceDir).startsWith("/data/apex/active/");
146 
147         // Trigger rollback
148         RollbackInfo available = RollbackUtils.getAvailableRollback(COMPRESSED_APEX_PACKAGE_NAME);
149         RollbackUtils.rollback(available.getRollbackId(), UNCOMPRESSED_APEX_V2);
150         RollbackInfo committed = RollbackUtils.getCommittedRollbackById(available.getRollbackId());
151         InstallUtils.waitForSessionReady(committed.getCommittedSessionId());
152     }
153 
154     @Test
testCompressedApexCanBeRolledBack_Verify()155     public void testCompressedApexCanBeRolledBack_Verify() throws Exception {
156         // Verify rollback worked
157         PackageInfo pi = mPm.getPackageInfo(
158                 COMPRESSED_APEX_PACKAGE_NAME, PackageManager.MATCH_APEX);
159         assertThat(pi.getLongVersionCode()).isEqualTo(1);
160         boolean isFactoryPackage = (pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
161         assertThat(isFactoryPackage).isFalse();
162         assertThat(pi.applicationInfo.sourceDir).startsWith("/data/apex/active/");
163     }
164 }
165