Loading core/java/android/app/admin/DevicePolicyManagerInternal.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.os.UserManager.EnforcingUser; import java.util.List; import java.util.List; import java.util.Set; import java.util.Set; import java.util.function.Consumer; /** /** * Device policy manager local system service interface. * Device policy manager local system service interface. Loading Loading @@ -338,4 +339,10 @@ public abstract class DevicePolicyManagerInternal { * Enforces resolved audit logging policy, should only be invoked from device policy engine. * Enforces resolved audit logging policy, should only be invoked from device policy engine. */ */ public abstract void enforceAuditLoggingPolicy(boolean enabled); public abstract void enforceAuditLoggingPolicy(boolean enabled); /** * Installs internal callback for security log events. */ public abstract void setInternalEventsCallback( @Nullable Consumer<List<SecurityLog.SecurityEvent>> callback); } } core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Original line Diff line number Diff line Loading @@ -151,6 +151,16 @@ flag { bug: "295324350" bug: "295324350" } } flag { name: "internal_log_event_listener" namespace: "enterprise" description: "Allow internal listeners to see unfiltered event stream" bug: "385730709" metadata { purpose: PURPOSE_BUGFIX } } flag { flag { name: "allow_querying_profile_type" name: "allow_querying_profile_type" is_exported: true is_exported: true Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -16086,6 +16086,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceLoggingPolicy(Boolean.TRUE.equals(securityLoggingEnabled), enabled); enforceLoggingPolicy(Boolean.TRUE.equals(securityLoggingEnabled), enabled); } } @Override public void setInternalEventsCallback( @Nullable Consumer<List<SecurityEvent>> callback) { mSecurityLogMonitor.setInternalEventsCallback(callback); } private List<EnforcingUser> getEnforcingUsers(Set<EnforcingAdmin> admins) { private List<EnforcingUser> getEnforcingUsers(Set<EnforcingAdmin> admins) { List<EnforcingUser> enforcingUsers = new ArrayList(); List<EnforcingUser> enforcingUsers = new ArrayList(); ComponentName deviceOwner = mOwners.getDeviceOwnerComponent(); ComponentName deviceOwner = mOwners.getDeviceOwnerComponent(); services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java +36 −4 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.server.devicepolicy; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import android.annotation.Nullable; import android.app.admin.DeviceAdminReceiver; import android.app.admin.DeviceAdminReceiver; import android.app.admin.IAuditLogEventsCallback; import android.app.admin.IAuditLogEventsCallback; import android.app.admin.SecurityLog; import android.app.admin.SecurityLog; import android.app.admin.SecurityLog.SecurityEvent; import android.app.admin.SecurityLog.SecurityEvent; import android.app.admin.flags.Flags; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.IBinder; import android.os.Process; import android.os.Process; Loading @@ -45,6 +47,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; /** /** * A class managing access to the security logs. It maintains an internal buffer of pending * A class managing access to the security logs. It maintains an internal buffer of pending Loading Loading @@ -183,6 +186,10 @@ class SecurityLogMonitor implements Runnable { @GuardedBy("mLock") @GuardedBy("mLock") private final ArrayDeque<SecurityEvent> mAuditLogEventBuffer = new ArrayDeque<>(); private final ArrayDeque<SecurityEvent> mAuditLogEventBuffer = new ArrayDeque<>(); @GuardedBy("mLock") @Nullable private Consumer<List<SecurityEvent>> mInternalEventsCallback; void stop() { void stop() { Slog.i(TAG, "Stopping security logging."); Slog.i(TAG, "Stopping security logging."); mLock.lock(); mLock.lock(); Loading Loading @@ -221,7 +228,6 @@ class SecurityLogMonitor implements Runnable { } finally { } finally { mLock.unlock(); mLock.unlock(); } } } } @GuardedBy("mLock") @GuardedBy("mLock") Loading Loading @@ -365,7 +371,9 @@ class SecurityLogMonitor implements Runnable { break; break; } } } } if (!Flags.internalLogEventListener()) { SecurityLog.redactEvents(newLogs, mEnabledUser); SecurityLog.redactEvents(newLogs, mEnabledUser); } if (DEBUG) Slog.d(TAG, "Got " + newLogs.size() + " new events."); if (DEBUG) Slog.d(TAG, "Got " + newLogs.size() + " new events."); } } Loading Loading @@ -400,7 +408,7 @@ class SecurityLogMonitor implements Runnable { */ */ @GuardedBy("mLock") @GuardedBy("mLock") private void mergeBatchLocked(final ArrayList<SecurityEvent> newLogs) { private void mergeBatchLocked(final ArrayList<SecurityEvent> newLogs) { List<SecurityEvent> dedupedLogs = new ArrayList<>(); ArrayList<SecurityEvent> dedupedLogs = new ArrayList<>(); // Run through the first events of the batch to check if there is an overlap with previous // Run through the first events of the batch to check if there is an overlap with previous // batch and if so, skip overlapping events. Events are sorted by timestamp, so we can // batch and if so, skip overlapping events. Events are sorted by timestamp, so we can // compare it in linear time by advancing two pointers, one for each batch. // compare it in linear time by advancing two pointers, one for each batch. Loading Loading @@ -438,8 +446,19 @@ class SecurityLogMonitor implements Runnable { curPos++; curPos++; } } } } // Assign an id to the new logs, after the overlap with mLastEvents. dedupedLogs.addAll(newLogs.subList(curPos, newLogs.size())); dedupedLogs.addAll(newLogs.subList(curPos, newLogs.size())); if (Flags.internalLogEventListener() && !dedupedLogs.isEmpty()) { if (mInternalEventsCallback != null) { final ArrayList<SecurityEvent> events = new ArrayList<>(dedupedLogs); final Consumer<List<SecurityEvent>> callback = mInternalEventsCallback; mHandler.post(() -> callback.accept(events)); } SecurityLog.redactEvents(dedupedLogs, mEnabledUser); } // Assign an id to the new logs, after the overlap with mLastEvents. for (SecurityEvent event : dedupedLogs) { for (SecurityEvent event : dedupedLogs) { assignLogId(event); assignLogId(event); } } Loading Loading @@ -719,4 +738,17 @@ class SecurityLogMonitor implements Runnable { mLock.unlock(); mLock.unlock(); } } } } public void setInternalEventsCallback(@Nullable Consumer<List<SecurityEvent>> callback) { if (!Flags.internalLogEventListener()) { Slog.wtf(TAG, "Internal callbacks not enabled"); return; } mLock.lock(); try { this.mInternalEventsCallback = callback; } finally { mLock.unlock(); } } } } Loading
core/java/android/app/admin/DevicePolicyManagerInternal.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.os.UserManager.EnforcingUser; import java.util.List; import java.util.List; import java.util.Set; import java.util.Set; import java.util.function.Consumer; /** /** * Device policy manager local system service interface. * Device policy manager local system service interface. Loading Loading @@ -338,4 +339,10 @@ public abstract class DevicePolicyManagerInternal { * Enforces resolved audit logging policy, should only be invoked from device policy engine. * Enforces resolved audit logging policy, should only be invoked from device policy engine. */ */ public abstract void enforceAuditLoggingPolicy(boolean enabled); public abstract void enforceAuditLoggingPolicy(boolean enabled); /** * Installs internal callback for security log events. */ public abstract void setInternalEventsCallback( @Nullable Consumer<List<SecurityLog.SecurityEvent>> callback); } }
core/java/android/app/admin/flags/flags.aconfig +10 −0 Original line number Original line Diff line number Diff line Loading @@ -151,6 +151,16 @@ flag { bug: "295324350" bug: "295324350" } } flag { name: "internal_log_event_listener" namespace: "enterprise" description: "Allow internal listeners to see unfiltered event stream" bug: "385730709" metadata { purpose: PURPOSE_BUGFIX } } flag { flag { name: "allow_querying_profile_type" name: "allow_querying_profile_type" is_exported: true is_exported: true Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -16086,6 +16086,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceLoggingPolicy(Boolean.TRUE.equals(securityLoggingEnabled), enabled); enforceLoggingPolicy(Boolean.TRUE.equals(securityLoggingEnabled), enabled); } } @Override public void setInternalEventsCallback( @Nullable Consumer<List<SecurityEvent>> callback) { mSecurityLogMonitor.setInternalEventsCallback(callback); } private List<EnforcingUser> getEnforcingUsers(Set<EnforcingAdmin> admins) { private List<EnforcingUser> getEnforcingUsers(Set<EnforcingAdmin> admins) { List<EnforcingUser> enforcingUsers = new ArrayList(); List<EnforcingUser> enforcingUsers = new ArrayList(); ComponentName deviceOwner = mOwners.getDeviceOwnerComponent(); ComponentName deviceOwner = mOwners.getDeviceOwnerComponent();
services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java +36 −4 Original line number Original line Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.server.devicepolicy; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import android.annotation.Nullable; import android.app.admin.DeviceAdminReceiver; import android.app.admin.DeviceAdminReceiver; import android.app.admin.IAuditLogEventsCallback; import android.app.admin.IAuditLogEventsCallback; import android.app.admin.SecurityLog; import android.app.admin.SecurityLog; import android.app.admin.SecurityLog.SecurityEvent; import android.app.admin.SecurityLog.SecurityEvent; import android.app.admin.flags.Flags; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.IBinder; import android.os.Process; import android.os.Process; Loading @@ -45,6 +47,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; /** /** * A class managing access to the security logs. It maintains an internal buffer of pending * A class managing access to the security logs. It maintains an internal buffer of pending Loading Loading @@ -183,6 +186,10 @@ class SecurityLogMonitor implements Runnable { @GuardedBy("mLock") @GuardedBy("mLock") private final ArrayDeque<SecurityEvent> mAuditLogEventBuffer = new ArrayDeque<>(); private final ArrayDeque<SecurityEvent> mAuditLogEventBuffer = new ArrayDeque<>(); @GuardedBy("mLock") @Nullable private Consumer<List<SecurityEvent>> mInternalEventsCallback; void stop() { void stop() { Slog.i(TAG, "Stopping security logging."); Slog.i(TAG, "Stopping security logging."); mLock.lock(); mLock.lock(); Loading Loading @@ -221,7 +228,6 @@ class SecurityLogMonitor implements Runnable { } finally { } finally { mLock.unlock(); mLock.unlock(); } } } } @GuardedBy("mLock") @GuardedBy("mLock") Loading Loading @@ -365,7 +371,9 @@ class SecurityLogMonitor implements Runnable { break; break; } } } } if (!Flags.internalLogEventListener()) { SecurityLog.redactEvents(newLogs, mEnabledUser); SecurityLog.redactEvents(newLogs, mEnabledUser); } if (DEBUG) Slog.d(TAG, "Got " + newLogs.size() + " new events."); if (DEBUG) Slog.d(TAG, "Got " + newLogs.size() + " new events."); } } Loading Loading @@ -400,7 +408,7 @@ class SecurityLogMonitor implements Runnable { */ */ @GuardedBy("mLock") @GuardedBy("mLock") private void mergeBatchLocked(final ArrayList<SecurityEvent> newLogs) { private void mergeBatchLocked(final ArrayList<SecurityEvent> newLogs) { List<SecurityEvent> dedupedLogs = new ArrayList<>(); ArrayList<SecurityEvent> dedupedLogs = new ArrayList<>(); // Run through the first events of the batch to check if there is an overlap with previous // Run through the first events of the batch to check if there is an overlap with previous // batch and if so, skip overlapping events. Events are sorted by timestamp, so we can // batch and if so, skip overlapping events. Events are sorted by timestamp, so we can // compare it in linear time by advancing two pointers, one for each batch. // compare it in linear time by advancing two pointers, one for each batch. Loading Loading @@ -438,8 +446,19 @@ class SecurityLogMonitor implements Runnable { curPos++; curPos++; } } } } // Assign an id to the new logs, after the overlap with mLastEvents. dedupedLogs.addAll(newLogs.subList(curPos, newLogs.size())); dedupedLogs.addAll(newLogs.subList(curPos, newLogs.size())); if (Flags.internalLogEventListener() && !dedupedLogs.isEmpty()) { if (mInternalEventsCallback != null) { final ArrayList<SecurityEvent> events = new ArrayList<>(dedupedLogs); final Consumer<List<SecurityEvent>> callback = mInternalEventsCallback; mHandler.post(() -> callback.accept(events)); } SecurityLog.redactEvents(dedupedLogs, mEnabledUser); } // Assign an id to the new logs, after the overlap with mLastEvents. for (SecurityEvent event : dedupedLogs) { for (SecurityEvent event : dedupedLogs) { assignLogId(event); assignLogId(event); } } Loading Loading @@ -719,4 +738,17 @@ class SecurityLogMonitor implements Runnable { mLock.unlock(); mLock.unlock(); } } } } public void setInternalEventsCallback(@Nullable Consumer<List<SecurityEvent>> callback) { if (!Flags.internalLogEventListener()) { Slog.wtf(TAG, "Internal callbacks not enabled"); return; } mLock.lock(); try { this.mInternalEventsCallback = callback; } finally { mLock.unlock(); } } } }