1 /*
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 package android.hardware.location;
17 
18 import android.annotation.NonNull;
19 import android.annotation.RequiresPermission;
20 import android.annotation.SystemApi;
21 import android.os.RemoteException;
22 
23 import com.android.internal.util.Preconditions;
24 
25 import dalvik.system.CloseGuard;
26 
27 import java.io.Closeable;
28 import java.util.concurrent.atomic.AtomicBoolean;
29 
30 /**
31  * A class describing a client of the Context Hub Service.
32  *
33  * Clients can send messages to nanoapps at a Context Hub through this object. The APIs supported
34  * by this object are thread-safe and can be used without external synchronization.
35  *
36  * @hide
37  */
38 @SystemApi
39 public class ContextHubClient implements Closeable {
40     /*
41      * The proxy to the client interface at the service.
42      */
43     private IContextHubClient mClientProxy = null;
44 
45     /*
46      * The Context Hub that this client is attached to.
47      */
48     private final ContextHubInfo mAttachedHub;
49 
50     private final CloseGuard mCloseGuard = CloseGuard.get();
51 
52     private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
53 
ContextHubClient(ContextHubInfo hubInfo)54     /* package */ ContextHubClient(ContextHubInfo hubInfo) {
55         mAttachedHub = hubInfo;
56         mCloseGuard.open("close");
57     }
58 
59     /**
60      * Sets the proxy interface of the client at the service. This method should always be called
61      * by the ContextHubManager after the client is registered at the service, and should only be
62      * called once.
63      *
64      * @param clientProxy the proxy of the client at the service
65      */
setClientProxy(IContextHubClient clientProxy)66     /* package */ void setClientProxy(IContextHubClient clientProxy) {
67         Preconditions.checkNotNull(clientProxy, "IContextHubClient cannot be null");
68         if (mClientProxy != null) {
69             throw new IllegalStateException("Cannot change client proxy multiple times");
70         }
71 
72         mClientProxy = clientProxy;
73     }
74 
75     /**
76      * Returns the hub that this client is attached to.
77      *
78      * @return the ContextHubInfo of the attached hub
79      */
80     @NonNull
getAttachedHub()81     public ContextHubInfo getAttachedHub() {
82         return mAttachedHub;
83     }
84 
85     /**
86      * Closes the connection for this client and the Context Hub Service.
87      *
88      * When this function is invoked, the messaging associated with this client is invalidated.
89      * All futures messages targeted for this client are dropped at the service.
90      */
close()91     public void close() {
92         if (!mIsClosed.getAndSet(true)) {
93             mCloseGuard.close();
94             try {
95                 mClientProxy.close();
96             } catch (RemoteException e) {
97                 throw e.rethrowFromSystemServer();
98             }
99         }
100     }
101 
102     /**
103      * Sends a message to a nanoapp through the Context Hub Service.
104      *
105      * This function returns TRANSACTION_SUCCESS if the message has reached the HAL, but
106      * does not guarantee delivery of the message to the target nanoapp.
107      *
108      * @param message the message object to send
109      *
110      * @return the result of sending the message defined as in ContextHubTransaction.Result
111      *
112      * @throws NullPointerException if NanoAppMessage is null
113      *
114      * @see NanoAppMessage
115      * @see ContextHubTransaction.Result
116      */
117     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
118     @ContextHubTransaction.Result
sendMessageToNanoApp(@onNull NanoAppMessage message)119     public int sendMessageToNanoApp(@NonNull NanoAppMessage message) {
120         Preconditions.checkNotNull(message, "NanoAppMessage cannot be null");
121 
122         try {
123             return mClientProxy.sendMessageToNanoApp(message);
124         } catch (RemoteException e) {
125             throw e.rethrowFromSystemServer();
126         }
127     }
128 
129     @Override
finalize()130     protected void finalize() throws Throwable {
131         try {
132             if (mCloseGuard != null) {
133                 mCloseGuard.warnIfOpen();
134             }
135             close();
136         } finally {
137             super.finalize();
138         }
139     }
140 }
141