• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 
17 package android.hardware.contexthub;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SystemApi;
24 import android.chre.flags.Flags;
25 import android.hardware.location.ContextHubTransaction;
26 import android.hardware.location.ContextHubTransactionHelper;
27 import android.hardware.location.IContextHubTransactionCallback;
28 import android.util.CloseGuard;
29 
30 import java.util.Objects;
31 import java.util.concurrent.atomic.AtomicBoolean;
32 
33 /**
34  * An object representing a communication session between two different hub endpoints.
35  *
36  * @hide
37  */
38 @SystemApi
39 @FlaggedApi(Flags.FLAG_OFFLOAD_API)
40 public class HubEndpointSession implements AutoCloseable {
41     private final CloseGuard mCloseGuard = new CloseGuard();
42 
43     private final int mId;
44 
45     @NonNull private final HubEndpoint mHubEndpoint;
46     @NonNull private final HubEndpointInfo mInitiator;
47     @NonNull private final HubEndpointInfo mDestination;
48     @Nullable private final String mServiceDescriptor;
49 
50     private final AtomicBoolean mIsClosed = new AtomicBoolean(true);
51 
52     /** @hide */
HubEndpointSession( int id, @NonNull HubEndpoint hubEndpoint, @NonNull HubEndpointInfo destination, @NonNull HubEndpointInfo initiator, @Nullable String serviceDescriptor)53     HubEndpointSession(
54             int id,
55             @NonNull HubEndpoint hubEndpoint,
56             @NonNull HubEndpointInfo destination,
57             @NonNull HubEndpointInfo initiator,
58             @Nullable String serviceDescriptor) {
59         mId = id;
60         mHubEndpoint = hubEndpoint;
61         mDestination = destination;
62         mInitiator = initiator;
63         mServiceDescriptor = serviceDescriptor;
64     }
65 
66     /**
67      * Send a message to the peer endpoint in this session.
68      *
69      * @param message The message object constructed with {@link HubMessage#createMessage}.
70      * @return For messages that does not require a response, the transaction will immediately
71      *     complete. For messages that requires a response, the transaction will complete after
72      *     receiving the response for the message.
73      * @throws SecurityException if the application doesn't have the right permissions to send this
74      *     message.
75      */
76     @NonNull
77     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
sendMessage(@onNull HubMessage message)78     public ContextHubTransaction<Void> sendMessage(@NonNull HubMessage message) {
79         if (mIsClosed.get()) {
80             throw new IllegalStateException("Session is already closed.");
81         }
82 
83         boolean isResponseRequired = message.isResponseRequired();
84         ContextHubTransaction<Void> ret =
85                 new ContextHubTransaction<>(
86                         isResponseRequired
87                                 ? ContextHubTransaction.TYPE_HUB_MESSAGE_REQUIRES_RESPONSE
88                                 : ContextHubTransaction.TYPE_HUB_MESSAGE_DEFAULT);
89         if (!isResponseRequired) {
90             // If the message doesn't require acknowledgement, respond with success immediately
91             mHubEndpoint.sendMessage(this, message, null);
92             ret.setResponse(
93                     new ContextHubTransaction.Response<>(
94                             ContextHubTransaction.RESULT_SUCCESS, null));
95         } else {
96             IContextHubTransactionCallback callback =
97                     ContextHubTransactionHelper.createTransactionCallback(ret);
98             // Sequence number will be assigned at the service
99             mHubEndpoint.sendMessage(this, message, callback);
100         }
101         return ret;
102     }
103 
104     /** @hide */
getId()105     public int getId() {
106         return mId;
107     }
108 
109     /** @hide */
setOpened()110     public void setOpened() {
111         mIsClosed.set(false);
112         mCloseGuard.open("close");
113     }
114 
115     /** @hide */
setClosed()116     public void setClosed() {
117         mIsClosed.set(true);
118         mCloseGuard.close();
119     }
120 
121     /**
122      * Closes the connection for this session between an endpoint and the Context Hub Service.
123      *
124      * <p>When this function is invoked, the messaging associated with this session is invalidated.
125      * All futures messages targeted for this client are dropped.
126      */
127     @RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
close()128     public void close() {
129         if (!mIsClosed.getAndSet(true)) {
130             mCloseGuard.close();
131             mHubEndpoint.closeSession(this);
132         }
133     }
134 
135     /**
136      * Get the service descriptor associated with this session. Null value indicates that there is
137      * no service associated to this session.
138      *
139      * <p>For hub initiated sessions, the object was previously used in as an argument for open
140      * request in {@link HubEndpointLifecycleCallback#onSessionOpenRequest}.
141      *
142      * <p>For app initiated sessions, the object was previously used in an open request in {@link
143      * android.hardware.location.ContextHubManager#openSession}
144      */
145     @Nullable
getServiceDescriptor()146     public String getServiceDescriptor() {
147         return mServiceDescriptor;
148     }
149 
150     @Override
toString()151     public String toString() {
152         StringBuilder stringBuilder = new StringBuilder();
153         stringBuilder.append("Session [");
154         stringBuilder.append(mId);
155         stringBuilder.append("]: [");
156         stringBuilder.append(mInitiator);
157         stringBuilder.append("]->[");
158         stringBuilder.append(mDestination);
159         stringBuilder.append("]");
160         return stringBuilder.toString();
161     }
162 
163     @Override
equals(@ullable Object object)164     public boolean equals(@Nullable Object object) {
165         if (object == this) {
166             return true;
167         }
168 
169         boolean isEqual = false;
170         if (object instanceof HubEndpointSession other) {
171             isEqual = (other.getId() == mId);
172             if (mServiceDescriptor != null) {
173                 isEqual &= mServiceDescriptor.equals(other.getServiceDescriptor());
174             } else {
175                 isEqual &= (other.getServiceDescriptor() == null);
176             }
177             isEqual &=
178                     mInitiator.equals(other.mInitiator) && mDestination.equals(other.mDestination);
179         }
180 
181         return isEqual;
182     }
183 
184     @Override
hashCode()185     public int hashCode() {
186         return Objects.hash(mId, mServiceDescriptor, mInitiator, mDestination);
187     }
188 
189     /** @hide */
finalize()190     protected void finalize() throws Throwable {
191         try {
192             // Note that guard could be null if the constructor threw.
193             if (mCloseGuard != null) {
194                 mCloseGuard.warnIfOpen();
195             }
196             close();
197         } finally {
198             super.finalize();
199         }
200     }
201 }
202