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; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assume.assumeTrue; 22 23 import android.cts.install.lib.host.InstallUtilsHost; 24 25 import com.android.compatibility.common.util.CpuFeatures; 26 import com.android.internal.util.test.SystemPreparer; 27 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 28 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 29 30 import org.junit.Rule; 31 import org.junit.Test; 32 import org.junit.rules.RuleChain; 33 import org.junit.rules.TemporaryFolder; 34 import org.junit.runner.RunWith; 35 36 import java.time.Duration; 37 38 @RunWith(DeviceJUnit4ClassRunner.class) 39 public class SharedLibsApexTest extends BaseHostJUnit4Test { 40 41 private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this); 42 private final TemporaryFolder mTemporaryFolder = new TemporaryFolder(); 43 private final SystemPreparer mPreparer = new SystemPreparer(mTemporaryFolder, 44 this::getDevice); 45 46 @Rule 47 public final RuleChain ruleChain = RuleChain.outerRule(mTemporaryFolder).around(mPreparer); 48 49 enum ApexName { 50 FOO, 51 BAR, 52 BAZ, 53 PONY, 54 SHAREDLIBS, 55 SHAREDLIBS_SECONDARY 56 } 57 58 enum ApexVersion { 59 ONE, 60 TWO 61 } 62 63 enum ApexType { 64 DEFAULT, 65 STRIPPED 66 } 67 68 enum SharedLibsVersion { 69 X, 70 Y, 71 Z 72 } 73 74 /** 75 * Utility function to generate test apex names in the form e.g.: 76 * "com.android.apex.test.bar.v1.libvX.apex" 77 */ getTestApex(ApexName apexName, ApexType apexType, ApexVersion apexVersion, SharedLibsVersion sharedLibsVersion)78 private String getTestApex(ApexName apexName, ApexType apexType, ApexVersion apexVersion, 79 SharedLibsVersion sharedLibsVersion) { 80 StringBuilder ret = new StringBuilder(); 81 ret.append("com.android.apex.test."); 82 switch(apexName) { 83 case FOO: 84 ret.append("foo"); 85 break; 86 case BAR: 87 ret.append("bar"); 88 break; 89 case BAZ: 90 ret.append("baz"); 91 break; 92 case PONY: 93 ret.append("pony"); 94 break; 95 case SHAREDLIBS: 96 ret.append("sharedlibs_generated"); 97 break; 98 case SHAREDLIBS_SECONDARY: 99 ret.append("sharedlibs_secondary_generated"); 100 break; 101 } 102 103 switch(apexType) { 104 case STRIPPED: 105 ret.append("_stripped"); 106 break; 107 case DEFAULT: 108 break; 109 } 110 111 switch(apexVersion) { 112 case ONE: 113 ret.append(".v1"); 114 break; 115 case TWO: 116 ret.append(".v2"); 117 break; 118 } 119 120 switch(sharedLibsVersion) { 121 case X: 122 ret.append(".libvX.apex"); 123 break; 124 case Y: 125 ret.append(".libvY.apex"); 126 break; 127 case Z: 128 ret.append(".libvZ.apex"); 129 break; 130 } 131 132 return ret.toString(); 133 } 134 135 /** 136 * Utility function to generate the file name of an installed package as per 137 * apexd convention e.g.: "com.android.apex.test.bar@1.apex" 138 */ getInstalledApexFileName(ApexName apexName, ApexVersion apexVersion)139 private String getInstalledApexFileName(ApexName apexName, ApexVersion apexVersion) { 140 StringBuilder ret = new StringBuilder(); 141 ret.append("com.android.apex.test."); 142 switch(apexName) { 143 case FOO: 144 ret.append("foo"); 145 break; 146 case BAR: 147 ret.append("bar"); 148 break; 149 case BAZ: 150 ret.append("baz"); 151 break; 152 case PONY: 153 ret.append("pony"); 154 break; 155 case SHAREDLIBS: 156 ret.append("sharedlibs"); 157 break; 158 case SHAREDLIBS_SECONDARY: 159 ret.append("sharedlibs_secondary"); 160 break; 161 } 162 ret.append("@"); 163 switch(apexVersion) { 164 case ONE: 165 ret.append("1"); 166 break; 167 case TWO: 168 ret.append("2"); 169 break; 170 } 171 ret.append(".apex"); 172 return ret.toString(); 173 } 174 175 /** 176 * Tests basic functionality of two apex packages being force-installed and the C++ binaries 177 * contained in them being executed correctly. 178 */ 179 @Test testInstallAndRunDefaultApexs()180 public void testInstallAndRunDefaultApexs() throws Exception { 181 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 182 assumeTrue("Device requires root", getDevice().isAdbRoot()); 183 184 for (String apex : new String[]{ 185 getTestApex(ApexName.BAR, ApexType.DEFAULT, ApexVersion.ONE, SharedLibsVersion.X), 186 getTestApex(ApexName.FOO, ApexType.DEFAULT, ApexVersion.ONE, SharedLibsVersion.X), 187 getTestApex(ApexName.PONY, ApexType.DEFAULT, ApexVersion.ONE, SharedLibsVersion.Z), 188 }) { 189 mPreparer.pushResourceFile(apex, 190 "/system/apex/" + apex); 191 } 192 mPreparer.reboot(); 193 194 getDevice().disableAdbRoot(); 195 String runAsResult = getDevice().executeShellCommand( 196 "/apex/com.android.apex.test.foo/bin/foo_test"); 197 assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X"); 198 runAsResult = getDevice().executeShellCommand( 199 "/apex/com.android.apex.test.bar/bin/bar_test32"); 200 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 201 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 202 runAsResult = getDevice().executeShellCommand( 203 "/apex/com.android.apex.test.bar/bin/bar_test64"); 204 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 205 } 206 runAsResult = getDevice().executeShellCommand( 207 "/apex/com.android.apex.test.pony/bin/pony_test"); 208 assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z"); 209 210 mPreparer.stageMultiplePackages( 211 new String[]{ 212 getTestApex(ApexName.BAR, ApexType.DEFAULT, ApexVersion.TWO, SharedLibsVersion.Y), 213 getTestApex(ApexName.FOO, ApexType.DEFAULT, ApexVersion.TWO, SharedLibsVersion.Y), 214 }, 215 new String[] { 216 "com.android.apex.test.bar", 217 "com.android.apex.test.foo", 218 }).reboot(); 219 220 runAsResult = getDevice().executeShellCommand( 221 "/apex/com.android.apex.test.foo/bin/foo_test"); 222 assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y"); 223 runAsResult = getDevice().executeShellCommand( 224 "/apex/com.android.apex.test.bar/bin/bar_test32"); 225 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 226 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 227 runAsResult = getDevice().executeShellCommand( 228 "/apex/com.android.apex.test.bar/bin/bar_test64"); 229 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 230 } 231 } 232 233 /** 234 * Tests functionality of shared libraries apex: installs two apexs "stripped" of libc++.so and 235 * one apex containing it and verifies that C++ binaries can run. 236 */ 237 @Test testInstallAndRunOptimizedApexs()238 public void testInstallAndRunOptimizedApexs() throws Exception { 239 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 240 assumeTrue("Device requires root", getDevice().isAdbRoot()); 241 242 // Base case: 243 // 244 // Pre-installed on /system: 245 // package bar version 1 using library version X 246 // package foo version 1 using library version X 247 // package sharedlibs version 1 exporting library version X 248 // 249 // package pony version 1 using library version Z 250 // package sharedlibs_secondary version 1 exporting library version Z 251 252 for (String apex : new String[]{ 253 getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 254 getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 255 getTestApex(ApexName.PONY, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.Z), 256 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE, 257 SharedLibsVersion.X), 258 getTestApex(ApexName.SHAREDLIBS_SECONDARY, ApexType.DEFAULT, ApexVersion.ONE, 259 SharedLibsVersion.Z), 260 }) { 261 mPreparer.pushResourceFile(apex, 262 "/system/apex/" + apex); 263 } 264 mPreparer.reboot(); 265 266 getDevice().disableAdbRoot(); 267 String runAsResult = getDevice().executeShellCommand( 268 "/apex/com.android.apex.test.foo/bin/foo_test"); 269 assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X"); 270 runAsResult = getDevice().executeShellCommand( 271 "/apex/com.android.apex.test.bar/bin/bar_test32"); 272 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 273 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 274 runAsResult = getDevice().executeShellCommand( 275 "/apex/com.android.apex.test.bar/bin/bar_test64"); 276 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 277 } 278 runAsResult = getDevice().executeShellCommand( 279 "/apex/com.android.apex.test.pony/bin/pony_test"); 280 assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z"); 281 282 // Edge case: sharedlibs updated with a same version apex. 283 // 284 // Updated packages (installed on /data/apex/active): 285 // package sharedlibs version 1 exporting library version X <-- new 286 // package sharedlibs_secondary version 1 exporting library version Z <-- new 287 // 288 // Pre-installed: 289 // package bar version 1 using library version X 290 // package foo version 1 using library version X 291 // (inactive) package sharedlibs version 1 exporting library version X 292 // 293 // package pony version 1 using library version Z 294 // (inactive) package sharedlibs_secondary version 1 exporting library version Z 295 296 mPreparer.stageMultiplePackages( 297 new String[]{ 298 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE, 299 SharedLibsVersion.X), 300 getTestApex(ApexName.SHAREDLIBS_SECONDARY, ApexType.DEFAULT, ApexVersion.ONE, 301 SharedLibsVersion.Z), 302 }, 303 new String[]{ 304 "com.android.apex.test.sharedlibs", 305 "com.android.apex.test.sharedlibs_secondary", 306 }).reboot(); 307 308 runAsResult = getDevice().executeShellCommand( 309 "/apex/com.android.apex.test.foo/bin/foo_test"); 310 assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X"); 311 runAsResult = getDevice().executeShellCommand( 312 "/apex/com.android.apex.test.bar/bin/bar_test32"); 313 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 314 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 315 runAsResult = getDevice().executeShellCommand( 316 "/apex/com.android.apex.test.bar/bin/bar_test64"); 317 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 318 } 319 runAsResult = getDevice().executeShellCommand( 320 "/apex/com.android.apex.test.pony/bin/pony_test"); 321 assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z"); 322 323 // Updated packages (installed on /data/apex/active): 324 // package bar version 2 using library version Y <-- new 325 // package foo version 2 using library version Y <-- new 326 // package sharedlibs version 2 exporting library version Y <-- new 327 // package sharedlibs_secondary version 1 exporting library version Z 328 // 329 // Pre-installed: 330 // (inactive) package bar version 1 using library version X 331 // (inactive) package foo version 1 using library version X 332 // package sharedlibs version 1 exporting library version X 333 // 334 // package pony version 1 using library version Z 335 // (inactive) package sharedlibs_secondary version 1 exporting library version Z 336 337 mPreparer.stageMultiplePackages( 338 new String[]{ 339 getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y), 340 getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y), 341 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.TWO, 342 SharedLibsVersion.Y), 343 }, 344 new String[]{ 345 "com.android.apex.test.bar", 346 "com.android.apex.test.foo", 347 "com.android.apex.test.sharedlibs", 348 }).reboot(); 349 350 runAsResult = getDevice().executeShellCommand( 351 "/apex/com.android.apex.test.foo/bin/foo_test"); 352 assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y"); 353 runAsResult = getDevice().executeShellCommand( 354 "/apex/com.android.apex.test.bar/bin/bar_test32"); 355 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 356 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 357 runAsResult = getDevice().executeShellCommand( 358 "/apex/com.android.apex.test.bar/bin/bar_test64"); 359 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 360 } 361 runAsResult = getDevice().executeShellCommand( 362 "/apex/com.android.apex.test.pony/bin/pony_test"); 363 assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z"); 364 365 // Assume that an OTA now adds a package baz on /system needing libraries installed on 366 // /system: 367 // 368 // Updated packages (installed on /data/apex/active): 369 // package bar version 2 using library version Y 370 // package foo version 2 using library version Y 371 // package sharedlibs version 2 exporting library version Y 372 // 373 // Pre-installed: 374 // (inactive) package bar version 1 using library version X 375 // package baz version 1 using library version X <-- new 376 // (inactive) package foo version 1 using library version X 377 // package sharedlibs version 1 exporting library version X 378 // package pony version 1 using library version Z 379 // package sharedlibs_secondary version 1 exporting library version Z 380 381 String baz_apex = 382 getTestApex(ApexName.BAZ, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X); 383 mPreparer.pushResourceFile(baz_apex, "/system/apex/" + baz_apex); 384 mPreparer.reboot(); 385 386 runAsResult = getDevice().executeShellCommand( 387 "/apex/com.android.apex.test.foo/bin/foo_test"); 388 assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y"); 389 runAsResult = getDevice().executeShellCommand( 390 "/apex/com.android.apex.test.bar/bin/bar_test32"); 391 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 392 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 393 runAsResult = getDevice().executeShellCommand( 394 "/apex/com.android.apex.test.bar/bin/bar_test64"); 395 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 396 } 397 runAsResult = getDevice().executeShellCommand( 398 "/apex/com.android.apex.test.baz/bin/baz_test"); 399 assertThat(runAsResult).isEqualTo("BAZ_VERSION_1 SHARED_LIB_VERSION_X"); 400 runAsResult = getDevice().executeShellCommand( 401 "/apex/com.android.apex.test.pony/bin/pony_test"); 402 assertThat(runAsResult).isEqualTo("PONY_VERSION_1 SHARED_LIB_VERSION_Z"); 403 } 404 405 /** 406 * Tests that when a shared library apex is updated via OTA the previously 407 * downloaded version is remoted. 408 */ 409 @Test testHigherVersionOnSystemDeletesDataVersion()410 public void testHigherVersionOnSystemDeletesDataVersion() throws Exception { 411 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 412 assumeTrue("Device requires root", getDevice().isAdbRoot()); 413 414 // Base case: 415 // 416 // Pre-installed on /system: 417 // package bar version 1 using library version X 418 // package foo version 1 using library version X 419 // package sharedlibs version 1 exporting library version X 420 for (String apex : new String[]{ 421 getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 422 getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 423 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE, 424 SharedLibsVersion.X), 425 }) { 426 mPreparer.pushResourceFile(apex, 427 "/system/apex/" + apex); 428 } 429 mPreparer.reboot(); 430 String runAsResult = getDevice().executeShellCommand( 431 "/apex/com.android.apex.test.foo/bin/foo_test"); 432 assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X"); 433 runAsResult = getDevice().executeShellCommand( 434 "/apex/com.android.apex.test.bar/bin/bar_test32"); 435 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 436 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 437 runAsResult = getDevice().executeShellCommand( 438 "/apex/com.android.apex.test.bar/bin/bar_test64"); 439 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 440 } 441 442 // Same-grade case: 443 // 444 // Pre-installed on /system: 445 // package bar version 1 using library version X 446 // package foo version 1 using library version X 447 // package sharedlibs version 1 exporting library version X 448 // Updated packages (installed on /data/apex/active): 449 // package bar version 1 using library version X 450 // package foo version 1 using library version X 451 // package sharedlibs version 1 exporting library version X 452 mPreparer.stageMultiplePackages( 453 new String[]{ 454 getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 455 getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 456 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE, 457 SharedLibsVersion.X), 458 }, 459 new String[]{ 460 "com.android.apex.test.bar", 461 "com.android.apex.test.foo", 462 "com.android.apex.test.sharedlibs", 463 }).reboot(); 464 465 runAsResult = getDevice().executeShellCommand( 466 "/apex/com.android.apex.test.foo/bin/foo_test"); 467 assertThat(runAsResult).isEqualTo("FOO_VERSION_1 SHARED_LIB_VERSION_X"); 468 runAsResult = getDevice().executeShellCommand( 469 "/apex/com.android.apex.test.bar/bin/bar_test32"); 470 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 471 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 472 runAsResult = getDevice().executeShellCommand( 473 "/apex/com.android.apex.test.bar/bin/bar_test64"); 474 assertThat(runAsResult).isEqualTo("BAR_VERSION_1 SHARED_LIB_VERSION_X"); 475 } 476 477 // Simulate OTA upgrading pre-installed modules: 478 // 479 // Pre-installed on /system: 480 // package bar version 2 using library version Y 481 // package foo version 2 using library version Y 482 // package sharedlibs version 2 exporting library version Y 483 // 484 // Updated packages (installed on /data/apex/active): 485 // package bar version 1 using library version X (deleted) 486 // package foo version 1 using library version X (deleted) 487 // package sharedlibs version 1 exporting library version X (deleted) 488 // 489 for (String apex : new String[]{ 490 getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 491 getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.ONE, SharedLibsVersion.X), 492 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.ONE, 493 SharedLibsVersion.X), 494 }) { 495 mPreparer.deleteFile("/system/apex/" + apex); 496 } 497 for (String apex : new String[]{ 498 getTestApex(ApexName.BAR, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y), 499 getTestApex(ApexName.FOO, ApexType.STRIPPED, ApexVersion.TWO, SharedLibsVersion.Y), 500 getTestApex(ApexName.SHAREDLIBS, ApexType.DEFAULT, ApexVersion.TWO, 501 SharedLibsVersion.Y), 502 }) { 503 mPreparer.pushResourceFile(apex, 504 "/system/apex/" + apex); 505 } 506 507 // Check that files in /data are deleted on first boot. 508 assertThat(getDevice().doesFileExist("/data/apex/active/" 509 + getInstalledApexFileName(ApexName.BAR, ApexVersion.ONE))).isTrue(); 510 assertThat(getDevice().doesFileExist("/data/apex/active/" 511 + getInstalledApexFileName(ApexName.FOO, ApexVersion.ONE))).isTrue(); 512 assertThat(getDevice().doesFileExist("/data/apex/active/" 513 + getInstalledApexFileName(ApexName.SHAREDLIBS, ApexVersion.ONE))).isTrue(); 514 mPreparer.reboot(); 515 mHostUtils.waitForFileDeleted("/data/apex/active/" 516 + getInstalledApexFileName(ApexName.BAR, ApexVersion.ONE), Duration.ofMinutes(3)); 517 mHostUtils.waitForFileDeleted("/data/apex/active/" 518 + getInstalledApexFileName(ApexName.FOO, ApexVersion.ONE), Duration.ofMinutes(3)); 519 mHostUtils.waitForFileDeleted("/data/apex/active/" 520 + getInstalledApexFileName(ApexName.SHAREDLIBS, ApexVersion.ONE), 521 Duration.ofMinutes(3)); 522 523 getDevice().disableAdbRoot(); 524 runAsResult = getDevice().executeShellCommand( 525 "/apex/com.android.apex.test.foo/bin/foo_test"); 526 assertThat(runAsResult).isEqualTo("FOO_VERSION_2 SHARED_LIB_VERSION_Y"); 527 runAsResult = getDevice().executeShellCommand( 528 "/apex/com.android.apex.test.bar/bin/bar_test32"); 529 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 530 if (CpuFeatures.isX86_64(getDevice()) || CpuFeatures.isArm64(getDevice())) { 531 runAsResult = getDevice().executeShellCommand( 532 "/apex/com.android.apex.test.bar/bin/bar_test64"); 533 assertThat(runAsResult).isEqualTo("BAR_VERSION_2 SHARED_LIB_VERSION_Y"); 534 } 535 } 536 } 537