Add AbstractDiscoveryProvider and Controller
Test: Successfully built. Unit test will be added.
Bug: 189954300
Change-Id: Iaed9c95d3b92a7dad00035d10086bec0303f5d41
diff --git a/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java b/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java
new file mode 100644
index 0000000..7cc859c
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/provider/AbstractDiscoveryProvider.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 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.nearby.provider;
+
+import static com.android.server.nearby.NearbyService.TAG;
+
+import android.content.Context;
+import android.nearby.NearbyDeviceParcelable;
+import android.nearby.ScanRequest;
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Base class for all discovery providers.
+ *
+ * @hide
+ */
+public abstract class AbstractDiscoveryProvider {
+
+ protected final Context mContext;
+ protected final DiscoveryProviderController mController;
+ protected final Executor mExecutor;
+ protected Listener mListener;
+
+ /**
+ * Interface for listening to discovery providers.
+ */
+ public interface Listener {
+ /**
+ * Called when a provider has a new nearby device available. May be invoked from any thread.
+ */
+ void onNearbyDeviceDiscovered(NearbyDeviceParcelable nearbyDevice);
+ }
+
+ protected AbstractDiscoveryProvider(Context context, Executor executor) {
+ mContext = context;
+ mExecutor = executor;
+ mController = new Controller();
+ }
+
+ /**
+ * Callback invoked when the provider is started, and signals that other callback invocations
+ * can now be expected. Always implies that the provider request is set to the empty request.
+ * Always invoked on the provider executor.
+ */
+ protected void onStart() { }
+
+ /**
+ * Callback invoked when the provider is stopped, and signals that no further callback
+ * invocations will occur (until a further call to {@link #onStart()}. Always invoked on the
+ * provider executor.
+ */
+ protected void onStop() { }
+
+ /**
+ * Callback invoked to inform the provider of a new provider request which replaces any prior
+ * provider request. Always invoked on the provider executor.
+ */
+ protected void invalidateScanMode() { }
+
+ /**
+ * Retrieves the controller for this discovery provider. Should never be invoked by subclasses,
+ * as a discovery provider should not be controlling itself. Using this method from subclasses
+ * could also result in deadlock.
+ */
+ protected DiscoveryProviderController getController() {
+ return mController;
+ }
+
+ private class Controller implements DiscoveryProviderController {
+
+ private boolean mStarted = false;
+ private @ScanRequest.ScanMode int mScanMode;
+
+ @Override
+ public void setListener(@Nullable Listener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public boolean isStarted() {
+ return mStarted;
+ }
+
+ @Override
+ public void start() {
+ if (mStarted) {
+ Log.d(TAG, "Provider already started.");
+ return;
+ }
+ mStarted = true;
+ mExecutor.execute(AbstractDiscoveryProvider.this::onStart);
+ }
+
+ @Override
+ public void stop() {
+ if (!mStarted) {
+ Log.d(TAG, "Provider already stopped.");
+ return;
+ }
+ mStarted = false;
+ mExecutor.execute(AbstractDiscoveryProvider.this::onStop);
+ }
+
+ @Override
+ public void setProviderScanMode(@ScanRequest.ScanMode int scanMode) {
+ if (mScanMode == scanMode) {
+ Log.d(TAG, "Provider already in desired scan mode.");
+ return;
+ }
+ mScanMode = scanMode;
+ mExecutor.execute(AbstractDiscoveryProvider.this::invalidateScanMode);
+ }
+
+ @ScanRequest.ScanMode
+ @Override
+ public int getProviderScanMode() {
+ return mScanMode;
+ }
+ }
+}
diff --git a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java
new file mode 100644
index 0000000..469f623
--- /dev/null
+++ b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderController.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 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.nearby.provider;
+
+import android.annotation.Nullable;
+import android.nearby.ScanRequest;
+
+/**
+ * Interface for controlling discovery providers.
+ */
+interface DiscoveryProviderController {
+
+ /**
+ * Sets the listener which can expect to receive all state updates from after this point.
+ * May be invoked at any time.
+ */
+ void setListener(@Nullable AbstractDiscoveryProvider.Listener listener);
+
+ /**
+ * Returns true if in the started state.
+ */
+ boolean isStarted();
+
+ /**
+ * Starts the discovery provider. Must be invoked before any other method (except
+ * {@link #setListener(AbstractDiscoveryProvider.Listener)} (Listener)}).
+ */
+ void start();
+
+ /**
+ * Stops the discovery provider. No other methods may be invoked after this method (except
+ * {@link #setListener(AbstractDiscoveryProvider.Listener)} (Listener)}), until {@link #start()} is called again.
+ */
+ void stop();
+
+ /**
+ * Sets the desired scan mode.
+ */
+ void setProviderScanMode(@ScanRequest.ScanMode int scanMode);
+
+ /** Gets the controller scan mode. */
+ @ScanRequest.ScanMode
+ int getProviderScanMode();
+}