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