blob: 41d9feb97c4e2a9bcf1e34f4e5efbaf6b2b9b9da [file] [log] [blame]
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -08001/*
2 * Copyright 2017 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
17package com.android.server.location;
18
19import android.content.Context;
20import android.hardware.contexthub.V1_0.ContextHubMsg;
21import android.hardware.contexthub.V1_0.IContexthub;
22import android.hardware.contexthub.V1_0.Result;
23import android.hardware.location.ContextHubTransaction;
24import android.hardware.location.IContextHubClient;
25import android.hardware.location.IContextHubClientCallback;
26import android.hardware.location.NanoAppMessage;
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080027import android.os.IBinder;
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080028import android.os.RemoteException;
29import android.util.Log;
30
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080031import java.util.concurrent.atomic.AtomicBoolean;
32
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080033/**
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080034 * A class that acts as a broker for the ContextHubClient, which handles messaging and life-cycle
35 * notification callbacks. This class implements the IContextHubClient object, and the implemented
36 * APIs must be thread-safe.
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080037 *
38 * @hide
39 */
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080040public class ContextHubClientBroker extends IContextHubClient.Stub
41 implements IBinder.DeathRecipient {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080042 private static final String TAG = "ContextHubClientBroker";
43
44 /*
45 * The context of the service.
46 */
47 private final Context mContext;
48
49 /*
50 * The proxy to talk to the Context Hub HAL.
51 */
52 private final IContexthub mContextHubProxy;
53
54 /*
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080055 * The manager that registered this client.
56 */
57 private final ContextHubClientManager mClientManager;
58
59 /*
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080060 * The ID of the hub that this client is attached to.
61 */
62 private final int mAttachedContextHubId;
63
64 /*
65 * The host end point ID of this client.
66 */
67 private final short mHostEndPointId;
68
69 /*
70 * The remote callback interface for this client.
71 */
72 private final IContextHubClientCallback mCallbackInterface;
73
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080074 /*
75 * false if the connection has been closed by the client, true otherwise.
76 */
77 private final AtomicBoolean mConnectionOpen = new AtomicBoolean(true);
78
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080079 /* package */ ContextHubClientBroker(
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080080 Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
81 int contextHubId, short hostEndPointId, IContextHubClientCallback callback) {
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080082 mContext = context;
83 mContextHubProxy = contextHubProxy;
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080084 mClientManager = clientManager;
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -080085 mAttachedContextHubId = contextHubId;
86 mHostEndPointId = hostEndPointId;
87 mCallbackInterface = callback;
88 }
89
90 /**
Arthur Ishiguro49e030f2017-11-16 11:54:42 -080091 * Attaches a death recipient for this client
92 *
93 * @throws RemoteException if the client has already died
94 */
95 /* package */ void attachDeathRecipient() throws RemoteException {
96 mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */);
97 }
98
99 /**
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800100 * Sends from this client to a nanoapp.
101 *
102 * @param message the message to send
103 * @return the error code of sending the message
104 */
105 @ContextHubTransaction.Result
106 @Override
107 public int sendMessageToNanoApp(NanoAppMessage message) {
108 ContextHubServiceUtil.checkPermissions(mContext);
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800109
110 int result;
Arthur Ishiguro49e030f2017-11-16 11:54:42 -0800111 if (mConnectionOpen.get()) {
112 ContextHubMsg messageToNanoApp = ContextHubServiceUtil.createHidlContextHubMessage(
113 mHostEndPointId, message);
114
115 try {
116 result = mContextHubProxy.sendMessageToHub(mAttachedContextHubId, messageToNanoApp);
117 } catch (RemoteException e) {
118 Log.e(TAG, "RemoteException in sendMessageToNanoApp (target hub ID = "
119 + mAttachedContextHubId + ")", e);
120 result = Result.UNKNOWN_FAILURE;
121 }
122 } else {
123 Log.e(TAG, "Failed to send message to nanoapp: client connection is closed");
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800124 result = Result.UNKNOWN_FAILURE;
125 }
Arthur Ishiguro49e030f2017-11-16 11:54:42 -0800126
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800127 return ContextHubServiceUtil.toTransactionResult(result);
128 }
129
130 /**
Arthur Ishiguro49e030f2017-11-16 11:54:42 -0800131 * Closes the connection for this client with the service.
132 */
133 @Override
134 public void close() {
135 if (mConnectionOpen.getAndSet(false)) {
136 mClientManager.unregisterClient(mHostEndPointId);
137 }
138 }
139
140 /**
141 * Invoked when the underlying binder of this broker has died at the client process.
142 */
143 public void binderDied() {
144 try {
145 IContextHubClient.Stub.asInterface(this).close();
146 } catch (RemoteException e) {
147 Log.e(TAG, "RemoteException while closing client on death", e);
148 }
149 }
150
151 /**
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800152 * @return the ID of the context hub this client is attached to
153 */
154 /* package */ int getAttachedContextHubId() {
155 return mAttachedContextHubId;
156 }
157
158 /**
159 * @return the host endpoint ID of this client
160 */
161 /* package */ short getHostEndPointId() {
162 return mHostEndPointId;
163 }
164
165 /**
166 * Sends a message to the client associated with this object.
167 *
168 * @param message the message that came from a nanoapp
169 */
170 /* package */ void sendMessageToClient(NanoAppMessage message) {
Arthur Ishiguro49e030f2017-11-16 11:54:42 -0800171 if (mConnectionOpen.get()) {
172 try {
173 mCallbackInterface.onMessageFromNanoApp(message);
174 } catch (RemoteException e) {
175 Log.e(TAG, "RemoteException while sending message to client (host endpoint ID = "
176 + mHostEndPointId + ")", e);
177 }
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800178 }
179 }
Arthur Ishiguro6d47c542017-11-17 15:49:07 -0800180
181 /**
Arthur Ishiguro0069f122017-11-20 15:07:14 -0800182 * Handles a nanoapp load event.
183 *
184 * @param nanoAppId the ID of the nanoapp that was loaded.
185 */
186 /* package */ void onNanoAppLoaded(long nanoAppId) {
187 if (mConnectionOpen.get()) {
188 try {
189 mCallbackInterface.onNanoAppLoaded(nanoAppId);
190 } catch (RemoteException e) {
191 Log.e(TAG, "RemoteException while calling onNanoAppLoaded on client"
192 + " (host endpoint ID = " + mHostEndPointId + ")", e);
193 }
194 }
195 }
196
197 /**
198 * Handles a nanoapp unload event.
199 *
200 * @param nanoAppId the ID of the nanoapp that was unloaded.
201 */
202 /* package */ void onNanoAppUnloaded(long nanoAppId) {
203 if (mConnectionOpen.get()) {
204 try {
205 mCallbackInterface.onNanoAppUnloaded(nanoAppId);
206 } catch (RemoteException e) {
207 Log.e(TAG, "RemoteException while calling onNanoAppUnloaded on client"
208 + " (host endpoint ID = " + mHostEndPointId + ")", e);
209 }
210 }
211 }
212
213 /**
Arthur Ishiguro6d47c542017-11-17 15:49:07 -0800214 * Handles a hub reset for this client.
215 */
216 /* package */ void onHubReset() {
217 if (mConnectionOpen.get()) {
218 try {
219 mCallbackInterface.onHubReset();
220 } catch (RemoteException e) {
221 Log.e(TAG, "RemoteException while calling onHubReset on client" +
222 " (host endpoint ID = " + mHostEndPointId + ")", e);
223 }
224 }
225 }
Arthur Ishiguro4e39aa12017-11-14 14:59:08 -0800226}