summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java54
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java120
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java33
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java60
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java62
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java2
6 files changed, 244 insertions, 87 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3b4f720c654f..3b80f83aab0d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -11718,8 +11718,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:
@@ -11759,7 +11762,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
*/
@@ -11773,14 +11776,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");
@@ -11792,9 +11797,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.
*
@@ -11806,11 +11816,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.
@@ -11818,8 +11828,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
*/
@@ -11938,11 +11949,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.
*
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a692be7f959..498ee38d442a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -781,8 +781,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);
@@ -7527,6 +7526,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));
@@ -8351,6 +8364,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
deleteTransferOwnershipBundleLocked(userId);
toggleBackupServiceActive(userId, true);
applyManagedProfileRestrictionIfDeviceOwnerLocked();
+ setNetworkLoggingActiveInternal(false);
}
@Override
@@ -14131,7 +14145,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()) {
@@ -14139,11 +14155,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);
@@ -14161,7 +14177,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"
@@ -14181,6 +14203,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()),
@@ -14201,10 +14242,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@GuardedBy("getLockObject()")
private void maybePauseDeviceWideLoggingLocked() {
if (!areAllUsersAffiliatedWithDeviceLocked()) {
- Slog.i(LOG_TAG, "There are unaffiliated users, network logging will be "
- + "paused if enabled.");
- if (mNetworkLogger != null) {
- mNetworkLogger.pause();
+ 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 "
@@ -14223,7 +14266,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();
}
@@ -14250,7 +14295,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));
@@ -14260,8 +14307,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;
}
/*
@@ -14278,9 +14325,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)));
- checkAllUsersAreAffiliatedWithDevice();
+ if (mOwners.hasDeviceOwner()) {
+ checkAllUsersAreAffiliatedWithDevice();
+ }
synchronized (getLockObject()) {
if (mNetworkLogger == null || !isNetworkLoggingEnabledInternalLocked()) {
@@ -14293,34 +14344,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);
@@ -14340,7 +14392,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());
}
/**
@@ -14404,8 +14456,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
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
index e9b2d7f56108..8843a5d5306e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
@@ -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;
@@ -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;
@@ -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);
@@ -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);
@@ -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() {
@@ -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;
@@ -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() {
@@ -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) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
index 0a7070ffe4f6..84e89a08e1f4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
@@ -50,7 +50,7 @@ final class NetworkLoggingHandler extends Handler {
private static final int MAX_EVENTS_PER_BATCH = 1200;
/**
- * Maximum number of batches to store in memory. If more batches are generated and the DO
+ * Maximum number of batches to store in memory. If more batches are generated and the admin
* doesn't fetch them, we will discard the oldest one.
*/
private static final int MAX_BATCHES = 5;
@@ -74,6 +74,7 @@ final class NetworkLoggingHandler extends Handler {
private final AlarmManager mAlarmManager;
private long mId;
+ private int mTargetUserId;
private final OnAlarmListener mBatchTimeoutAlarmListener = new OnAlarmListener() {
@Override
@@ -82,10 +83,10 @@ final class NetworkLoggingHandler extends Handler {
+ mNetworkEvents.size() + " pending events.");
Bundle notificationExtras = null;
synchronized (NetworkLoggingHandler.this) {
- notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked();
+ notificationExtras = finalizeBatchAndBuildAdminMessageLocked();
}
if (notificationExtras != null) {
- notifyDeviceOwner(notificationExtras);
+ notifyDeviceOwnerOrProfileOwner(notificationExtras);
}
}
};
@@ -98,8 +99,8 @@ final class NetworkLoggingHandler extends Handler {
private ArrayList<NetworkEvent> mNetworkEvents = new ArrayList<>();
/**
- * Up to {@code MAX_BATCHES} finalized batches of logs ready to be retrieved by the DO. Already
- * retrieved batches are discarded after {@code RETRIEVED_BATCH_DISCARD_DELAY_MS}.
+ * Up to {@code MAX_BATCHES} finalized batches of logs ready to be retrieved by the admin.
+ * Already retrieved batches are discarded after {@code RETRIEVED_BATCH_DISCARD_DELAY_MS}.
*/
@GuardedBy("this")
private final LongSparseArray<ArrayList<NetworkEvent>> mBatches =
@@ -115,16 +116,18 @@ final class NetworkLoggingHandler extends Handler {
@GuardedBy("this")
private long mLastRetrievedBatchToken;
- NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) {
- this(looper, dpm, 0 /* event id */);
+ NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm, int targetUserId) {
+ this(looper, dpm, 0 /* event id */, targetUserId);
}
@VisibleForTesting
- NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm, long id) {
+ NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm, long id,
+ int targetUserId) {
super(looper);
this.mDpm = dpm;
this.mAlarmManager = mDpm.mInjector.getAlarmManager();
this.mId = id;
+ this.mTargetUserId = targetUserId;
}
@Override
@@ -137,11 +140,11 @@ final class NetworkLoggingHandler extends Handler {
synchronized (NetworkLoggingHandler.this) {
mNetworkEvents.add(networkEvent);
if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) {
- notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked();
+ notificationExtras = finalizeBatchAndBuildAdminMessageLocked();
}
}
if (notificationExtras != null) {
- notifyDeviceOwner(notificationExtras);
+ notifyDeviceOwnerOrProfileOwner(notificationExtras);
}
}
break;
@@ -176,10 +179,10 @@ final class NetworkLoggingHandler extends Handler {
if (toWaitNanos > 0) {
return NANOSECONDS.toMillis(toWaitNanos) + 1; // Round up.
}
- notificationExtras = finalizeBatchAndBuildDeviceOwnerMessageLocked();
+ notificationExtras = finalizeBatchAndBuildAdminMessageLocked();
}
if (notificationExtras != null) {
- notifyDeviceOwner(notificationExtras);
+ notifyDeviceOwnerOrProfileOwner(notificationExtras);
}
return 0;
}
@@ -201,14 +204,15 @@ final class NetworkLoggingHandler extends Handler {
+ ", LastRetrievedBatch=" + mLastRetrievedBatchToken);
mPaused = false;
- // If there is a batch ready that the device owner hasn't been notified about, do it now.
+ // If there is a batch ready that the device owner or profile owner hasn't been
+ // notified about, do it now.
if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) {
scheduleBatchFinalization();
- notificationExtras = buildDeviceOwnerMessageLocked();
+ notificationExtras = buildAdminMessageLocked();
}
}
if (notificationExtras != null) {
- notifyDeviceOwner(notificationExtras);
+ notifyDeviceOwnerOrProfileOwner(notificationExtras);
}
}
@@ -219,8 +223,8 @@ final class NetworkLoggingHandler extends Handler {
}
@GuardedBy("this")
- /** @returns extras if a message should be sent to the device owner */
- private Bundle finalizeBatchAndBuildDeviceOwnerMessageLocked() {
+ /** @return extras if a message should be sent to the device owner or profile owner */
+ private Bundle finalizeBatchAndBuildAdminMessageLocked() {
mLastFinalizationNanos = System.nanoTime();
Bundle notificationExtras = null;
if (mNetworkEvents.size() > 0) {
@@ -243,10 +247,10 @@ final class NetworkLoggingHandler extends Handler {
mBatches.append(mCurrentBatchToken, mNetworkEvents);
mNetworkEvents = new ArrayList<>();
if (!mPaused) {
- notificationExtras = buildDeviceOwnerMessageLocked();
+ notificationExtras = buildAdminMessageLocked();
}
} else {
- // Don't notify the DO, since there are no events; DPC can still retrieve
+ // Don't notify the admin, since there are no events; DPC can still retrieve
// the last full batch if not paused.
Slog.d(TAG, "Was about to finalize the batch, but there were no events to send to"
+ " the DPC, the batchToken of last available batch: " + mCurrentBatchToken);
@@ -257,9 +261,9 @@ final class NetworkLoggingHandler extends Handler {
}
@GuardedBy("this")
- /** Build extras notification to the DO. Should only be called when there
+ /** Build extras notification to the admin. Should only be called when there
is a batch available. */
- private Bundle buildDeviceOwnerMessageLocked() {
+ private Bundle buildAdminMessageLocked() {
final Bundle extras = new Bundle();
final int lastBatchSize = mBatches.valueAt(mBatches.size() - 1).size();
extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentBatchToken);
@@ -267,16 +271,18 @@ final class NetworkLoggingHandler extends Handler {
return extras;
}
- /** Sends a notification to the DO. Should not hold locks as DevicePolicyManagerService may
- call into NetworkLoggingHandler. */
- private void notifyDeviceOwner(Bundle extras) {
- Slog.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: "
- + extras.getLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, -1));
+ /** Sends a notification to the device owner or profile owner. Should not hold locks as
+ DevicePolicyManagerService may call into NetworkLoggingHandler. */
+ private void notifyDeviceOwnerOrProfileOwner(Bundle extras) {
if (Thread.holdsLock(this)) {
Slog.wtfStack(TAG, "Shouldn't be called with NetworkLoggingHandler lock held");
return;
}
- mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras);
+ Slog.d(TAG, "Sending network logging batch broadcast to device owner or profile owner, "
+ + "batchToken: "
+ + extras.getLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, -1));
+ mDpm.sendDeviceOwnerOrProfileOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE,
+ extras, mTargetUserId);
}
synchronized List<NetworkEvent> retrieveFullLogBatch(final long batchToken) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 7597cbf322f5..4002f5b4939e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4329,6 +4329,68 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@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);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
index 7506dd45ad82..743b25f5c2b4 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
@@ -125,7 +125,7 @@ public class NetworkEventTest extends DpmTestBase {
private List<NetworkEvent> fillHandlerWithFullBatchOfEvents(long startingId) throws Exception {
// GIVEN a handler with events
NetworkLoggingHandler handler = new NetworkLoggingHandler(new TestLooper().getLooper(),
- mDpmTestable, startingId);
+ mDpmTestable, startingId, DpmMockContext.CALLER_USER_HANDLE);
// GIVEN network events are sent to the handler.
for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
ConnectEvent event = new ConnectEvent("some_ip_address", 800, "com.google.foo",