Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07d9bb82 authored by Michal Karpinski's avatar Michal Karpinski Committed by Android (Google) Code Review
Browse files

Merge "Removing lock contention in SecurityLogMonitor" into nyc-dev

parents f19e7822 a0ea967d
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -7734,12 +7734,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            if (mUserSetupComplete.equals(uri)) {
                updateUserSetupComplete();
            } else if (mDeviceProvisioned.equals(uri)) {
                synchronized (DevicePolicyManagerService.this) {
                    // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
                    // is delayed until device is marked as provisioned.
                    setDeviceOwnerSystemPropertyLocked();
                }
            }
        }
    }

    @VisibleForTesting
    final class LocalService extends DevicePolicyManagerInternal {
@@ -8433,7 +8435,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return false;
    }

    private void disableDeviceLoggingIfNotCompliant() {
    private synchronized void disableDeviceLoggingIfNotCompliant() {
        if (!isDeviceOwnerManagedSingleUserDevice()) {
            mInjector.securityLogSetLoggingEnabledProperty(false);
            Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device.");
@@ -8446,6 +8448,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        ensureDeviceOwnerManagingSingleUser(admin);

        synchronized (this) {
            if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
                return;
            }
            mInjector.securityLogSetLoggingEnabledProperty(enabled);
            if (enabled) {
                mSecurityLogMonitor.start();
+62 −39
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import android.os.Process;

@@ -42,6 +44,8 @@ import android.os.Process;
class SecurityLogMonitor implements Runnable {
    private final DevicePolicyManagerService mService;

    private final Lock mLock = new ReentrantLock();

    SecurityLogMonitor(DevicePolicyManagerService service) {
        mService = service;
    }
@@ -68,17 +72,19 @@ class SecurityLogMonitor implements Runnable {
     */
    private static final long POLLING_INTERVAL_MILLISECONDS = TimeUnit.MINUTES.toMillis(1);

    @GuardedBy("this")
    @GuardedBy("mLock")
    private Thread mMonitorThread = null;
    @GuardedBy("this")
    @GuardedBy("mLock")
    private ArrayList<SecurityEvent> mPendingLogs = new ArrayList<SecurityEvent>();
    @GuardedBy("this")
    @GuardedBy("mLock")
    private boolean mAllowedToRetrieve = false;
    // When DO will be allowed to retrieves the log, in milliseconds.
    @GuardedBy("this")
    @GuardedBy("mLock")
    private long mNextAllowedRetrivalTimeMillis = -1;

    synchronized void start() {
    void start() {
        mLock.lock();
        try {
            if (mMonitorThread == null) {
                mPendingLogs = new ArrayList<SecurityEvent>();
                mAllowedToRetrieve = false;
@@ -87,9 +93,14 @@ class SecurityLogMonitor implements Runnable {
                mMonitorThread = new Thread(this);
                mMonitorThread.start();
            }
        } finally {
            mLock.unlock();
        }
    }

    synchronized void stop() {
    void stop() {
        mLock.lock();
        try {
            if (mMonitorThread != null) {
                mMonitorThread.interrupt();
                try {
@@ -97,15 +108,24 @@ class SecurityLogMonitor implements Runnable {
                } catch (InterruptedException e) {
                    Log.e(TAG, "Interrupted while waiting for thread to stop", e);
                }
                // Reset state and clear buffer
                mPendingLogs = new ArrayList<SecurityEvent>();
                mAllowedToRetrieve = false;
                mNextAllowedRetrivalTimeMillis = -1;
                mMonitorThread = null;
            }
        } finally {
            mLock.unlock();
        }
    }

    /**
     * Returns the new batch of logs since the last call to this method. Returns null if
     * rate limit is exceeded.
     */
    synchronized List<SecurityEvent> retrieveLogs() {
    List<SecurityEvent> retrieveLogs() {
        mLock.lock();
        try {
            if (mAllowedToRetrieve) {
                mAllowedToRetrieve = false;
                mNextAllowedRetrivalTimeMillis = System.currentTimeMillis()
@@ -116,6 +136,9 @@ class SecurityLogMonitor implements Runnable {
            } else {
                return null;
            }
        } finally {
            mLock.unlock();
        }
    }

    @Override
@@ -141,7 +164,8 @@ class SecurityLogMonitor implements Runnable {
                }
                if (!logs.isEmpty()) {
                    if (DEBUG) Slog.d(TAG, "processing new logs");
                    synchronized (this) {
                    mLock.lockInterruptibly();
                    try {
                        mPendingLogs.addAll(logs);
                        if (mPendingLogs.size() > BUFFER_ENTRIES_MAXIMUM_LEVEL) {
                            // Truncate buffer down to half of BUFFER_ENTRIES_MAXIMUM_LEVEL
@@ -149,6 +173,8 @@ class SecurityLogMonitor implements Runnable {
                                    mPendingLogs.size() - (BUFFER_ENTRIES_MAXIMUM_LEVEL / 2),
                                    mPendingLogs.size()));
                        }
                    } finally {
                        mLock.unlock();
                    }
                    lastLogTimestampNanos = logs.get(logs.size() - 1).getTimeNanos();
                    logs.clear();
@@ -163,18 +189,13 @@ class SecurityLogMonitor implements Runnable {
            }
        }
        if (DEBUG) Slog.d(TAG, "MonitorThread exit.");
        synchronized (this) {
            // Reset state and clear buffer
            mPendingLogs = new ArrayList<SecurityEvent>();
            mAllowedToRetrieve = false;
            mNextAllowedRetrivalTimeMillis = -1;
        }
    }

    private void notifyDeviceOwnerIfNeeded() {
    private void notifyDeviceOwnerIfNeeded() throws InterruptedException {
        boolean shouldNotifyDO = false;
        boolean allowToRetrieveNow = false;
        synchronized (this) {
        mLock.lockInterruptibly();
        try {
            int logSize = mPendingLogs.size();
            if (logSize >= BUFFER_ENTRIES_NOTIFICATION_LEVEL) {
                // Allow DO to retrieve logs if too many pending logs
@@ -188,6 +209,8 @@ class SecurityLogMonitor implements Runnable {
            }
            shouldNotifyDO = (!mAllowedToRetrieve) && allowToRetrieveNow;
            mAllowedToRetrieve = allowToRetrieveNow;
        } finally {
            mLock.unlock();
        }
        if (shouldNotifyDO) {
            if (DEBUG) Slog.d(TAG, "notify DO");