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

Commit 4da4a5d0 authored by Michal Karpinski's avatar Michal Karpinski
Browse files

[DPM] Improvements to the network logs batch finalization mechanism

The full batch will still be available to DPC if there were no
network logs pending.
Added some more debug logging to better investigate the issues.

Test: manual for both cases - pending batch was empty and non-empty,
      with locally decreased timeout
Test: cts-tradefed run cts --module DevicePolicyManager --test com.android.cts.devicepolicy.DeviceOwnerTest#testNetworkLoggingWithSingleUser

Bug: 34245471
Bug: 29748723
Change-Id: Iee229d74d4b0a06025b305a15687f336a0aa337e
parent c687aa08
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import android.content.pm.PackageManagerInternal;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -115,8 +114,7 @@ final class NetworkLogger {
                mHandlerThread.start();
                mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(),
                        mDpm);
                mNetworkLoggingHandler.scheduleBatchFinalization(
                        NetworkLoggingHandler.BATCH_FINALIZATION_TIMEOUT_MS);
                mNetworkLoggingHandler.scheduleBatchFinalization();
                mIsLoggingEnabled.set(true);
                return true;
            } else {
+20 −19
Original line number Diff line number Diff line
@@ -17,16 +17,11 @@
package com.android.server.devicepolicy;

import android.app.admin.DeviceAdminReceiver;
import android.app.admin.ConnectEvent;
import android.app.admin.DnsEvent;
import android.app.admin.NetworkEvent;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
@@ -44,10 +39,9 @@ final class NetworkLoggingHandler extends Handler {

    static final String NETWORK_EVENT_KEY = "network_event";

    // est. ~128kB of memory usage per full batch TODO(mkarpinski): fine tune based on testing data
    // If this value changes, update DevicePolicyManager#retrieveNetworkLogs() javadoc
    private static final int MAX_EVENTS_PER_BATCH = 1200;
    static final long BATCH_FINALIZATION_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(90);
    private static final long BATCH_FINALIZATION_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(90);

    static final int LOG_NETWORK_EVENT_MSG = 1;
    static final int FINALIZE_BATCH_MSG = 2;
@@ -78,31 +72,32 @@ final class NetworkLoggingHandler extends Handler {
                if (networkEvent != null) {
                    mNetworkEvents.add(networkEvent);
                    if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) {
                        finalizeBatchAndNotifyDeviceOwner();
                        finalizeBatchAndNotifyDeviceOwnerIfNotEmpty();
                    }
                }
                break;
            }
            case FINALIZE_BATCH_MSG: {
                finalizeBatchAndNotifyDeviceOwner();
                finalizeBatchAndNotifyDeviceOwnerIfNotEmpty();
                break;
            }
        }
    }

    void scheduleBatchFinalization(long delay) {
    void scheduleBatchFinalization() {
        removeMessages(FINALIZE_BATCH_MSG);
        sendMessageDelayed(obtainMessage(FINALIZE_BATCH_MSG), delay);
        sendMessageDelayed(obtainMessage(FINALIZE_BATCH_MSG), BATCH_FINALIZATION_TIMEOUT_MS);
        Log.d(TAG, "Scheduled new batch finalization " + BATCH_FINALIZATION_TIMEOUT_MS
                + "ms from now.");
    }

    private synchronized void finalizeBatchAndNotifyDeviceOwner() {
    private synchronized void finalizeBatchAndNotifyDeviceOwnerIfNotEmpty() {
        if (mNetworkEvents.size() > 0) {
            // finalize the batch and start a new one from scratch
            mFullBatch = mNetworkEvents;
        // start a new batch from scratch
            mCurrentFullBatchToken++;
            mNetworkEvents = new ArrayList<NetworkEvent>();
        scheduleBatchFinalization(BATCH_FINALIZATION_TIMEOUT_MS);
            // notify DO that there's a new non-empty batch waiting
        if (mFullBatch.size() > 0) {
            mCurrentFullBatchToken++;
            Bundle extras = new Bundle();
            extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentFullBatchToken);
            extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, mFullBatch.size());
@@ -110,8 +105,14 @@ final class NetworkLoggingHandler extends Handler {
                    + mCurrentFullBatchToken);
            mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras);
        } else {
            mFullBatch = null;
            // don't notify the DO, since there are no events; DPC can still retrieve
            // the last full batch
            Log.d(TAG, "Was about to finalize the batch, but there were no events to send to"
                    + " the DPC, the batchToken of last available batch: "
                    + mCurrentFullBatchToken);
        }
        // regardless of whether the batch was non-empty schedule a new finalization after timeout
        scheduleBatchFinalization();
    }

    synchronized List<NetworkEvent> retrieveFullLogBatch(long batchToken) {