QS: Do not display specific disclosure when the work profile is off

* Work-profile related disclosures (e.g. network logging on
  the work profile) should disappear when the work profile is off.
* BYOD device with a work profile
   * A disclosure isn't shown if there aren't any policies set.
   * A specific disclosure is shown if a policy is set. If the work
     profile is off, no disclosure is shown.
* COPE device
   * The disclosure 'This device belongs to your organization'
     is shown if there aren't any policies set.
   * A specific disclosure is shown if a policy is set. If the work
     profile is off, the disclosure 'This device belongs to your
     organization'is shown.

Manual testing scenarios (using TestDPC)
- PO no policy -> verify no disclosure
- PO with policy -> verify specific disclosure
- PO with policy but WP is off -> verify no disclosure
- COPE PO no policy -> verify org-owned device disclosure
- COPE PO with policy -> verify specific disclosure
- COPE PO with policy but WP is off -> verify org-owned device disclosure

Bug: 191741537
Test: atest QSSecurityFooterTest
      atest SecurityControllerTest
      Manual testing
Change-Id: I8036bbf8eba40329ae9fbf502aff1f33cd8d1c4a
This commit is contained in:
Alex Johnston
2021-06-22 13:39:03 +01:00
parent 5b24daa483
commit b5129c71a7
5 changed files with 88 additions and 16 deletions

View File

@@ -185,15 +185,22 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen
final boolean isProfileOwnerOfOrganizationOwnedDevice =
mSecurityController.isProfileOwnerOfOrganizationOwnedDevice();
final boolean isParentalControlsEnabled = mSecurityController.isParentalControlsEnabled();
final boolean isWorkProfileOn = mSecurityController.isWorkProfileOn();
final boolean hasDisclosableWorkProfilePolicy = hasCACertsInWorkProfile
|| vpnNameWorkProfile != null || (hasWorkProfile && isNetworkLoggingEnabled);
// Update visibility of footer
mIsVisible = (isDeviceManaged && !isDemoDevice) || hasCACerts || hasCACertsInWorkProfile
|| vpnName != null || vpnNameWorkProfile != null
|| isProfileOwnerOfOrganizationOwnedDevice || isParentalControlsEnabled
|| (hasWorkProfile && isNetworkLoggingEnabled);
mIsVisible = (isDeviceManaged && !isDemoDevice)
|| hasCACerts
|| vpnName != null
|| isProfileOwnerOfOrganizationOwnedDevice
|| isParentalControlsEnabled
|| (hasDisclosableWorkProfilePolicy && isWorkProfileOn);
// Update the view to be untappable if the device is an organization-owned device with a
// managed profile and there is no policy set which requires a privacy disclosure.
if (mIsVisible && isProfileOwnerOfOrganizationOwnedDevice && !isNetworkLoggingEnabled
&& !hasCACertsInWorkProfile && vpnNameWorkProfile == null) {
// managed profile and there is either:
// a) no policy set which requires a privacy disclosure.
// b) a specific work policy set but the work profile is turned off.
if (mIsVisible && isProfileOwnerOfOrganizationOwnedDevice
&& (!hasDisclosableWorkProfilePolicy || !isWorkProfileOn)) {
mRootView.setClickable(false);
mRootView.findViewById(R.id.footer_icon).setVisibility(View.GONE);
} else {
@@ -204,7 +211,8 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen
mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile,
hasCACerts, hasCACertsInWorkProfile, isNetworkLoggingEnabled, vpnName,
vpnNameWorkProfile, organizationName, workProfileOrganizationName,
isProfileOwnerOfOrganizationOwnedDevice, isParentalControlsEnabled);
isProfileOwnerOfOrganizationOwnedDevice, isParentalControlsEnabled,
isWorkProfileOn);
// Update the icon
int footerIconId = R.drawable.ic_info_outline;
if (vpnName != null || vpnNameWorkProfile != null) {
@@ -236,7 +244,8 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen
boolean hasCACerts, boolean hasCACertsInWorkProfile, boolean isNetworkLoggingEnabled,
String vpnName, String vpnNameWorkProfile, CharSequence organizationName,
CharSequence workProfileOrganizationName,
boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isParentalControlsEnabled) {
boolean isProfileOwnerOfOrganizationOwnedDevice, boolean isParentalControlsEnabled,
boolean isWorkProfileOn) {
if (isParentalControlsEnabled) {
return mContext.getString(R.string.quick_settings_disclosure_parental_controls);
}
@@ -280,7 +289,7 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen
organizationName);
}
} // end if(isDeviceManaged)
if (hasCACertsInWorkProfile) {
if (hasCACertsInWorkProfile && isWorkProfileOn) {
if (workProfileOrganizationName == null) {
return mContext.getString(
R.string.quick_settings_disclosure_managed_profile_monitoring);
@@ -295,7 +304,7 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen
if (vpnName != null && vpnNameWorkProfile != null) {
return mContext.getString(R.string.quick_settings_disclosure_vpns);
}
if (vpnNameWorkProfile != null) {
if (vpnNameWorkProfile != null && isWorkProfileOn) {
return mContext.getString(R.string.quick_settings_disclosure_managed_profile_named_vpn,
vpnNameWorkProfile);
}
@@ -308,7 +317,7 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen
return mContext.getString(R.string.quick_settings_disclosure_named_vpn,
vpnName);
}
if (hasWorkProfile && isNetworkLoggingEnabled) {
if (hasWorkProfile && isNetworkLoggingEnabled && isWorkProfileOn) {
return mContext.getString(
R.string.quick_settings_disclosure_managed_profile_network_activity);
}

View File

@@ -28,6 +28,8 @@ public interface SecurityController extends CallbackController<SecurityControlle
boolean isDeviceManaged();
boolean hasProfileOwner();
boolean hasWorkProfile();
/** Whether the work profile is turned on. */
boolean isWorkProfileOn();
/** Whether this device is organization-owned with a work profile **/
boolean isProfileOwnerOfOrganizationOwnedDevice();
String getDeviceOwnerName();
@@ -57,7 +59,6 @@ public interface SecurityController extends CallbackController<SecurityControlle
/** Label for admin */
CharSequence getLabel(DeviceAdminInfo info);
public interface SecurityControllerCallback {
void onStateChanged();
}

View File

@@ -210,6 +210,12 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
return getWorkProfileUserId(mCurrentUserId) != UserHandle.USER_NULL;
}
@Override
public boolean isWorkProfileOn() {
final UserHandle userHandle = UserHandle.of(getWorkProfileUserId(mCurrentUserId));
return userHandle != null && !mUserManager.isQuietModeEnabled(userHandle);
}
@Override
public boolean isProfileOwnerOfOrganizationOwnedDevice() {
return mDevicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile();

View File

@@ -204,6 +204,8 @@ public class QSSecurityFooterTest extends SysuiTestCase {
public void testTappableView_profileOwnerOfOrgOwnedDevice_networkLoggingEnabled() {
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
when(mSecurityController.hasWorkProfile()).thenReturn(true);
mFooter.refreshState();
@@ -212,6 +214,19 @@ public class QSSecurityFooterTest extends SysuiTestCase {
assertEquals(View.VISIBLE, mRootView.findViewById(R.id.footer_icon).getVisibility());
}
@Test
public void testUntappableView_profileOwnerOfOrgOwnedDevice_workProfileOff() {
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
assertFalse(mRootView.isClickable());
assertEquals(View.GONE, mRootView.findViewById(R.id.footer_icon).getVisibility());
}
@Test
public void testNetworkLoggingEnabled_deviceOwner() {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
@@ -237,9 +252,10 @@ public class QSSecurityFooterTest extends SysuiTestCase {
}
@Test
public void testNetworkLoggingEnabled_managedProfileOwner() {
public void testNetworkLoggingEnabled_managedProfileOwner_workProfileOn() {
when(mSecurityController.hasWorkProfile()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
@@ -248,6 +264,17 @@ public class QSSecurityFooterTest extends SysuiTestCase {
mFooterText.getText());
}
@Test
public void testNetworkLoggingEnabled_managedProfileOwner_workProfileOff() {
when(mSecurityController.hasWorkProfile()).thenReturn(true);
when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
assertEquals("", mFooterText.getText());
}
@Test
public void testManagedCACertsInstalled() {
when(mSecurityController.isDeviceManaged()).thenReturn(true);
@@ -326,9 +353,10 @@ public class QSSecurityFooterTest extends SysuiTestCase {
}
@Test
public void testWorkProfileCACertsInstalled() {
public void testWorkProfileCACertsInstalled_workProfileOn() {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
@@ -349,6 +377,17 @@ public class QSSecurityFooterTest extends SysuiTestCase {
mFooterText.getText());
}
@Test
public void testWorkProfileCACertsInstalled_workProfileOff() {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
when(mSecurityController.hasCACertInWorkProfile()).thenReturn(true);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
assertEquals("", mFooterText.getText());
}
@Test
public void testCACertsInstalled() {
when(mSecurityController.isDeviceManaged()).thenReturn(false);
@@ -375,9 +414,10 @@ public class QSSecurityFooterTest extends SysuiTestCase {
}
@Test
public void testWorkProfileVpnEnabled() {
public void testWorkProfileVpnEnabled_workProfileOn() {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
when(mSecurityController.isWorkProfileOn()).thenReturn(true);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
@@ -388,6 +428,17 @@ public class QSSecurityFooterTest extends SysuiTestCase {
mFooterText.getText());
}
@Test
public void testWorkProfileVpnEnabled_workProfileOff() {
when(mSecurityController.isVpnEnabled()).thenReturn(true);
when(mSecurityController.getWorkProfileVpnName()).thenReturn(VPN_PACKAGE_2);
when(mSecurityController.isWorkProfileOn()).thenReturn(false);
mFooter.refreshState();
TestableLooper.get(this).processAllMessages();
assertEquals("", mFooterText.getText());
}
@Test
public void testProfileOwnerOfOrganizationOwnedDeviceNoName() {
when(mSecurityController.isProfileOwnerOfOrganizationOwnedDevice()).thenReturn(true);

View File

@@ -43,6 +43,11 @@ public class FakeSecurityController extends BaseLeakChecker<SecurityControllerCa
return false;
}
@Override
public boolean isWorkProfileOn() {
return false;
}
@Override
public boolean isProfileOwnerOfOrganizationOwnedDevice() {
return false;