diff options
| -rw-r--r-- | Android.bp | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/ContextHubService.java | 76 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/IContextHubWrapper.java | 141 |
3 files changed, 193 insertions, 25 deletions
diff --git a/Android.bp b/Android.bp index 3fff2d4c3919..b3c9e2a720f6 100644 --- a/Android.bp +++ b/Android.bp @@ -346,6 +346,7 @@ java_library { "android.hardware.cas-V1.1-java", "android.hardware.cas-V1.2-java", "android.hardware.contexthub-V1.0-java", + "android.hardware.contexthub-V1.1-java", "android.hardware.gnss-V1.0-java", "android.hardware.gnss-V2.1-java", "android.hardware.health-V1.0-java-constants", diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java index e79eddf247cb..48b22704fd07 100644 --- a/services/core/java/com/android/server/location/ContextHubService.java +++ b/services/core/java/com/android/server/location/ContextHubService.java @@ -18,14 +18,16 @@ package com.android.server.location; import android.app.PendingIntent; import android.content.Context; +import android.database.ContentObserver; import android.hardware.contexthub.V1_0.AsyncEventType; import android.hardware.contexthub.V1_0.ContextHub; import android.hardware.contexthub.V1_0.ContextHubMsg; import android.hardware.contexthub.V1_0.HubAppInfo; -import android.hardware.contexthub.V1_0.IContexthub; import android.hardware.contexthub.V1_0.IContexthubCallback; import android.hardware.contexthub.V1_0.Result; import android.hardware.contexthub.V1_0.TransactionResult; +import android.hardware.contexthub.V1_1.Setting; +import android.hardware.contexthub.V1_1.SettingValue; import android.hardware.location.ContextHubInfo; import android.hardware.location.ContextHubMessage; import android.hardware.location.ContextHubTransaction; @@ -40,8 +42,11 @@ import android.hardware.location.NanoAppFilter; import android.hardware.location.NanoAppInstanceInfo; import android.hardware.location.NanoAppMessage; import android.hardware.location.NanoAppState; +import android.location.LocationManager; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.Settings; import android.util.Log; import android.util.proto.ProtoOutputStream; @@ -56,7 +61,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; /** * @hide @@ -92,7 +96,7 @@ public class ContextHubService extends IContextHubService.Stub { new RemoteCallbackList<>(); // Proxy object to communicate with the Context Hub HAL - private final IContexthub mContextHubProxy; + private final IContextHubWrapper mContextHubWrapper; // The manager for transaction queue private final ContextHubTransactionManager mTransactionManager; @@ -145,8 +149,8 @@ public class ContextHubService extends IContextHubService.Stub { public ContextHubService(Context context) { mContext = context; - mContextHubProxy = getContextHubProxy(); - if (mContextHubProxy == null) { + mContextHubWrapper = getContextHubWrapper(); + if (mContextHubWrapper == null) { mTransactionManager = null; mClientManager = null; mDefaultClientMap = Collections.emptyMap(); @@ -155,13 +159,13 @@ public class ContextHubService extends IContextHubService.Stub { return; } - mClientManager = new ContextHubClientManager(mContext, mContextHubProxy); + mClientManager = new ContextHubClientManager(mContext, mContextHubWrapper.getHub()); mTransactionManager = new ContextHubTransactionManager( - mContextHubProxy, mClientManager, mNanoAppStateManager); + mContextHubWrapper.getHub(), mClientManager, mNanoAppStateManager); List<ContextHub> hubList; try { - hubList = mContextHubProxy.getHubs(); + hubList = mContextHubWrapper.getHub().getHubs(); } catch (RemoteException e) { Log.e(TAG, "RemoteException while getting Context Hub info", e); hubList = Collections.emptyList(); @@ -178,7 +182,7 @@ public class ContextHubService extends IContextHubService.Stub { defaultClientMap.put(contextHubId, client); try { - mContextHubProxy.registerCallback( + mContextHubWrapper.getHub().registerCallback( contextHubId, new ContextHubServiceCallback(contextHubId)); } catch (RemoteException e) { Log.e(TAG, "RemoteException while registering service callback for hub (ID = " @@ -190,6 +194,19 @@ public class ContextHubService extends IContextHubService.Stub { queryNanoAppsInternal(contextHubId); } mDefaultClientMap = Collections.unmodifiableMap(defaultClientMap); + + if (mContextHubWrapper.supportsSettingNotifications()) { + sendLocationSettingUpdate(); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), + true /* notifyForDescendants */, + new ContentObserver(null /* handler */) { + @Override + public void onChange(boolean selfChange) { + sendLocationSettingUpdate(); + } + }, UserHandle.USER_ALL); + } } /** @@ -239,19 +256,15 @@ public class ContextHubService extends IContextHubService.Stub { } /** - * @return the IContexthub proxy interface + * @return the IContextHubWrapper interface */ - private IContexthub getContextHubProxy() { - IContexthub proxy = null; - try { - proxy = IContexthub.getService(true /* retry */); - } catch (RemoteException e) { - Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); - } catch (NoSuchElementException e) { - Log.i(TAG, "Context Hub HAL service not found"); + private IContextHubWrapper getContextHubWrapper() { + IContextHubWrapper wrapper = IContextHubWrapper.maybeConnectTo1_1(); + if (wrapper == null) { + wrapper = IContextHubWrapper.maybeConnectTo1_0(); } - return proxy; + return wrapper; } @Override @@ -355,7 +368,7 @@ public class ContextHubService extends IContextHubService.Stub { @Override public int loadNanoApp(int contextHubHandle, NanoApp nanoApp) throws RemoteException { checkPermissions(); - if (mContextHubProxy == null) { + if (mContextHubWrapper == null) { return -1; } if (!isValidContextHubId(contextHubHandle)) { @@ -382,7 +395,7 @@ public class ContextHubService extends IContextHubService.Stub { @Override public int unloadNanoApp(int nanoAppHandle) throws RemoteException { checkPermissions(); - if (mContextHubProxy == null) { + if (mContextHubWrapper == null) { return -1; } @@ -444,7 +457,7 @@ public class ContextHubService extends IContextHubService.Stub { * @throws IllegalStateException if the transaction queue is full */ private int queryNanoAppsInternal(int contextHubId) { - if (mContextHubProxy == null) { + if (mContextHubWrapper == null) { return Result.UNKNOWN_FAILURE; } @@ -461,7 +474,7 @@ public class ContextHubService extends IContextHubService.Stub { public int sendMessage(int contextHubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException { checkPermissions(); - if (mContextHubProxy == null) { + if (mContextHubWrapper == null) { return -1; } if (msg == null) { @@ -563,6 +576,8 @@ public class ContextHubService extends IContextHubService.Stub { */ private void handleHubEventCallback(int contextHubId, int eventType) { if (eventType == AsyncEventType.RESTARTED) { + sendLocationSettingUpdate(); + mTransactionManager.onHubReset(); queryNanoAppsInternal(contextHubId); @@ -870,12 +885,12 @@ public class ContextHubService extends IContextHubService.Stub { * @param callback the client transaction callback interface * @param transactionType the type of the transaction * - * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise + * @return {@code true} if mContextHubWrapper and contextHubId is valid, {@code false} otherwise */ private boolean checkHalProxyAndContextHubId( int contextHubId, IContextHubTransactionCallback callback, @ContextHubTransaction.Type int transactionType) { - if (mContextHubProxy == null) { + if (mContextHubWrapper == null) { try { callback.onTransactionComplete( ContextHubTransaction.RESULT_FAILED_HAL_UNAVAILABLE); @@ -898,4 +913,15 @@ public class ContextHubService extends IContextHubService.Stub { return true; } + + /** + * Obtains the latest location setting value and notifies the Contexthub. + */ + private void sendLocationSettingUpdate() { + boolean enabled = mContext.getSystemService(LocationManager.class) + .isLocationEnabledForUser(UserHandle.CURRENT); + + mContextHubWrapper.onSettingChanged(Setting.LOCATION, + enabled ? SettingValue.ENABLED : SettingValue.DISABLED); + } } diff --git a/services/core/java/com/android/server/location/IContextHubWrapper.java b/services/core/java/com/android/server/location/IContextHubWrapper.java new file mode 100644 index 000000000000..79fa5c7b3a95 --- /dev/null +++ b/services/core/java/com/android/server/location/IContextHubWrapper.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2020 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.annotation.Nullable; +import android.hardware.contexthub.V1_1.Setting; +import android.hardware.contexthub.V1_1.SettingValue; +import android.os.RemoteException; +import android.util.Log; + +import java.util.NoSuchElementException; + +/** + * @hide + */ +public abstract class IContextHubWrapper { + private static final String TAG = "IContextHubWrapper"; + + /** + * Attempts to connect to the Contexthub HAL 1.0 service, if it exists. + * + * @return A valid IContextHubWrapper if the connection was successful, null otherwise. + */ + @Nullable + public static IContextHubWrapper maybeConnectTo1_0() { + android.hardware.contexthub.V1_0.IContexthub proxy = null; + try { + proxy = android.hardware.contexthub.V1_0.IContexthub.getService(true /* retry */); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); + } catch (NoSuchElementException e) { + Log.i(TAG, "Context Hub HAL service not found"); + } + + ContextHubWrapperV1_0 wrapper = null; + if (proxy != null) { + wrapper = new ContextHubWrapperV1_0(proxy); + } + + return wrapper; + } + + /** + * Attempts to connect to the Contexthub HAL 1.1 service, if it exists. + * + * @return A valid IContextHubWrapper if the connection was successful, null otherwise. + */ + @Nullable + public static IContextHubWrapper maybeConnectTo1_1() { + android.hardware.contexthub.V1_1.IContexthub proxy = null; + try { + proxy = android.hardware.contexthub.V1_1.IContexthub.getService(true /* retry */); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e); + } catch (NoSuchElementException e) { + Log.i(TAG, "Context Hub HAL service not found"); + } + + ContextHubWrapperV1_1 wrapper = null; + if (proxy != null) { + wrapper = new ContextHubWrapperV1_1(proxy); + } + + return wrapper; + } + + /** + * @return A valid instance of Contexthub HAL 1.0. + */ + public abstract android.hardware.contexthub.V1_0.IContexthub getHub(); + + /** + * @return True if this version of the Contexthub HAL supports setting notifications. + */ + public abstract boolean supportsSettingNotifications(); + + /** + * Notifies the Contexthub implementation of a user setting change. + * + * @param setting The user setting that has changed. MUST be one of the values from the + * {@link Setting} enum + * @param newValue The value of the user setting that changed. MUST be one of the values + * from the {@link SettingValue} enum. + */ + public abstract void onSettingChanged(byte setting, byte newValue); + + private static class ContextHubWrapperV1_0 extends IContextHubWrapper { + private android.hardware.contexthub.V1_0.IContexthub mHub; + + ContextHubWrapperV1_0(android.hardware.contexthub.V1_0.IContexthub hub) { + mHub = hub; + } + + public android.hardware.contexthub.V1_0.IContexthub getHub() { + return mHub; + } + + public boolean supportsSettingNotifications() { + return false; + } + + public void onSettingChanged(byte setting, byte newValue) {} + } + + private static class ContextHubWrapperV1_1 extends IContextHubWrapper { + private android.hardware.contexthub.V1_1.IContexthub mHub; + + ContextHubWrapperV1_1(android.hardware.contexthub.V1_1.IContexthub hub) { + mHub = hub; + } + + public android.hardware.contexthub.V1_0.IContexthub getHub() { + return mHub; + } + + public boolean supportsSettingNotifications() { + return true; + } + + public void onSettingChanged(byte setting, byte newValue) { + try { + mHub.onSettingChanged(setting, newValue); + } catch (RemoteException e) { + Log.e(TAG, "Failed to send setting change to Contexthub", e); + } + } + } +} |