1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.chre.utils.pigweed; 17 18 import android.content.Intent; 19 import android.hardware.location.ContextHubClient; 20 import android.hardware.location.ContextHubClientCallback; 21 import android.hardware.location.ContextHubInfo; 22 import android.hardware.location.ContextHubManager; 23 import android.hardware.location.NanoAppRpcService; 24 import android.hardware.location.NanoAppState; 25 26 import java.util.List; 27 import java.util.Objects; 28 29 import dev.pigweed.pw_rpc.Channel; 30 import dev.pigweed.pw_rpc.Client; 31 import dev.pigweed.pw_rpc.MethodClient; 32 import dev.pigweed.pw_rpc.Service; 33 34 /** 35 * Pigweed RPC Client Helper. 36 * 37 * See https://g3doc.corp.google.com/location/lbs/contexthub/g3doc/nanoapps/pw_rpc_host.md 38 */ 39 public class ChreRpcClient { 40 41 // Non null. 42 private final Client mRpcClient; 43 // Non null. 44 private final Channel mChannel; 45 // Non null. 46 private final ChreChannelOutput mChannelOutput; 47 private final long mServerNanoappId; 48 // Non null. 49 private final ContextHubClient mContextHubClient; 50 private ChreIntentHandler mIntentHandler; 51 52 /** 53 * Creates a ContextHubClient and initializes the helper. 54 * 55 * Use this constructor for persistent clients using callbacks. 56 * 57 * @param manager The context manager used to create a client, non null 58 * @param info Context hub info, non null 59 * @param serverNanoappId The ID of the RPC server nanoapp 60 * @param services The list of services provided by the server, non null 61 * @param callback The callbacks receiving messages and life-cycle events from nanoapps, 62 * nullable 63 */ ChreRpcClient(ContextHubManager manager, ContextHubInfo info, long serverNanoappId, List<Service> services, ContextHubClientCallback callback)64 public ChreRpcClient(ContextHubManager manager, ContextHubInfo info, 65 long serverNanoappId, List<Service> services, 66 ContextHubClientCallback callback) { 67 Objects.requireNonNull(manager); 68 Objects.requireNonNull(info); 69 Objects.requireNonNull(services); 70 ChreCallbackHandler callbackHandler = new ChreCallbackHandler(serverNanoappId, callback); 71 mContextHubClient = manager.createClient(info, callbackHandler); 72 mServerNanoappId = serverNanoappId; 73 mChannelOutput = new ChreChannelOutput(mContextHubClient, serverNanoappId); 74 mChannel = new Channel(mChannelOutput.getChannelId(), mChannelOutput); 75 mRpcClient = Client.create(List.of(mChannel), services); 76 callbackHandler.lateInit(mRpcClient, mChannelOutput); 77 } 78 79 /** 80 * Initializes the helper 81 * 82 * Use this constructor for non-persistent clients using intents. 83 * 84 * handleIntent() must be called with any CHRE intent received by the BroadcastReceiver. 85 * 86 * @param contextHubClient The context hub client providing the RPC server nanoapp, non null 87 * @param serverNanoappId The ID of the RPC server nanoapp 88 * @param services The list of services provided by the server, non null 89 */ ChreRpcClient(ContextHubClient contextHubClient, long serverNanoappId, List<Service> services)90 public ChreRpcClient(ContextHubClient contextHubClient, long serverNanoappId, 91 List<Service> services) { 92 mContextHubClient = Objects.requireNonNull(contextHubClient); 93 Objects.requireNonNull(services); 94 mServerNanoappId = serverNanoappId; 95 mChannelOutput = new ChreChannelOutput(contextHubClient, serverNanoappId); 96 mChannel = new Channel(mChannelOutput.getChannelId(), mChannelOutput); 97 mRpcClient = Client.create(List.of(mChannel), services); 98 } 99 100 /** 101 * Returns whether the state matches the server nanoapp and the service is provided. 102 * 103 * @param state A nanoapp state 104 * @param serverNanoappId The ID of the RPC server nanoapp 105 * @param serviceId ID of the service 106 * @param serviceVersion Version of the service 107 * @return the state matches the server nanoapp and the service is provided 108 */ hasService(NanoAppState state, long serverNanoappId, long serviceId, int serviceVersion)109 public static boolean hasService(NanoAppState state, long serverNanoappId, long serviceId, 110 int serviceVersion) { 111 if (state.getNanoAppId() != serverNanoappId) { 112 return false; 113 } 114 115 for (NanoAppRpcService service : state.getRpcServices()) { 116 if (service.getId() == serviceId) { 117 return service.getVersion() == serviceVersion; 118 } 119 } 120 121 return false; 122 } 123 124 /** 125 * Handles CHRE intents. 126 * 127 * @param intent The CHRE intent, non null 128 */ handleIntent(Intent intent)129 public void handleIntent(Intent intent) { 130 ChreIntentHandler.handle(intent, mServerNanoappId, mRpcClient, mChannelOutput); 131 } 132 133 /** 134 * Returns the context hub client. 135 */ getContextHubClient()136 public ContextHubClient getContextHubClient() { 137 return mContextHubClient; 138 } 139 140 /** 141 * Shorthand for closing the underlying ContextHubClient. 142 */ close()143 public void close() { 144 mContextHubClient.close(); 145 } 146 147 /** 148 * Returns a MethodClient. 149 * 150 * Use the client to invoke the service. 151 * 152 * @param methodName the method name as "package.Service.Method" or "package.Service/Method" 153 * @return The MethodClient instance 154 */ getMethodClient(String methodName)155 public MethodClient getMethodClient(String methodName) { 156 return mRpcClient.method(mChannel.id(), methodName); 157 } 158 } 159