Merge "Controls API - New method for suggested controls"
This commit is contained in:
@@ -43305,6 +43305,7 @@ package android.service.controls {
|
||||
public abstract class ControlsProviderService extends android.app.Service {
|
||||
ctor public ControlsProviderService();
|
||||
method public abstract void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
|
||||
method public void loadSuggestedControls(int, @NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
|
||||
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
|
||||
method public abstract void performControlAction(@NonNull String, @NonNull android.service.controls.actions.ControlAction, @NonNull java.util.function.Consumer<java.lang.Integer>);
|
||||
method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherFor(@NonNull java.util.List<java.lang.String>);
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.util.Log;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Flow.Publisher;
|
||||
import java.util.concurrent.Flow.Subscriber;
|
||||
@@ -72,6 +73,18 @@ public abstract class ControlsProviderService extends Service {
|
||||
*/
|
||||
public abstract void loadAvailableControls(@NonNull Consumer<List<Control>> consumer);
|
||||
|
||||
/**
|
||||
* (Optional) The service may be asked to provide a small number of recommended controls, in
|
||||
* order to suggest some controls to the user for favoriting. The controls shall be built using
|
||||
* the stateless builder {@link Control.StatelessBuilder}, followed by an invocation to the
|
||||
* provided consumer to callback to the call originator. If the number of controls
|
||||
* is greater than maxNumber, the list will be truncated.
|
||||
*/
|
||||
public void loadSuggestedControls(int maxNumber, @NonNull Consumer<List<Control>> consumer) {
|
||||
// Override to change the default behavior
|
||||
consumer.accept(Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a valid Publisher for the given controlIds. This publisher will be asked
|
||||
* to provide updates for the given list of controlIds as long as the Subscription
|
||||
@@ -104,6 +117,11 @@ public abstract class ControlsProviderService extends Service {
|
||||
mHandler.obtainMessage(RequestHandler.MSG_LOAD, cb).sendToTarget();
|
||||
}
|
||||
|
||||
public void loadSuggested(int maxNumber, IControlsLoadCallback cb) {
|
||||
LoadMessage msg = new LoadMessage(maxNumber, cb);
|
||||
mHandler.obtainMessage(RequestHandler.MSG_LOAD_SUGGESTED, msg).sendToTarget();
|
||||
}
|
||||
|
||||
public void subscribe(List<String> controlIds,
|
||||
IControlsSubscriber subscriber) {
|
||||
SubscribeMessage msg = new SubscribeMessage(controlIds, subscriber);
|
||||
@@ -128,6 +146,14 @@ public abstract class ControlsProviderService extends Service {
|
||||
private static final int MSG_LOAD = 1;
|
||||
private static final int MSG_SUBSCRIBE = 2;
|
||||
private static final int MSG_ACTION = 3;
|
||||
private static final int MSG_LOAD_SUGGESTED = 4;
|
||||
|
||||
/**
|
||||
* This the maximum number of controls that can be loaded via
|
||||
* {@link ControlsProviderService#loadAvailablecontrols}. Anything over this number
|
||||
* will be truncated.
|
||||
*/
|
||||
private static final int MAX_NUMBER_OF_CONTROLS_ALLOWED = 1000;
|
||||
|
||||
RequestHandler(Looper looper) {
|
||||
super(looper);
|
||||
@@ -137,7 +163,14 @@ public abstract class ControlsProviderService extends Service {
|
||||
switch(msg.what) {
|
||||
case MSG_LOAD:
|
||||
final IControlsLoadCallback cb = (IControlsLoadCallback) msg.obj;
|
||||
ControlsProviderService.this.loadAvailableControls(consumerFor(cb));
|
||||
ControlsProviderService.this.loadAvailableControls(consumerFor(
|
||||
MAX_NUMBER_OF_CONTROLS_ALLOWED, cb));
|
||||
break;
|
||||
|
||||
case MSG_LOAD_SUGGESTED:
|
||||
final LoadMessage lMsg = (LoadMessage) msg.obj;
|
||||
ControlsProviderService.this.loadSuggestedControls(lMsg.mMaxNumber,
|
||||
consumerFor(lMsg.mMaxNumber, lMsg.mCb));
|
||||
break;
|
||||
|
||||
case MSG_SUBSCRIBE:
|
||||
@@ -201,9 +234,15 @@ public abstract class ControlsProviderService extends Service {
|
||||
};
|
||||
}
|
||||
|
||||
private Consumer<List<Control>> consumerFor(IControlsLoadCallback cb) {
|
||||
private Consumer<List<Control>> consumerFor(int maxNumber, IControlsLoadCallback cb) {
|
||||
return (@NonNull List<Control> controls) -> {
|
||||
Preconditions.checkNotNull(controls);
|
||||
if (controls.size() > maxNumber) {
|
||||
Log.w(TAG, "Too many controls. Provided: " + controls.size() + ", Max allowed: "
|
||||
+ maxNumber + ". Truncating the list.");
|
||||
controls = controls.subList(0, maxNumber);
|
||||
}
|
||||
|
||||
List<Control> list = new ArrayList<>();
|
||||
for (Control control: controls) {
|
||||
if (control == null) {
|
||||
@@ -268,4 +307,14 @@ public abstract class ControlsProviderService extends Service {
|
||||
this.mSubscriber = subscriber;
|
||||
}
|
||||
}
|
||||
|
||||
private static class LoadMessage {
|
||||
final int mMaxNumber;
|
||||
final IControlsLoadCallback mCb;
|
||||
|
||||
LoadMessage(int maxNumber, IControlsLoadCallback cb) {
|
||||
this.mMaxNumber = maxNumber;
|
||||
this.mCb = cb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import android.service.controls.actions.ControlActionWrapper;
|
||||
oneway interface IControlsProvider {
|
||||
void load(IControlsLoadCallback cb);
|
||||
|
||||
void loadSuggested(int maxNumber, IControlsLoadCallback cb);
|
||||
|
||||
void subscribe(in List<String> controlIds,
|
||||
IControlsSubscriber subscriber);
|
||||
|
||||
|
||||
@@ -146,6 +146,34 @@ public class ControlProviderServiceTest {
|
||||
assertEquals(Control.STATUS_UNKNOWN, l.get(0).getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadSuggested_withMaxNumber() throws RemoteException {
|
||||
Control control1 = new Control.StatelessBuilder("TEST_ID", mPendingIntent).build();
|
||||
Control control2 = new Control.StatelessBuilder("TEST_ID_2", mPendingIntent)
|
||||
.setDeviceType(DeviceTypes.TYPE_AIR_FRESHENER).build();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
|
||||
|
||||
ArrayList<Control> list = new ArrayList<>();
|
||||
list.add(control1);
|
||||
list.add(control2);
|
||||
|
||||
final int maxSuggested = 1;
|
||||
|
||||
mControlsProviderService.setControls(list);
|
||||
mControlsProvider.loadSuggested(maxSuggested, mLoadCallback);
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
|
||||
|
||||
verify(mLoadCallback).accept(eq(mToken), captor.capture());
|
||||
List<Control> l = captor.getValue();
|
||||
assertEquals(maxSuggested, l.size());
|
||||
|
||||
for (int i = 0; i < maxSuggested; ++i) {
|
||||
assertTrue(equals(list.get(i), l.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubscribe() throws RemoteException {
|
||||
Control control = new Control.StatefulBuilder("TEST_ID", mPendingIntent)
|
||||
@@ -215,6 +243,11 @@ public class ControlProviderServiceTest {
|
||||
cb.accept(mControls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadSuggestedControls(int maxNumber, Consumer<List<Control>> cb) {
|
||||
cb.accept(mControls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Publisher<Control> publisherFor(List<String> ids) {
|
||||
return new Publisher<Control>() {
|
||||
|
||||
Reference in New Issue
Block a user