Loading keystore/java/android/security/KeyChain.java +3 −3 Original line number Original line Diff line number Diff line Loading @@ -599,7 +599,7 @@ public final class KeyChain { private final Context context; private final Context context; private final ServiceConnection serviceConnection; private final ServiceConnection serviceConnection; private final IKeyChainService service; private final IKeyChainService service; private KeyChainConnection(Context context, protected KeyChainConnection(Context context, ServiceConnection serviceConnection, ServiceConnection serviceConnection, IKeyChainService service) { IKeyChainService service) { this.context = context; this.context = context; Loading packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +69 −4 Original line number Original line Diff line number Diff line Loading @@ -17,7 +17,10 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException; Loading @@ -28,16 +31,23 @@ import android.net.IConnectivityManager; import android.net.Network; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.NetworkRequest; import android.os.AsyncTask; import android.os.Handler; import android.os.RemoteException; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; import android.util.ArrayMap; import android.util.Log; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnConfig; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.settings.CurrentUserTracker; Loading @@ -59,6 +69,8 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; private static final int CA_CERT_LOADING_RETRY_TIME_IN_MS = 30_000; private final Context mContext; private final Context mContext; private final ConnectivityManager mConnectivityManager; private final ConnectivityManager mConnectivityManager; private final IConnectivityManager mConnectivityManagerService; private final IConnectivityManager mConnectivityManagerService; Loading @@ -73,6 +85,10 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private int mCurrentUserId; private int mCurrentUserId; private int mVpnUserId; private int mVpnUserId; // Key: userId, Value: whether the user has CACerts installed // Needs to be cached here since the query has to be asynchronous private ArrayMap<Integer, Boolean> mHasCACerts = new ArrayMap<Integer, Boolean>(); public SecurityControllerImpl(Context context) { public SecurityControllerImpl(Context context) { super(context); super(context); mContext = context; mContext = context; Loading @@ -86,6 +102,11 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi mUserManager = (UserManager) mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); context.getSystemService(Context.USER_SERVICE); IntentFilter filter = new IntentFilter(); filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, new Handler(Dependency.get(Dependency.BG_LOOPER))); // TODO: re-register network callback on user change. // TODO: re-register network callback on user change. mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); onUserSwitched(ActivityManager.getCurrentUser()); onUserSwitched(ActivityManager.getCurrentUser()); Loading Loading @@ -218,14 +239,16 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi @Override @Override public boolean hasCACertInCurrentUser() { public boolean hasCACertInCurrentUser() { //TODO: implement Boolean hasCACerts = mHasCACerts.get(mCurrentUserId); return false; return hasCACerts != null && hasCACerts.booleanValue(); } } @Override @Override public boolean hasCACertInWorkProfile() { public boolean hasCACertInWorkProfile() { //TODO: implement int userId = getWorkProfileUserId(mCurrentUserId); return false; if (userId == UserHandle.USER_NULL) return false; Boolean hasCACerts = mHasCACerts.get(userId); return hasCACerts != null && hasCACerts.booleanValue(); } } @Override @Override Loading Loading @@ -256,9 +279,16 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi } else { } else { mVpnUserId = mCurrentUserId; mVpnUserId = mCurrentUserId; } } refreshCACerts(); fireCallbacks(); fireCallbacks(); } } private void refreshCACerts() { new CACertLoader().execute(mCurrentUserId); int workProfileId = getWorkProfileUserId(mCurrentUserId); if (workProfileId != UserHandle.USER_NULL) new CACertLoader().execute(workProfileId); } private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) { private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) { if (cfg.legacy) { if (cfg.legacy) { return mContext.getString(R.string.legacy_vpn_name); return mContext.getString(R.string.legacy_vpn_name); Loading Loading @@ -348,4 +378,39 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi fireCallbacks(); fireCallbacks(); }; }; }; }; private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (KeyChain.ACTION_TRUST_STORE_CHANGED.equals(intent.getAction())) { refreshCACerts(); } } }; protected class CACertLoader extends AsyncTask<Integer, Void, Pair<Integer, Boolean> > { @Override protected Pair<Integer, Boolean> doInBackground(Integer... userId) { try (KeyChainConnection conn = KeyChain.bindAsUser(mContext, UserHandle.of(userId[0]))) { boolean hasCACerts = !(conn.getService().getUserCaAliases().getList().isEmpty()); return new Pair<Integer, Boolean>(userId[0], hasCACerts); } catch (RemoteException | InterruptedException | AssertionError e) { Log.i(TAG, e.getMessage()); new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed( () -> new CACertLoader().execute(userId[0]), CA_CERT_LOADING_RETRY_TIME_IN_MS); return new Pair<Integer, Boolean>(userId[0], null); } } @Override protected void onPostExecute(Pair<Integer, Boolean> result) { if (DEBUG) Log.d(TAG, "onPostExecute " + result); if (result.second != null) { mHasCACerts.put(result.first, result.second); fireCallbacks(); } } } } } packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java +83 −1 Original line number Original line Diff line number Diff line Loading @@ -21,31 +21,76 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doNothing; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.pm.StringParceledListSlice; import android.net.ConnectivityManager; import android.net.ConnectivityManager; import android.security.IKeyChainService; import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest; import com.android.systemui.statusbar.policy.SecurityController.SecurityControllerCallback; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; @SmallTest @SmallTest @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) public class SecurityControllerTest extends SysuiTestCase { public class SecurityControllerTest extends SysuiTestCase implements SecurityControllerCallback { private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); private final IKeyChainService.Stub mKeyChainService = mock(IKeyChainService.Stub.class); private SecurityControllerImpl mSecurityController; private SecurityControllerImpl mSecurityController; private CountDownLatch mStateChangedLatch; // implementing SecurityControllerCallback @Override public void onStateChanged() { mStateChangedLatch.countDown(); } @Before @Before public void setUp() throws Exception { public void setUp() throws Exception { mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mock(ConnectivityManager.class)); mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mock(ConnectivityManager.class)); Intent intent = new Intent(IKeyChainService.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); mContext.addMockService(comp, mKeyChainService); when(mKeyChainService.getUserCaAliases()) .thenReturn(new StringParceledListSlice(new ArrayList<String>())); // Without this line, mKeyChainService gets wrapped in a proxy when Stub.asInterface() is // used on it, and the mocking above does not work. when(mKeyChainService.queryLocalInterface("android.security.IKeyChainService")) .thenReturn(mKeyChainService); mSecurityController = new SecurityControllerImpl(mContext); mSecurityController = new SecurityControllerImpl(mContext); // Wait for one or two state changes from the CACertLoader(s) in the constructor of // mSecurityController mStateChangedLatch = new CountDownLatch(mSecurityController.hasWorkProfile() ? 2 : 1); mSecurityController.addCallback(this); } @After public void tearDown() { mSecurityController.removeCallback(this); } } @Test @Test Loading @@ -62,4 +107,41 @@ public class SecurityControllerTest extends SysuiTestCase { when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization"); when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization"); assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName()); assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName()); } } @Test @Ignore("Flaky") public void testCaCertLoader() throws Exception { assertTrue(mStateChangedLatch.await(3, TimeUnit.SECONDS)); assertFalse(mSecurityController.hasCACertInCurrentUser()); // With a CA cert mStateChangedLatch = new CountDownLatch(1); when(mKeyChainService.getUserCaAliases()) .thenReturn(new StringParceledListSlice(Arrays.asList("One CA Alias"))); mSecurityController.new CACertLoader() .execute(0); assertTrue(mStateChangedLatch.await(3, TimeUnit.SECONDS)); assertTrue(mSecurityController.hasCACertInCurrentUser()); // Exception mStateChangedLatch = new CountDownLatch(1); when(mKeyChainService.getUserCaAliases()) .thenThrow(new AssertionError("Test AssertionError")) .thenReturn(new StringParceledListSlice(new ArrayList<String>())); mSecurityController.new CACertLoader() .execute(0); assertFalse(mStateChangedLatch.await(3, TimeUnit.SECONDS)); assertTrue(mSecurityController.hasCACertInCurrentUser()); // The retry takes 30s //assertTrue(mStateChangedLatch.await(31, TimeUnit.SECONDS)); //assertFalse(mSecurityController.hasCACertInCurrentUser()); } } } Loading
keystore/java/android/security/KeyChain.java +3 −3 Original line number Original line Diff line number Diff line Loading @@ -599,7 +599,7 @@ public final class KeyChain { private final Context context; private final Context context; private final ServiceConnection serviceConnection; private final ServiceConnection serviceConnection; private final IKeyChainService service; private final IKeyChainService service; private KeyChainConnection(Context context, protected KeyChainConnection(Context context, ServiceConnection serviceConnection, ServiceConnection serviceConnection, IKeyChainService service) { IKeyChainService service) { this.context = context; this.context = context; Loading
packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +69 −4 Original line number Original line Diff line number Diff line Loading @@ -17,7 +17,10 @@ package com.android.systemui.statusbar.policy; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.NameNotFoundException; Loading @@ -28,16 +31,23 @@ import android.net.IConnectivityManager; import android.net.Network; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.NetworkRequest; import android.os.AsyncTask; import android.os.Handler; import android.os.RemoteException; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; import android.util.ArrayMap; import android.util.Log; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnConfig; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.settings.CurrentUserTracker; Loading @@ -59,6 +69,8 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED"; private static final int CA_CERT_LOADING_RETRY_TIME_IN_MS = 30_000; private final Context mContext; private final Context mContext; private final ConnectivityManager mConnectivityManager; private final ConnectivityManager mConnectivityManager; private final IConnectivityManager mConnectivityManagerService; private final IConnectivityManager mConnectivityManagerService; Loading @@ -73,6 +85,10 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi private int mCurrentUserId; private int mCurrentUserId; private int mVpnUserId; private int mVpnUserId; // Key: userId, Value: whether the user has CACerts installed // Needs to be cached here since the query has to be asynchronous private ArrayMap<Integer, Boolean> mHasCACerts = new ArrayMap<Integer, Boolean>(); public SecurityControllerImpl(Context context) { public SecurityControllerImpl(Context context) { super(context); super(context); mContext = context; mContext = context; Loading @@ -86,6 +102,11 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi mUserManager = (UserManager) mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); context.getSystemService(Context.USER_SERVICE); IntentFilter filter = new IntentFilter(); filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, new Handler(Dependency.get(Dependency.BG_LOOPER))); // TODO: re-register network callback on user change. // TODO: re-register network callback on user change. mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback); onUserSwitched(ActivityManager.getCurrentUser()); onUserSwitched(ActivityManager.getCurrentUser()); Loading Loading @@ -218,14 +239,16 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi @Override @Override public boolean hasCACertInCurrentUser() { public boolean hasCACertInCurrentUser() { //TODO: implement Boolean hasCACerts = mHasCACerts.get(mCurrentUserId); return false; return hasCACerts != null && hasCACerts.booleanValue(); } } @Override @Override public boolean hasCACertInWorkProfile() { public boolean hasCACertInWorkProfile() { //TODO: implement int userId = getWorkProfileUserId(mCurrentUserId); return false; if (userId == UserHandle.USER_NULL) return false; Boolean hasCACerts = mHasCACerts.get(userId); return hasCACerts != null && hasCACerts.booleanValue(); } } @Override @Override Loading Loading @@ -256,9 +279,16 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi } else { } else { mVpnUserId = mCurrentUserId; mVpnUserId = mCurrentUserId; } } refreshCACerts(); fireCallbacks(); fireCallbacks(); } } private void refreshCACerts() { new CACertLoader().execute(mCurrentUserId); int workProfileId = getWorkProfileUserId(mCurrentUserId); if (workProfileId != UserHandle.USER_NULL) new CACertLoader().execute(workProfileId); } private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) { private String getNameForVpnConfig(VpnConfig cfg, UserHandle user) { if (cfg.legacy) { if (cfg.legacy) { return mContext.getString(R.string.legacy_vpn_name); return mContext.getString(R.string.legacy_vpn_name); Loading Loading @@ -348,4 +378,39 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi fireCallbacks(); fireCallbacks(); }; }; }; }; private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (KeyChain.ACTION_TRUST_STORE_CHANGED.equals(intent.getAction())) { refreshCACerts(); } } }; protected class CACertLoader extends AsyncTask<Integer, Void, Pair<Integer, Boolean> > { @Override protected Pair<Integer, Boolean> doInBackground(Integer... userId) { try (KeyChainConnection conn = KeyChain.bindAsUser(mContext, UserHandle.of(userId[0]))) { boolean hasCACerts = !(conn.getService().getUserCaAliases().getList().isEmpty()); return new Pair<Integer, Boolean>(userId[0], hasCACerts); } catch (RemoteException | InterruptedException | AssertionError e) { Log.i(TAG, e.getMessage()); new Handler(Dependency.get(Dependency.BG_LOOPER)).postDelayed( () -> new CACertLoader().execute(userId[0]), CA_CERT_LOADING_RETRY_TIME_IN_MS); return new Pair<Integer, Boolean>(userId[0], null); } } @Override protected void onPostExecute(Pair<Integer, Boolean> result) { if (DEBUG) Log.d(TAG, "onPostExecute " + result); if (result.second != null) { mHasCACerts.put(result.first, result.second); fireCallbacks(); } } } } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java +83 −1 Original line number Original line Diff line number Diff line Loading @@ -21,31 +21,76 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.doNothing; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.pm.StringParceledListSlice; import android.net.ConnectivityManager; import android.net.ConnectivityManager; import android.security.IKeyChainService; import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest; import com.android.systemui.statusbar.policy.SecurityController.SecurityControllerCallback; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runner.RunWith; @SmallTest @SmallTest @RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class) public class SecurityControllerTest extends SysuiTestCase { public class SecurityControllerTest extends SysuiTestCase implements SecurityControllerCallback { private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); private final IKeyChainService.Stub mKeyChainService = mock(IKeyChainService.Stub.class); private SecurityControllerImpl mSecurityController; private SecurityControllerImpl mSecurityController; private CountDownLatch mStateChangedLatch; // implementing SecurityControllerCallback @Override public void onStateChanged() { mStateChangedLatch.countDown(); } @Before @Before public void setUp() throws Exception { public void setUp() throws Exception { mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mock(ConnectivityManager.class)); mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mock(ConnectivityManager.class)); Intent intent = new Intent(IKeyChainService.class.getName()); ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); mContext.addMockService(comp, mKeyChainService); when(mKeyChainService.getUserCaAliases()) .thenReturn(new StringParceledListSlice(new ArrayList<String>())); // Without this line, mKeyChainService gets wrapped in a proxy when Stub.asInterface() is // used on it, and the mocking above does not work. when(mKeyChainService.queryLocalInterface("android.security.IKeyChainService")) .thenReturn(mKeyChainService); mSecurityController = new SecurityControllerImpl(mContext); mSecurityController = new SecurityControllerImpl(mContext); // Wait for one or two state changes from the CACertLoader(s) in the constructor of // mSecurityController mStateChangedLatch = new CountDownLatch(mSecurityController.hasWorkProfile() ? 2 : 1); mSecurityController.addCallback(this); } @After public void tearDown() { mSecurityController.removeCallback(this); } } @Test @Test Loading @@ -62,4 +107,41 @@ public class SecurityControllerTest extends SysuiTestCase { when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization"); when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization"); assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName()); assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName()); } } @Test @Ignore("Flaky") public void testCaCertLoader() throws Exception { assertTrue(mStateChangedLatch.await(3, TimeUnit.SECONDS)); assertFalse(mSecurityController.hasCACertInCurrentUser()); // With a CA cert mStateChangedLatch = new CountDownLatch(1); when(mKeyChainService.getUserCaAliases()) .thenReturn(new StringParceledListSlice(Arrays.asList("One CA Alias"))); mSecurityController.new CACertLoader() .execute(0); assertTrue(mStateChangedLatch.await(3, TimeUnit.SECONDS)); assertTrue(mSecurityController.hasCACertInCurrentUser()); // Exception mStateChangedLatch = new CountDownLatch(1); when(mKeyChainService.getUserCaAliases()) .thenThrow(new AssertionError("Test AssertionError")) .thenReturn(new StringParceledListSlice(new ArrayList<String>())); mSecurityController.new CACertLoader() .execute(0); assertFalse(mStateChangedLatch.await(3, TimeUnit.SECONDS)); assertTrue(mSecurityController.hasCACertInCurrentUser()); // The retry takes 30s //assertTrue(mStateChangedLatch.await(31, TimeUnit.SECONDS)); //assertFalse(mSecurityController.hasCACertInCurrentUser()); } } }