Skip to content

Commit 785aaa2

Browse files
krutonAndroid (Google) Code Review
authored andcommitted
Merge "Add more testing for native libraries" into jb-mr1-dev
2 parents 69d6b53 + 7e921a1 commit 785aaa2

File tree

1 file changed

+189
-69
lines changed

1 file changed

+189
-69
lines changed

core/tests/coretests/src/android/content/pm/PackageManagerTests.java

Lines changed: 189 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package android.content.pm;
1818

19+
import static libcore.io.OsConstants.*;
20+
1921
import com.android.frameworks.coretests.R;
2022
import com.android.internal.content.PackageHelper;
2123

@@ -32,9 +34,11 @@
3234
import android.os.Environment;
3335
import android.os.FileUtils;
3436
import android.os.IBinder;
37+
import android.os.Process;
3538
import android.os.RemoteException;
3639
import android.os.ServiceManager;
3740
import android.os.StatFs;
41+
import android.os.SystemClock;
3842
import android.os.storage.IMountService;
3943
import android.os.storage.StorageListener;
4044
import android.os.storage.StorageManager;
@@ -52,6 +56,12 @@
5256
import java.io.InputStream;
5357

5458
import java.util.List;
59+
import java.util.concurrent.CountDownLatch;
60+
import java.util.concurrent.TimeUnit;
61+
62+
import libcore.io.ErrnoException;
63+
import libcore.io.Libcore;
64+
import libcore.io.StructStat;
5565

5666
public class PackageManagerTests extends AndroidTestCase {
5767
private static final boolean localLOGV = true;
@@ -404,15 +414,12 @@ private void assertInstall(PackageParser.Package pkg, int flags, int expInstallL
404414
if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
405415
assertTrue("The application should be installed forward locked",
406416
(info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
407-
assertTrue("The APK path (" + srcPath + ") should start with "
408-
+ SECURE_CONTAINERS_PREFIX,
409-
srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
410-
assertTrue("The public APK path (" + publicSrcPath + ") should start with "
411-
+ SECURE_CONTAINERS_PREFIX,
412-
publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
413-
assertTrue("The native library path (" + info.nativeLibraryDir
414-
+ ") should start with " + SECURE_CONTAINERS_PREFIX,
415-
info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
417+
assertStartsWith("The APK path should point to the ASEC",
418+
SECURE_CONTAINERS_PREFIX, srcPath);
419+
assertStartsWith("The public APK path should point to the ASEC",
420+
SECURE_CONTAINERS_PREFIX, publicSrcPath);
421+
assertStartsWith("The native library path should point to the ASEC",
422+
SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
416423
try {
417424
String compatLib = new File(info.dataDir + "/lib").getCanonicalPath();
418425
assertEquals("The compatibility lib directory should be a symbolic link to "
@@ -425,7 +432,14 @@ private void assertInstall(PackageParser.Package pkg, int flags, int expInstallL
425432
assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
426433
assertEquals(srcPath, appInstallPath);
427434
assertEquals(publicSrcPath, appInstallPath);
428-
assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
435+
assertStartsWith("Native library should point to shared lib directory",
436+
dataDir.getPath(),
437+
info.nativeLibraryDir);
438+
assertDirOwnerGroupPerms(
439+
"Native library directory should be owned by system:system and 0755",
440+
Process.SYSTEM_UID, Process.SYSTEM_UID,
441+
S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
442+
info.nativeLibraryDir);
429443
}
430444
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
431445

@@ -435,8 +449,7 @@ private void assertInstall(PackageParser.Package pkg, int flags, int expInstallL
435449
nativeLibDir.exists());
436450
try {
437451
assertEquals("Native library dir should not be a symlink",
438-
info.nativeLibraryDir,
439-
nativeLibDir.getCanonicalPath());
452+
info.nativeLibraryDir, nativeLibDir.getCanonicalPath());
440453
} catch (IOException e) {
441454
fail("Can't read " + nativeLibDir.getPath());
442455
}
@@ -453,14 +466,12 @@ private void assertInstall(PackageParser.Package pkg, int flags, int expInstallL
453466
(info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
454467
// Might need to check:
455468
// ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0)
456-
assertTrue("The APK path (" + srcPath + ") should start with "
457-
+ SECURE_CONTAINERS_PREFIX, srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
458-
assertTrue("The public APK path (" + publicSrcPath + ") should start with "
459-
+ SECURE_CONTAINERS_PREFIX,
460-
publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
461-
assertTrue("The native library path (" + info.nativeLibraryDir
462-
+ ") should start with " + SECURE_CONTAINERS_PREFIX,
463-
info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
469+
assertStartsWith("The APK path should point to the ASEC",
470+
SECURE_CONTAINERS_PREFIX, srcPath);
471+
assertStartsWith("The public APK path should point to the ASEC",
472+
SECURE_CONTAINERS_PREFIX, publicSrcPath);
473+
assertStartsWith("The native library path should point to the ASEC",
474+
SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
464475

465476
// Make sure the native library in /data/data/<app>/lib is a
466477
// symlink to the ASEC
@@ -483,6 +494,66 @@ private void assertInstall(PackageParser.Package pkg, int flags, int expInstallL
483494
}
484495
}
485496

497+
private void assertDirOwnerGroupPerms(String reason, int uid, int gid, int perms, String path) {
498+
final StructStat stat;
499+
500+
try {
501+
stat = Libcore.os.lstat(path);
502+
} catch (ErrnoException e) {
503+
throw new AssertionError(reason + "\n" + "Got: " + path + " does not exist");
504+
}
505+
506+
StringBuilder sb = new StringBuilder();
507+
508+
if (!S_ISDIR(stat.st_mode)) {
509+
sb.append("\nExpected type: ");
510+
sb.append(S_IFDIR);
511+
sb.append("\ngot type: ");
512+
sb.append((stat.st_mode & S_IFMT));
513+
}
514+
515+
if (stat.st_uid != uid) {
516+
sb.append("\nExpected owner: ");
517+
sb.append(uid);
518+
sb.append("\nGot owner: ");
519+
sb.append(stat.st_uid);
520+
}
521+
522+
if (stat.st_gid != gid) {
523+
sb.append("\nExpected group: ");
524+
sb.append(gid);
525+
sb.append("\nGot group: ");
526+
sb.append(stat.st_gid);
527+
}
528+
529+
if ((stat.st_mode & ~S_IFMT) != perms) {
530+
sb.append("\nExpected permissions: ");
531+
sb.append(Integer.toOctalString(perms));
532+
sb.append("\nGot permissions: ");
533+
sb.append(Integer.toOctalString(stat.st_mode & ~S_IFMT));
534+
}
535+
536+
if (sb.length() > 0) {
537+
throw new AssertionError(reason + sb.toString());
538+
}
539+
}
540+
541+
private static void assertStartsWith(String prefix, String actual) {
542+
assertStartsWith("", prefix, actual);
543+
}
544+
545+
private static void assertStartsWith(String description, String prefix, String actual) {
546+
if (!actual.startsWith(prefix)) {
547+
StringBuilder sb = new StringBuilder(description);
548+
sb.append("\nExpected prefix: ");
549+
sb.append(prefix);
550+
sb.append("\n got: ");
551+
sb.append(actual);
552+
sb.append('\n');
553+
throw new AssertionError(sb.toString());
554+
}
555+
}
556+
486557
private void assertNotInstalled(String pkgName) {
487558
try {
488559
ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
@@ -820,22 +891,51 @@ public void testReplaceSdcard() throws Exception {
820891
| PackageManager.INSTALL_EXTERNAL);
821892
}
822893

823-
/* -------------- Delete tests ---*/
894+
/* -------------- Delete tests --- */
824895
private static class DeleteObserver extends IPackageDeleteObserver.Stub {
896+
private CountDownLatch mLatch = new CountDownLatch(1);
825897

826-
public boolean succeeded;
827-
private boolean doneFlag = false;
898+
private int mReturnCode;
828899

829-
public boolean isDone() {
830-
return doneFlag;
900+
private final String mPackageName;
901+
902+
private String mObservedPackage;
903+
904+
public DeleteObserver(String packageName) {
905+
mPackageName = packageName;
906+
}
907+
908+
public boolean isSuccessful() {
909+
return mReturnCode == PackageManager.DELETE_SUCCEEDED;
831910
}
832911

833912
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
834-
synchronized(this) {
835-
this.succeeded = returnCode == PackageManager.DELETE_SUCCEEDED;
836-
doneFlag = true;
837-
notifyAll();
913+
mObservedPackage = packageName;
914+
915+
mReturnCode = returnCode;
916+
917+
mLatch.countDown();
918+
}
919+
920+
public void waitForCompletion(long timeoutMillis) {
921+
final long deadline = SystemClock.uptimeMillis() + timeoutMillis;
922+
923+
long waitTime = timeoutMillis;
924+
while (waitTime > 0) {
925+
try {
926+
boolean done = mLatch.await(waitTime, TimeUnit.MILLISECONDS);
927+
if (done) {
928+
assertEquals(mPackageName, mObservedPackage);
929+
return;
930+
}
931+
} catch (InterruptedException e) {
932+
// TODO Auto-generated catch block
933+
e.printStackTrace();
934+
}
935+
waitTime = deadline - SystemClock.uptimeMillis();
838936
}
937+
938+
throw new AssertionError("Timeout waiting for package deletion");
839939
}
840940
}
841941

@@ -863,41 +963,40 @@ public boolean notifyNow(Intent intent) {
863963
}
864964
}
865965

866-
public boolean invokeDeletePackage(final String pkgName, int flags,
867-
GenericReceiver receiver) throws Exception {
868-
DeleteObserver observer = new DeleteObserver();
869-
final boolean received = false;
966+
public boolean invokeDeletePackage(final String pkgName, int flags, GenericReceiver receiver)
967+
throws Exception {
968+
ApplicationInfo info = getPm().getApplicationInfo(pkgName,
969+
PackageManager.GET_UNINSTALLED_PACKAGES);
970+
870971
mContext.registerReceiver(receiver, receiver.filter);
871972
try {
872-
// Wait on observer
873-
synchronized(observer) {
874-
synchronized (receiver) {
875-
getPm().deletePackage(pkgName, observer, flags);
876-
long waitTime = 0;
877-
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
878-
observer.wait(WAIT_TIME_INCR);
879-
waitTime += WAIT_TIME_INCR;
880-
}
881-
if(!observer.isDone()) {
882-
throw new Exception("Timed out waiting for packageInstalled callback");
883-
}
884-
// Verify we received the broadcast
885-
waitTime = 0;
886-
while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
887-
receiver.wait(WAIT_TIME_INCR);
888-
waitTime += WAIT_TIME_INCR;
889-
}
890-
if(!receiver.isDone()) {
891-
throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
892-
}
893-
return receiver.received;
894-
}
973+
DeleteObserver observer = new DeleteObserver(pkgName);
974+
975+
getPm().deletePackage(pkgName, observer, flags);
976+
observer.waitForCompletion(MAX_WAIT_TIME);
977+
978+
assertUninstalled(info);
979+
980+
// Verify we received the broadcast
981+
long waitTime = 0;
982+
while ((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME)) {
983+
receiver.wait(WAIT_TIME_INCR);
984+
waitTime += WAIT_TIME_INCR;
895985
}
986+
if (!receiver.isDone()) {
987+
throw new Exception("Timed out waiting for PACKAGE_REMOVED notification");
988+
}
989+
return receiver.received;
896990
} finally {
897991
mContext.unregisterReceiver(receiver);
898992
}
899993
}
900994

995+
private static void assertUninstalled(ApplicationInfo info) throws Exception {
996+
File nativeLibraryFile = new File(info.nativeLibraryDir);
997+
assertFalse("Native library directory should be erased", nativeLibraryFile.exists());
998+
}
999+
9011000
public void deleteFromRawResource(int iFlags, int dFlags) throws Exception {
9021001
InstallParams ip = sampleInstallFromRawResource(iFlags, false);
9031002
boolean retainData = ((dFlags & PackageManager.DELETE_KEEP_DATA) != 0);
@@ -1212,11 +1311,29 @@ void cleanUpInstall(InstallParams ip) throws Exception {
12121311
return;
12131312
}
12141313
Runtime.getRuntime().gc();
1215-
Log.i(TAG, "Deleting package : " + ip.pkg.packageName);
1216-
getPm().deletePackage(ip.pkg.packageName, null, 0);
1217-
File outFile = new File(ip.pkg.mScanPath);
1218-
if (outFile != null && outFile.exists()) {
1219-
outFile.delete();
1314+
1315+
final String packageName = ip.pkg.packageName;
1316+
Log.i(TAG, "Deleting package : " + packageName);
1317+
1318+
ApplicationInfo info = null;
1319+
try {
1320+
info = getPm().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
1321+
} catch (NameNotFoundException ignored) {
1322+
}
1323+
1324+
DeleteObserver observer = new DeleteObserver(packageName);
1325+
getPm().deletePackage(packageName, observer, 0);
1326+
observer.waitForCompletion(MAX_WAIT_TIME);
1327+
1328+
try {
1329+
if (info != null) {
1330+
assertUninstalled(info);
1331+
}
1332+
} finally {
1333+
File outFile = new File(ip.pkg.mScanPath);
1334+
if (outFile != null && outFile.exists()) {
1335+
outFile.delete();
1336+
}
12201337
}
12211338
}
12221339

@@ -1230,7 +1347,10 @@ private void cleanUpInstall(String pkgName) throws Exception {
12301347
PackageManager.GET_UNINSTALLED_PACKAGES);
12311348

12321349
if (info != null) {
1233-
getPm().deletePackage(pkgName, null, 0);
1350+
DeleteObserver observer = new DeleteObserver(pkgName);
1351+
getPm().deletePackage(pkgName, observer, 0);
1352+
observer.waitForCompletion(MAX_WAIT_TIME);
1353+
assertUninstalled(info);
12341354
}
12351355
} catch (NameNotFoundException e) {
12361356
}
@@ -1587,16 +1707,16 @@ private void moveFromRawResource(String outFileName, int rawResId, int installFl
15871707
if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
15881708
assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should NOT be set",
15891709
(info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
1590-
assertTrue("ApplicationInfo.nativeLibraryDir should start with " + info.dataDir,
1591-
info.nativeLibraryDir.startsWith(info.dataDir));
1592-
} else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
1710+
assertStartsWith("Native library dir should be in dataDir",
1711+
info.dataDir, info.nativeLibraryDir);
1712+
} else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0) {
15931713
assertTrue("ApplicationInfo.FLAG_EXTERNAL_STORAGE flag should be set",
15941714
(info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
1595-
assertTrue("ApplicationInfo.nativeLibraryDir should start with " + SECURE_CONTAINERS_PREFIX,
1596-
info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
1715+
assertStartsWith("Native library dir should point to ASEC",
1716+
SECURE_CONTAINERS_PREFIX, info.nativeLibraryDir);
15971717
final File nativeLibSymLink = new File(info.dataDir, "lib");
1598-
assertTrue("The data directory should have a 'lib' symlink that points to the ASEC container",
1599-
nativeLibSymLink.getCanonicalPath().startsWith(SECURE_CONTAINERS_PREFIX));
1718+
assertStartsWith("The data directory should have a 'lib' symlink that points to the ASEC container",
1719+
SECURE_CONTAINERS_PREFIX, nativeLibSymLink.getCanonicalPath());
16001720
}
16011721
}
16021722
} catch (NameNotFoundException e) {

0 commit comments

Comments
 (0)