Loading core/java/android/app/admin/DevicePolicyManager.java +33 −21 Original line number Diff line number Diff line Loading @@ -11796,8 +11796,11 @@ public class DevicePolicyManager { } /** * Called by a device owner or delegated app with {@link #DELEGATION_NETWORK_LOGGING} to * control the network logging feature. * Called by a device owner, profile owner of a managed profile or delegated app with * {@link #DELEGATION_NETWORK_LOGGING} to control the network logging feature. * * <p> When network logging is enabled by a profile owner, the network logs will only include * work profile network activity, not activity on the personal profile. * * <p> Network logs contain DNS lookup and connect() library call events. The following library * functions are recorded while network logging is active: Loading Loading @@ -11837,7 +11840,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if called by a delegated app. * @param enabled whether network logging should be enabled or not. * @throws SecurityException if {@code admin} is not a device owner. * @throws SecurityException if {@code admin} is not a device owner or profile owner. * @see #setAffiliationIds * @see #retrieveNetworkLogs */ Loading @@ -11851,14 +11854,16 @@ public class DevicePolicyManager { } /** * Return whether network logging is enabled by a device owner. * Return whether network logging is enabled by a device owner or profile owner of * a managed profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only * be {@code null} if the caller is a delegated app with {@link #DELEGATION_NETWORK_LOGGING} * or has MANAGE_USERS permission. * @return {@code true} if network logging is enabled by device owner, {@code false} otherwise. * @throws SecurityException if {@code admin} is not a device owner and caller has * no MANAGE_USERS permission * @return {@code true} if network logging is enabled by device owner or profile owner, * {@code false} otherwise. * @throws SecurityException if {@code admin} is not a device owner or profile owner and * caller has no MANAGE_USERS permission */ public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) { throwIfParentInstance("isNetworkLoggingEnabled"); Loading @@ -11870,9 +11875,14 @@ public class DevicePolicyManager { } /** * Called by device owner or delegated app with {@link #DELEGATION_NETWORK_LOGGING} to retrieve * the most recent batch of network logging events. * A device owner has to provide a batchToken provided as part of * Called by device owner, profile owner of a managed profile or delegated app with * {@link #DELEGATION_NETWORK_LOGGING} to retrieve the most recent batch of * network logging events. * * <p> When network logging is enabled by a profile owner, the network logs will only include * work profile network activity, not activity on the personal profile. * * A device owner or profile owner has to provide a batchToken provided as part of * {@link DeviceAdminReceiver#onNetworkLogsAvailable} callback. If the token doesn't match the * token of the most recent available batch of logs, {@code null} will be returned. * Loading @@ -11884,11 +11894,11 @@ public class DevicePolicyManager { * after the device device owner has been notified via * {@link DeviceAdminReceiver#onNetworkLogsAvailable}. * * <p>If a secondary user or profile is created, calling this method will throw a * {@link SecurityException} until all users become affiliated again. It will also no longer be * possible to retrieve the network logs batch with the most recent batchToken provided * by {@link DeviceAdminReceiver#onNetworkLogsAvailable}. See * {@link DevicePolicyManager#setAffiliationIds}. * <p>If the caller is not a profile owner and a secondary user or profile is created, calling * this method will throw a {@link SecurityException} until all users become affiliated again. * It will also no longer be possible to retrieve the network logs batch with the most recent * batchToken provided by {@link DeviceAdminReceiver#onNetworkLogsAvailable}. * See {@link DevicePolicyManager#setAffiliationIds}. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if called by a delegated app. Loading @@ -11896,8 +11906,9 @@ public class DevicePolicyManager { * @return A new batch of network logs which is a list of {@link NetworkEvent}. Returns * {@code null} if the batch represented by batchToken is no longer available or if * logging is disabled. * @throws SecurityException if {@code admin} is not a device owner, or there is at least one * profile or secondary user that is not affiliated with the device. * @throws SecurityException if {@code admin} is not a device owner, profile owner or if the * {@code admin} is not a profile owner and there is at least one profile or secondary user * that is not affiliated with the device. * @see #setAffiliationIds * @see DeviceAdminReceiver#onNetworkLogsAvailable */ Loading Loading @@ -12016,11 +12027,12 @@ public class DevicePolicyManager { } /** * Called by the system to get the time at which the device owner last retrieved network logging * events. * Called by the system to get the time at which the device owner or profile owner of a * managed profile last retrieved network logging events. * * @return the time at which the device owner most recently retrieved network logging events, in * milliseconds since epoch; -1 if network logging events were never retrieved. * @return the time at which the device owner or profile owner most recently retrieved network * logging events, in milliseconds since epoch; -1 if network logging events were * never retrieved. * @throws SecurityException if the caller is not the device owner, does not hold the * MANAGE_USERS permission and is not the system. * services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +88 −32 Original line number Diff line number Diff line Loading @@ -782,8 +782,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * however it's too early in the boot process to register with IIpConnectivityMetrics * to listen for events. */ if (Intent.ACTION_USER_STARTED.equals(action) && userHandle == mOwners.getDeviceOwnerUserId()) { if (Intent.ACTION_USER_STARTED.equals(action) && userHandle == UserHandle.USER_SYSTEM) { synchronized (getLockObject()) { if (isNetworkLoggingEnabledInternalLocked()) { setNetworkLoggingActiveInternal(true); Loading Loading @@ -7533,6 +7532,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { sendActiveAdminCommand(action, extras, deviceOwnerUserId, receiverComponent); } void sendDeviceOwnerOrProfileOwnerCommand(String action, Bundle extras, int userId) { if (userId == UserHandle.USER_ALL) { userId = UserHandle.USER_SYSTEM; } ComponentName receiverComponent = null; if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) { receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId); } if (receiverComponent == null) { receiverComponent = getOwnerComponent(userId); } sendActiveAdminCommand(action, extras, userId, receiverComponent); } private void sendProfileOwnerCommand(String action, Bundle extras, @UserIdInt int userId) { sendActiveAdminCommand(action, extras, userId, mOwners.getProfileOwnerComponent(userId)); Loading Loading @@ -8357,6 +8370,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { deleteTransferOwnershipBundleLocked(userId); toggleBackupServiceActive(userId, true); applyManagedProfileRestrictionIfDeviceOwnerLocked(); setNetworkLoggingActiveInternal(false); } @Override Loading Loading @@ -14184,7 +14198,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } final CallerIdentity caller = getCallerIdentity(admin, packageName); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller)) Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING))); synchronized (getLockObject()) { Loading @@ -14192,11 +14208,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // already in the requested state return; } ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); deviceOwner.isNetworkLoggingEnabled = enabled; final ActiveAdmin activeAdmin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId()); activeAdmin.isNetworkLoggingEnabled = enabled; if (!enabled) { deviceOwner.numNetworkLoggingNotifications = 0; deviceOwner.lastNetworkLoggingNotificationTimeMs = 0; activeAdmin.numNetworkLoggingNotifications = 0; activeAdmin.lastNetworkLoggingNotificationTimeMs = 0; } saveSettingsLocked(caller.getUserId()); setNetworkLoggingActiveInternal(enabled); Loading @@ -14214,7 +14230,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { mInjector.binderWithCleanCallingIdentity(() -> { if (active) { mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal()); if (mNetworkLogger == null) { final int affectedUserId = getNetworkLoggingAffectedUser(); mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal(), affectedUserId == UserHandle.USER_SYSTEM ? UserHandle.USER_ALL : affectedUserId); } if (!mNetworkLogger.startNetworkLogging()) { mNetworkLogger = null; Slog.wtf(LOG_TAG, "Network logging could not be started due to the logging" Loading @@ -14234,6 +14256,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private @UserIdInt int getNetworkLoggingAffectedUser() { synchronized (getLockObject()) { if (mOwners.hasDeviceOwner()) { return mOwners.getDeviceOwnerUserId(); } else { return mInjector.binderWithCleanCallingIdentity( () -> getManagedUserId(UserHandle.USER_SYSTEM)); } } } private ActiveAdmin getNetworkLoggingControllingAdminLocked() { int affectedUserId = getNetworkLoggingAffectedUser(); if (affectedUserId < 0) { return null; } return getDeviceOrProfileOwnerAdminLocked(affectedUserId); } @Override public long forceNetworkLogs() { Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()), Loading @@ -14254,11 +14295,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @GuardedBy("getLockObject()") private void maybePauseDeviceWideLoggingLocked() { if (!areAllUsersAffiliatedWithDeviceLocked()) { if (mOwners.hasDeviceOwner()) { Slog.i(LOG_TAG, "There are unaffiliated users, network logging will be " + "paused if enabled."); if (mNetworkLogger != null) { mNetworkLogger.pause(); } } if (!isOrganizationOwnedDeviceWithManagedProfile()) { Slog.i(LOG_TAG, "Not org-owned managed profile device, security logging will be " + "paused if enabled."); Loading @@ -14276,7 +14319,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (allUsersAffiliated || orgOwnedProfileDevice) { mSecurityLogMonitor.resume(); } if (allUsersAffiliated) { // If there is no device owner, then per-user network logging may be enabled for the // managed profile. In which case, all users do not need to be affiliated. if (allUsersAffiliated || !mOwners.hasDeviceOwner()) { if (mNetworkLogger != null) { mNetworkLogger.resume(); } Loading @@ -14303,7 +14348,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } final CallerIdentity caller = getCallerIdentity(admin, packageName); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller)) Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING)) || hasCallingOrSelfPermission(permission.MANAGE_USERS)); Loading @@ -14313,8 +14360,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private boolean isNetworkLoggingEnabledInternalLocked() { ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); return (deviceOwner != null) && deviceOwner.isNetworkLoggingEnabled; ActiveAdmin activeAdmin = getNetworkLoggingControllingAdminLocked(); return (activeAdmin != null) && activeAdmin.isNetworkLoggingEnabled; } /* Loading @@ -14331,9 +14378,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } final CallerIdentity caller = getCallerIdentity(admin, packageName); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller)) Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING))); if (mOwners.hasDeviceOwner()) { checkAllUsersAreAffiliatedWithDevice(); } synchronized (getLockObject()) { if (mNetworkLogger == null || !isNetworkLoggingEnabledInternalLocked()) { Loading @@ -14346,34 +14397,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .write(); final long currentTime = System.currentTimeMillis(); DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM); DevicePolicyData policyData = getUserData(caller.getUserId()); if (currentTime > policyData.mLastNetworkLogsRetrievalTime) { policyData.mLastNetworkLogsRetrievalTime = currentTime; saveSettingsLocked(UserHandle.USER_SYSTEM); saveSettingsLocked(caller.getUserId()); } return mNetworkLogger.retrieveLogs(batchToken); } } private void sendNetworkLoggingNotificationLocked() { final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (deviceOwner == null || !deviceOwner.isNetworkLoggingEnabled) { ensureLocked(); final ActiveAdmin activeAdmin = getNetworkLoggingControllingAdminLocked(); if (activeAdmin == null || !activeAdmin.isNetworkLoggingEnabled) { return; } if (deviceOwner.numNetworkLoggingNotifications >= ActiveAdmin.DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN) { if (activeAdmin.numNetworkLoggingNotifications >= ActiveAdmin.DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN) { return; } final long now = System.currentTimeMillis(); if (now - deviceOwner.lastNetworkLoggingNotificationTimeMs < MS_PER_DAY) { if (now - activeAdmin.lastNetworkLoggingNotificationTimeMs < MS_PER_DAY) { return; } deviceOwner.numNetworkLoggingNotifications++; if (deviceOwner.numNetworkLoggingNotifications activeAdmin.numNetworkLoggingNotifications++; if (activeAdmin.numNetworkLoggingNotifications >= ActiveAdmin.DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN) { deviceOwner.lastNetworkLoggingNotificationTimeMs = 0; activeAdmin.lastNetworkLoggingNotificationTimeMs = 0; } else { deviceOwner.lastNetworkLoggingNotificationTimeMs = now; activeAdmin.lastNetworkLoggingNotificationTimeMs = now; } final PackageManagerInternal pm = mInjector.getPackageManagerInternal(); final Intent intent = new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); Loading @@ -14393,7 +14445,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .bigText(mContext.getString(R.string.network_logging_notification_text))) .build(); mInjector.getNotificationManager().notify(SystemMessage.NOTE_NETWORK_LOGGING, notification); saveSettingsLocked(mOwners.getDeviceOwnerUserId()); saveSettingsLocked(activeAdmin.getUserHandle().getIdentifier()); } /** Loading Loading @@ -14457,8 +14509,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public long getLastNetworkLogRetrievalTime() { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller)); return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime; Preconditions.checkCallAuthorization(isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())) || canManageUsers(caller)); final int affectedUserId = getNetworkLoggingAffectedUser(); return affectedUserId >= 0 ? getUserData(affectedUserId).mLastNetworkLogsRetrievalTime : -1; } @Override services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java +27 −6 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.os.Bundle; import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; Loading @@ -47,6 +48,10 @@ final class NetworkLogger { private final PackageManagerInternal mPm; private final AtomicBoolean mIsLoggingEnabled = new AtomicBoolean(false); // The target userId to collect network events on. The target userId will be // {@link android.os.UserHandle#USER_ALL} if network events should be collected for all users. private final int mTargetUserId; private IIpConnectivityMetrics mIpConnectivityMetrics; private ServiceThread mHandlerThread; private NetworkLoggingHandler mNetworkLoggingHandler; Loading @@ -58,6 +63,11 @@ final class NetworkLogger { if (!mIsLoggingEnabled.get()) { return; } // If the network logging was enabled by the profile owner, then do not // include events in the personal profile. if (!shouldLogNetworkEvent(uid)) { return; } DnsEvent dnsEvent = new DnsEvent(hostname, ipAddresses, ipAddressesCount, mPm.getNameForUid(uid), timestamp); sendNetworkEvent(dnsEvent); Loading @@ -68,6 +78,11 @@ final class NetworkLogger { if (!mIsLoggingEnabled.get()) { return; } // If the network logging was enabled by the profile owner, then do not // include events in the personal profile. if (!shouldLogNetworkEvent(uid)) { return; } ConnectEvent connectEvent = new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid), timestamp); sendNetworkEvent(connectEvent); Loading @@ -81,11 +96,17 @@ final class NetworkLogger { msg.setData(bundle); mNetworkLoggingHandler.sendMessage(msg); } private boolean shouldLogNetworkEvent(int uid) { return mTargetUserId == UserHandle.USER_ALL || mTargetUserId == UserHandle.getUserId(uid); } }; NetworkLogger(DevicePolicyManagerService dpm, PackageManagerInternal pm) { NetworkLogger(DevicePolicyManagerService dpm, PackageManagerInternal pm, int targetUserId) { mDpm = dpm; mPm = pm; mTargetUserId = targetUserId; } private boolean checkIpConnectivityMetricsService() { Loading Loading @@ -114,7 +135,7 @@ final class NetworkLogger { /* allowIo */ false); mHandlerThread.start(); mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(), mDpm); mDpm, mTargetUserId); mNetworkLoggingHandler.scheduleBatchFinalization(); mIsLoggingEnabled.set(true); return true; Loading Loading @@ -153,7 +174,7 @@ final class NetworkLogger { } /** * If logs are being collected, keep collecting them but stop notifying the device owner that * If logs are being collected, keep collecting them but stop notifying the admin that * new logs are available (since they cannot be retrieved) */ void pause() { Loading @@ -163,11 +184,11 @@ final class NetworkLogger { } /** * If logs are being collected, start notifying the device owner when logs are ready to be * If logs are being collected, start notifying the admin when logs are ready to be * collected again (if it was paused). * <p>If logging is enabled and there are logs ready to be retrieved, this method will attempt * to notify the device owner. Therefore calling identity should be cleared before calling it * (in case the method is called from a user other than the DO's user). * to notify the admin. Therefore calling identity should be cleared before calling it * (in case the method is called from a user other than the admin's user). */ void resume() { if (mNetworkLoggingHandler != null) { Loading services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java +33 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -4353,6 +4353,68 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); } @Test public void testSetNetworkLoggingEnabled_asPo() throws Exception { final int managedProfileUserId = CALLER_USER_HANDLE; final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, DpmMockContext.SYSTEM_UID); mContext.binder.callingUid = managedProfileAdminUid; mContext.applicationInfo = new ApplicationInfo(); mContext.packageName = admin1.getPackageName(); addManagedProfile(admin1, managedProfileAdminUid, admin1, VERSION_CODES.S); when(getServices().iipConnectivityMetrics .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true); // Check no logs have been retrieved so far. assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Enable network logging dpm.setNetworkLoggingEnabled(admin1, true); assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Retrieve the network logs and verify timestamp has been updated. final long beforeRetrieval = System.currentTimeMillis(); dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */); final long networkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime(); final long afterRetrieval = System.currentTimeMillis(); assertThat(networkLogRetrievalTime >= beforeRetrieval).isTrue(); assertThat(networkLogRetrievalTime <= afterRetrieval).isTrue(); } @Test public void testSetNetworkLoggingEnabled_asPoOfOrgOwnedDevice() throws Exception { // Setup profile owner on organization-owned device final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; mContext.packageName = admin1.getPackageName(); mContext.applicationInfo = new ApplicationInfo(); when(getServices().iipConnectivityMetrics .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true); // Check no logs have been retrieved so far. assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Enable network logging dpm.setNetworkLoggingEnabled(admin1, true); assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Retrieve the network logs and verify timestamp has been updated. final long beforeRetrieval = System.currentTimeMillis(); dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */); final long networkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime(); final long afterRetrieval = System.currentTimeMillis(); assertThat(networkLogRetrievalTime >= beforeRetrieval).isTrue(); assertThat(networkLogRetrievalTime <= afterRetrieval).isTrue(); } @Test public void testGetBindDeviceAdminTargetUsers() throws Exception { mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS); Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +33 −21 Original line number Diff line number Diff line Loading @@ -11796,8 +11796,11 @@ public class DevicePolicyManager { } /** * Called by a device owner or delegated app with {@link #DELEGATION_NETWORK_LOGGING} to * control the network logging feature. * Called by a device owner, profile owner of a managed profile or delegated app with * {@link #DELEGATION_NETWORK_LOGGING} to control the network logging feature. * * <p> When network logging is enabled by a profile owner, the network logs will only include * work profile network activity, not activity on the personal profile. * * <p> Network logs contain DNS lookup and connect() library call events. The following library * functions are recorded while network logging is active: Loading Loading @@ -11837,7 +11840,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if called by a delegated app. * @param enabled whether network logging should be enabled or not. * @throws SecurityException if {@code admin} is not a device owner. * @throws SecurityException if {@code admin} is not a device owner or profile owner. * @see #setAffiliationIds * @see #retrieveNetworkLogs */ Loading @@ -11851,14 +11854,16 @@ public class DevicePolicyManager { } /** * Return whether network logging is enabled by a device owner. * Return whether network logging is enabled by a device owner or profile owner of * a managed profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only * be {@code null} if the caller is a delegated app with {@link #DELEGATION_NETWORK_LOGGING} * or has MANAGE_USERS permission. * @return {@code true} if network logging is enabled by device owner, {@code false} otherwise. * @throws SecurityException if {@code admin} is not a device owner and caller has * no MANAGE_USERS permission * @return {@code true} if network logging is enabled by device owner or profile owner, * {@code false} otherwise. * @throws SecurityException if {@code admin} is not a device owner or profile owner and * caller has no MANAGE_USERS permission */ public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) { throwIfParentInstance("isNetworkLoggingEnabled"); Loading @@ -11870,9 +11875,14 @@ public class DevicePolicyManager { } /** * Called by device owner or delegated app with {@link #DELEGATION_NETWORK_LOGGING} to retrieve * the most recent batch of network logging events. * A device owner has to provide a batchToken provided as part of * Called by device owner, profile owner of a managed profile or delegated app with * {@link #DELEGATION_NETWORK_LOGGING} to retrieve the most recent batch of * network logging events. * * <p> When network logging is enabled by a profile owner, the network logs will only include * work profile network activity, not activity on the personal profile. * * A device owner or profile owner has to provide a batchToken provided as part of * {@link DeviceAdminReceiver#onNetworkLogsAvailable} callback. If the token doesn't match the * token of the most recent available batch of logs, {@code null} will be returned. * Loading @@ -11884,11 +11894,11 @@ public class DevicePolicyManager { * after the device device owner has been notified via * {@link DeviceAdminReceiver#onNetworkLogsAvailable}. * * <p>If a secondary user or profile is created, calling this method will throw a * {@link SecurityException} until all users become affiliated again. It will also no longer be * possible to retrieve the network logs batch with the most recent batchToken provided * by {@link DeviceAdminReceiver#onNetworkLogsAvailable}. See * {@link DevicePolicyManager#setAffiliationIds}. * <p>If the caller is not a profile owner and a secondary user or profile is created, calling * this method will throw a {@link SecurityException} until all users become affiliated again. * It will also no longer be possible to retrieve the network logs batch with the most recent * batchToken provided by {@link DeviceAdminReceiver#onNetworkLogsAvailable}. * See {@link DevicePolicyManager#setAffiliationIds}. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if called by a delegated app. Loading @@ -11896,8 +11906,9 @@ public class DevicePolicyManager { * @return A new batch of network logs which is a list of {@link NetworkEvent}. Returns * {@code null} if the batch represented by batchToken is no longer available or if * logging is disabled. * @throws SecurityException if {@code admin} is not a device owner, or there is at least one * profile or secondary user that is not affiliated with the device. * @throws SecurityException if {@code admin} is not a device owner, profile owner or if the * {@code admin} is not a profile owner and there is at least one profile or secondary user * that is not affiliated with the device. * @see #setAffiliationIds * @see DeviceAdminReceiver#onNetworkLogsAvailable */ Loading Loading @@ -12016,11 +12027,12 @@ public class DevicePolicyManager { } /** * Called by the system to get the time at which the device owner last retrieved network logging * events. * Called by the system to get the time at which the device owner or profile owner of a * managed profile last retrieved network logging events. * * @return the time at which the device owner most recently retrieved network logging events, in * milliseconds since epoch; -1 if network logging events were never retrieved. * @return the time at which the device owner or profile owner most recently retrieved network * logging events, in milliseconds since epoch; -1 if network logging events were * never retrieved. * @throws SecurityException if the caller is not the device owner, does not hold the * MANAGE_USERS permission and is not the system. *
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +88 −32 Original line number Diff line number Diff line Loading @@ -782,8 +782,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * however it's too early in the boot process to register with IIpConnectivityMetrics * to listen for events. */ if (Intent.ACTION_USER_STARTED.equals(action) && userHandle == mOwners.getDeviceOwnerUserId()) { if (Intent.ACTION_USER_STARTED.equals(action) && userHandle == UserHandle.USER_SYSTEM) { synchronized (getLockObject()) { if (isNetworkLoggingEnabledInternalLocked()) { setNetworkLoggingActiveInternal(true); Loading Loading @@ -7533,6 +7532,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { sendActiveAdminCommand(action, extras, deviceOwnerUserId, receiverComponent); } void sendDeviceOwnerOrProfileOwnerCommand(String action, Bundle extras, int userId) { if (userId == UserHandle.USER_ALL) { userId = UserHandle.USER_SYSTEM; } ComponentName receiverComponent = null; if (action.equals(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)) { receiverComponent = resolveDelegateReceiver(DELEGATION_NETWORK_LOGGING, action, userId); } if (receiverComponent == null) { receiverComponent = getOwnerComponent(userId); } sendActiveAdminCommand(action, extras, userId, receiverComponent); } private void sendProfileOwnerCommand(String action, Bundle extras, @UserIdInt int userId) { sendActiveAdminCommand(action, extras, userId, mOwners.getProfileOwnerComponent(userId)); Loading Loading @@ -8357,6 +8370,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { deleteTransferOwnershipBundleLocked(userId); toggleBackupServiceActive(userId, true); applyManagedProfileRestrictionIfDeviceOwnerLocked(); setNetworkLoggingActiveInternal(false); } @Override Loading Loading @@ -14184,7 +14198,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return; } final CallerIdentity caller = getCallerIdentity(admin, packageName); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller)) Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING))); synchronized (getLockObject()) { Loading @@ -14192,11 +14208,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // already in the requested state return; } ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); deviceOwner.isNetworkLoggingEnabled = enabled; final ActiveAdmin activeAdmin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId()); activeAdmin.isNetworkLoggingEnabled = enabled; if (!enabled) { deviceOwner.numNetworkLoggingNotifications = 0; deviceOwner.lastNetworkLoggingNotificationTimeMs = 0; activeAdmin.numNetworkLoggingNotifications = 0; activeAdmin.lastNetworkLoggingNotificationTimeMs = 0; } saveSettingsLocked(caller.getUserId()); setNetworkLoggingActiveInternal(enabled); Loading @@ -14214,7 +14230,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { synchronized (getLockObject()) { mInjector.binderWithCleanCallingIdentity(() -> { if (active) { mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal()); if (mNetworkLogger == null) { final int affectedUserId = getNetworkLoggingAffectedUser(); mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal(), affectedUserId == UserHandle.USER_SYSTEM ? UserHandle.USER_ALL : affectedUserId); } if (!mNetworkLogger.startNetworkLogging()) { mNetworkLogger = null; Slog.wtf(LOG_TAG, "Network logging could not be started due to the logging" Loading @@ -14234,6 +14256,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private @UserIdInt int getNetworkLoggingAffectedUser() { synchronized (getLockObject()) { if (mOwners.hasDeviceOwner()) { return mOwners.getDeviceOwnerUserId(); } else { return mInjector.binderWithCleanCallingIdentity( () -> getManagedUserId(UserHandle.USER_SYSTEM)); } } } private ActiveAdmin getNetworkLoggingControllingAdminLocked() { int affectedUserId = getNetworkLoggingAffectedUser(); if (affectedUserId < 0) { return null; } return getDeviceOrProfileOwnerAdminLocked(affectedUserId); } @Override public long forceNetworkLogs() { Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()), Loading @@ -14254,11 +14295,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @GuardedBy("getLockObject()") private void maybePauseDeviceWideLoggingLocked() { if (!areAllUsersAffiliatedWithDeviceLocked()) { if (mOwners.hasDeviceOwner()) { Slog.i(LOG_TAG, "There are unaffiliated users, network logging will be " + "paused if enabled."); if (mNetworkLogger != null) { mNetworkLogger.pause(); } } if (!isOrganizationOwnedDeviceWithManagedProfile()) { Slog.i(LOG_TAG, "Not org-owned managed profile device, security logging will be " + "paused if enabled."); Loading @@ -14276,7 +14319,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { if (allUsersAffiliated || orgOwnedProfileDevice) { mSecurityLogMonitor.resume(); } if (allUsersAffiliated) { // If there is no device owner, then per-user network logging may be enabled for the // managed profile. In which case, all users do not need to be affiliated. if (allUsersAffiliated || !mOwners.hasDeviceOwner()) { if (mNetworkLogger != null) { mNetworkLogger.resume(); } Loading @@ -14303,7 +14348,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } final CallerIdentity caller = getCallerIdentity(admin, packageName); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller)) Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING)) || hasCallingOrSelfPermission(permission.MANAGE_USERS)); Loading @@ -14313,8 +14360,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private boolean isNetworkLoggingEnabledInternalLocked() { ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); return (deviceOwner != null) && deviceOwner.isNetworkLoggingEnabled; ActiveAdmin activeAdmin = getNetworkLoggingControllingAdminLocked(); return (activeAdmin != null) && activeAdmin.isNetworkLoggingEnabled; } /* Loading @@ -14331,9 +14378,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return null; } final CallerIdentity caller = getCallerIdentity(admin, packageName); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller)) Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING))); if (mOwners.hasDeviceOwner()) { checkAllUsersAreAffiliatedWithDevice(); } synchronized (getLockObject()) { if (mNetworkLogger == null || !isNetworkLoggingEnabledInternalLocked()) { Loading @@ -14346,34 +14397,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .write(); final long currentTime = System.currentTimeMillis(); DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM); DevicePolicyData policyData = getUserData(caller.getUserId()); if (currentTime > policyData.mLastNetworkLogsRetrievalTime) { policyData.mLastNetworkLogsRetrievalTime = currentTime; saveSettingsLocked(UserHandle.USER_SYSTEM); saveSettingsLocked(caller.getUserId()); } return mNetworkLogger.retrieveLogs(batchToken); } } private void sendNetworkLoggingNotificationLocked() { final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked(); if (deviceOwner == null || !deviceOwner.isNetworkLoggingEnabled) { ensureLocked(); final ActiveAdmin activeAdmin = getNetworkLoggingControllingAdminLocked(); if (activeAdmin == null || !activeAdmin.isNetworkLoggingEnabled) { return; } if (deviceOwner.numNetworkLoggingNotifications >= ActiveAdmin.DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN) { if (activeAdmin.numNetworkLoggingNotifications >= ActiveAdmin.DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN) { return; } final long now = System.currentTimeMillis(); if (now - deviceOwner.lastNetworkLoggingNotificationTimeMs < MS_PER_DAY) { if (now - activeAdmin.lastNetworkLoggingNotificationTimeMs < MS_PER_DAY) { return; } deviceOwner.numNetworkLoggingNotifications++; if (deviceOwner.numNetworkLoggingNotifications activeAdmin.numNetworkLoggingNotifications++; if (activeAdmin.numNetworkLoggingNotifications >= ActiveAdmin.DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN) { deviceOwner.lastNetworkLoggingNotificationTimeMs = 0; activeAdmin.lastNetworkLoggingNotificationTimeMs = 0; } else { deviceOwner.lastNetworkLoggingNotificationTimeMs = now; activeAdmin.lastNetworkLoggingNotificationTimeMs = now; } final PackageManagerInternal pm = mInjector.getPackageManagerInternal(); final Intent intent = new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); Loading @@ -14393,7 +14445,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { .bigText(mContext.getString(R.string.network_logging_notification_text))) .build(); mInjector.getNotificationManager().notify(SystemMessage.NOTE_NETWORK_LOGGING, notification); saveSettingsLocked(mOwners.getDeviceOwnerUserId()); saveSettingsLocked(activeAdmin.getUserHandle().getIdentifier()); } /** Loading Loading @@ -14457,8 +14509,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public long getLastNetworkLogRetrievalTime() { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller)); return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime; Preconditions.checkCallAuthorization(isDeviceOwner(caller) || (isProfileOwner(caller) && isManagedProfile(caller.getUserId())) || canManageUsers(caller)); final int affectedUserId = getNetworkLoggingAffectedUser(); return affectedUserId >= 0 ? getUserData(affectedUserId).mLastNetworkLogsRetrievalTime : -1; } @Override
services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java +27 −6 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.os.Bundle; import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; Loading @@ -47,6 +48,10 @@ final class NetworkLogger { private final PackageManagerInternal mPm; private final AtomicBoolean mIsLoggingEnabled = new AtomicBoolean(false); // The target userId to collect network events on. The target userId will be // {@link android.os.UserHandle#USER_ALL} if network events should be collected for all users. private final int mTargetUserId; private IIpConnectivityMetrics mIpConnectivityMetrics; private ServiceThread mHandlerThread; private NetworkLoggingHandler mNetworkLoggingHandler; Loading @@ -58,6 +63,11 @@ final class NetworkLogger { if (!mIsLoggingEnabled.get()) { return; } // If the network logging was enabled by the profile owner, then do not // include events in the personal profile. if (!shouldLogNetworkEvent(uid)) { return; } DnsEvent dnsEvent = new DnsEvent(hostname, ipAddresses, ipAddressesCount, mPm.getNameForUid(uid), timestamp); sendNetworkEvent(dnsEvent); Loading @@ -68,6 +78,11 @@ final class NetworkLogger { if (!mIsLoggingEnabled.get()) { return; } // If the network logging was enabled by the profile owner, then do not // include events in the personal profile. if (!shouldLogNetworkEvent(uid)) { return; } ConnectEvent connectEvent = new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid), timestamp); sendNetworkEvent(connectEvent); Loading @@ -81,11 +96,17 @@ final class NetworkLogger { msg.setData(bundle); mNetworkLoggingHandler.sendMessage(msg); } private boolean shouldLogNetworkEvent(int uid) { return mTargetUserId == UserHandle.USER_ALL || mTargetUserId == UserHandle.getUserId(uid); } }; NetworkLogger(DevicePolicyManagerService dpm, PackageManagerInternal pm) { NetworkLogger(DevicePolicyManagerService dpm, PackageManagerInternal pm, int targetUserId) { mDpm = dpm; mPm = pm; mTargetUserId = targetUserId; } private boolean checkIpConnectivityMetricsService() { Loading Loading @@ -114,7 +135,7 @@ final class NetworkLogger { /* allowIo */ false); mHandlerThread.start(); mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(), mDpm); mDpm, mTargetUserId); mNetworkLoggingHandler.scheduleBatchFinalization(); mIsLoggingEnabled.set(true); return true; Loading Loading @@ -153,7 +174,7 @@ final class NetworkLogger { } /** * If logs are being collected, keep collecting them but stop notifying the device owner that * If logs are being collected, keep collecting them but stop notifying the admin that * new logs are available (since they cannot be retrieved) */ void pause() { Loading @@ -163,11 +184,11 @@ final class NetworkLogger { } /** * If logs are being collected, start notifying the device owner when logs are ready to be * If logs are being collected, start notifying the admin when logs are ready to be * collected again (if it was paused). * <p>If logging is enabled and there are logs ready to be retrieved, this method will attempt * to notify the device owner. Therefore calling identity should be cleared before calling it * (in case the method is called from a user other than the DO's user). * to notify the admin. Therefore calling identity should be cleared before calling it * (in case the method is called from a user other than the admin's user). */ void resume() { if (mNetworkLoggingHandler != null) { Loading
services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java +33 −27 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -4353,6 +4353,68 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); } @Test public void testSetNetworkLoggingEnabled_asPo() throws Exception { final int managedProfileUserId = CALLER_USER_HANDLE; final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, DpmMockContext.SYSTEM_UID); mContext.binder.callingUid = managedProfileAdminUid; mContext.applicationInfo = new ApplicationInfo(); mContext.packageName = admin1.getPackageName(); addManagedProfile(admin1, managedProfileAdminUid, admin1, VERSION_CODES.S); when(getServices().iipConnectivityMetrics .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true); // Check no logs have been retrieved so far. assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Enable network logging dpm.setNetworkLoggingEnabled(admin1, true); assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Retrieve the network logs and verify timestamp has been updated. final long beforeRetrieval = System.currentTimeMillis(); dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */); final long networkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime(); final long afterRetrieval = System.currentTimeMillis(); assertThat(networkLogRetrievalTime >= beforeRetrieval).isTrue(); assertThat(networkLogRetrievalTime <= afterRetrieval).isTrue(); } @Test public void testSetNetworkLoggingEnabled_asPoOfOrgOwnedDevice() throws Exception { // Setup profile owner on organization-owned device final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID); addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1); configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE); mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID; mContext.packageName = admin1.getPackageName(); mContext.applicationInfo = new ApplicationInfo(); when(getServices().iipConnectivityMetrics .addNetdEventCallback(anyInt(), anyObject())).thenReturn(true); // Check no logs have been retrieved so far. assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Enable network logging dpm.setNetworkLoggingEnabled(admin1, true); assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1); // Retrieve the network logs and verify timestamp has been updated. final long beforeRetrieval = System.currentTimeMillis(); dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */); final long networkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime(); final long afterRetrieval = System.currentTimeMillis(); assertThat(networkLogRetrievalTime >= beforeRetrieval).isTrue(); assertThat(networkLogRetrievalTime <= afterRetrieval).isTrue(); } @Test public void testGetBindDeviceAdminTargetUsers() throws Exception { mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS); Loading