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

Commit ef99fb85 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Make device wide DO features available if all users affiliated"

parents 74f50acf d36dd15d
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -768,6 +768,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
    /**
     * Called when a new batch of security logs can be retrieved.
     *
     * <p>If a secondary user or profile is created, this callback won't be received until all users
     * become affiliated again (even if security logging is enabled).
     * See {@link DevicePolicyManager#setAffiliationIds}
     *
     * <p>This callback is only applicable to device owners.
     *
     * @param context The running context as per {@link #onReceive}.
@@ -782,13 +786,18 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * ever be called when network logging is enabled. The logs can only be retrieved while network
     * logging is enabled.
     *
     * <p>If a secondary user or profile is created, this callback won't be received until all users
     * become affiliated again (even if network logging is enabled). It will also no longer be
     * possible to retrieve the network logs batch with the most recent {@code batchToken} provided
     * by this callback. See {@link DevicePolicyManager#setAffiliationIds}.
     *
     * <p>This callback is only applicable to device owners.
     *
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     * @param batchToken The token representing the current batch of network logs.
     * @param networkLogsCount The total count of events in the current batch of network logs.
     * @see DevicePolicyManager#retrieveNetworkLogs(ComponentName)
     * @see DevicePolicyManager#retrieveNetworkLogs
     */
    public void onNetworkLogsAvailable(Context context, Intent intent, long batchToken,
            int networkLogsCount) {
+47 −21
Original line number Diff line number Diff line
@@ -3651,15 +3651,16 @@ public class DevicePolicyManager {
    /**
     * Called by a device owner to request a bugreport.
     * <p>
     * There must be only one user on the device, managed by the device owner. Otherwise a
     * {@link SecurityException} will be thrown.
     * If the device contains secondary users or profiles, they must be affiliated with the device
     * owner user. Otherwise a {@link SecurityException} will be thrown. See
     * {@link #setAffiliationIds}.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @return {@code true} if the bugreport collection started successfully, or {@code false} if it
     *         wasn't triggered because a previous bugreport operation is still active (either the
     *         bugreport is still running or waiting for the user to share or decline)
     * @throws SecurityException if {@code admin} is not a device owner, or if there are users other
     *             than the one managed by the device owner.
     * @throws SecurityException if {@code admin} is not a device owner, or there is at least one
     *         profile or secondary user that is not affiliated with the device owner user.
     */
    public boolean requestBugreport(@NonNull ComponentName admin) {
        throwIfParentInstance("requestBugreport");
@@ -6631,14 +6632,16 @@ public class DevicePolicyManager {
    }

    /**
     * Called by device owner to control the security logging feature. Logging can only be
     * enabled on single user devices where the sole user is managed by the device owner.
     * Called by device owner to control the security logging feature.
     *
     * <p> Security logs contain various information intended for security auditing purposes.
     * See {@link SecurityEvent} for details.
     *
     * <p>There must be only one user on the device, managed by the device owner.
     * Otherwise a {@link SecurityException} will be thrown.
     * <p><strong>Note:</strong> The device owner won't be able to retrieve security logs if there
     * are unaffiliated secondary users or profiles on the device, regardless of whether the
     * feature is enabled. Logs will be discarded if the internal buffer fills up while waiting for
     * all users to become affiliated. Therefore it's recommended that affiliation ids are set for
     * new users as soon as possible after provisioning via {@link #setAffiliationIds}.
     *
     * @param admin Which device owner this request is associated with.
     * @param enabled whether security logging should be enabled or not.
@@ -6680,13 +6683,16 @@ public class DevicePolicyManager {
     * <p> Access to the logs is rate limited and it will only return new logs after the device
     * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
     *
     * <p>There must be only one user on the device, managed by the device owner.
     * Otherwise a {@link SecurityException} will be thrown.
     * <p>If there is any other user or profile on the device, it must be affiliated with the
     * device owner. Otherwise a {@link SecurityException} will be thrown. See
     * {@link #setAffiliationIds}
     *
     * @param admin Which device owner this request is associated with.
     * @return the new batch of security logs which is a list of {@link SecurityEvent},
     * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
     * @throws SecurityException if {@code admin} is not a device owner.
     * @throws SecurityException if {@code admin} is not a device owner, or there is at least one
     * profile or secondary user that is not affiliated with the device owner user.
     * @see DeviceAdminReceiver#onSecurityLogsAvailable
     */
    public @Nullable List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) {
        throwIfParentInstance("retrieveSecurityLogs");
@@ -6726,14 +6732,17 @@ public class DevicePolicyManager {
     * will result in {@code null} being returned. The device logs are retrieved from a RAM region
     * which is not guaranteed to be corruption-free during power cycles, as a result be cautious
     * about data corruption when parsing. </strong>
     * <p>
     * There must be only one user on the device, managed by the device owner. Otherwise a
     * {@link SecurityException} will be thrown.
     *
     * <p>If there is any other user or profile on the device, it must be affiliated with the
     * device owner. Otherwise a {@link SecurityException} will be thrown. See
     * {@link #setAffiliationIds}
     *
     * @param admin Which device owner this request is associated with.
     * @return Device logs from before the latest reboot of the system, or {@code null} if this API
     *         is not supported on the device.
     * @throws SecurityException if {@code admin} is not a device owner.
     * @throws SecurityException if {@code admin} is not a device owner, or there is at least one
     * profile or secondary user that is not affiliated with the device owner user.
     * @see #retrieveSecurityLogs
     */
    public @Nullable List<SecurityEvent> retrievePreRebootSecurityLogs(
            @NonNull ComponentName admin) {
@@ -6939,6 +6948,12 @@ public class DevicePolicyManager {
     * Indicates the entity that controls the device or profile owner. Two users/profiles are
     * affiliated if the set of ids set by their device or profile owners intersect.
     *
     * <p><strong>Note:</strong> Features that depend on user affiliation (such as security logging
     * or {@link #bindDeviceAdminServiceAsUser}) won't be available when a secondary user or profile
     * is created, until it becomes affiliated. Therefore it is recommended that the appropriate
     * affiliation ids are set by its profile owner as soon as possible after the user/profile is
     * created.
     *
     * @param admin Which profile or device owner this request is associated with.
     * @param ids A list of opaque non-empty affiliation ids. Duplicate elements will be ignored.
     *
@@ -7138,15 +7153,19 @@ public class DevicePolicyManager {
    }

    /**
     * Called by a device owner to control the network logging feature. Logging can only be
     * enabled on single user devices where the sole user is managed by the device owner. If a new
     * user is added on the device, logging is disabled.
     * Called by a device owner to control the network logging feature.
     *
     * <p> Network logs contain DNS lookup and connect() library call events.
     *
     * <p><strong>Note:</strong> The device owner won't be able to retrieve network logs if there
     * are unaffiliated secondary users or profiles on the device, regardless of whether the
     * feature is enabled. Logs will be discarded if the internal buffer fills up while waiting for
     * all users to become affiliated. Therefore it's recommended that affiliation ids are set for
     * new users as soon as possible after provisioning via {@link #setAffiliationIds}.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param enabled whether network logging should be enabled or not.
     * @throws {@link SecurityException} if {@code admin} is not a device owner.
     * @throws SecurityException if {@code admin} is not a device owner.
     * @see #retrieveNetworkLogs
     */
    public void setNetworkLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
@@ -7164,7 +7183,7 @@ public class DevicePolicyManager {
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only
     * be {@code null} if the caller has MANAGE_USERS permission.
     * @return {@code true} if network logging is enabled by device owner, {@code false} otherwise.
     * @throws {@link SecurityException} if {@code admin} is not a device owner and caller has
     * @throws SecurityException if {@code admin} is not a device owner and caller has
     * no MANAGE_USERS permission
     */
    public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) {
@@ -7190,12 +7209,19 @@ public class DevicePolicyManager {
     * after the device device owner has been notified via
     * {@link DeviceAdminReceiver#onNetworkLogsAvailable}.
     *
     * <p>If a secondary user or profile is created, calling this method will throw a
     * {@link SecurityException} until all users become affiliated again. It will also no longer be
     * possible to retrieve the network logs batch with the most recent batchToken provided
     * by {@link DeviceAdminReceiver#onNetworkLogsAvailable}. See
     * {@link DevicePolicyManager#setAffiliationIds}.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param batchToken A token of the batch to retrieve
     * @return A new batch of network logs which is a list of {@link NetworkEvent}. Returns
     *        {@code null} if the batch represented by batchToken is no longer available or if
     *        logging is disabled.
     * @throws {@link SecurityException} if {@code admin} is not a device owner.
     * @throws SecurityException if {@code admin} is not a device owner, or there is at least one
     * profile or secondary user that is not affiliated with the device owner user.
     * @see DeviceAdminReceiver#onNetworkLogsAvailable
     */
    public @Nullable List<NetworkEvent> retrieveNetworkLogs(@NonNull ComponentName admin,
+175 −122

File changed.

Preview size limit exceeded, changes collapsed.

+38 −3
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import android.util.Slog;

import com.android.server.ServiceThread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

@@ -130,6 +129,8 @@ final class NetworkLogger {
        Log.d(TAG, "Stopping network logging");
        // stop the logging regardless of whether we fail to unregister listener
        mIsLoggingEnabled.set(false);
        discardLogs();

        try {
            if (!checkIpConnectivityMetricsService()) {
                // the IIpConnectivityMetrics service should have been present at this point
@@ -140,9 +141,43 @@ final class NetworkLogger {
            return mIpConnectivityMetrics.unregisterNetdEventCallback();
        } catch (RemoteException re) {
            Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re);
            return true;
        } finally {
            if (mHandlerThread != null) {
                mHandlerThread.quitSafely();
            return true;
            }
        }
    }

    /**
     * If logs are being collected, keep collecting them but stop notifying the device owner that
     * new logs are available (since they cannot be retrieved)
     */
    void pause() {
        if (mNetworkLoggingHandler != null) {
            mNetworkLoggingHandler.pause();
        }
    }

    /**
     * If logs are being collected, start notifying the device owner when logs are ready to be
     * collected again (if it was paused).
     * <p>If logging is enabled and there are logs ready to be retrieved, this method will attempt
     * to notify the device owner. Therefore calling identity should be cleared before calling it
     * (in case the method is called from a user other than the DO's user).
     */
    void resume() {
        if (mNetworkLoggingHandler != null) {
            mNetworkLoggingHandler.resume();
        }
    }

    /**
     * Discard all collected logs.
     */
    void discardLogs() {
        if (mNetworkLoggingHandler != null) {
            mNetworkLoggingHandler.discardLogs();
        }
    }

+62 −14
Original line number Diff line number Diff line
@@ -55,10 +55,16 @@ final class NetworkLoggingHandler extends Handler {
    @GuardedBy("this")
    private ArrayList<NetworkEvent> mFullBatch;

    // each full batch is represented by its token, which the DPC has to provide back to revieve it
    @GuardedBy("this")
    private boolean mPaused = false;

    // each full batch is represented by its token, which the DPC has to provide back to retrieve it
    @GuardedBy("this")
    private long mCurrentFullBatchToken;

    @GuardedBy("this")
    private long mLastRetrievedFullBatchToken;

    NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) {
        super(looper);
        mDpm = dpm;
@@ -70,15 +76,19 @@ final class NetworkLoggingHandler extends Handler {
            case LOG_NETWORK_EVENT_MSG: {
                NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY);
                if (networkEvent != null) {
                    synchronized (NetworkLoggingHandler.this) {
                        mNetworkEvents.add(networkEvent);
                        if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) {
                        finalizeBatchAndNotifyDeviceOwnerIfNotEmpty();
                            finalizeBatchAndNotifyDeviceOwnerLocked();
                        }
                    }
                }
                break;
            }
            case FINALIZE_BATCH_MSG: {
                finalizeBatchAndNotifyDeviceOwnerIfNotEmpty();
                synchronized (NetworkLoggingHandler.this) {
                    finalizeBatchAndNotifyDeviceOwnerLocked();
                }
                break;
            }
        }
@@ -91,22 +101,49 @@ final class NetworkLoggingHandler extends Handler {
                + "ms from now.");
    }

    private synchronized void finalizeBatchAndNotifyDeviceOwnerIfNotEmpty() {
    synchronized void pause() {
        Log.d(TAG, "Paused network logging");
        mPaused = true;
    }

    synchronized void resume() {
        if (!mPaused) {
            Log.d(TAG, "Attempted to resume network logging, but logging is not paused.");
            return;
        }

        Log.d(TAG, "Resumed network logging. Current batch="
                + mCurrentFullBatchToken + ", LastRetrievedBatch=" + mLastRetrievedFullBatchToken);
        mPaused = false;

        // If there is a full batch ready that the device owner hasn't been notified about, do it
        // now.
        if (mFullBatch != null && mFullBatch.size() > 0
                && mLastRetrievedFullBatchToken != mCurrentFullBatchToken) {
            scheduleBatchFinalization();
            notifyDeviceOwnerLocked();
        }
    }

    synchronized void discardLogs() {
        mFullBatch = null;
        mNetworkEvents = new ArrayList<NetworkEvent>();
        Log.d(TAG, "Discarded all network logs");
    }

    @GuardedBy("this")
    private void finalizeBatchAndNotifyDeviceOwnerLocked() {
        if (mNetworkEvents.size() > 0) {
            // finalize the batch and start a new one from scratch
            mFullBatch = mNetworkEvents;
            mCurrentFullBatchToken++;
            mNetworkEvents = new ArrayList<NetworkEvent>();
            // notify DO that there's a new non-empty batch waiting
            Bundle extras = new Bundle();
            extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentFullBatchToken);
            extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, mFullBatch.size());
            Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: "
                    + mCurrentFullBatchToken);
            mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras);
            if (!mPaused) {
                notifyDeviceOwnerLocked();
            }
        } else {
            // don't notify the DO, since there are no events; DPC can still retrieve
            // the last full batch
            // the last full batch if not paused.
            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);
@@ -115,10 +152,21 @@ final class NetworkLoggingHandler extends Handler {
        scheduleBatchFinalization();
    }

    @GuardedBy("this")
    private void notifyDeviceOwnerLocked() {
        Bundle extras = new Bundle();
        extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentFullBatchToken);
        extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, mFullBatch.size());
        Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: "
                + mCurrentFullBatchToken);
        mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras);
    }

    synchronized List<NetworkEvent> retrieveFullLogBatch(long batchToken) {
        if (batchToken != mCurrentFullBatchToken) {
            return null;
        }
        mLastRetrievedFullBatchToken = mCurrentFullBatchToken;
        return mFullBatch;
    }
}
Loading