SecurityLogMonitor.java revision a0ea967d111b9f8e01ebbb1ac8d393270e1788b6
1cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath/*
2cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * Copyright (C) 2016 The Android Open Source Project
3cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath *
4cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * Licensed under the Apache License, Version 2.0 (the "License");
5cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * you may not use this file except in compliance with the License.
6cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * You may obtain a copy of the License at
7cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath *
8cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
9cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath *
10cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * Unless required by applicable law or agreed to in writing, software
11cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * distributed under the License is distributed on an "AS IS" BASIS,
12cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * See the License for the specific language governing permissions and
14cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * limitations under the License.
15cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath */
16cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
17ab762bb740405d0fefcccf4a0899a234f995be13Narayan Kamathpackage com.android.server.devicepolicy;
18cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
19cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport android.app.admin.DeviceAdminReceiver;
20cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport android.auditing.SecurityLog;
21cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport android.auditing.SecurityLog.SecurityEvent;
22cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport android.util.Log;
23cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport android.util.Slog;
24cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
25cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport com.android.internal.annotations.GuardedBy;
26cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
27cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport java.io.IOException;
28cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport java.util.ArrayList;
29cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport java.util.List;
30cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport java.util.concurrent.TimeUnit;
31cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport java.util.concurrent.locks.Lock;
32cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport java.util.concurrent.locks.ReentrantLock;
33cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
34cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathimport android.os.Process;
35cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
36cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath/**
37cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * A class managing access to the security logs. It maintains an internal buffer of pending
38cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * logs to be retrieved by the device owner. The logs are retrieved from the logd daemon via
39cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * JNI binding, and kept until device owner has retrieved to prevent loss of logs. Access to
40cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * the logs from the device owner is rate-limited, and device owner is notified when the logs
41cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * are ready to be retrieved. This happens every two hours, or when our internal buffer is
42cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath * larger than a certain threshold.
43cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath */
44cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamathclass SecurityLogMonitor implements Runnable {
45cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private final DevicePolicyManagerService mService;
46cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
47cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private final Lock mLock = new ReentrantLock();
48cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
49cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    SecurityLogMonitor(DevicePolicyManagerService service) {
50cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        mService = service;
51cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    }
52cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
53cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private static final boolean DEBUG = false;
54cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private static final String TAG = "SecurityLogMonitor";
55cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    /**
56cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * Each log entry can hold up to 4K bytes (but as of {@link android.os.Build.VERSION_CODES#N}
57cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * it should be less than 100 bytes), setting 1024 entries as the threshold to notify Device
58cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * Owner.
59cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     */
60cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private static final int BUFFER_ENTRIES_NOTIFICATION_LEVEL = 1024;
61cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    /**
62cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * The maximum number of entries we should store before dropping earlier logs, to limit the
63cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * memory usage.
64cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     */
65cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private static final int BUFFER_ENTRIES_MAXIMUM_LEVEL = BUFFER_ENTRIES_NOTIFICATION_LEVEL * 10;
66cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    /**
67cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * How often should Device Owner be notified under normal circumstances.
68cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     */
69cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private static final long RATE_LIMIT_INTERVAL_MILLISECONDS = TimeUnit.HOURS.toMillis(2);
70cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    /**
71cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * Internally how often should the monitor poll the security logs from logd.
72cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     */
73cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private static final long POLLING_INTERVAL_MILLISECONDS = TimeUnit.MINUTES.toMillis(1);
74cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
75cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    @GuardedBy("mLock")
76cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private Thread mMonitorThread = null;
77cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    @GuardedBy("mLock")
78cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private ArrayList<SecurityEvent> mPendingLogs = new ArrayList<SecurityEvent>();
79cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    @GuardedBy("mLock")
80cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private boolean mAllowedToRetrieve = false;
81cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    // When DO will be allowed to retrieves the log, in milliseconds.
82cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    @GuardedBy("mLock")
83cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private long mNextAllowedRetrivalTimeMillis = -1;
84cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
85cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    void start() {
86cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        mLock.lock();
87cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        try {
88cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            if (mMonitorThread == null) {
89cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mPendingLogs = new ArrayList<SecurityEvent>();
90cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mAllowedToRetrieve = false;
91cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mNextAllowedRetrivalTimeMillis = -1;
92cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
93cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mMonitorThread = new Thread(this);
94cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mMonitorThread.start();
95cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            }
96cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        } finally {
97cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            mLock.unlock();
98cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        }
99cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    }
100cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
101cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    void stop() {
102cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        mLock.lock();
103cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        try {
104cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            if (mMonitorThread != null) {
105cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mMonitorThread.interrupt();
106cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                try {
107cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    mMonitorThread.join(TimeUnit.SECONDS.toMillis(5));
108cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                } catch (InterruptedException e) {
109cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    Log.e(TAG, "Interrupted while waiting for thread to stop", e);
110cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                }
111cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                // Reset state and clear buffer
112cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mPendingLogs = new ArrayList<SecurityEvent>();
113cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mAllowedToRetrieve = false;
114cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mNextAllowedRetrivalTimeMillis = -1;
115cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mMonitorThread = null;
116cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            }
117cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        } finally {
118cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            mLock.unlock();
119cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        }
120cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    }
121cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
122cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    /**
123cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * Returns the new batch of logs since the last call to this method. Returns null if
124cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     * rate limit is exceeded.
125cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath     */
126cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    List<SecurityEvent> retrieveLogs() {
127cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        mLock.lock();
128cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        try {
129cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            if (mAllowedToRetrieve) {
130cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mAllowedToRetrieve = false;
131cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mNextAllowedRetrivalTimeMillis = System.currentTimeMillis()
132cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                        + RATE_LIMIT_INTERVAL_MILLISECONDS;
133cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                List<SecurityEvent> result = mPendingLogs;
134cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                mPendingLogs = new ArrayList<SecurityEvent>();
135cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                return result;
136cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            } else {
137cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                return null;
138cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            }
139cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        } finally {
140cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            mLock.unlock();
141cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        }
142cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    }
143cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
144cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    @Override
145cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    public void run() {
146cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
147cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
148cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        ArrayList<SecurityEvent> logs = new ArrayList<SecurityEvent>();
149cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        // The timestamp of the latest log entry that has been read, in nanoseconds
150cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        long lastLogTimestampNanos = -1;
151cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        while (!Thread.currentThread().isInterrupted()) {
152cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            try {
153cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                Thread.sleep(POLLING_INTERVAL_MILLISECONDS);
154cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
155cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                if (lastLogTimestampNanos < 0) {
156cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    // Non-blocking read that returns all logs immediately.
157cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    if (DEBUG) Slog.d(TAG, "SecurityLog.readEvents");
158cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    SecurityLog.readEvents(logs);
159cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                } else {
160cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    if (DEBUG) Slog.d(TAG,
161cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                            "SecurityLog.readEventsSince: " + lastLogTimestampNanos);
162cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    // Non-blocking read that returns all logs >= the  timestamp immediately.
163cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    SecurityLog.readEventsSince(lastLogTimestampNanos + 1, logs);
164cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                }
165cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                if (!logs.isEmpty()) {
166cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    if (DEBUG) Slog.d(TAG, "processing new logs");
167cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    mLock.lockInterruptibly();
168cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    try {
169cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                        mPendingLogs.addAll(logs);
170cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                        if (mPendingLogs.size() > BUFFER_ENTRIES_MAXIMUM_LEVEL) {
171cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                            // Truncate buffer down to half of BUFFER_ENTRIES_MAXIMUM_LEVEL
172cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                            mPendingLogs = new ArrayList<SecurityEvent>(mPendingLogs.subList(
173cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                                    mPendingLogs.size() - (BUFFER_ENTRIES_MAXIMUM_LEVEL / 2),
174cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                                    mPendingLogs.size()));
175cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                        }
176cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    } finally {
177cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                        mLock.unlock();
178cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    }
179cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    lastLogTimestampNanos = logs.get(logs.size() - 1).getTimeNanos();
180cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    logs.clear();
181cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                }
182cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                notifyDeviceOwnerIfNeeded();
183cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            } catch (IOException e) {
184cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                Log.e(TAG, "Failed to read security log", e);
185cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            } catch (InterruptedException e) {
186cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                Log.i(TAG, "Thread interrupted, exiting.", e);
187cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                // We are asked to stop.
188cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                break;
189cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            }
190cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        }
191cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        if (DEBUG) Slog.d(TAG, "MonitorThread exit.");
192cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    }
193cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath
194cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    private void notifyDeviceOwnerIfNeeded() throws InterruptedException {
195cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        boolean shouldNotifyDO = false;
196cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        boolean allowToRetrieveNow = false;
197cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        mLock.lockInterruptibly();
198cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        try {
199cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            int logSize = mPendingLogs.size();
200cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            if (logSize >= BUFFER_ENTRIES_NOTIFICATION_LEVEL) {
201cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                // Allow DO to retrieve logs if too many pending logs
202cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                allowToRetrieveNow = true;
203cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            } else if (logSize > 0) {
204cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                if (mNextAllowedRetrivalTimeMillis == -1 ||
205cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                        System.currentTimeMillis() >= mNextAllowedRetrivalTimeMillis) {
206cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    // Rate limit reset
207cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    allowToRetrieveNow = true;
208cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                }
209cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            }
210cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            shouldNotifyDO = (!mAllowedToRetrieve) && allowToRetrieveNow;
211cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            mAllowedToRetrieve = allowToRetrieveNow;
212cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        } finally {
213cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            mLock.unlock();
214cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        }
215cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        if (shouldNotifyDO) {
216cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            if (DEBUG) Slog.d(TAG, "notify DO");
217cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath            mService.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_SECURITY_LOGS_AVAILABLE,
218cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath                    null);
219cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath        }
220cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath    }
221cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath}
222cb318c6f4fe5b0e20099fa85f1b95ccb2d24119fNarayan Kamath