Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +31 −34 Original line number Diff line number Diff line Loading @@ -278,7 +278,6 @@ import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Environment; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -7235,47 +7234,45 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkState(admin != null, "Lost mode location updates can only be sent on an organization-owned device."); mInjector.binderWithCleanCallingIdentity(() -> { final List<String> providers = mInjector.getLocationManager().getAllProviders().stream() .filter(mInjector.getLocationManager()::isProviderEnabled) .collect(Collectors.toList()); if (providers.isEmpty()) { future.complete(false); return; String[] providers = {LocationManager.FUSED_PROVIDER, LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER}; tryRetrieveAndSendLocationUpdate(admin, future, providers, /* index= */ 0); }); } } final CancellationSignal cancellationSignal = new CancellationSignal(); List<String> providersWithNullLocation = new ArrayList<String>(); for (String provider : providers) { mInjector.getLocationManager().getCurrentLocation(provider, cancellationSignal, mContext.getMainExecutor(), location -> { if (cancellationSignal.isCanceled()) { /** Send lost mode location updates recursively, in order of the list of location providers. */ private void tryRetrieveAndSendLocationUpdate(ActiveAdmin admin, AndroidFuture<Boolean> future, String[] providers, int index) { // None of the providers were able to get location, return false if (index == providers.length) { future.complete(false); return; } else if (location != null) { sendLostModeLocationUpdate(admin, location); cancellationSignal.cancel(); } if (mInjector.getLocationManager().isProviderEnabled(providers[index])) { mInjector.getLocationManager().getCurrentLocation(providers[index], /* cancellationSignal= */ null, mContext.getMainExecutor(), location -> { if (location != null) { mContext.sendBroadcastAsUser( newLostModeLocationUpdateIntent(admin, location), admin.getUserHandle()); future.complete(true); } else { // location == null, provider wasn't able to get location, see // if there are more providers providersWithNullLocation.add(provider); if (providers.size() == providersWithNullLocation.size()) { future.complete(false); } tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1); } } ); } }); } else { tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1); } } private void sendLostModeLocationUpdate(ActiveAdmin admin, Location location) { private Intent newLostModeLocationUpdateIntent(ActiveAdmin admin, Location location) { final Intent intent = new Intent( DevicePolicyManager.ACTION_LOST_MODE_LOCATION_UPDATE); intent.putExtra(DevicePolicyManager.EXTRA_LOST_MODE_LOCATION, location); intent.setPackage(admin.info.getPackageName()); mContext.sendBroadcastAsUser(intent, admin.getUserHandle()); return intent; } /** Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +21 −8 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL; import static android.app.admin.DevicePolicyManager.WIPE_EUICC; import static android.app.admin.PasswordMetrics.computeForPasswordOrPin; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; import static android.location.LocationManager.FUSED_PROVIDER; import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK; Loading Loading @@ -8462,34 +8465,44 @@ public class DevicePolicyManagerTest extends DpmTestBase { @Test public void testSendLostModeLocationUpdate_asDeviceOwner() throws Exception { final String TEST_PROVIDER = "network"; mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); setDeviceOwner(); when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER)); when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true); when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, times(1)).getCurrentLocation( eq(TEST_PROVIDER), any(), eq(getServices().executor), any()); eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } @Test public void testSendLostModeLocationUpdate_asProfileOwnerOfOrgOwnedDevice() throws Exception { final String TEST_PROVIDER = "network"; final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER)); when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true); when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, times(1)).getCurrentLocation( eq(TEST_PROVIDER), any(), eq(getServices().executor), any()); eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } @Test public void testSendLostModeLocationUpdate_noProviderIsEnabled() throws Exception { mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); setDeviceOwner(); when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(false); when(getServices().locationManager.isProviderEnabled(NETWORK_PROVIDER)).thenReturn(false); when(getServices().locationManager.isProviderEnabled(GPS_PROVIDER)).thenReturn(false); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, never()).getCurrentLocation( eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { Loading Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +31 −34 Original line number Diff line number Diff line Loading @@ -278,7 +278,6 @@ import android.net.wifi.WifiManager; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.Environment; import android.os.Handler; import android.os.IBinder; Loading Loading @@ -7235,47 +7234,45 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkState(admin != null, "Lost mode location updates can only be sent on an organization-owned device."); mInjector.binderWithCleanCallingIdentity(() -> { final List<String> providers = mInjector.getLocationManager().getAllProviders().stream() .filter(mInjector.getLocationManager()::isProviderEnabled) .collect(Collectors.toList()); if (providers.isEmpty()) { future.complete(false); return; String[] providers = {LocationManager.FUSED_PROVIDER, LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER}; tryRetrieveAndSendLocationUpdate(admin, future, providers, /* index= */ 0); }); } } final CancellationSignal cancellationSignal = new CancellationSignal(); List<String> providersWithNullLocation = new ArrayList<String>(); for (String provider : providers) { mInjector.getLocationManager().getCurrentLocation(provider, cancellationSignal, mContext.getMainExecutor(), location -> { if (cancellationSignal.isCanceled()) { /** Send lost mode location updates recursively, in order of the list of location providers. */ private void tryRetrieveAndSendLocationUpdate(ActiveAdmin admin, AndroidFuture<Boolean> future, String[] providers, int index) { // None of the providers were able to get location, return false if (index == providers.length) { future.complete(false); return; } else if (location != null) { sendLostModeLocationUpdate(admin, location); cancellationSignal.cancel(); } if (mInjector.getLocationManager().isProviderEnabled(providers[index])) { mInjector.getLocationManager().getCurrentLocation(providers[index], /* cancellationSignal= */ null, mContext.getMainExecutor(), location -> { if (location != null) { mContext.sendBroadcastAsUser( newLostModeLocationUpdateIntent(admin, location), admin.getUserHandle()); future.complete(true); } else { // location == null, provider wasn't able to get location, see // if there are more providers providersWithNullLocation.add(provider); if (providers.size() == providersWithNullLocation.size()) { future.complete(false); } tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1); } } ); } }); } else { tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1); } } private void sendLostModeLocationUpdate(ActiveAdmin admin, Location location) { private Intent newLostModeLocationUpdateIntent(ActiveAdmin admin, Location location) { final Intent intent = new Intent( DevicePolicyManager.ACTION_LOST_MODE_LOCATION_UPDATE); intent.putExtra(DevicePolicyManager.EXTRA_LOST_MODE_LOCATION, location); intent.setPackage(admin.info.getPackageName()); mContext.sendBroadcastAsUser(intent, admin.getUserHandle()); return intent; } /** Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +21 −8 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL; import static android.app.admin.DevicePolicyManager.WIPE_EUICC; import static android.app.admin.PasswordMetrics.computeForPasswordOrPin; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; import static android.location.LocationManager.FUSED_PROVIDER; import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE; import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK; Loading Loading @@ -8462,34 +8465,44 @@ public class DevicePolicyManagerTest extends DpmTestBase { @Test public void testSendLostModeLocationUpdate_asDeviceOwner() throws Exception { final String TEST_PROVIDER = "network"; mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); setDeviceOwner(); when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER)); when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true); when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, times(1)).getCurrentLocation( eq(TEST_PROVIDER), any(), eq(getServices().executor), any()); eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } @Test public void testSendLostModeLocationUpdate_asProfileOwnerOfOrgOwnedDevice() throws Exception { final String TEST_PROVIDER = "network"; final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER)); when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true); when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, times(1)).getCurrentLocation( eq(TEST_PROVIDER), any(), eq(getServices().executor), any()); eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } @Test public void testSendLostModeLocationUpdate_noProviderIsEnabled() throws Exception { mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE); setDeviceOwner(); when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(false); when(getServices().locationManager.isProviderEnabled(NETWORK_PROVIDER)).thenReturn(false); when(getServices().locationManager.isProviderEnabled(GPS_PROVIDER)).thenReturn(false); dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {}); verify(getServices().locationManager, never()).getCurrentLocation( eq(FUSED_PROVIDER), any(), eq(getServices().executor), any()); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { Loading