Merge "Allow device owner to configure profile network preference"

This commit is contained in:
Sooraj Sasindran
2022-05-02 07:13:21 +00:00
committed by Gerrit Code Review
2 changed files with 63 additions and 6 deletions

View File

@@ -108,6 +108,7 @@ import android.annotation.TargetApi;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.BroadcastOptions; import android.app.BroadcastOptions;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.usage.NetworkStatsManager; import android.app.usage.NetworkStatsManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
@@ -10639,13 +10640,29 @@ public class ConnectivityService extends IConnectivityManager.Stub
mQosCallbackTracker.unregisterCallback(callback); mQosCallbackTracker.unregisterCallback(callback);
} }
private boolean isNetworkPreferenceAllowedForProfile(@NonNull UserHandle profile) {
// UserManager.isManagedProfile returns true for all apps in managed user profiles.
// Enterprise device can be fully managed like device owner and such use case
// also should be supported. Calling app check for work profile and fully managed device
// is already done in DevicePolicyManager.
// This check is an extra caution to be sure device is fully managed or not.
final UserManager um = mContext.getSystemService(UserManager.class);
final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
if (um.isManagedProfile(profile.getIdentifier())) {
return true;
}
if (SdkLevel.isAtLeastT() && dpm.getDeviceOwner() != null) return true;
return false;
}
/** /**
* Request that a user profile is put by default on a network matching a given preference. * Set a list of default network selection policies for a user profile or device owner.
* *
* See the documentation for the individual preferences for a description of the supported * See the documentation for the individual preferences for a description of the supported
* behaviors. * behaviors.
* *
* @param profile the user profile for whih the preference is being set. * @param profile If the device owner is set, any profile is allowed.
Otherwise, the given profile can only be managed profile.
* @param preferences the list of profile network preferences for the * @param preferences the list of profile network preferences for the
* provided profile. * provided profile.
* @param listener an optional listener to listen for completion of the operation. * @param listener an optional listener to listen for completion of the operation.
@@ -10670,9 +10687,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
throw new IllegalArgumentException("Must explicitly specify a user handle (" throw new IllegalArgumentException("Must explicitly specify a user handle ("
+ "UserHandle.CURRENT not supported)"); + "UserHandle.CURRENT not supported)");
} }
final UserManager um = mContext.getSystemService(UserManager.class); if (!isNetworkPreferenceAllowedForProfile(profile)) {
if (!um.isManagedProfile(profile.getIdentifier())) { throw new IllegalArgumentException("Profile must be a managed profile "
throw new IllegalArgumentException("Profile must be a managed profile"); + "or the device owner must be set. ");
} }
final List<ProfileNetworkPreferenceList.Preference> preferenceList = final List<ProfileNetworkPreferenceList.Preference> preferenceList =

View File

@@ -194,6 +194,7 @@ import android.app.AlarmManager;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.usage.NetworkStatsManager; import android.app.usage.NetworkStatsManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
@@ -541,6 +542,7 @@ public class ConnectivityServiceTest {
@Mock NetworkPolicyManager mNetworkPolicyManager; @Mock NetworkPolicyManager mNetworkPolicyManager;
@Mock VpnProfileStore mVpnProfileStore; @Mock VpnProfileStore mVpnProfileStore;
@Mock SystemConfigManager mSystemConfigManager; @Mock SystemConfigManager mSystemConfigManager;
@Mock DevicePolicyManager mDevicePolicyManager;
@Mock Resources mResources; @Mock Resources mResources;
@Mock ClatCoordinator mClatCoordinator; @Mock ClatCoordinator mClatCoordinator;
@Mock PacProxyManager mPacProxyManager; @Mock PacProxyManager mPacProxyManager;
@@ -663,6 +665,7 @@ public class ConnectivityServiceTest {
if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager; if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager; if (Context.NETWORK_POLICY_SERVICE.equals(name)) return mNetworkPolicyManager;
if (Context.DEVICE_POLICY_SERVICE.equals(name)) return mDevicePolicyManager;
if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager; if (Context.SYSTEM_CONFIG_SERVICE.equals(name)) return mSystemConfigManager;
if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager; if (Context.NETWORK_STATS_SERVICE.equals(name)) return mStatsManager;
if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager; if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
@@ -691,6 +694,14 @@ public class ConnectivityServiceTest {
doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier())); doReturn(value).when(mUserManager).isManagedProfile(eq(userHandle.getIdentifier()));
} }
public void setDeviceOwner(@NonNull final UserHandle userHandle, String value) {
// This relies on all contexts for a given user returning the same UM mock
final DevicePolicyManager dpmMock = createContextAsUser(userHandle, 0 /* flags */)
.getSystemService(DevicePolicyManager.class);
doReturn(value).when(dpmMock).getDeviceOwner();
doReturn(value).when(mDevicePolicyManager).getDeviceOwner();
}
@Override @Override
public ContentResolver getContentResolver() { public ContentResolver getContentResolver() {
return mContentResolver; return mContentResolver;
@@ -14731,12 +14742,41 @@ public class ConnectivityServiceTest {
public void testProfileNetworkPrefWrongProfile() throws Exception { public void testProfileNetworkPrefWrongProfile() throws Exception {
final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID); final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
mServiceContext.setWorkProfile(testHandle, false); mServiceContext.setWorkProfile(testHandle, false);
assertThrows("Should not be able to set a user pref for a non-work profile", mServiceContext.setDeviceOwner(testHandle, null);
assertThrows("Should not be able to set a user pref for a non-work profile "
+ "and non device owner",
IllegalArgumentException.class , () -> IllegalArgumentException.class , () ->
mCm.setProfileNetworkPreference(testHandle, mCm.setProfileNetworkPreference(testHandle,
PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null)); PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
} }
/**
* Make sure requests for per-profile default networking for a device owner is
* accepted on T and not accepted on S
*/
public void testProfileNetworkDeviceOwner() throws Exception {
final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
mServiceContext.setWorkProfile(testHandle, false);
mServiceContext.setDeviceOwner(testHandle, "deviceOwnerPackage");
ProfileNetworkPreference.Builder profileNetworkPreferenceBuilder =
new ProfileNetworkPreference.Builder();
profileNetworkPreferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
profileNetworkPreferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
final TestOnCompleteListener listener = new TestOnCompleteListener();
if (SdkLevel.isAtLeastT()) {
mCm.setProfileNetworkPreferences(testHandle,
List.of(profileNetworkPreferenceBuilder.build()),
r -> r.run(), listener);
} else {
// S should not allow setting preference on device owner
assertThrows("Should not be able to set a user pref for a non-work profile on S",
IllegalArgumentException.class , () ->
mCm.setProfileNetworkPreferences(testHandle,
List.of(profileNetworkPreferenceBuilder.build()),
r -> r.run(), listener));
}
}
@Test @Test
public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception { public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception {
mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED); mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED);