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

Commit 45749e04 authored by Chalard Jean's avatar Chalard Jean Committed by Automerger Merge Worker
Browse files

Move utilities to libs/net am: 6f67521f am: a39fe804

Original change: https://android-review.googlesource.com/c/platform/packages/modules/NetworkStack/+/1350222

Change-Id: I4c75c2f7ca2a8eb3a8f4f928bcebf8148fbce6c4
parents 516a58a8 a39fe804
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ java_defaults {
        "datastallprotosnano",
        "statsprotos",
        "captiveportal-lib",
        "net-utils-device-common",
    ],
    plugins: ["java_api_finder"],
}
+1 −15
Original line number Diff line number Diff line
@@ -56,22 +56,8 @@ filegroup {
        "src/android/net/netlink/*.java",
        "src/android/net/shared/NetdUtils.java",
        "src/android/net/shared/RouteUtils.java",
        "src/android/net/util/FdEventsReader.java",
        "src/android/net/util/InterfaceParams.java",
        "src/android/net/util/PacketReader.java",
        "src/android/net/util/SharedLog.java"
        "src/android/net/util/SharedLog.java",
    ],
    visibility: ["//frameworks/base/packages/Tethering"],
}

// Utility sources used by test libraries.
// This is its own group to limit indiscriminate dependency of test code on production code.
// TODO: move these classes and NetworkStack/tests/lib to frameworks/libs/net, and remove this.
filegroup {
    name: "net-module-utils-srcs-for-tests",
    visibility: ["//packages/modules/NetworkStack/tests/lib"],
    srcs: [
        "src/android/net/util/FdEventsReader.java",
        "src/android/net/util/PacketReader.java",
    ],
}
+0 −267
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.util;

import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;

import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import java.io.FileDescriptor;
import java.io.IOException;


/**
 * This class encapsulates the mechanics of registering a file descriptor
 * with a thread's Looper and handling read events (and errors).
 *
 * Subclasses MUST implement createFd() and SHOULD override handlePacket(). They MAY override
 * onStop() and onStart().
 *
 * Subclasses can expect a call life-cycle like the following:
 *
 *     [1] when a client calls start(), createFd() is called, followed by the onStart() hook if all
 *         goes well. Implementations may override onStart() for additional initialization.
 *
 *     [2] yield, waiting for read event or error notification:
 *
 *             [a] readPacket() && handlePacket()
 *
 *             [b] if (no error):
 *                     goto 2
 *                 else:
 *                     goto 3
 *
 *     [3] when a client calls stop(), the onStop() hook is called (unless already stopped or never
 *         started). Implementations may override onStop() for additional cleanup.
 *
 * The packet receive buffer is recycled on every read call, so subclasses
 * should make any copies they would like inside their handlePacket()
 * implementation.
 *
 * All public methods MUST only be called from the same thread with which
 * the Handler constructor argument is associated.
 *
 * @param <BufferType> the type of the buffer used to read data.
 */
public abstract class FdEventsReader<BufferType> {
    private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
    private static final int UNREGISTER_THIS_FD = 0;

    @NonNull
    private final Handler mHandler;
    @NonNull
    private final MessageQueue mQueue;
    @NonNull
    private final BufferType mBuffer;
    @Nullable
    private FileDescriptor mFd;
    private long mPacketsReceived;

    protected static void closeFd(FileDescriptor fd) {
        try {
            SocketUtils.closeSocket(fd);
        } catch (IOException ignored) {
        }
    }

    protected FdEventsReader(@NonNull Handler h, @NonNull BufferType buffer) {
        mHandler = h;
        mQueue = mHandler.getLooper().getQueue();
        mBuffer = buffer;
    }

    @VisibleForTesting
    @NonNull
    protected MessageQueue getMessageQueue() {
        return mQueue;
    }

    /** Start this FdEventsReader. */
    public boolean start() {
        if (!onCorrectThread()) {
            throw new IllegalStateException("start() called from off-thread");
        }

        return createAndRegisterFd();
    }

    /** Stop this FdEventsReader and destroy the file descriptor. */
    public void stop() {
        if (!onCorrectThread()) {
            throw new IllegalStateException("stop() called from off-thread");
        }

        unregisterAndDestroyFd();
    }

    @NonNull
    public Handler getHandler() {
        return mHandler;
    }

    protected abstract int recvBufSize(@NonNull BufferType buffer);

    /** Returns the size of the receive buffer. */
    public int recvBufSize() {
        return recvBufSize(mBuffer);
    }

    /**
     * Get the number of successful calls to {@link #readPacket(FileDescriptor, Object)}.
     *
     * <p>A call was successful if {@link #readPacket(FileDescriptor, Object)} returned a value > 0.
     */
    public final long numPacketsReceived() {
        return mPacketsReceived;
    }

    /**
     * Subclasses MUST create the listening socket here, including setting all desired socket
     * options, interface or address/port binding, etc. The socket MUST be created nonblocking.
     */
    @Nullable
    protected abstract FileDescriptor createFd();

    /**
     * Implementations MUST return the bytes read or throw an Exception.
     *
     * <p>The caller may throw a {@link ErrnoException} with {@link OsConstants#EAGAIN} or
     * {@link OsConstants#EINTR}, in which case {@link FdEventsReader} will ignore the buffer
     * contents and respectively wait for further input or retry the read immediately. For all other
     * exceptions, the {@link FdEventsReader} will be stopped with no more interactions with this
     * method.
     */
    protected abstract int readPacket(@NonNull FileDescriptor fd, @NonNull BufferType buffer)
            throws Exception;

    /**
     * Called by the main loop for every packet.  Any desired copies of
     * |recvbuf| should be made in here, as the underlying byte array is
     * reused across all reads.
     */
    protected void handlePacket(@NonNull BufferType recvbuf, int length) {}

    /**
     * Called by the main loop to log errors.  In some cases |e| may be null.
     */
    protected void logError(@NonNull String msg, @Nullable Exception e) {}

    /**
     * Called by start(), if successful, just prior to returning.
     */
    protected void onStart() {}

    /**
     * Called by stop() just prior to returning.
     */
    protected void onStop() {}

    private boolean createAndRegisterFd() {
        if (mFd != null) return true;

        try {
            mFd = createFd();
        } catch (Exception e) {
            logError("Failed to create socket: ", e);
            closeFd(mFd);
            mFd = null;
        }

        if (mFd == null) return false;

        getMessageQueue().addOnFileDescriptorEventListener(
                mFd,
                FD_EVENTS,
                (fd, events) -> {
                    // Always call handleInput() so read/recvfrom are given
                    // a proper chance to encounter a meaningful errno and
                    // perhaps log a useful error message.
                    if (!isRunning() || !handleInput()) {
                        unregisterAndDestroyFd();
                        return UNREGISTER_THIS_FD;
                    }
                    return FD_EVENTS;
                });
        onStart();
        return true;
    }

    private boolean isRunning() {
        return (mFd != null) && mFd.valid();
    }

    // Keep trying to read until we get EAGAIN/EWOULDBLOCK or some fatal error.
    private boolean handleInput() {
        while (isRunning()) {
            final int bytesRead;

            try {
                bytesRead = readPacket(mFd, mBuffer);
                if (bytesRead < 1) {
                    if (isRunning()) logError("Socket closed, exiting", null);
                    break;
                }
                mPacketsReceived++;
            } catch (ErrnoException e) {
                if (e.errno == OsConstants.EAGAIN) {
                    // We've read everything there is to read this time around.
                    return true;
                } else if (e.errno == OsConstants.EINTR) {
                    continue;
                } else {
                    if (isRunning()) logError("readPacket error: ", e);
                    break;
                }
            } catch (Exception e) {
                if (isRunning()) logError("readPacket error: ", e);
                break;
            }

            try {
                handlePacket(mBuffer, bytesRead);
            } catch (Exception e) {
                logError("handlePacket error: ", e);
                Log.wtf(FdEventsReader.class.getSimpleName(), "Error handling packet", e);
            }
        }

        return false;
    }

    private void unregisterAndDestroyFd() {
        if (mFd == null) return;

        getMessageQueue().removeOnFileDescriptorEventListener(mFd);
        closeFd(mFd);
        mFd = null;
        onStop();
    }

    private boolean onCorrectThread() {
        return (mHandler.getLooper() == Looper.myLooper());
    }
}
+0 −59
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.util;

import static java.lang.Math.max;

import android.os.Handler;
import android.system.Os;

import java.io.FileDescriptor;

/**
 * Specialization of {@link FdEventsReader} that reads packets into a byte array.
 *
 * TODO: rename this class to something more correctly descriptive (something
 * like [or less horrible than] FdReadEventsHandler?).
 */
public abstract class PacketReader extends FdEventsReader<byte[]> {

    public static final int DEFAULT_RECV_BUF_SIZE = 2 * 1024;

    protected PacketReader(Handler h) {
        this(h, DEFAULT_RECV_BUF_SIZE);
    }

    protected PacketReader(Handler h, int recvBufSize) {
        super(h, new byte[max(recvBufSize, DEFAULT_RECV_BUF_SIZE)]);
    }

    @Override
    protected final int recvBufSize(byte[] buffer) {
        return buffer.length;
    }

    /**
     * Subclasses MAY override this to change the default read() implementation
     * in favour of, say, recvfrom().
     *
     * Implementations MUST return the bytes read or throw an Exception.
     */
    @Override
    protected int readPacket(FileDescriptor fd, byte[] packetBuffer) throws Exception {
        return Os.read(fd, packetBuffer, 0, packetBuffer.length);
    }
}

tests/lib/Android.bp

deleted100644 → 0
+0 −56
Original line number Diff line number Diff line
//
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

java_library {
    name: "net-tests-utils-multivariant",
    srcs: [
        "multivariant/**/*.java",
        "multivariant/**/*.kt",
    ],
    host_supported: true,
    static_libs: [
        "kotlin-test",
        "junit",
    ],
}

java_library {
    name: "net-tests-utils",
    srcs: [
        "src/**/*.java",
        "src/**/*.kt",
        ":net-module-utils-srcs-for-tests",
    ],
    defaults: ["lib_mockito_extended"],
    libs: [
        "androidx.annotation_annotation",
    ],
    static_libs: [
        "androidx.test.ext.junit",
        "net-tests-utils-multivariant",
    ],
}

java_defaults {
    name: "lib_mockito_extended",
    static_libs: [
        "mockito-target-extended-minus-junit4"
    ],
    jni_libs: [
         "libdexmakerjvmtiagent",
         "libstaticjvmtiagent",
    ],
}
Loading