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

Commit 4190b9a6 authored by Arthur Ishiguro's avatar Arthur Ishiguro
Browse files

Adds APIs for hub endpoint discovery callbacks

API-Coverage-Bug: 377554469
Bug: 375487784
Flag: android.chre.flags.offload_api
Test: Compile

Change-Id: I8fc4b75d33de98b6c4d94fb963eae38df5ff99d3
parent 3fa794b6
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -5293,6 +5293,11 @@ package android.hardware.contexthub {
    method @NonNull public android.hardware.contexthub.HubServiceInfo build();
  }
  @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointDiscoveryCallback {
    method public void onEndpointsStarted(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>);
    method public void onEndpointsStopped(@NonNull java.util.List<android.hardware.contexthub.HubDiscoveryInfo>);
  }
  @FlaggedApi("android.chre.flags.offload_api") public interface IHubEndpointLifecycleCallback {
    method public void onSessionClosed(@NonNull android.hardware.contexthub.HubEndpointSession, int);
    method @NonNull public android.hardware.contexthub.HubEndpointSessionResult onSessionOpenRequest(@NonNull android.hardware.contexthub.HubEndpointInfo, @Nullable android.hardware.contexthub.HubServiceInfo);
@@ -6315,11 +6320,16 @@ package android.hardware.location {
    method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
    method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpoint(@NonNull android.hardware.contexthub.HubEndpoint);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(long, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(long, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback, @NonNull java.util.concurrent.Executor);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull String, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void registerEndpointDiscoveryCallback(@NonNull String, @NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback, @NonNull java.util.concurrent.Executor);
    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage);
    method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public int unloadNanoApp(int);
    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
    method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpoint(@NonNull android.hardware.contexthub.HubEndpoint);
    method @FlaggedApi("android.chre.flags.offload_api") @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) public void unregisterEndpointDiscoveryCallback(@NonNull android.hardware.contexthub.IHubEndpointDiscoveryCallback);
    field public static final int AUTHORIZATION_DENIED = 0; // 0x0
    field public static final int AUTHORIZATION_DENIED_GRACE_PERIOD = 1; // 0x1
    field public static final int AUTHORIZATION_GRANTED = 2; // 0x2
+36 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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.hardware.contexthub;

import android.hardware.contexthub.HubEndpointInfo;

/**
 * @hide
 */
oneway interface IContextHubEndpointDiscoveryCallback {
    /**
     * Called when endpoint(s) start.
     * @param hubEndpointInfoList The list of endpoints that started.
     */
    void onEndpointsStarted(in HubEndpointInfo[] hubEndpointInfoList);

    /**
     * Called when endpoint(s) stopped.
     * @param hubEndpointInfoList The list of endpoints that started.
     */
    void onEndpointsStopped(in HubEndpointInfo[] hubEndpointInfoList);
}
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.hardware.contexthub;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.chre.flags.Flags;

import java.util.List;

/**
 * Interface for listening to updates about endpoint availability.
 *
 * @hide
 */
@SystemApi
@FlaggedApi(Flags.FLAG_OFFLOAD_API)
public interface IHubEndpointDiscoveryCallback {
    /**
     * Called when a list of hub endpoints have started.
     *
     * @param discoveryInfoList The list containing hub discovery information.
     */
    void onEndpointsStarted(@NonNull List<HubDiscoveryInfo> discoveryInfoList);

    /**
     * Called when a list of hub endpoints have stopped.
     *
     * @param discoveryInfoList The list containing hub discovery information.
     */
    // TODO(b/375487784): Add endpoint stop reason
    void onEndpointsStopped(@NonNull List<HubDiscoveryInfo> discoveryInfoList);
}
+190 −4
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ import android.hardware.contexthub.HubDiscoveryInfo;
import android.hardware.contexthub.HubEndpoint;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.HubServiceInfo;
import android.hardware.contexthub.IContextHubEndpointDiscoveryCallback;
import android.hardware.contexthub.IHubEndpointDiscoveryCallback;
import android.hardware.contexthub.IHubEndpointLifecycleCallback;
import android.os.Handler;
import android.os.HandlerExecutor;
@@ -49,7 +51,9 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

/**
@@ -202,6 +206,10 @@ public final class ContextHubManager {
    private Callback mCallback;
    private Handler mCallbackHandler;

    /** A map of endpoint discovery callbacks currently registered */
    private Map<IHubEndpointDiscoveryCallback, IContextHubEndpointDiscoveryCallback>
            mDiscoveryCallbacks = new ConcurrentHashMap<>();

    /**
     * @deprecated Use {@code mCallback} instead.
     */
@@ -694,8 +702,6 @@ public final class ContextHubManager {
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @NonNull
    public List<HubDiscoveryInfo> findEndpoints(long endpointId) {
        // TODO(b/379323274): Consider improving these getters to avoid racing with nano app load
        //  timing.
        try {
            List<HubEndpointInfo> endpointInfos = mService.findEndpoints(endpointId);
            List<HubDiscoveryInfo> results = new ArrayList<>(endpointInfos.size());
@@ -720,8 +726,6 @@ public final class ContextHubManager {
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @NonNull
    public List<HubDiscoveryInfo> findEndpoints(@NonNull String serviceDescriptor) {
        // TODO(b/379323274): Consider improving these getters to avoid racing with nano app load
        //  timing.
        if (serviceDescriptor.isBlank()) {
            throw new IllegalArgumentException("Invalid service descriptor: " + serviceDescriptor);
        }
@@ -743,6 +747,188 @@ public final class ContextHubManager {
        }
    }

    /**
     * Creates an interface to invoke endpoint discovery callbacks to send down to the service.
     *
     * @param callback the callback to invoke at the client process
     * @param executor the executor to invoke callbacks for this client
     * @return the callback interface
     */
    private IContextHubEndpointDiscoveryCallback createDiscoveryCallback(
            IHubEndpointDiscoveryCallback callback,
            Executor executor,
            @Nullable String serviceDescriptor) {
        return new IContextHubEndpointDiscoveryCallback.Stub() {
            @Override
            public void onEndpointsStarted(HubEndpointInfo[] hubEndpointInfoList) {
                if (hubEndpointInfoList.length == 0) {
                    Log.w(TAG, "onEndpointsStarted: received empty discovery list");
                    return;
                }
                executor.execute(
                        () -> {
                            // TODO(b/380293951): Refactor
                            List<HubDiscoveryInfo> discoveryList =
                                    new ArrayList<>(hubEndpointInfoList.length);
                            for (HubEndpointInfo info : hubEndpointInfoList) {
                                if (serviceDescriptor != null) {
                                    for (HubServiceInfo sInfo : info.getServiceInfoCollection()) {
                                        if (sInfo.getServiceDescriptor()
                                                .equals(serviceDescriptor)) {
                                            discoveryList.add(new HubDiscoveryInfo(info, sInfo));
                                        }
                                    }
                                } else {
                                    discoveryList.add(new HubDiscoveryInfo(info));
                                }
                            }
                            if (discoveryList.isEmpty()) {
                                Log.w(TAG, "onEndpointsStarted: no matching service descriptor");
                            } else {
                                callback.onEndpointsStarted(discoveryList);
                            }
                        });
            }

            @Override
            public void onEndpointsStopped(HubEndpointInfo[] hubEndpointInfoList) {
                if (hubEndpointInfoList.length == 0) {
                    Log.w(TAG, "onEndpointsStopped: received empty discovery list");
                    return;
                }
                executor.execute(
                        () -> {
                            List<HubDiscoveryInfo> discoveryList =
                                    new ArrayList<>(hubEndpointInfoList.length);
                            for (HubEndpointInfo info : hubEndpointInfoList) {
                                if (serviceDescriptor != null) {
                                    for (HubServiceInfo sInfo : info.getServiceInfoCollection()) {
                                        if (sInfo.getServiceDescriptor()
                                                .equals(serviceDescriptor)) {
                                            discoveryList.add(new HubDiscoveryInfo(info, sInfo));
                                        }
                                    }
                                } else {
                                    discoveryList.add(new HubDiscoveryInfo(info));
                                }
                            }
                            if (discoveryList.isEmpty()) {
                                Log.w(TAG, "onEndpointsStopped: no matching service descriptor");
                            } else {
                                callback.onEndpointsStopped(discoveryList);
                            }
                        });
            }
        };
    }

    /**
     * Equivalent to {@link #registerEndpointDiscoveryCallback(long, IHubEndpointDiscoveryCallback,
     * Executor)} with the default executor in the main thread.
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @FlaggedApi(Flags.FLAG_OFFLOAD_API)
    public void registerEndpointDiscoveryCallback(
            long endpointId, @NonNull IHubEndpointDiscoveryCallback callback) {
        registerEndpointDiscoveryCallback(
                endpointId, callback, new HandlerExecutor(Handler.getMain()));
    }

    /**
     * Registers a callback to be notified when the hub endpoint with the corresponding endpoint ID
     * has started or stopped.
     *
     * @param endpointId The identifier of the hub endpoint.
     * @param callback The callback to be invoked.
     * @param executor The executor to invoke the callback on.
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @FlaggedApi(Flags.FLAG_OFFLOAD_API)
    public void registerEndpointDiscoveryCallback(
            long endpointId,
            @NonNull IHubEndpointDiscoveryCallback callback,
            @NonNull Executor executor) {
        Objects.requireNonNull(callback, "callback cannot be null");
        Objects.requireNonNull(executor, "executor cannot be null");
        IContextHubEndpointDiscoveryCallback iCallback =
                createDiscoveryCallback(callback, executor, null);
        try {
            mService.registerEndpointDiscoveryCallbackId(endpointId, iCallback);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }

        mDiscoveryCallbacks.put(callback, iCallback);
    }

    /**
     * Equivalent to {@link #registerEndpointDiscoveryCallback(String,
     * IHubEndpointDiscoveryCallback, Executor)} with the default executor in the main thread.
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @FlaggedApi(Flags.FLAG_OFFLOAD_API)
    public void registerEndpointDiscoveryCallback(
            @NonNull String serviceDescriptor, @NonNull IHubEndpointDiscoveryCallback callback) {
        registerEndpointDiscoveryCallback(
                serviceDescriptor, callback, new HandlerExecutor(Handler.getMain()));
    }

    /**
     * Registers a callback to be notified when the hub endpoint with the corresponding service
     * descriptor has started or stopped.
     *
     * @param serviceDescriptor The service descriptor of the hub endpoint.
     * @param callback The callback to be invoked.
     * @param executor The executor to invoke the callback on.
     * @throws IllegalArgumentException if the serviceDescriptor is empty.
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @FlaggedApi(Flags.FLAG_OFFLOAD_API)
    public void registerEndpointDiscoveryCallback(
            @NonNull String serviceDescriptor,
            @NonNull IHubEndpointDiscoveryCallback callback,
            @NonNull Executor executor) {
        Objects.requireNonNull(serviceDescriptor, "serviceDescriptor cannot be null");
        Objects.requireNonNull(callback, "callback cannot be null");
        Objects.requireNonNull(executor, "executor cannot be null");
        if (serviceDescriptor.isBlank()) {
            throw new IllegalArgumentException("Invalid service descriptor: " + serviceDescriptor);
        }

        IContextHubEndpointDiscoveryCallback iCallback =
                createDiscoveryCallback(callback, executor, serviceDescriptor);
        try {
            mService.registerEndpointDiscoveryCallbackDescriptor(serviceDescriptor, iCallback);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }

        mDiscoveryCallbacks.put(callback, iCallback);
    }

    /**
     * Unregisters a previously registered endpoint discovery callback.
     *
     * @param callback The callback previously registered.
     * @throws IllegalArgumentException If the callback was not previously registered.
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
    @FlaggedApi(Flags.FLAG_OFFLOAD_API)
    public void unregisterEndpointDiscoveryCallback(
            @NonNull IHubEndpointDiscoveryCallback callback) {
        Objects.requireNonNull(callback, "callback cannot be null");
        IContextHubEndpointDiscoveryCallback iCallback = mDiscoveryCallbacks.remove(callback);
        if (iCallback == null) {
            throw new IllegalArgumentException("Callback not previously registered");
        }

        try {
            mService.unregisterEndpointDiscoveryCallback(iCallback);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Set a callback to receive messages from the context hub
     *
+13 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.app.PendingIntent;
import android.hardware.contexthub.HubEndpointInfo;
import android.hardware.contexthub.IContextHubEndpoint;
import android.hardware.contexthub.IContextHubEndpointCallback;
import android.hardware.contexthub.IContextHubEndpointDiscoveryCallback;
import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubMessage;
import android.hardware.location.HubInfo;
@@ -137,4 +138,16 @@ interface IContextHubService {
    // Register an endpoint with the context hub
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    IContextHubEndpoint registerEndpoint(in HubEndpointInfo pendingEndpointInfo, in IContextHubEndpointCallback callback);

    // Register an endpoint discovery callback (id)
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    void registerEndpointDiscoveryCallbackId(long endpointId, in IContextHubEndpointDiscoveryCallback callback);

    // Register an endpoint discovery callback (descriptor)
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    void registerEndpointDiscoveryCallbackDescriptor(String serviceDescriptor, in IContextHubEndpointDiscoveryCallback callback);

    // Unregister an endpoint with the context hub
    @EnforcePermission("ACCESS_CONTEXT_HUB")
    void unregisterEndpointDiscoveryCallback(in IContextHubEndpointDiscoveryCallback callback);
}
Loading