Introduced AppRestrictionsLock

It is used to serialize access to app restrictions state and reduce
contention on PM lock.

Bug: 65096648
Test: com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testApplicationRestrictions
Change-Id: I87c364e641e511f6cbe1e55f4fa3aa12c453c08f
This commit is contained in:
Fyodor Kupolov
2017-09-05 16:31:08 -07:00
parent aa4c059da1
commit d31cee9aae
2 changed files with 26 additions and 21 deletions

View File

@@ -128,6 +128,7 @@ import java.util.List;
*
* Method naming convention:
* <ul>
* <li> Methods suffixed with "LAr" should be called within the {@link #mAppRestrictionsLock} lock.
* <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock.
* <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
* <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
@@ -232,6 +233,8 @@ public class UserManagerService extends IUserManager.Stub {
// Short-term lock for internal state, when interaction/sync with PM is not required
private final Object mUsersLock = LockGuard.installNewLock(LockGuard.INDEX_USER);
private final Object mRestrictionsLock = new Object();
// Used for serializing access to app restriction files
private final Object mAppRestrictionsLock = new Object();
private final Handler mHandler;
@@ -2328,13 +2331,11 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Removes the app restrictions file for a specific package and user id, if it exists.
*/
private void cleanAppRestrictionsForPackage(String pkg, int userId) {
synchronized (mPackagesLock) {
File dir = Environment.getUserSystemDirectory(userId);
File resFile = new File(dir, packageToRestrictionsFileName(pkg));
if (resFile.exists()) {
resFile.delete();
}
private static void cleanAppRestrictionsForPackageLAr(String pkg, int userId) {
File dir = Environment.getUserSystemDirectory(userId);
File resFile = new File(dir, packageToRestrictionsFileName(pkg));
if (resFile.exists()) {
resFile.delete();
}
}
@@ -2853,9 +2854,9 @@ public class UserManagerService extends IUserManager.Stub {
|| !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
checkSystemOrRoot("get application restrictions for other user/app " + packageName);
}
synchronized (mPackagesLock) {
synchronized (mAppRestrictionsLock) {
// Read the restrictions from XML
return readApplicationRestrictionsLP(packageName, userId);
return readApplicationRestrictionsLAr(packageName, userId);
}
}
@@ -2866,12 +2867,12 @@ public class UserManagerService extends IUserManager.Stub {
if (restrictions != null) {
restrictions.setDefusable(true);
}
synchronized (mPackagesLock) {
synchronized (mAppRestrictionsLock) {
if (restrictions == null || restrictions.isEmpty()) {
cleanAppRestrictionsForPackage(packageName, userId);
cleanAppRestrictionsForPackageLAr(packageName, userId);
} else {
// Write the restrictions to XML
writeApplicationRestrictionsLP(packageName, restrictions, userId);
writeApplicationRestrictionsLAr(packageName, restrictions, userId);
}
}
@@ -2894,15 +2895,17 @@ public class UserManagerService extends IUserManager.Stub {
}
}
private Bundle readApplicationRestrictionsLP(String packageName, int userId) {
@GuardedBy("mAppRestrictionsLock")
private static Bundle readApplicationRestrictionsLAr(String packageName, int userId) {
AtomicFile restrictionsFile =
new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
packageToRestrictionsFileName(packageName)));
return readApplicationRestrictionsLP(restrictionsFile);
return readApplicationRestrictionsLAr(restrictionsFile);
}
@VisibleForTesting
static Bundle readApplicationRestrictionsLP(AtomicFile restrictionsFile) {
@GuardedBy("mAppRestrictionsLock")
static Bundle readApplicationRestrictionsLAr(AtomicFile restrictionsFile) {
final Bundle restrictions = new Bundle();
final ArrayList<String> values = new ArrayList<>();
if (!restrictionsFile.getBaseFile().exists()) {
@@ -2985,16 +2988,18 @@ public class UserManagerService extends IUserManager.Stub {
return childBundle;
}
private void writeApplicationRestrictionsLP(String packageName,
@GuardedBy("mAppRestrictionsLock")
private static void writeApplicationRestrictionsLAr(String packageName,
Bundle restrictions, int userId) {
AtomicFile restrictionsFile = new AtomicFile(
new File(Environment.getUserSystemDirectory(userId),
packageToRestrictionsFileName(packageName)));
writeApplicationRestrictionsLP(restrictions, restrictionsFile);
writeApplicationRestrictionsLAr(restrictions, restrictionsFile);
}
@VisibleForTesting
static void writeApplicationRestrictionsLP(Bundle restrictions, AtomicFile restrictionsFile) {
@GuardedBy("mAppRestrictionsLock")
static void writeApplicationRestrictionsLAr(Bundle restrictions, AtomicFile restrictionsFile) {
FileOutputStream fos = null;
try {
fos = restrictionsFile.startWrite();
@@ -3238,7 +3243,7 @@ public class UserManagerService extends IUserManager.Stub {
return -1;
}
private String packageToRestrictionsFileName(String packageName) {
private static String packageToRestrictionsFileName(String packageName) {
return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
}

View File

@@ -55,11 +55,11 @@ public class UserManagerServiceTest extends AndroidTestCase {
public void testWriteReadApplicationRestrictions() throws IOException {
AtomicFile atomicFile = new AtomicFile(restrictionsFile);
Bundle bundle = createBundle();
UserManagerService.writeApplicationRestrictionsLP(bundle, atomicFile);
UserManagerService.writeApplicationRestrictionsLAr(bundle, atomicFile);
assertTrue(atomicFile.getBaseFile().exists());
String s = FileUtils.readTextFile(restrictionsFile, 10000, "");
System.out.println("restrictionsFile: " + s);
bundle = UserManagerService.readApplicationRestrictionsLP(atomicFile);
bundle = UserManagerService.readApplicationRestrictionsLAr(atomicFile);
System.out.println("readApplicationRestrictionsLocked bundle: " + bundle);
assertBundle(bundle);
}