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

Commit 5bb5156a authored by Matthew Sedam's avatar Matthew Sedam Committed by Android (Google) Code Review
Browse files

Merge "ContextHubService: Implement CHRE reliable messages" into main

parents 5c6d75fe efe1e6f6
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -5676,6 +5676,7 @@ package android.hardware.location {
    method @NonNull public android.hardware.location.ContextHubInfo getAttachedHub();
    method @IntRange(from=0, to=65535) public int getId();
    method @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int sendMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
    method @FlaggedApi("android.chre.flags.reliable_message") @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> sendReliableMessageToNanoApp(@NonNull android.hardware.location.NanoAppMessage);
  }
  public class ContextHubClientCallback {
@@ -5711,6 +5712,7 @@ package android.hardware.location {
    method public String getToolchain();
    method public int getToolchainVersion();
    method public String getVendor();
    method @FlaggedApi("android.chre.flags.reliable_message") public boolean supportsReliableMessages();
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR;
  }
@@ -5794,6 +5796,7 @@ package android.hardware.location {
    field public static final int RESULT_FAILED_BAD_PARAMS = 2; // 0x2
    field public static final int RESULT_FAILED_BUSY = 4; // 0x4
    field public static final int RESULT_FAILED_HAL_UNAVAILABLE = 8; // 0x8
    field @FlaggedApi("android.chre.flags.reliable_message") public static final int RESULT_FAILED_NOT_SUPPORTED = 9; // 0x9
    field public static final int RESULT_FAILED_SERVICE_INTERNAL_FAILURE = 7; // 0x7
    field public static final int RESULT_FAILED_TIMEOUT = 6; // 0x6
    field public static final int RESULT_FAILED_UNINITIALIZED = 3; // 0x3
@@ -5803,6 +5806,7 @@ package android.hardware.location {
    field public static final int TYPE_ENABLE_NANOAPP = 2; // 0x2
    field public static final int TYPE_LOAD_NANOAPP = 0; // 0x0
    field public static final int TYPE_QUERY_NANOAPPS = 4; // 0x4
    field @FlaggedApi("android.chre.flags.reliable_message") public static final int TYPE_RELIABLE_MESSAGE = 5; // 0x5
    field public static final int TYPE_UNLOAD_NANOAPP = 1; // 0x1
  }
@@ -5985,12 +5989,17 @@ package android.hardware.location {
  public final class NanoAppMessage implements android.os.Parcelable {
    method public static android.hardware.location.NanoAppMessage createMessageFromNanoApp(long, int, byte[], boolean);
    method @FlaggedApi("android.chre.flags.reliable_message") @NonNull public static android.hardware.location.NanoAppMessage createMessageFromNanoApp(long, int, @NonNull byte[], boolean, boolean, int);
    method public static android.hardware.location.NanoAppMessage createMessageToNanoApp(long, int, byte[]);
    method public int describeContents();
    method public byte[] getMessageBody();
    method @FlaggedApi("android.chre.flags.reliable_message") public int getMessageSequenceNumber();
    method public int getMessageType();
    method public long getNanoAppId();
    method public boolean isBroadcastMessage();
    method @FlaggedApi("android.chre.flags.reliable_message") public boolean isReliable();
    method @FlaggedApi("android.chre.flags.reliable_message") public void setIsReliable(boolean);
    method @FlaggedApi("android.chre.flags.reliable_message") public void setMessageSequenceNumber(int);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppMessage> CREATOR;
  }
+86 −15
Original line number Diff line number Diff line
@@ -15,11 +15,14 @@
 */
package android.hardware.location;

import android.annotation.FlaggedApi;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.chre.flags.Flags;
import android.os.RemoteException;
import android.util.Log;

@@ -185,23 +188,75 @@ public class ContextHubClient implements Closeable {
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @ContextHubTransaction.Result
    public int sendMessageToNanoApp(@NonNull NanoAppMessage message) {
        return doSendMessageToNanoApp(message, null);
    }

    /**
     * Sends a reliable message to a nanoapp.
     *
     * This method is similar to {@link ContextHubClient#sendMessageToNanoApp} with the
     * difference that it expects the message to be acknowledged by CHRE.
     *
     * The transaction succeeds after we received an ACK from CHRE without error.
     * In all other cases the transaction will fail.
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @NonNull
    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
    public ContextHubTransaction<Void> sendReliableMessageToNanoApp(
            @NonNull NanoAppMessage message) {
        if (!Flags.reliableMessageImplementation()) {
            return null;
        }

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_RELIABLE_MESSAGE);

        if (!mAttachedHub.supportsReliableMessages()) {
            transaction.setResponse(new ContextHubTransaction.Response<Void>(
                    ContextHubTransaction.RESULT_FAILED_NOT_SUPPORTED, null));
            return transaction;
        }

        IContextHubTransactionCallback callback =
                ContextHubTransactionHelper.createTransactionCallback(transaction);

        @ContextHubTransaction.Result int result = doSendMessageToNanoApp(message, callback);
        if (result != ContextHubTransaction.RESULT_SUCCESS) {
            transaction.setResponse(new ContextHubTransaction.Response<Void>(result, null));
        }

        return transaction;
    }

    /**
     * Sends a message to a nanoapp.
     *
     * @param message The message to send.
     * @param transactionCallback The callback to use when the message is reliable. null for regular
     *         messages.
     * @return A {@link ContextHubTransaction.Result} error code.
     */
    @ContextHubTransaction.Result
    private int doSendMessageToNanoApp(@NonNull NanoAppMessage message,
            @Nullable IContextHubTransactionCallback transactionCallback) {
        Objects.requireNonNull(message, "NanoAppMessage cannot be null");

        int maxPayloadBytes = mAttachedHub.getMaxPacketLengthBytes();

        byte[] payload = message.getMessageBody();
        if (payload != null && payload.length > maxPayloadBytes) {
            Log.e(
                    TAG,
                    "Message ("
                            + payload.length
                            + " bytes) exceeds max payload length ("
                            + maxPayloadBytes
                            + " bytes)");
            Log.e(TAG,
                    "Message (%d bytes) exceeds max payload length (%d bytes)".formatted(
                            payload.length, maxPayloadBytes));
            return ContextHubTransaction.RESULT_FAILED_BAD_PARAMS;
        }

        try {
            if (transactionCallback == null) {
                return mClientProxy.sendMessageToNanoApp(message);
            }
            return mClientProxy.sendReliableMessageToNanoApp(message, transactionCallback);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -224,6 +279,26 @@ public class ContextHubClient implements Closeable {
    /** @hide */
    public synchronized void callbackFinished() {
        try {
            waitForClientProxy();
            mClientProxy.callbackFinished();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    public synchronized void reliableMessageCallbackFinished(int messageSequenceNumber,
            byte errorCode) {
        try {
            waitForClientProxy();
            mClientProxy.reliableMessageCallbackFinished(messageSequenceNumber, errorCode);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    private void waitForClientProxy() {
        while (mClientProxy == null) {
            try {
                this.wait();
@@ -231,9 +306,5 @@ public class ContextHubClient implements Closeable {
                Thread.currentThread().interrupt();
            }
        }
            mClientProxy.callbackFinished();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
+31 −5
Original line number Diff line number Diff line
@@ -15,9 +15,11 @@
 */
package android.hardware.location;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.chre.flags.Flags;
import android.hardware.contexthub.V1_0.ContextHub;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,6 +43,7 @@ public class ContextHubInfo implements Parcelable {
    private float mSleepPowerDrawMw;
    private float mPeakPowerDrawMw;
    private int mMaxPacketLengthBytes;
    private boolean mSupportsReliableMessages;
    private byte mChreApiMajorVersion;
    private byte mChreApiMinorVersion;
    private short mChrePatchVersion;
@@ -71,6 +74,7 @@ public class ContextHubInfo implements Parcelable {
        mSleepPowerDrawMw = contextHub.sleepPowerDrawMw;
        mPeakPowerDrawMw = contextHub.peakPowerDrawMw;
        mMaxPacketLengthBytes = contextHub.maxSupportedMsgLen;
        mSupportsReliableMessages = false;
        mChrePlatformId = contextHub.chrePlatformId;
        mChreApiMajorVersion = contextHub.chreApiMajorVersion;
        mChreApiMinorVersion = contextHub.chreApiMinorVersion;
@@ -94,6 +98,8 @@ public class ContextHubInfo implements Parcelable {
        mSleepPowerDrawMw = 0;
        mPeakPowerDrawMw = 0;
        mMaxPacketLengthBytes = contextHub.maxSupportedMessageLengthBytes;
        mSupportsReliableMessages = Flags.reliableMessageImplementation()
                && contextHub.supportsReliableMessages;
        mChrePlatformId = contextHub.chrePlatformId;
        mChreApiMajorVersion = contextHub.chreApiMajorVersion;
        mChreApiMinorVersion = contextHub.chreApiMinorVersion;
@@ -104,15 +110,24 @@ public class ContextHubInfo implements Parcelable {
    }

    /**
     * returns the maximum number of bytes that can be sent per message to the hub
     * Returns the maximum number of bytes for a message to the hub.
     *
     * @return int - maximum bytes that can be transmitted in a
     *         single packet
     * @return int - maximum bytes that can be transmitted in a single packet.
     */
    public int getMaxPacketLengthBytes() {
        return mMaxPacketLengthBytes;
    }

    /**
     * Returns whether reliable messages are supported
     *
     * @return whether reliable messages are supported.
     */
    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
    public boolean supportsReliableMessages() {
        return mSupportsReliableMessages;
    }

    /**
     * get the context hub unique identifer
     *
@@ -164,7 +179,10 @@ public class ContextHubInfo implements Parcelable {
     * @return int - platform version number
     */
    public int getStaticSwVersion() {
        return (mChreApiMajorVersion << 24) | (mChreApiMinorVersion << 16) | (mChrePatchVersion);
        // Version parts are all unsigned values.
        return (Byte.toUnsignedInt(mChreApiMajorVersion) << 24)
                | (Byte.toUnsignedInt(mChreApiMinorVersion) << 16)
                | (Short.toUnsignedInt(mChrePatchVersion));
    }

    /**
@@ -284,12 +302,14 @@ public class ContextHubInfo implements Parcelable {
        retVal += ", Toolchain version: 0x" + Integer.toHexString(mToolchainVersion);
        retVal += "\n\tPlatformVersion : 0x" + Integer.toHexString(mPlatformVersion);
        retVal += ", SwVersion : "
                + mChreApiMajorVersion + "." + mChreApiMinorVersion + "." + mChrePatchVersion;
                + Byte.toUnsignedInt(mChreApiMajorVersion) + "." + Byte.toUnsignedInt(
                mChreApiMinorVersion) + "." + Short.toUnsignedInt(mChrePatchVersion);
        retVal += ", CHRE platform ID: 0x" + Long.toHexString(mChrePlatformId);
        retVal += "\n\tPeakMips : " + mPeakMips;
        retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
        retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
        retVal += ", MaxPacketLength : " + mMaxPacketLengthBytes + " Bytes";
        retVal += ", SupportsReliableMessage : " + mSupportsReliableMessages;

        return retVal;
    }
@@ -316,6 +336,8 @@ public class ContextHubInfo implements Parcelable {
        proto.write(ContextHubInfoProto.SLEEP_POWER_DRAW_MW, mSleepPowerDrawMw);
        proto.write(ContextHubInfoProto.PEAK_POWER_DRAW_MW, mPeakPowerDrawMw);
        proto.write(ContextHubInfoProto.MAX_PACKET_LENGTH_BYTES, mMaxPacketLengthBytes);
        proto.write(ContextHubInfoProto.SUPPORTS_RELIABLE_MESSAGES,
                mSupportsReliableMessages);
    }

    @Override
@@ -339,6 +361,8 @@ public class ContextHubInfo implements Parcelable {
                    && (other.getSleepPowerDrawMw() == mSleepPowerDrawMw)
                    && (other.getPeakPowerDrawMw() == mPeakPowerDrawMw)
                    && (other.getMaxPacketLengthBytes() == mMaxPacketLengthBytes)
                    && (!Flags.reliableMessage()
                            || (other.supportsReliableMessages() == mSupportsReliableMessages))
                    && Arrays.equals(other.getSupportedSensors(), mSupportedSensors)
                    && Arrays.equals(other.getMemoryRegions(), mMemoryRegions);
        }
@@ -367,6 +391,7 @@ public class ContextHubInfo implements Parcelable {
        mSupportedSensors = new int[numSupportedSensors];
        in.readIntArray(mSupportedSensors);
        mMemoryRegions = in.createTypedArray(MemoryRegion.CREATOR);
        mSupportsReliableMessages = in.readBoolean();
    }

    public int describeContents() {
@@ -393,6 +418,7 @@ public class ContextHubInfo implements Parcelable {
        out.writeInt(mSupportedSensors.length);
        out.writeIntArray(mSupportedSensors);
        out.writeTypedArray(mMemoryRegions, flags);
        out.writeBoolean(mSupportsReliableMessages);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ContextHubInfo> CREATOR
+18 −33
Original line number Diff line number Diff line
@@ -29,15 +29,15 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.ActivityThread;
import android.app.PendingIntent;
import android.chre.flags.Flags;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.contexthub.ErrorCode;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;

import java.lang.annotation.Retention;
@@ -456,32 +456,6 @@ public final class ContextHubManager {
        }
    }

    /**
     * Helper function to generate a stub for a non-query transaction callback.
     *
     * @param transaction the transaction to unblock when complete
     *
     * @return the callback
     *
     * @hide
     */
    private IContextHubTransactionCallback createTransactionCallback(
            ContextHubTransaction<Void> transaction) {
        return new IContextHubTransactionCallback.Stub() {
            @Override
            public void onQueryResponse(int result, List<NanoAppState> nanoappList) {
                Log.e(TAG, "Received a query callback on a non-query request");
                transaction.setResponse(new ContextHubTransaction.Response<Void>(
                        ContextHubTransaction.RESULT_FAILED_SERVICE_INTERNAL_FAILURE, null));
            }

            @Override
            public void onTransactionComplete(int result) {
                transaction.setResponse(new ContextHubTransaction.Response<Void>(result, null));
            }
        };
    }

   /**
    * Helper function to generate a stub for a query transaction callback.
    *
@@ -532,7 +506,8 @@ public final class ContextHubManager {

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);
        IContextHubTransactionCallback callback =
                ContextHubTransactionHelper.createTransactionCallback(transaction);

        try {
            mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary);
@@ -560,7 +535,8 @@ public final class ContextHubManager {

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);
        IContextHubTransactionCallback callback =
                ContextHubTransactionHelper.createTransactionCallback(transaction);

        try {
            mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId);
@@ -588,7 +564,8 @@ public final class ContextHubManager {

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_ENABLE_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);
        IContextHubTransactionCallback callback =
                ContextHubTransactionHelper.createTransactionCallback(transaction);

        try {
            mService.enableNanoApp(hubInfo.getId(), callback, nanoAppId);
@@ -616,7 +593,8 @@ public final class ContextHubManager {

        ContextHubTransaction<Void> transaction =
                new ContextHubTransaction<>(ContextHubTransaction.TYPE_DISABLE_NANOAPP);
        IContextHubTransactionCallback callback = createTransactionCallback(transaction);
        IContextHubTransactionCallback callback =
                ContextHubTransactionHelper.createTransactionCallback(transaction);

        try {
            mService.disableNanoApp(hubInfo.getId(), callback, nanoAppId);
@@ -732,7 +710,14 @@ public final class ContextHubManager {
                executor.execute(
                        () -> {
                            callback.onMessageFromNanoApp(client, message);
                            if (Flags.reliableMessage()
                                        && Flags.reliableMessageImplementation()
                                        && message.isReliable()) {
                                client.reliableMessageCallbackFinished(
                                        message.getMessageSequenceNumber(), ErrorCode.OK);
                            } else {
                                client.callbackFinished();
                            }
                        });
            }

+18 −2
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@
package android.hardware.location;

import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.chre.flags.Flags;
import android.os.Handler;
import android.os.HandlerExecutor;

@@ -57,7 +59,8 @@ public class ContextHubTransaction<T> {
            TYPE_UNLOAD_NANOAPP,
            TYPE_ENABLE_NANOAPP,
            TYPE_DISABLE_NANOAPP,
            TYPE_QUERY_NANOAPPS
            TYPE_QUERY_NANOAPPS,
            TYPE_RELIABLE_MESSAGE,
    })
    public @interface Type { }

@@ -66,6 +69,8 @@ public class ContextHubTransaction<T> {
    public static final int TYPE_ENABLE_NANOAPP = 2;
    public static final int TYPE_DISABLE_NANOAPP = 3;
    public static final int TYPE_QUERY_NANOAPPS = 4;
    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
    public static final int TYPE_RELIABLE_MESSAGE = 5;

    /**
     * Constants describing the result of a transaction or request through the Context Hub Service.
@@ -81,7 +86,8 @@ public class ContextHubTransaction<T> {
            RESULT_FAILED_AT_HUB,
            RESULT_FAILED_TIMEOUT,
            RESULT_FAILED_SERVICE_INTERNAL_FAILURE,
            RESULT_FAILED_HAL_UNAVAILABLE
            RESULT_FAILED_HAL_UNAVAILABLE,
            RESULT_FAILED_NOT_SUPPORTED,
    })
    public @interface Result {}
    public static final int RESULT_SUCCESS = 0;
@@ -117,6 +123,11 @@ public class ContextHubTransaction<T> {
     * Failure mode when the Context Hub HAL was not available.
     */
    public static final int RESULT_FAILED_HAL_UNAVAILABLE = 8;
    /**
     * Failure mode when the operation is not supported.
     */
    @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
    public static final int RESULT_FAILED_NOT_SUPPORTED = 9;

    /**
     * A class describing the response for a ContextHubTransaction.
@@ -221,6 +232,11 @@ public class ContextHubTransaction<T> {
                return upperCase ? "Disable" : "disable";
            case ContextHubTransaction.TYPE_QUERY_NANOAPPS:
                return upperCase ? "Query" : "query";
            case ContextHubTransaction.TYPE_RELIABLE_MESSAGE: {
                if (Flags.reliableMessage()) {
                    return upperCase ? "Reliable Message" : "reliable message";
                }
            }
            default:
                return upperCase ? "Unknown" : "unknown";
        }
Loading