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

Commit 0943bee0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Cancel pending reliable message transactions on HAL restart" into main

parents cbcc1dab a3697593
Loading
Loading
Loading
Loading
+93 −44
Original line number Diff line number Diff line
@@ -43,7 +43,10 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;

import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;

/**
 * A class that represents a broker for the endpoint registered by the client app. This class
@@ -111,6 +114,11 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub

        private final boolean mRemoteInitiated;

        /**
         * The set of seq # for pending reliable messages started by this endpoint for this session.
         */
        private final Set<Integer> mPendingSequenceNumbers = new HashSet<>();

        SessionInfo(HubEndpointInfo remoteEndpointInfo, boolean remoteInitiated) {
            mRemoteEndpointInfo = remoteEndpointInfo;
            mRemoteInitiated = remoteInitiated;
@@ -131,6 +139,24 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
        public boolean isActive() {
            return mSessionState == SessionState.ACTIVE;
        }

        public boolean isReliableMessagePending(int sequenceNumber) {
            return mPendingSequenceNumbers.contains(sequenceNumber);
        }

        public void setReliableMessagePending(int sequenceNumber) {
            mPendingSequenceNumbers.add(sequenceNumber);
        }

        public void setReliableMessageCompleted(int sequenceNumber) {
            mPendingSequenceNumbers.remove(sequenceNumber);
        }

        public void forEachPendingReliableMessage(Consumer<Integer> consumer) {
            for (int sequenceNumber : mPendingSequenceNumbers) {
                consumer.accept(sequenceNumber);
            }
        }
    }

    /** A map between a session ID which maps to its current state. */
@@ -208,10 +234,7 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            try {
                mSessionInfoMap.put(sessionId, new SessionInfo(destination, false));
                mHubInterface.openEndpointSession(
                        sessionId,
                        halEndpointInfo.id,
                        mHalEndpointInfo.id,
                        serviceDescriptor);
                        sessionId, halEndpointInfo.id, mHalEndpointInfo.id, serviceDescriptor);
            } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) {
                Log.e(TAG, "Exception while calling HAL openEndpointSession", e);
                cleanupSessionResources(sessionId);
@@ -286,12 +309,18 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
    public void sendMessage(
            int sessionId, HubMessage message, IContextHubTransactionCallback callback) {
        super.sendMessage_enforcePermission();
        Message halMessage = ContextHubServiceUtil.createHalMessage(message);
        if (!isSessionActive(sessionId)) {
        synchronized (mOpenSessionLock) {
            SessionInfo info = mSessionInfoMap.get(sessionId);
            if (info == null) {
                throw new IllegalArgumentException(
                        "sendMessage for invalid session id=" + sessionId);
            }
            if (!info.isActive()) {
                throw new SecurityException(
                        "sendMessage called on inactive session (id= " + sessionId + ")");
            }

            Message halMessage = ContextHubServiceUtil.createHalMessage(message);
            if (callback == null) {
                try {
                    mHubInterface.sendMessageToEndpoint(sessionId, halMessage);
@@ -304,6 +333,7 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
                                mHubInterface, sessionId, halMessage, mPackageName, callback);
                try {
                    mTransactionManager.addTransaction(transaction);
                    info.setReliableMessagePending(transaction.getMessageSequenceNumber());
                } catch (IllegalStateException e) {
                    Log.e(
                            TAG,
@@ -317,6 +347,7 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
                }
            }
        }
    }

    @Override
    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
@@ -393,7 +424,9 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
                int id = mSessionInfoMap.keyAt(i);
                int count = i + 1;
                sb.append(
                        "  " + count + ". id="
                        "  "
                                + count
                                + ". id="
                                + id
                                + ", remote:"
                                + mSessionInfoMap.get(id).getRemoteEndpointInfo());
@@ -461,13 +494,24 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
    /* package */ void onMessageReceived(int sessionId, HubMessage message) {
        byte code = onMessageReceivedInternal(sessionId, message);
        if (code != ErrorCode.OK && message.isResponseRequired()) {
            sendMessageDeliveryStatus(
                    sessionId, message.getMessageSequenceNumber(), code);
            sendMessageDeliveryStatus(sessionId, message.getMessageSequenceNumber(), code);
        }
    }

    /* package */ void onMessageDeliveryStatusReceived(
            int sessionId, int sequenceNumber, byte errorCode) {
        synchronized (mOpenSessionLock) {
            SessionInfo info = mSessionInfoMap.get(sessionId);
            if (info == null || !info.isActive()) {
                Log.w(TAG, "Received delivery status for invalid session: id=" + sessionId);
                return;
            }
            if (!info.isReliableMessagePending(sequenceNumber)) {
                Log.w(TAG, "Received delivery status for unknown seq: " + sequenceNumber);
                return;
            }
            info.setReliableMessageCompleted(sequenceNumber);
        }
        mTransactionManager.onMessageDeliveryResponse(sequenceNumber, errorCode == ErrorCode.OK);
    }

@@ -492,7 +536,6 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
                onCloseEndpointSession(id, Reason.HUB_RESET);
            }
        }
        // TODO(b/390029594): Cancel any ongoing reliable communication transactions
    }

    private Optional<Byte> onEndpointSessionOpenRequestInternal(
@@ -515,9 +558,11 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
            mSessionInfoMap.put(sessionId, new SessionInfo(initiator, true));
        }

        boolean success = invokeCallback(
        boolean success =
                invokeCallback(
                        (consumer) ->
                        consumer.onSessionOpenRequest(sessionId, initiator, serviceDescriptor));
                                consumer.onSessionOpenRequest(
                                        sessionId, initiator, serviceDescriptor));
        return success ? Optional.empty() : Optional.of(Reason.UNSPECIFIED);
    }

@@ -590,8 +635,15 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
    private boolean cleanupSessionResources(int sessionId) {
        synchronized (mOpenSessionLock) {
            SessionInfo info = mSessionInfoMap.get(sessionId);
            if (info != null && !info.isRemoteInitiated()) {
            if (info != null) {
                if (!info.isRemoteInitiated()) {
                    mEndpointManager.returnSessionId(sessionId);
                }
                info.forEachPendingReliableMessage(
                        (sequenceNumber) -> {
                            mTransactionManager.onMessageDeliveryResponse(
                                    sequenceNumber, /* success= */ false);
                        });
                mSessionInfoMap.remove(sessionId);
            }
            return info != null;
@@ -646,10 +698,7 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub
                        try {
                            mWakeLock.release();
                        } catch (RuntimeException e) {
                            Log.e(
                                    TAG,
                                    "Releasing the wakelock for all acquisitions fails - ",
                                    e);
                            Log.e(TAG, "Releasing the wakelock for all acquisitions fails - ", e);
                            break;
                        }
                    }
+131 −76
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.os.SystemClock;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.time.Duration;
import java.util.ArrayDeque;
@@ -171,19 +172,26 @@ import java.util.concurrent.atomic.AtomicInteger;
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createLoadTransaction(
            int contextHubId, NanoAppBinary nanoAppBinary,
            IContextHubTransactionCallback onCompleteCallback, String packageName) {
            int contextHubId,
            NanoAppBinary nanoAppBinary,
            IContextHubTransactionCallback onCompleteCallback,
            String packageName) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_LOAD_NANOAPP,
                nanoAppBinary.getNanoAppId(), packageName) {
                mNextAvailableId.getAndIncrement(),
                ContextHubTransaction.TYPE_LOAD_NANOAPP,
                nanoAppBinary.getNanoAppId(),
                packageName) {
            @Override
            /* package */ int onTransact() {
                try {
                    return mContextHubProxy.loadNanoapp(
                            contextHubId, nanoAppBinary, this.getTransactionId());
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to load nanoapp with ID 0x" +
                            Long.toHexString(nanoAppBinary.getNanoAppId()), e);
                    Log.e(
                            TAG,
                            "RemoteException while trying to load nanoapp with ID 0x"
                                    + Long.toHexString(nanoAppBinary.getNanoAppId()),
                            e);
                    return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
                }
            }
@@ -198,7 +206,8 @@ import java.util.concurrent.atomic.AtomicInteger;
                                .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_TYPE__TYPE_LOAD,
                        toStatsTransactionResult(result));

                ContextHubEventLogger.getInstance().logNanoappLoad(
                ContextHubEventLogger.getInstance()
                        .logNanoappLoad(
                                contextHubId,
                                nanoAppBinary.getNanoAppId(),
                                nanoAppBinary.getNanoAppVersion(),
@@ -210,7 +219,8 @@ import java.util.concurrent.atomic.AtomicInteger;
                    // to synchronize the service cache. Instead store the binary that was
                    // requested to load to update the cache later without doing a query.
                    mNanoAppStateManager.addNanoAppInstance(
                            contextHubId, nanoAppBinary.getNanoAppId(),
                            contextHubId,
                            nanoAppBinary.getNanoAppId(),
                            nanoAppBinary.getNanoAppVersion());
                }
                try {
@@ -234,19 +244,26 @@ import java.util.concurrent.atomic.AtomicInteger;
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createUnloadTransaction(
            int contextHubId, long nanoAppId, IContextHubTransactionCallback onCompleteCallback,
            int contextHubId,
            long nanoAppId,
            IContextHubTransactionCallback onCompleteCallback,
            String packageName) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_UNLOAD_NANOAPP,
                nanoAppId, packageName) {
                mNextAvailableId.getAndIncrement(),
                ContextHubTransaction.TYPE_UNLOAD_NANOAPP,
                nanoAppId,
                packageName) {
            @Override
            /* package */ int onTransact() {
                try {
                    return mContextHubProxy.unloadNanoapp(
                            contextHubId, nanoAppId, this.getTransactionId());
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to unload nanoapp with ID 0x" +
                            Long.toHexString(nanoAppId), e);
                    Log.e(
                            TAG,
                            "RemoteException while trying to unload nanoapp with ID 0x"
                                    + Long.toHexString(nanoAppId),
                            e);
                    return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
                }
            }
@@ -254,13 +271,15 @@ import java.util.concurrent.atomic.AtomicInteger;
            @Override
            /* package */ void onTransactionComplete(@ContextHubTransaction.Result int result) {
                ContextHubStatsLog.write(
                        ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED, nanoAppId,
                        ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED,
                        nanoAppId,
                        0 /* nanoappVersion */,
                        ContextHubStatsLog
                                .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_TYPE__TYPE_UNLOAD,
                        toStatsTransactionResult(result));

                ContextHubEventLogger.getInstance().logNanoappUnload(
                ContextHubEventLogger.getInstance()
                        .logNanoappUnload(
                                contextHubId,
                                nanoAppId,
                                result == ContextHubTransaction.RESULT_SUCCESS);
@@ -289,10 +308,13 @@ import java.util.concurrent.atomic.AtomicInteger;
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createEnableTransaction(
            int contextHubId, long nanoAppId, IContextHubTransactionCallback onCompleteCallback,
            int contextHubId,
            long nanoAppId,
            IContextHubTransactionCallback onCompleteCallback,
            String packageName) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_ENABLE_NANOAPP,
                mNextAvailableId.getAndIncrement(),
                ContextHubTransaction.TYPE_ENABLE_NANOAPP,
                packageName) {
            @Override
            /* package */ int onTransact() {
@@ -300,8 +322,11 @@ import java.util.concurrent.atomic.AtomicInteger;
                    return mContextHubProxy.enableNanoapp(
                            contextHubId, nanoAppId, this.getTransactionId());
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to enable nanoapp with ID 0x" +
                            Long.toHexString(nanoAppId), e);
                    Log.e(
                            TAG,
                            "RemoteException while trying to enable nanoapp with ID 0x"
                                    + Long.toHexString(nanoAppId),
                            e);
                    return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
                }
            }
@@ -326,10 +351,13 @@ import java.util.concurrent.atomic.AtomicInteger;
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createDisableTransaction(
            int contextHubId, long nanoAppId, IContextHubTransactionCallback onCompleteCallback,
            int contextHubId,
            long nanoAppId,
            IContextHubTransactionCallback onCompleteCallback,
            String packageName) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_DISABLE_NANOAPP,
                mNextAvailableId.getAndIncrement(),
                ContextHubTransaction.TYPE_DISABLE_NANOAPP,
                packageName) {
            @Override
            /* package */ int onTransact() {
@@ -337,8 +365,11 @@ import java.util.concurrent.atomic.AtomicInteger;
                    return mContextHubProxy.disableNanoapp(
                            contextHubId, nanoAppId, this.getTransactionId());
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to disable nanoapp with ID 0x" +
                            Long.toHexString(nanoAppId), e);
                    Log.e(
                            TAG,
                            "RemoteException while trying to disable nanoapp with ID 0x"
                                    + Long.toHexString(nanoAppId),
                            e);
                    return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
                }
            }
@@ -452,10 +483,12 @@ import java.util.concurrent.atomic.AtomicInteger;
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createQueryTransaction(
            int contextHubId, IContextHubTransactionCallback onCompleteCallback,
            int contextHubId,
            IContextHubTransactionCallback onCompleteCallback,
            String packageName) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_QUERY_NANOAPPS,
                mNextAvailableId.getAndIncrement(),
                ContextHubTransaction.TYPE_QUERY_NANOAPPS,
                packageName) {
            @Override
            /* package */ int onTransact() {
@@ -539,6 +572,14 @@ import java.util.concurrent.atomic.AtomicInteger;
        }
    }

    @VisibleForTesting
    /* package */
    int numReliableMessageTransactionPending() {
        synchronized (mReliableMessageLock) {
            return mReliableMessageTransactionMap.size();
        }
    }

    /**
     * Handles a transaction response from a Context Hub.
     *
@@ -585,13 +626,16 @@ import java.util.concurrent.atomic.AtomicInteger;
    void onMessageDeliveryResponse(int messageSequenceNumber, boolean success) {
        if (!Flags.reliableMessageRetrySupportService()) {
            TransactionAcceptConditions conditions =
                    transaction -> transaction.getTransactionType()
                    transaction ->
                            transaction.getTransactionType()
                                            == ContextHubTransaction.TYPE_RELIABLE_MESSAGE
                                    && transaction.getMessageSequenceNumber()
                                            == messageSequenceNumber;
            ContextHubServiceTransaction transaction = getTransactionAndHandleNext(conditions);
            if (transaction == null) {
                Log.w(TAG, "Received unexpected message delivery response (expected"
                Log.w(
                        TAG,
                        "Received unexpected message delivery response (expected"
                                + " message sequence number = "
                                + messageSequenceNumber
                                + ", received messageSequenceNumber = "
@@ -640,8 +684,10 @@ import java.util.concurrent.atomic.AtomicInteger;
     */
    /* package */
    void onQueryResponse(List<NanoAppState> nanoAppStateList) {
        TransactionAcceptConditions conditions = transaction ->
                transaction.getTransactionType() == ContextHubTransaction.TYPE_QUERY_NANOAPPS;
        TransactionAcceptConditions conditions =
                transaction ->
                        transaction.getTransactionType()
                                == ContextHubTransaction.TYPE_QUERY_NANOAPPS;
        ContextHubServiceTransaction transaction = getTransactionAndHandleNext(conditions);
        if (transaction == null) {
            Log.w(TAG, "Received unexpected query response");
@@ -968,24 +1014,33 @@ import java.util.concurrent.atomic.AtomicInteger;
    private int toStatsTransactionResult(@ContextHubTransaction.Result int result) {
        switch (result) {
            case ContextHubTransaction.RESULT_SUCCESS:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_SUCCESS;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_SUCCESS;
            case ContextHubTransaction.RESULT_FAILED_BAD_PARAMS:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_BAD_PARAMS;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_BAD_PARAMS;
            case ContextHubTransaction.RESULT_FAILED_UNINITIALIZED:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_UNINITIALIZED;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_UNINITIALIZED;
            case ContextHubTransaction.RESULT_FAILED_BUSY:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_BUSY;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_BUSY;
            case ContextHubTransaction.RESULT_FAILED_AT_HUB:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_AT_HUB;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_AT_HUB;
            case ContextHubTransaction.RESULT_FAILED_TIMEOUT:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_TIMEOUT;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_TIMEOUT;
            case ContextHubTransaction.RESULT_FAILED_SERVICE_INTERNAL_FAILURE:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_SERVICE_INTERNAL_FAILURE;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_SERVICE_INTERNAL_FAILURE;
            case ContextHubTransaction.RESULT_FAILED_HAL_UNAVAILABLE:
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_HAL_UNAVAILABLE;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_HAL_UNAVAILABLE;
            case ContextHubTransaction.RESULT_FAILED_UNKNOWN:
            default: /* fall through */
                return ContextHubStatsLog.CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_UNKNOWN;
                return ContextHubStatsLog
                        .CHRE_CODE_DOWNLOAD_TRANSACTED__TRANSACTION_RESULT__TRANSACTION_RESULT_FAILED_UNKNOWN;
        }
    }

+72 −4

File changed.

Preview size limit exceeded, changes collapsed.