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

This commit is contained in:
Michal Karpinski
2016-02-24 12:12:25 +00:00
committed by Android (Google) Code Review
2 changed files with 71 additions and 43 deletions

View File

@@ -7734,9 +7734,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (mUserSetupComplete.equals(uri)) {
updateUserSetupComplete();
} else if (mDeviceProvisioned.equals(uri)) {
// Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
// is delayed until device is marked as provisioned.
setDeviceOwnerSystemPropertyLocked();
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();
}
}
}
}
@@ -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();

View File

@@ -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,36 +72,50 @@ 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() {
if (mMonitorThread == null) {
mPendingLogs = new ArrayList<SecurityEvent>();
mAllowedToRetrieve = false;
mNextAllowedRetrivalTimeMillis = -1;
void start() {
mLock.lock();
try {
if (mMonitorThread == null) {
mPendingLogs = new ArrayList<SecurityEvent>();
mAllowedToRetrieve = false;
mNextAllowedRetrivalTimeMillis = -1;
mMonitorThread = new Thread(this);
mMonitorThread.start();
mMonitorThread = new Thread(this);
mMonitorThread.start();
}
} finally {
mLock.unlock();
}
}
synchronized void stop() {
if (mMonitorThread != null) {
mMonitorThread.interrupt();
try {
mMonitorThread.join(TimeUnit.SECONDS.toMillis(5));
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while waiting for thread to stop", e);
void stop() {
mLock.lock();
try {
if (mMonitorThread != null) {
mMonitorThread.interrupt();
try {
mMonitorThread.join(TimeUnit.SECONDS.toMillis(5));
} 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;
}
mMonitorThread = null;
} finally {
mLock.unlock();
}
}
@@ -105,16 +123,21 @@ class SecurityLogMonitor implements Runnable {
* Returns the new batch of logs since the last call to this method. Returns null if
* rate limit is exceeded.
*/
synchronized List<SecurityEvent> retrieveLogs() {
if (mAllowedToRetrieve) {
mAllowedToRetrieve = false;
mNextAllowedRetrivalTimeMillis = System.currentTimeMillis()
+ RATE_LIMIT_INTERVAL_MILLISECONDS;
List<SecurityEvent> result = mPendingLogs;
mPendingLogs = new ArrayList<SecurityEvent>();
return result;
} else {
return null;
List<SecurityEvent> retrieveLogs() {
mLock.lock();
try {
if (mAllowedToRetrieve) {
mAllowedToRetrieve = false;
mNextAllowedRetrivalTimeMillis = System.currentTimeMillis()
+ RATE_LIMIT_INTERVAL_MILLISECONDS;
List<SecurityEvent> result = mPendingLogs;
mPendingLogs = new ArrayList<SecurityEvent>();
return result;
} else {
return null;
}
} finally {
mLock.unlock();
}
}
@@ -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");
@@ -195,4 +218,4 @@ class SecurityLogMonitor implements Runnable {
null);
}
}
}
}