Creates framework for new API messaging

- Creates IContextHubClientCallback as a proxy to invoke
messaging/life-cycle callbacks for the client.
- Creates IContextHubClient as a proxy to send messages at the client
side.
- Creates a ContextHubClientManager at the service to manage
clients and messaging/lifecycle event callbacks.
- Implements generation of clients at ContextHubManager and sending
messages through ContextHubClient

Bug: 67734082
Test: make from root
Change-Id: I3a7e69f89cd70ea59160a651dcdb729e18027e9f
This commit is contained in:
Arthur Ishiguro
2017-11-14 14:59:08 -08:00
parent 3fbc4f3845
commit 4e39aa1e19
10 changed files with 570 additions and 40 deletions

View File

@@ -219,6 +219,8 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/location/IGeofenceHardwareCallback.aidl \
core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
core/java/android/hardware/location/IContextHubCallback.aidl \
core/java/android/hardware/location/IContextHubClient.aidl \
core/java/android/hardware/location/IContextHubClientCallback.aidl \
core/java/android/hardware/location/IContextHubService.aidl \
core/java/android/hardware/location/IContextHubTransactionCallback.aidl \
core/java/android/hardware/radio/IRadioService.aidl \

View File

@@ -16,7 +16,7 @@
package android.hardware.location;
import android.annotation.RequiresPermission;
import android.os.Handler;
import android.os.RemoteException;
import java.io.Closeable;
@@ -29,29 +29,25 @@ import java.io.Closeable;
*/
public class ContextHubClient implements Closeable {
/*
* The ContextHubClient interface associated with this client.
* The proxy to the client interface at the service.
*/
// TODO: Implement this interface and associate with ContextHubClient object
// private final IContextHubClient mClientInterface;
private final IContextHubClient mClientProxy;
/*
* The listening callback associated with this client.
* The callback interface associated with this client.
*/
private ContextHubClientCallback mCallback;
private final IContextHubClientCallback mCallbackInterface;
/*
* The Context Hub that this client is attached to.
*/
private ContextHubInfo mAttachedHub;
private final ContextHubInfo mAttachedHub;
/*
* The handler to invoke mCallback.
*/
private Handler mCallbackHandler;
ContextHubClient(ContextHubClientCallback callback, Handler handler, ContextHubInfo hubInfo) {
mCallback = callback;
mCallbackHandler = handler;
/* package */ ContextHubClient(
IContextHubClient clientProxy, IContextHubClientCallback callback,
ContextHubInfo hubInfo) {
mClientProxy = clientProxy;
mCallbackInterface = callback;
mAttachedHub = hubInfo;
}
@@ -90,6 +86,10 @@ public class ContextHubClient implements Closeable {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@ContextHubTransaction.Result
public int sendMessageToNanoApp(NanoAppMessage message) {
throw new UnsupportedOperationException("TODO: Implement this");
try {
return mClientProxy.sendMessageToNanoApp(message);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}

View File

@@ -455,6 +455,54 @@ public final class ContextHubManager {
return 0;
}
/**
* Creates an interface to the ContextHubClient to send down to the service.
*
* @param callback the callback to invoke at the client process
* @param handler the handler to post callbacks for this client
*
* @return the callback interface
*/
private IContextHubClientCallback createClientCallback(
ContextHubClientCallback callback, Handler handler) {
return new IContextHubClientCallback.Stub() {
@Override
public void onMessageFromNanoApp(NanoAppMessage message) {
handler.post(() -> callback.onMessageFromNanoApp(message));
}
@Override
public void onHubReset() {
handler.post(() -> callback.onHubReset());
}
@Override
public void onNanoAppAborted(long nanoAppId, int abortCode) {
handler.post(() -> callback.onNanoAppAborted(nanoAppId, abortCode));
}
@Override
public void onNanoAppLoaded(long nanoAppId) {
handler.post(() -> callback.onNanoAppLoaded(nanoAppId));
}
@Override
public void onNanoAppUnloaded(long nanoAppId) {
handler.post(() -> callback.onNanoAppUnloaded(nanoAppId));
}
@Override
public void onNanoAppEnabled(long nanoAppId) {
handler.post(() -> callback.onNanoAppEnabled(nanoAppId));
}
@Override
public void onNanoAppDisabled(long nanoAppId) {
handler.post(() -> callback.onNanoAppDisabled(nanoAppId));
}
};
}
/**
* Creates and registers a client and its callback with the Context Hub Service.
*
@@ -463,19 +511,37 @@ public final class ContextHubManager {
* {@link ContextHubClient} object, and receive notifications through the provided callback.
*
* @param callback the notification callback to register
* @param hubInfo the hub to attach this client to
* @param handler the handler to invoke the callback, if null uses the main thread's Looper
*
* @param hubInfo the hub to attach this client to
* @param handler the handler to invoke the callback, if null uses the main thread's Looper
* @return the registered client object
*
* @see ContextHubClientCallback
* @throws IllegalArgumentException if hubInfo does not represent a valid hub
* @throws IllegalStateException if there were too many registered clients at the service
* @throws NullPointerException if callback or hubInfo is null
*
* @hide
* @see ContextHubClientCallback
*/
public ContextHubClient createClient(
ContextHubClientCallback callback, ContextHubInfo hubInfo, @Nullable Handler handler) {
throw new UnsupportedOperationException(
"TODO: Implement this, and throw an exception on error");
if (callback == null) {
throw new NullPointerException("Callback cannot be null");
}
if (hubInfo == null) {
throw new NullPointerException("Hub info cannot be null");
}
Handler realHandler = (handler == null) ? new Handler(mMainLooper) : handler;
IContextHubClientCallback clientInterface = createClientCallback(callback, realHandler);
IContextHubClient client;
try {
client = mService.createClient(clientInterface, hubInfo.getId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return new ContextHubClient(client, clientInterface, hubInfo);
}
/**

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.location;
import android.hardware.location.NanoAppMessage;
/**
* @hide
*/
interface IContextHubClient {
// Sends a message to a nanoapp
int sendMessageToNanoApp(in NanoAppMessage message);
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.hardware.location;
import android.hardware.location.NanoAppMessage;
/**
* An interface used by the Context Hub Service to invoke callbacks for lifecycle notifications of a
* Context Hub and nanoapps, as well as for nanoapp messaging.
*
* @hide
*/
oneway interface IContextHubClientCallback {
// Callback invoked when receiving a message from a nanoapp.
void onMessageFromNanoApp(in NanoAppMessage message);
// Callback invoked when the attached Context Hub has reset.
void onHubReset();
// Callback invoked when a nanoapp aborts at the attached Context Hub.
void onNanoAppAborted(long nanoAppId, int abortCode);
// Callback invoked when a nanoapp is loaded at the attached Context Hub.
void onNanoAppLoaded(long nanoAppId);
// Callback invoked when a nanoapp is unloaded from the attached Context Hub.
void onNanoAppUnloaded(long nanoAppId);
// Callback invoked when a nanoapp is enabled at the attached Context Hub.
void onNanoAppEnabled(long nanoAppId);
// Callback invoked when a nanoapp is disabled at the attached Context Hub.
void onNanoAppDisabled(long nanoAppId);
}

View File

@@ -17,12 +17,14 @@
package android.hardware.location;
// Declare any non-default types here with import statements
import android.hardware.location.ContextHubMessage;
import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubMessage;
import android.hardware.location.NanoApp;
import android.hardware.location.NanoAppInstanceInfo;
import android.hardware.location.NanoAppFilter;
import android.hardware.location.NanoAppInstanceInfo;
import android.hardware.location.IContextHubCallback;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
/**
* @hide
@@ -52,4 +54,7 @@ interface IContextHubService {
// send a message to a nanoApp
int sendMessage(int hubHandle, int nanoAppHandle, in ContextHubMessage msg);
// Creates a client to send and receive messages
IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId);
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.location;
import android.content.Context;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.IContexthub;
import android.hardware.contexthub.V1_0.Result;
import android.hardware.location.ContextHubTransaction;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.NanoAppMessage;
import android.os.RemoteException;
import android.util.Log;
/**
* A broker for the ContextHubClient that handles messaging and life-cycle notification callbacks.
*
* @hide
*/
public class ContextHubClientBroker extends IContextHubClient.Stub {
private static final String TAG = "ContextHubClientBroker";
/*
* The context of the service.
*/
private final Context mContext;
/*
* The proxy to talk to the Context Hub HAL.
*/
private final IContexthub mContextHubProxy;
/*
* The ID of the hub that this client is attached to.
*/
private final int mAttachedContextHubId;
/*
* The host end point ID of this client.
*/
private final short mHostEndPointId;
/*
* The remote callback interface for this client.
*/
private final IContextHubClientCallback mCallbackInterface;
/* package */ ContextHubClientBroker(
Context context, IContexthub contextHubProxy, int contextHubId, short hostEndPointId,
IContextHubClientCallback callback) {
mContext = context;
mContextHubProxy = contextHubProxy;
mAttachedContextHubId = contextHubId;
mHostEndPointId = hostEndPointId;
mCallbackInterface = callback;
}
/**
* Sends from this client to a nanoapp.
*
* @param message the message to send
* @return the error code of sending the message
*/
@ContextHubTransaction.Result
@Override
public int sendMessageToNanoApp(NanoAppMessage message) {
ContextHubServiceUtil.checkPermissions(mContext);
ContextHubMsg messageToNanoApp =
ContextHubServiceUtil.createHidlContextHubMessage(mHostEndPointId, message);
int result;
try {
result = mContextHubProxy.sendMessageToHub(mAttachedContextHubId, messageToNanoApp);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in sendMessageToNanoApp (target hub ID = "
+ mAttachedContextHubId + ")", e);
result = Result.UNKNOWN_FAILURE;
}
return ContextHubServiceUtil.toTransactionResult(result);
}
/**
* @return the ID of the context hub this client is attached to
*/
/* package */ int getAttachedContextHubId() {
return mAttachedContextHubId;
}
/**
* @return the host endpoint ID of this client
*/
/* package */ short getHostEndPointId() {
return mHostEndPointId;
}
/**
* Sends a message to the client associated with this object.
*
* @param message the message that came from a nanoapp
*/
/* package */ void sendMessageToClient(NanoAppMessage message) {
try {
mCallbackInterface.onMessageFromNanoApp(message);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException while sending message to client (host endpoint ID = "
+ mHostEndPointId + ")", e);
}
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.location;
import android.content.Context;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.IContexthub;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.NanoAppMessage;
import android.util.Log;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
/**
* A class that manages registration/unregistration of clients and manages messages to/from clients.
*
* @hide
*/
/* package */ class ContextHubClientManager {
private static final String TAG = "ContextHubClientManager";
/*
* The maximum host endpoint ID value that a client can be assigned.
*/
private static final int MAX_CLIENT_ID = 0x7fff;
/*
* Local flag to enable debug logging.
*/
private static final boolean DEBUG_LOG_ENABLED = true;
/*
* The context of the service.
*/
private final Context mContext;
/*
* The proxy to talk to the Context Hub.
*/
private final IContexthub mContextHubProxy;
/*
* A mapping of host endpoint IDs to the ContextHubClientBroker object of registered clients.
* A concurrent data structure is used since the registration/unregistration can occur in
* multiple threads.
*/
private final ConcurrentHashMap<Short, ContextHubClientBroker> mHostEndPointIdToClientMap =
new ConcurrentHashMap<>();
/*
* The next host endpoint ID to start iterating for the next available host endpoint ID.
*/
private int mNextHostEndpointId = 0;
/* package */ ContextHubClientManager(
Context context, IContexthub contextHubProxy) {
mContext = context;
mContextHubProxy = contextHubProxy;
}
/**
* Registers a new client with the service.
*
* @param clientCallback the callback interface of the client to register
* @param contextHubId the ID of the hub this client is attached to
*
* @return the client interface
*
* @throws IllegalStateException if max number of clients have already registered
*/
/* package */ IContextHubClient registerClient(
IContextHubClientCallback clientCallback, int contextHubId) {
ContextHubClientBroker broker = createNewClientBroker(clientCallback, contextHubId);
Log.d(TAG, "Registered client with host endpoint ID " + broker.getHostEndPointId());
return IContextHubClient.Stub.asInterface(broker);
}
/**
* Handles a message sent from a nanoapp.
*
* @param contextHubId the ID of the hub where the nanoapp sent the message from
* @param message the message send by a nanoapp
*/
/* package */ void onMessageFromNanoApp(int contextHubId, ContextHubMsg message) {
NanoAppMessage clientMessage = ContextHubServiceUtil.createNanoAppMessage(message);
if (DEBUG_LOG_ENABLED) {
String targetAudience = clientMessage.isBroadcastMessage() ? "broadcast" : "unicast";
Log.v(TAG, "Received a " + targetAudience + " message from nanoapp 0x"
+ Long.toHexString(clientMessage.getNanoAppId()));
}
if (clientMessage.isBroadcastMessage()) {
broadcastMessage(contextHubId, clientMessage);
} else {
ContextHubClientBroker proxy = mHostEndPointIdToClientMap.get(message.hostEndPoint);
if (proxy != null) {
proxy.sendMessageToClient(clientMessage);
} else {
Log.e(TAG, "Cannot send message to unregistered client (host endpoint ID = "
+ message.hostEndPoint + ")");
}
}
}
/**
* Creates a new ContextHubClientBroker object for a client and registers it with the client
* manager.
*
* @param clientCallback the callback interface of the client to register
* @param contextHubId the ID of the hub this client is attached to
*
* @return the ContextHubClientBroker object
*
* @throws IllegalStateException if max number of clients have already registered
*/
private synchronized ContextHubClientBroker createNewClientBroker(
IContextHubClientCallback clientCallback, int contextHubId) {
if (mHostEndPointIdToClientMap.size() == MAX_CLIENT_ID + 1) {
throw new IllegalStateException("Could not register client - max limit exceeded");
}
ContextHubClientBroker broker = null;
int id = mNextHostEndpointId;
for (int i = 0; i <= MAX_CLIENT_ID; i++) {
if (!mHostEndPointIdToClientMap.containsKey(id)) {
broker = new ContextHubClientBroker(
mContext, mContextHubProxy, contextHubId, (short)id, clientCallback);
mHostEndPointIdToClientMap.put((short)id, broker);
mNextHostEndpointId = (id == MAX_CLIENT_ID) ? 0 : id + 1;
break;
}
id = (id == MAX_CLIENT_ID) ? 0 : id + 1;
}
return broker;
}
/**
* Broadcasts a message from a nanoapp to all clients attached to the associated hub.
*
* @param contextHubId the ID of the hub where the nanoapp sent the message from
* @param message the message send by a nanoapp
*/
private void broadcastMessage(int contextHubId, NanoAppMessage message) {
for (ContextHubClientBroker proxy : mHostEndPointIdToClientMap.values()) {
if (proxy.getAttachedContextHubId() == contextHubId) {
proxy.sendMessageToClient(message);
}
}
}
}

View File

@@ -16,7 +16,6 @@
package com.android.server.location;
import android.Manifest;
import android.content.Context;
import android.hardware.contexthub.V1_0.AsyncEventType;
import android.hardware.contexthub.V1_0.ContextHub;
@@ -30,6 +29,8 @@ import android.hardware.contexthub.V1_0.TransactionResult;
import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubMessage;
import android.hardware.location.IContextHubCallback;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.IContextHubService;
import android.hardware.location.IContextHubTransactionCallback;
import android.hardware.location.NanoApp;
@@ -58,9 +59,6 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class ContextHubService extends IContextHubService.Stub {
private static final String TAG = "ContextHubService";
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
/*
* Constants for the type of transaction that is defined by ContextHubService.
@@ -104,6 +102,9 @@ public class ContextHubService extends IContextHubService.Stub {
// The manager for transaction queue
private final ContextHubTransactionManager mTransactionManager;
// The manager for sending messages to/from clients
private final ContextHubClientManager mClientManager;
/**
* Class extending the callback to register with a Context Hub.
*/
@@ -146,17 +147,19 @@ public class ContextHubService extends IContextHubService.Stub {
mContextHubProxy = getContextHubProxy();
if (mContextHubProxy == null) {
mTransactionManager = null;
mClientManager = null;
mContextHubInfo = new ContextHubInfo[0];
return;
}
mClientManager = new ContextHubClientManager(mContext, mContextHubProxy);
mTransactionManager = new ContextHubTransactionManager(mContextHubProxy);
List<ContextHub> hubList;
try {
hubList = mContextHubProxy.getHubs();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException while getting Context Hub info");
Log.e(TAG, "RemoteException while getting Context Hub info", e);
hubList = Collections.emptyList();
}
mContextHubInfo = ContextHubServiceUtil.createContextHubInfoArray(hubList);
@@ -168,7 +171,7 @@ public class ContextHubService extends IContextHubService.Stub {
contextHubId, new ContextHubServiceCallback(contextHubId));
} catch (RemoteException e) {
Log.e(TAG, "RemoteException while registering service callback for hub (ID = "
+ contextHubId + ")");
+ contextHubId + ")", e);
}
}
@@ -192,7 +195,7 @@ public class ContextHubService extends IContextHubService.Stub {
try {
proxy = IContexthub.getService(true /* retry */);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy");
Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e);
} catch (NoSuchElementException e) {
Log.i(TAG, "Context Hub HAL service not found");
}
@@ -292,7 +295,7 @@ public class ContextHubService extends IContextHubService.Stub {
@Override
public void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
byte[] data = {(byte) result};
onMessageReceipt(MSG_QUERY_NANO_APPS, contextHubId, OS_APP_INSTANCE, data);
onMessageReceiptOldApi(MSG_QUERY_NANO_APPS, contextHubId, OS_APP_INSTANCE, data);
}
};
}
@@ -473,7 +476,7 @@ public class ContextHubService extends IContextHubService.Stub {
try {
result = mContextHubProxy.sendMessageToHub(hubHandle, hubMessage);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send nanoapp message - RemoteException");
Log.e(TAG, "Failed to send nanoapp message - RemoteException", e);
result = Result.UNKNOWN_FAILURE;
}
} else {
@@ -493,12 +496,13 @@ public class ContextHubService extends IContextHubService.Stub {
* @param message the message contents
*/
private void handleClientMessageCallback(int contextHubId, ContextHubMsg message) {
// TODO(b/67734082): Send to new API clients
byte[] data = ContextHubServiceUtil.createPrimitiveByteArray(message.msg);
int nanoAppInstanceId = mNanoAppIdToInstanceMap.containsKey(message.appName) ?
mNanoAppIdToInstanceMap.get(message.appName) : -1;
onMessageReceipt(message.msgType, contextHubId, nanoAppInstanceId, data);
onMessageReceiptOldApi(message.msgType, contextHubId, nanoAppInstanceId, data);
mClientManager.onMessageFromNanoApp(contextHubId, message);
}
/**
@@ -534,7 +538,7 @@ public class ContextHubService extends IContextHubService.Stub {
data[0] = (byte) result;
ByteBuffer.wrap(data, 1, 4).order(ByteOrder.nativeOrder()).putInt(instanceId);
onMessageReceipt(MSG_LOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
onMessageReceiptOldApi(MSG_LOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
}
/**
@@ -552,7 +556,7 @@ public class ContextHubService extends IContextHubService.Stub {
byte[] data = new byte[1];
data[0] = (byte) result;
onMessageReceipt(MSG_UNLOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
onMessageReceiptOldApi(MSG_UNLOAD_NANO_APP, contextHubId, OS_APP_INSTANCE, data);
}
/**
@@ -578,7 +582,7 @@ public class ContextHubService extends IContextHubService.Stub {
queryNanoAppsInternal(contextHubId);
byte[] data = {TransactionResult.SUCCESS};
onMessageReceipt(MSG_HUB_RESET, contextHubId, OS_APP_INSTANCE, data);
onMessageReceiptOldApi(MSG_HUB_RESET, contextHubId, OS_APP_INSTANCE, data);
} else {
Log.i(TAG, "Received unknown hub event (hub ID = " + contextHubId + ", type = "
+ eventType + ")");
@@ -641,6 +645,45 @@ public class ContextHubService extends IContextHubService.Stub {
}
}
/**
* @param contextHubId the hub ID to validate
* @return {@code true} if the ID represents that of an available hub, {@code false} otherwise
*/
private boolean isValidContextHubId(int contextHubId) {
for (ContextHubInfo hubInfo : mContextHubInfo) {
if (hubInfo.getId() == contextHubId) {
return true;
}
}
return false;
}
/**
* Creates and registers a client at the service for the specified Context Hub.
*
* @param clientCallback the client interface to register with the service
* @param contextHubId the ID of the hub this client is attached to
* @return the generated client interface, null if registration was unsuccessful
*
* @throws IllegalArgumentException if contextHubId is not a valid ID
* @throws IllegalStateException if max number of clients have already registered
* @throws NullPointerException if clientCallback is null
*/
@Override
public IContextHubClient createClient(
IContextHubClientCallback clientCallback, int contextHubId) throws RemoteException {
checkPermissions();
if (!isValidContextHubId(contextHubId)) {
throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);
}
if (clientCallback == null) {
throw new NullPointerException("Cannot register client with null callback");
}
return mClientManager.registerClient(clientCallback, contextHubId);
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -664,10 +707,10 @@ public class ContextHubService extends IContextHubService.Stub {
}
private void checkPermissions() {
mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
ContextHubServiceUtil.checkPermissions(mContext);
}
private int onMessageReceipt(int msgType, int hubHandle, int appInstance, byte[] data) {
private int onMessageReceiptOldApi(int msgType, int hubHandle, int appInstance, byte[] data) {
if (data == null) {
return -1;
}

View File

@@ -16,11 +16,15 @@
package com.android.server.location;
import android.Manifest;
import android.content.Context;
import android.hardware.contexthub.V1_0.ContextHub;
import android.hardware.contexthub.V1_0.ContextHubMsg;
import android.hardware.contexthub.V1_0.HostEndPoint;
import android.hardware.contexthub.V1_0.HubAppInfo;
import android.hardware.contexthub.V1_0.Result;
import android.hardware.location.ContextHubInfo;
import android.hardware.location.ContextHubTransaction;
import android.hardware.location.NanoAppBinary;
import android.hardware.location.NanoAppMessage;
import android.hardware.location.NanoAppState;
@@ -34,6 +38,9 @@ import java.util.ArrayList;
*/
/* package */ class ContextHubServiceUtil {
private static final String TAG = "ContextHubServiceUtil";
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
/**
* Creates a ContextHubInfo array from an ArrayList of HIDL ContextHub objects.
@@ -165,4 +172,40 @@ import java.util.ArrayList;
message.appName, message.msgType, messageArray,
message.hostEndPoint == HostEndPoint.BROADCAST);
}
/**
* Checks for location hardware permissions.
*
* @param context the context of the service
*/
/* package */
static void checkPermissions(Context context) {
context.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
}
/**
* Helper function to convert from the HAL Result enum error code to the
* ContextHubTransaction.Result type.
*
* @param halResult the Result enum error code
* @return the ContextHubTransaction.Result equivalent
*/
@ContextHubTransaction.Result
/* package */
static int toTransactionResult(int halResult) {
switch (halResult) {
case Result.OK:
return ContextHubTransaction.TRANSACTION_SUCCESS;
case Result.BAD_PARAMS:
return ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS;
case Result.NOT_INIT:
return ContextHubTransaction.TRANSACTION_FAILED_UNINITIALIZED;
case Result.TRANSACTION_PENDING:
return ContextHubTransaction.TRANSACTION_FAILED_PENDING;
case Result.TRANSACTION_FAILED:
case Result.UNKNOWN_FAILURE:
default: /* fall through */
return ContextHubTransaction.TRANSACTION_FAILED_UNKNOWN;
}
}
}