Enforce cross profile calendar policies in one place.
Instead of checking dpm policy in primary user and settings value
in managed profile user, we'd better check them all in primary user.
Calendar provider will need INTERACT_ACROSS_USER_FULL to access
settings provider and this permission is not granted to any app
in privapp-permissions-platform.xml. So I think it's safer to
change isPackageAllowedToAccessCalendar to check both
admin policy & settings value.
Bug: 123629973
Test: atest CalendarProvider2Test
Change-Id: I632204290454c2a00a2348333064e79a02557d9a
diff --git a/src/com/android/providers/calendar/CalendarProvider2.java b/src/com/android/providers/calendar/CalendarProvider2.java
index 9f5c87c..91610ea 100644
--- a/src/com/android/providers/calendar/CalendarProvider2.java
+++ b/src/com/android/providers/calendar/CalendarProvider2.java
@@ -832,14 +832,6 @@
String sortOrder) {
CalendarSanityChecker.getInstance(mContext).checkLastCheckTime();
- // Check if cross profile calendar is enabled in settings if caller does not come from
- // the same profile.
- if (isCallerCrossProfile()) {
- if (!mCrossProfileCalendarHelper.isCrossProfileCalendarEnabledInSettings()) {
- return createEmptyCursor(projection);
- }
- }
-
// Note don't use mCallingUid here. That's only used by mutation functions.
final int callingUid = Binder.getCallingUid();
@@ -894,23 +886,17 @@
}
/**
- * @VisibleForTesting
- */
- protected boolean isCallerCrossProfile() {
- return Binder.getCallingUserHandle().getIdentifier() != UserHandle.myUserId();
- }
-
- /**
* @return {@code true} if the calling package can access cross profile calendar. {@code false}
* otherwise.
*/
private boolean canAccessCrossProfileCalendar(int workProfileUserId) {
// The criteria include:
// 1. There exists a work profile linked to the current user.
- // 2. Profile owner of the work profile has whitelisted the calling package for cross
+ // 2. Profile owner of the work profile has allowed the calling package for cross
// profile calendar.
+ // 3. CROSS_PROFILE_CALENDAR_ENABLED is turned on in Settings.
return workProfileUserId != UserHandle.USER_NULL
- && mCrossProfileCalendarHelper.isPackageWhitelisted(
+ && mCrossProfileCalendarHelper.isPackageAllowedToAccessCalendar(
getCallingPackageName(), workProfileUserId);
}
diff --git a/src/com/android/providers/calendar/enterprise/CrossProfileCalendarHelper.java b/src/com/android/providers/calendar/enterprise/CrossProfileCalendarHelper.java
index 1c969bf..5e5cb95 100644
--- a/src/com/android/providers/calendar/enterprise/CrossProfileCalendarHelper.java
+++ b/src/com/android/providers/calendar/enterprise/CrossProfileCalendarHelper.java
@@ -108,14 +108,18 @@
}
/**
- * Returns whether a packaged is whitelisted by the profile owner of a work profile to access
- * the work calendar provider.
+ * Returns whether a package is allowed to access cross-profile calendar APIs.
+ *
+ * A package is allowed to access cross-profile calendar APIs if it's allowed by the
+ * profile owner of a managed profile to access the managed profile calendar provider,
+ * and the setting {@link Settings.Secure#CROSS_PROFILE_CALENDAR_ENABLED} is turned
+ * on in the managed profile.
*
* @param packageName the name of the package
- * @param managedProfileUserId the user id of the work profile
- * @return {@code true} if the package is whitelisted, {@false} otherwise.
+ * @param managedProfileUserId the user id of the managed profile
+ * @return {@code true} if the package is allowed, {@false} otherwise.
*/
- public boolean isPackageWhitelisted(String packageName, int managedProfileUserId) {
+ public boolean isPackageAllowedToAccessCalendar(String packageName, int managedProfileUserId) {
final Context managedProfileUserContext = createPackageContextAsUser(
mContext, managedProfileUserId);
final DevicePolicyManager mDpm = managedProfileUserContext.getSystemService(
@@ -123,17 +127,6 @@
return mDpm.isPackageAllowedToAccessCalendar(packageName);
}
- /**
- * Returns if cross profile calendar is allowed for a work profile in Settings.
- *
- * @return {@code true} if cross profile calendar is allowed in Settings, {@false} otherwise.
- */
- public boolean isCrossProfileCalendarEnabledInSettings() {
- final int enabled = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED, /* default = */0);
- return enabled == 1;
- }
-
private static void ensureProjectionAllowed(String[] projection, Set<String> validColumnsSet) {
for (String column : projection) {
if (!validColumnsSet.contains(column)) {
diff --git a/tests/src/com/android/providers/calendar/CalendarProvider2Test.java b/tests/src/com/android/providers/calendar/CalendarProvider2Test.java
index b66eb8a..19a5c26 100644
--- a/tests/src/com/android/providers/calendar/CalendarProvider2Test.java
+++ b/tests/src/com/android/providers/calendar/CalendarProvider2Test.java
@@ -1016,11 +1016,6 @@
protected void initCrossProfileCalendarHelper() {
mCrossProfileCalendarHelper = new MockCrossProfileCalendarHelper(mContext);
}
-
- @Override
- protected boolean isCallerCrossProfile() {
- return false;
- }
};
ProviderInfo info = new ProviderInfo();
info.authority = CalendarContract.AUTHORITY;
@@ -1031,11 +1026,6 @@
protected void initCrossProfileCalendarHelper() {
mCrossProfileCalendarHelper = new MockCrossProfileCalendarHelper(mContext);
}
-
- @Override
- protected boolean isCallerCrossProfile() {
- return true;
- }
};
ProviderInfo workProviderInfo = new ProviderInfo();
workProviderInfo.authority = WORK_PROFILE_AUTHORITY;
@@ -3202,8 +3192,7 @@
insertWorkEvent(WORK_EVENT_TITLE_STANDBY, calendarId,
WORK_EVENT_DTSTART_STANDBY, WORK_EVENT_DTEND_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
Uri.Builder builder = Instances.ENTERPRISE_CONTENT_URI.buildUpon();
ContentUris.appendId(builder, WORK_EVENT_DTSTART - DateUtils.YEAR_IN_MILLIS);
@@ -3238,8 +3227,7 @@
insertWorkEvent(WORK_EVENT_TITLE_STANDBY, calendarId,
WORK_EVENT_DTSTART_STANDBY, WORK_EVENT_DTEND_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
Uri.Builder builder = Instances.ENTERPRISE_CONTENT_SEARCH_URI.buildUpon();
ContentUris.appendId(builder, WORK_EVENT_DTSTART - DateUtils.YEAR_IN_MILLIS);
@@ -3274,8 +3262,7 @@
insertWorkEvent(WORK_EVENT_TITLE_STANDBY, calendarId,
WORK_EVENT_DTSTART_STANDBY, WORK_EVENT_DTEND_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
String selection = "(" + Events.TITLE + " = ? )";
String[] selectionArgs = new String[]{
@@ -3313,8 +3300,7 @@
insertWorkEvent(WORK_EVENT_TITLE_STANDBY, calendarId,
WORK_EVENT_DTSTART_STANDBY, WORK_EVENT_DTEND_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
// Test ENTERPRISE_CONTENT_URI_ID.
String[] projection = new String[]{
@@ -3348,8 +3334,7 @@
insertWorkEvent(WORK_EVENT_TITLE_STANDBY, calendarId,
WORK_EVENT_DTSTART_STANDBY, WORK_EVENT_DTEND_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
// Test all whitelisted columns are returned when projection is empty.
String selection = "(" + Events.TITLE + " = ? )";
@@ -3404,8 +3389,7 @@
final long idToTest = insertWorkCalendar(WORK_CALENDAR_TITLE);
insertWorkCalendar(WORK_CALENDAR_TITLE_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
// Test the return cursor is correct when the all checks are met.
String selection = "(" + Calendars.CALENDAR_DISPLAY_NAME + " = ? )";
@@ -3435,8 +3419,7 @@
final long idToTest = insertWorkCalendar(WORK_CALENDAR_TITLE);
insertWorkCalendar(WORK_CALENDAR_TITLE_STANDBY);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
// Test Calendars.ENTERPRISE_CONTENT_URI with id.
String[] projection = new String[] {
@@ -3461,8 +3444,7 @@
public void testEnterpriseCalendarsProjectionCalibration() {
final long idToTest = insertWorkCalendar(WORK_CALENDAR_TITLE);
// Assume cross profile uri access is allowed by policy and settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(true);
// Test all whitelisted columns are returned when projection is empty.
final Cursor cursor = mResolver.query(
@@ -3503,11 +3485,10 @@
}
}
- public void testEnterpriseCalendarsDisabledInSettings() {
+ public void testEnterpriseCalendarsNotAllowed() {
insertWorkCalendar(WORK_CALENDAR_TITLE);
- // Assume cross profile uri access is allowed by policy but disabled settings.
- MockCrossProfileCalendarHelper.setPackageWhitelisted(true);
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(false);
+ // Assume cross profile uri access is not allowed by policy or disabled in settings.
+ MockCrossProfileCalendarHelper.setPackageAllowedToAccessCalendar(false);
// Test empty cursor is returned if cross profile calendar is disabled in settings.
final Cursor cursor = mResolver.query(
@@ -3519,22 +3500,6 @@
cleanupEnterpriseTestForCalendars(1);
}
- public void testEnterpriseCalendarsNonWhitelistedPackage() {
- insertWorkCalendar(WORK_CALENDAR_TITLE);
- // Assume cross profile uri access is allowed by settings but disabled by policy.
- MockCrossProfileCalendarHelper.setCrossProfileCalendarEnabledInSettings(true);
- MockCrossProfileCalendarHelper.setPackageWhitelisted(false);
-
- // Test empty cursor is returned if cross profile calendar is disabled by policy.
- final Cursor cursor = mResolver.query(
- Calendars.ENTERPRISE_CONTENT_URI,
- new String[]{}, null, null, null);
- assertTrue(cursor != null);
- assertTrue(cursor.getCount() == 0);
-
- cleanupEnterpriseTestForCalendars(1);
- }
-
// Remove the two inserted calendars.
private void cleanupEnterpriseTestForCalendars(int numToDelete) {
final int numDeleted = mWorkProfileProvider.delete(Calendars.CONTENT_URI, null, null);
diff --git a/tests/src/com/android/providers/calendar/MockCrossProfileCalendarHelper.java b/tests/src/com/android/providers/calendar/MockCrossProfileCalendarHelper.java
index 2eba442..5b7e4f4 100644
--- a/tests/src/com/android/providers/calendar/MockCrossProfileCalendarHelper.java
+++ b/tests/src/com/android/providers/calendar/MockCrossProfileCalendarHelper.java
@@ -22,36 +22,22 @@
public class MockCrossProfileCalendarHelper extends CrossProfileCalendarHelper {
- private static boolean mCrossProfileCalendarEnabledInSettings = true;
- private static boolean mCallingPackageWhitelisted = true;
+ private static boolean mCallingPackageAllowed = true;
public MockCrossProfileCalendarHelper (Context context) {
super(context);
}
/**
- * Mock this method in unit test since it depends on Settings provider.
+ * Mock this method in unit test since it depends on DevicePolicyManager and SettingsProvider.
* It will be tested in integration test.
*/
@Override
- public boolean isCrossProfileCalendarEnabledInSettings() {
- return mCrossProfileCalendarEnabledInSettings;
+ public boolean isPackageAllowedToAccessCalendar(String packageName, int managedProfileUserId) {
+ return mCallingPackageAllowed;
}
- public static void setCrossProfileCalendarEnabledInSettings(boolean enabled) {
- mCrossProfileCalendarEnabledInSettings = enabled;
- }
-
- /**
- * Mock this method in unit test since it depends on DevicePolicyManager.
- * It will be tested in integration test.
- */
- @Override
- public boolean isPackageWhitelisted(String packageName, int managedProfileUserId) {
- return mCallingPackageWhitelisted;
- }
-
- public static void setPackageWhitelisted(boolean isWhitelisted) {
- mCallingPackageWhitelisted = isWhitelisted;
+ public static void setPackageAllowedToAccessCalendar(boolean isCallingPackageAllowed) {
+ mCallingPackageAllowed = isCallingPackageAllowed;
}
}