blob: 8a95f4d0f566df9d305a7a29f1bcb78cb2f6e414 [file] [log] [blame]
/*
* Copyright (C) 2019 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.service.controls;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.service.controls.actions.ControlAction;
import java.util.List;
/**
* Service implementation allowing applications to contribute controls to the
* System UI.
* @hide
*/
public abstract class ControlsProviderService extends Service {
@SdkConstant(SdkConstantType.SERVICE_ACTION)
public static final String CONTROLS_ACTION = "android.service.controls.ControlsProviderService";
private IControlsProviderCallback mCallback;
private RequestHandler mHandler;
/**
* Signal to retrieve all Controls. When complete, call
* {@link IControlsProviderCallback#onLoad} to inform the caller.
*/
public abstract void load();
/**
* Informs the service that the caller is listening for updates to the given controlIds.
* {@link IControlsProviderCallback#onRefreshState} should be called any time
* there are Control updates to render.
*/
public abstract void subscribe(@NonNull List<String> controlIds);
/**
* Informs the service that the caller is done listening for updates,
* and any calls to {@link IControlsProviderCallback#onRefreshState} will be ignored.
*/
public abstract void unsubscribe();
/**
* The user has interacted with a Control. The action is dictated by the type of
* {@link ControlAction} that was sent.
*/
public abstract void onAction(@NonNull String controlId, @NonNull ControlAction action);
protected IControlsProviderCallback getControlsProviderCallback() {
return mCallback;
}
@Override
public IBinder onBind(Intent intent) {
mHandler = new RequestHandler(Looper.getMainLooper());
Bundle bundle = intent.getBundleExtra("CALLBACK_BUNDLE");
IBinder callbackBinder = bundle.getBinder("CALLBACK_BINDER");
mCallback = IControlsProviderCallback.Stub.asInterface(callbackBinder);
return new IControlsProvider.Stub() {
public void load() {
mHandler.sendEmptyMessage(RequestHandler.MSG_LOAD);
}
public void subscribe(List<String> ids) {
mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, ids).sendToTarget();
}
public void unsubscribe() {
mHandler.sendEmptyMessage(RequestHandler.MSG_UNSUBSCRIBE);
}
public void onAction(String id, ControlAction action) {
ActionMessage msg = new ActionMessage(id, action);
mHandler.obtainMessage(RequestHandler.MSG_SUBSCRIBE, msg).sendToTarget();
}
};
}
@Override
public boolean onUnbind(Intent intent) {
mCallback = null;
mHandler = null;
return true;
}
private class RequestHandler extends Handler {
private static final int MSG_LOAD = 1;
private static final int MSG_SUBSCRIBE = 2;
private static final int MSG_UNSUBSCRIBE = 3;
private static final int MSG_ON_ACTION = 4;
RequestHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_LOAD:
ControlsProviderService.this.load();
break;
case MSG_SUBSCRIBE:
List<String> ids = (List<String>) msg.obj;
ControlsProviderService.this.subscribe(ids);
break;
case MSG_UNSUBSCRIBE:
ControlsProviderService.this.unsubscribe();
break;
case MSG_ON_ACTION:
ActionMessage aMsg = (ActionMessage) msg.obj;
ControlsProviderService.this.onAction(aMsg.mId, aMsg.mAction);
break;
}
}
}
private class ActionMessage {
final String mId;
final ControlAction mAction;
ActionMessage(String id, ControlAction action) {
this.mId = id;
this.mAction = action;
}
}
}