1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.policy; 18 19 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; 20 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 21 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertFalse; 24 import static org.junit.Assert.assertTrue; 25 import static org.mockito.Matchers.any; 26 import static org.mockito.Matchers.anyInt; 27 import static org.mockito.Matchers.anyObject; 28 import static org.mockito.Matchers.argThat; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.app.admin.DevicePolicyManager; 35 import android.content.BroadcastReceiver; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.pm.StringParceledListSlice; 40 import android.content.pm.UserInfo; 41 import android.net.ConnectivityManager; 42 import android.net.ConnectivityManager.NetworkCallback; 43 import android.net.NetworkRequest; 44 import android.os.Handler; 45 import android.os.UserManager; 46 import android.security.IKeyChainService; 47 48 import androidx.test.filters.SmallTest; 49 import androidx.test.runner.AndroidJUnit4; 50 51 import com.android.systemui.SysuiTestCase; 52 import com.android.systemui.broadcast.BroadcastDispatcher; 53 import com.android.systemui.dump.DumpManager; 54 import com.android.systemui.settings.UserTracker; 55 import com.android.systemui.util.concurrency.FakeExecutor; 56 import com.android.systemui.util.time.FakeSystemClock; 57 58 import org.junit.Before; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 import org.mockito.ArgumentCaptor; 62 import org.mockito.Mockito; 63 64 import java.util.ArrayList; 65 import java.util.Arrays; 66 import java.util.List; 67 import java.util.concurrent.atomic.AtomicBoolean; 68 69 @SmallTest 70 @RunWith(AndroidJUnit4.class) 71 public class SecurityControllerTest extends SysuiTestCase { 72 private static final ComponentName DEVICE_OWNER_COMPONENT = 73 new ComponentName("com.android.foo", "bar"); 74 75 private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class); 76 private final IKeyChainService.Stub mKeyChainService = mock(IKeyChainService.Stub.class); 77 private final UserManager mUserManager = mock(UserManager.class); 78 private final UserTracker mUserTracker = mock(UserTracker.class); 79 private final BroadcastDispatcher mBroadcastDispatcher = mock(BroadcastDispatcher.class); 80 private final Handler mHandler = mock(Handler.class); 81 private SecurityControllerImpl mSecurityController; 82 private ConnectivityManager mConnectivityManager = mock(ConnectivityManager.class); 83 private FakeExecutor mMainExecutor; 84 private FakeExecutor mBgExecutor; 85 private BroadcastReceiver mBroadcastReceiver; 86 87 @Before setUp()88 public void setUp() throws Exception { 89 mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager); 90 mContext.addMockSystemService(Context.USER_SERVICE, mUserManager); 91 mContext.addMockSystemService(Context.CONNECTIVITY_SERVICE, mConnectivityManager); 92 93 Intent intent = new Intent(IKeyChainService.class.getName()); 94 ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); 95 mContext.addMockService(comp, mKeyChainService); 96 97 when(mUserManager.getUserInfo(anyInt())).thenReturn(new UserInfo()); 98 when(mUserManager.isUserUnlocked(any())).thenReturn(true); 99 100 when(mKeyChainService.getUserCaAliases()) 101 .thenReturn(new StringParceledListSlice(new ArrayList<String>())); 102 // Without this line, mKeyChainService gets wrapped in a proxy when Stub.asInterface() is 103 // used on it, and the mocking above does not work. 104 when(mKeyChainService.queryLocalInterface("android.security.IKeyChainService")) 105 .thenReturn(mKeyChainService); 106 107 ArgumentCaptor<BroadcastReceiver> brCaptor = 108 ArgumentCaptor.forClass(BroadcastReceiver.class); 109 110 mMainExecutor = new FakeExecutor(new FakeSystemClock()); 111 mBgExecutor = new FakeExecutor(new FakeSystemClock()); 112 mSecurityController = new SecurityControllerImpl( 113 mContext, 114 mUserTracker, 115 mHandler, 116 mBroadcastDispatcher, 117 mMainExecutor, 118 mBgExecutor, 119 Mockito.mock(DumpManager.class)); 120 121 verify(mBroadcastDispatcher).registerReceiverWithHandler( 122 brCaptor.capture(), 123 anyObject(), 124 anyObject(), 125 anyObject()); 126 127 mBroadcastReceiver = brCaptor.getValue(); 128 } 129 130 @Test testIsDeviceManaged()131 public void testIsDeviceManaged() { 132 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(true); 133 assertTrue(mSecurityController.isDeviceManaged()); 134 135 when(mDevicePolicyManager.isDeviceManaged()).thenReturn(false); 136 assertFalse(mSecurityController.isDeviceManaged()); 137 } 138 139 @Test testGetDeviceOwnerOrganizationName()140 public void testGetDeviceOwnerOrganizationName() { 141 when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn("organization"); 142 assertEquals("organization", mSecurityController.getDeviceOwnerOrganizationName()); 143 } 144 145 @Test testGetDeviceOwnerComponentOnAnyUser()146 public void testGetDeviceOwnerComponentOnAnyUser() { 147 when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()) 148 .thenReturn(DEVICE_OWNER_COMPONENT); 149 assertEquals(mSecurityController.getDeviceOwnerComponentOnAnyUser(), 150 DEVICE_OWNER_COMPONENT); 151 } 152 153 @Test testIsFinancedDevice()154 public void testIsFinancedDevice() { 155 when(mDevicePolicyManager.isFinancedDevice()).thenReturn(true); 156 // TODO(b/259908270): remove 157 when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) 158 .thenReturn(DEVICE_OWNER_TYPE_FINANCED); 159 assertEquals(mSecurityController.isFinancedDevice(), true); 160 } 161 162 @Test testWorkAccount()163 public void testWorkAccount() throws Exception { 164 assertFalse(mSecurityController.hasCACertInCurrentUser()); 165 166 final int PRIMARY_USER_ID = 0; 167 final int MANAGED_USER_ID = 1; 168 List<UserInfo> profiles = Arrays.asList(new UserInfo(PRIMARY_USER_ID, "Primary", 169 UserInfo.FLAG_PRIMARY), 170 new UserInfo(MANAGED_USER_ID, "Working", 171 UserInfo.FLAG_MANAGED_PROFILE)); 172 when(mUserManager.getProfiles(anyInt())).thenReturn(profiles); 173 assertTrue(mSecurityController.hasWorkProfile()); 174 assertFalse(mSecurityController.hasCACertInWorkProfile()); 175 176 when(mKeyChainService.getUserCaAliases()) 177 .thenReturn(new StringParceledListSlice(Arrays.asList("One CA Alias"))); 178 179 refreshCACerts(MANAGED_USER_ID); 180 mBgExecutor.runAllReady(); 181 182 assertTrue(mSecurityController.hasCACertInWorkProfile()); 183 } 184 185 @Test testCaCertLoader()186 public void testCaCertLoader() throws Exception { 187 assertFalse(mSecurityController.hasCACertInCurrentUser()); 188 189 // With a CA cert 190 when(mKeyChainService.getUserCaAliases()) 191 .thenReturn(new StringParceledListSlice(Arrays.asList("One CA Alias"))); 192 193 refreshCACerts(0); 194 mBgExecutor.runAllReady(); 195 196 assertTrue(mSecurityController.hasCACertInCurrentUser()); 197 198 // Exception 199 when(mKeyChainService.getUserCaAliases()) 200 .thenThrow(new AssertionError("Test AssertionError")) 201 .thenReturn(new StringParceledListSlice(new ArrayList<String>())); 202 203 refreshCACerts(0); 204 mBgExecutor.runAllReady(); 205 206 assertTrue(mSecurityController.hasCACertInCurrentUser()); 207 208 refreshCACerts(0); 209 mBgExecutor.runAllReady(); 210 211 assertFalse(mSecurityController.hasCACertInCurrentUser()); 212 } 213 214 @Test testNetworkRequest()215 public void testNetworkRequest() { 216 verify(mConnectivityManager, times(1)).registerNetworkCallback(argThat( 217 (NetworkRequest request) -> 218 request.equals(new NetworkRequest.Builder() 219 .clearCapabilities().addTransportType(TRANSPORT_VPN).build()) 220 ), any(NetworkCallback.class)); 221 } 222 223 @Test testRemoveCallbackWhileDispatch_doesntCrash()224 public void testRemoveCallbackWhileDispatch_doesntCrash() { 225 final AtomicBoolean remove = new AtomicBoolean(false); 226 SecurityController.SecurityControllerCallback callback = 227 new SecurityController.SecurityControllerCallback() { 228 @Override 229 public void onStateChanged() { 230 if (remove.get()) { 231 mSecurityController.removeCallback(this); 232 } 233 } 234 }; 235 mSecurityController.addCallback(callback); 236 // Add another callback so the iteration continues 237 mSecurityController.addCallback(() -> {}); 238 mBgExecutor.runAllReady(); 239 remove.set(true); 240 241 mSecurityController.onUserSwitched(10); 242 mBgExecutor.runAllReady(); 243 } 244 245 /** 246 * refresh CA certs by sending a user unlocked broadcast for the desired user 247 */ refreshCACerts(int userId)248 private void refreshCACerts(int userId) { 249 Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED); 250 intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); 251 mBroadcastReceiver.onReceive(mContext, intent); 252 } 253 } 254