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.hardware.location.ContextHubClient; 19 import android.hardware.location.ContextHubTransaction; 20 import android.hardware.location.NanoAppMessage; 21 22 import java.util.concurrent.atomic.AtomicBoolean; 23 24 import dev.pigweed.pw_rpc.Channel; 25 import dev.pigweed.pw_rpc.ChannelOutputException; 26 27 /** 28 * Implements the Channel.Output interface of Pigweed RPC and provides a layer of abstraction on top 29 * of Pigweed RPC to make it more friendly to use with CHRE APIs. 30 */ 31 public class ChreChannelOutput implements Channel.Output { 32 /** 33 * Random value chosen not too close to max value to try to avoid conflicts with other messages 34 * in case pw rpc isn't the only way the client chooses to communicate. 35 */ 36 public static final int PW_RPC_CHRE_MESSAGE_TYPE = Integer.MAX_VALUE - 10; 37 38 // 1 denotes that a host endpoint is the client that created the channel. 39 private static final int CHANNEL_ID_HOST_CLIENT = (1 << 16); 40 41 private final ContextHubClient mClient; 42 private final long mNanoappId; 43 44 // Whether this output channel is no longer able to communicate with the nanoapp. 45 private AtomicBoolean mAuthDenied = new AtomicBoolean(false); 46 ChreChannelOutput(ContextHubClient client, long nanoappId)47 public ChreChannelOutput(ContextHubClient client, long nanoappId) { 48 mClient = client; 49 mNanoappId = nanoappId; 50 } 51 52 /** 53 * This method MUST NOT be called directly from users of this class. 54 */ 55 @Override send(byte[] packet)56 public void send(byte[] packet) throws ChannelOutputException { 57 NanoAppMessage message = NanoAppMessage.createMessageToNanoApp(mNanoappId, 58 PW_RPC_CHRE_MESSAGE_TYPE, packet); 59 if (mAuthDenied.get() 60 || ContextHubTransaction.RESULT_SUCCESS != mClient.sendMessageToNanoApp(message)) { 61 throw new ChannelOutputException(); 62 } 63 } 64 65 /** 66 * @return Channel ID to use for all Channels that use this output to send 67 * messages to a nanoapp. 68 */ getChannelId()69 public int getChannelId() { 70 return (CHANNEL_ID_HOST_CLIENT | mClient.getId()); 71 } 72 73 /** 74 * Used to indicate whether the particular nanoapp cannot be communicated 75 * with any more (e.g. due to permissions loss). 76 */ setAuthDenied(boolean denied)77 void setAuthDenied(boolean denied) { 78 mAuthDenied.set(denied); 79 } 80 } 81