Merge "Control API review changes" into rvc-dev am: 8ebe5c222d am: 56f02d3893

Change-Id: Id9107084cd2c0b18041822e9d4bb91fd59f8ae35
This commit is contained in:
Automerger Merge Worker
2020-03-06 20:14:19 +00:00
13 changed files with 123 additions and 329 deletions

View File

@@ -43552,9 +43552,9 @@ package android.service.controls.actions {
public abstract class ControlAction {
method public abstract int getActionType();
method @Nullable public String getChallengeValue();
method @NonNull public static android.service.controls.actions.ControlAction getErrorAction();
method @NonNull public String getTemplateId();
method public static final boolean isValidResponse(int);
field @NonNull public static final android.service.controls.actions.ControlAction ERROR_ACTION;
field public static final int RESPONSE_CHALLENGE_ACK = 3; // 0x3
field public static final int RESPONSE_CHALLENGE_PASSPHRASE = 5; // 0x5
field public static final int RESPONSE_CHALLENGE_PIN = 4; // 0x4
@@ -43566,7 +43566,6 @@ package android.service.controls.actions {
field public static final int TYPE_ERROR = -1; // 0xffffffff
field public static final int TYPE_FLOAT = 2; // 0x2
field public static final int TYPE_MODE = 4; // 0x4
field public static final int TYPE_MULTI_FLOAT = 3; // 0x3
}
public final class FloatAction extends android.service.controls.actions.ControlAction {
@@ -43583,13 +43582,6 @@ package android.service.controls.actions {
method public int getNewMode();
}
public final class MultiFloatAction extends android.service.controls.actions.ControlAction {
ctor public MultiFloatAction(@NonNull String, @NonNull float[], @Nullable String);
ctor public MultiFloatAction(@NonNull String, @NonNull float[]);
method public int getActionType();
method @NonNull public float[] getNewValues();
}
}
package android.service.controls.templates {
@@ -43604,16 +43596,15 @@ package android.service.controls.templates {
}
public abstract class ControlTemplate {
method @NonNull public static android.service.controls.templates.ControlTemplate getErrorTemplate();
method @NonNull public static android.service.controls.templates.ControlTemplate getNoTemplateObject();
method @NonNull public String getTemplateId();
method public abstract int getTemplateType();
field @NonNull public static final android.service.controls.templates.ControlTemplate ERROR_TEMPLATE;
field @NonNull public static final android.service.controls.templates.ControlTemplate NO_TEMPLATE;
field public static final int TYPE_ERROR = -1; // 0xffffffff
field public static final int TYPE_NONE = 0; // 0x0
field public static final int TYPE_NO_TEMPLATE = 0; // 0x0
field public static final int TYPE_RANGE = 2; // 0x2
field public static final int TYPE_STATELESS = 8; // 0x8
field public static final int TYPE_TEMPERATURE = 7; // 0x7
field public static final int TYPE_THUMBNAIL = 3; // 0x3
field public static final int TYPE_TOGGLE = 1; // 0x1
field public static final int TYPE_TOGGLE_RANGE = 6; // 0x6
}
@@ -43653,13 +43644,6 @@ package android.service.controls.templates {
field public static final int MODE_UNKNOWN = 0; // 0x0
}
public final class ThumbnailTemplate extends android.service.controls.templates.ControlTemplate {
ctor public ThumbnailTemplate(@NonNull String, @NonNull android.graphics.drawable.Icon, @NonNull CharSequence);
method @NonNull public CharSequence getContentDescription();
method public int getTemplateType();
method @NonNull public android.graphics.drawable.Icon getThumbnail();
}
public final class ToggleRangeTemplate extends android.service.controls.templates.ControlTemplate {
ctor public ToggleRangeTemplate(@NonNull String, @NonNull android.service.controls.templates.ControlButton, @NonNull android.service.controls.templates.RangeTemplate);
ctor public ToggleRangeTemplate(@NonNull String, boolean, @NonNull CharSequence, @NonNull android.service.controls.templates.RangeTemplate);

View File

@@ -395,7 +395,7 @@ public final class Control implements Parcelable {
* {@link ControlsProviderService#createPublisherForAllAvailable}:
* <ul>
* <li> Status: {@link Status#STATUS_UNKNOWN}
* <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
* <li> Control template: {@link ControlTemplate#getNoTemplateObject}
* <li> Status text: {@code ""}
* </ul>
*/
@@ -593,7 +593,7 @@ public final class Control implements Parcelable {
* <li> Title: {@code ""}
* <li> Subtitle: {@code ""}
* <li> Status: {@link Status#STATUS_UNKNOWN}
* <li> Control template: {@link ControlTemplate#NO_TEMPLATE}
* <li> Control template: {@link ControlTemplate#getNoTemplateObject}
* <li> Status text: {@code ""}
* </ul>
*/

View File

@@ -239,7 +239,8 @@ public abstract class ControlsProviderService extends Service {
private static boolean isStatelessControl(Control control) {
return (control.getStatus() == Control.STATUS_UNKNOWN
&& control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
&& control.getControlTemplate().getTemplateType()
== ControlTemplate.TYPE_NO_TEMPLATE
&& TextUtils.isEmpty(control.getStatusText()));
}

View File

@@ -23,6 +23,18 @@ import java.lang.annotation.RetentionPolicy;
/**
* Device types for {@link Control}.
*
* Each {@link Control} declares a type for the device they represent. This type will be used to
* determine icons and colors.
* <p>
* The type of the device may change on status updates of the {@link Control}. For example, a
* device of {@link #TYPE_OUTLET} could be determined by the {@link ControlsProviderService} to be
* a {@link #TYPE_COFFEE_MAKER} and change the type for that {@link Control}, therefore possibly
* changing icon and color.
* <p>
* In case the device type is not know by the application but the basic function is, or there is no
* provided type, one of the generic types (those starting with {@code TYPE_GENERIC}) can be used.
* These will provide an identifiable icon based on the basic function of the device.
*/
public class DeviceTypes {

View File

@@ -22,7 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.service.controls.Control;
import android.service.controls.IControlsActionCallback;
import android.service.controls.ControlsProviderService;
import android.service.controls.templates.ControlTemplate;
import android.util.Log;
@@ -34,8 +34,15 @@ import java.lang.annotation.RetentionPolicy;
/**
* An abstract action indicating a user interaction with a {@link Control}.
*
* The action may have a value to authenticate the input, when the provider has requested it to
* complete the action.
* In some cases, an action needs to be validated by the user, using a password, PIN or simple
* acknowledgment. For those cases, an optional (nullable) parameter can be passed to send the user
* input. This <b>challenge value</b> will be requested from the user and sent as part
* of a {@link ControlAction} only if the service has responded to an action with one of:
* <ul>
* <li> {@link #RESPONSE_CHALLENGE_ACK}
* <li> {@link #RESPONSE_CHALLENGE_PIN}
* <li> {@link #RESPONSE_CHALLENGE_PASSPHRASE}
* </ul>
*/
public abstract class ControlAction {
@@ -53,7 +60,6 @@ public abstract class ControlAction {
TYPE_ERROR,
TYPE_BOOLEAN,
TYPE_FLOAT,
TYPE_MULTI_FLOAT,
TYPE_MODE,
TYPE_COMMAND
})
@@ -61,6 +67,7 @@ public abstract class ControlAction {
/**
* Object returned when there is an unparcelling error.
* @hide
*/
public static final @NonNull ControlAction ERROR_ACTION = new ControlAction() {
@Override
@@ -70,7 +77,7 @@ public abstract class ControlAction {
};
/**
* The identifier of {@link #ERROR_ACTION}
* The identifier of the action returned by {@link #getErrorAction}.
*/
public static final @ActionType int TYPE_ERROR = -1;
@@ -84,11 +91,6 @@ public abstract class ControlAction {
*/
public static final @ActionType int TYPE_FLOAT = 2;
/**
* The identifier of {@link MultiFloatAction}.
*/
public static final @ActionType int TYPE_MULTI_FLOAT = 3;
/**
* The identifier of {@link ModeAction}.
*/
@@ -121,28 +123,32 @@ public abstract class ControlAction {
public static final @ResponseResult int RESPONSE_UNKNOWN = 0;
/**
* Response code for {@link IControlsActionCallback#accept} indicating that
* the action has been performed. The action may still fail later and the state may not change.
* Response code for the {@code consumer} in
* {@link ControlsProviderService#performControlAction} indicating that the action has been
* performed. The action may still fail later and the state may not change.
*/
public static final @ResponseResult int RESPONSE_OK = 1;
/**
* Response code for {@link IControlsActionCallback#accept} indicating that
* the action has failed.
* Response code for the {@code consumer} in
* {@link ControlsProviderService#performControlAction} indicating that the action has failed.
*/
public static final @ResponseResult int RESPONSE_FAIL = 2;
/**
* Response code for {@link IControlsActionCallback#accept} indicating that
* in order for the action to be performed, acknowledgment from the user is required.
* Response code for the {@code consumer} in
* {@link ControlsProviderService#performControlAction} indicating that in order for the action
* to be performed, acknowledgment from the user is required.
*/
public static final @ResponseResult int RESPONSE_CHALLENGE_ACK = 3;
/**
* Response code for {@link IControlsActionCallback#accept} indicating that
* in order for the action to be performed, a PIN is required.
* Response code for the {@code consumer} in
* {@link ControlsProviderService#performControlAction} indicating that in order for the action
* to be performed, a PIN is required.
*/
public static final @ResponseResult int RESPONSE_CHALLENGE_PIN = 4;
/**
* Response code for {@link IControlsActionCallback#accept} indicating that
* in order for the action to be performed, an alphanumeric passphrase is required.
* Response code for the {@code consumer} in
* {@link ControlsProviderService#performControlAction} indicating that in order for the action
* to be performed, an alphanumeric passphrase is required.
*/
public static final @ResponseResult int RESPONSE_CHALLENGE_PASSPHRASE = 5;
@@ -228,8 +234,6 @@ public abstract class ControlAction {
return new BooleanAction(bundle);
case TYPE_FLOAT:
return new FloatAction(bundle);
case TYPE_MULTI_FLOAT:
return new MultiFloatAction(bundle);
case TYPE_MODE:
return new ModeAction(bundle);
case TYPE_COMMAND:
@@ -243,4 +247,12 @@ public abstract class ControlAction {
return ERROR_ACTION;
}
}
/**
* Returns a singleton {@link ControlAction} used for indicating an error in unparceling.
*/
@NonNull
public static ControlAction getErrorAction() {
return ERROR_ACTION;
}
}

View File

@@ -1,82 +0,0 @@
/*
* 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.actions;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.util.Log;
import com.android.internal.util.Preconditions;
public final class MultiFloatAction extends ControlAction {
private static final String TAG = "MultiFloatAction";
private static final @ActionType int TYPE = TYPE_MULTI_FLOAT;
private static final String KEY_VALUES = "key_values";
private final @NonNull float[] mNewValues;
@Override
public int getActionType() {
return TYPE;
}
public MultiFloatAction(@NonNull String templateId,
@NonNull float[] newValues,
@Nullable String challengeValue) {
super(templateId, challengeValue);
Preconditions.checkNotNull(newValues);
if (newValues.length == 0) {
throw new IllegalArgumentException("newValues array length 0");
}
if (newValues.length == 1) {
Log.w(TAG, "newValues array length 1");
}
mNewValues = newValues.clone();
}
public MultiFloatAction(@NonNull String templateId, @NonNull float[] newValues) {
this(templateId, newValues, null);
}
/**
* @param b
* @hide
*/
MultiFloatAction(Bundle b) {
super(b);
mNewValues = b.getFloatArray(KEY_VALUES);
}
@NonNull
public float[] getNewValues() {
return mNewValues.clone();
}
/**
* @return
* @hide
*/
@Override
@NonNull
Bundle getDataBundle() {
Bundle b = super.getDataBundle();
b.putFloatArray(KEY_VALUES, mNewValues);
return b;
}
}

View File

@@ -49,18 +49,20 @@ public abstract class ControlTemplate {
/**
* Singleton representing a {@link Control} with no input.
* @hide
*/
public static final @NonNull ControlTemplate NO_TEMPLATE = new ControlTemplate("") {
@Override
public int getTemplateType() {
return TYPE_NONE;
return TYPE_NO_TEMPLATE;
}
};
/**
* Object returned when there is an unparcelling error.
* @hide
*/
public static final @NonNull ControlTemplate ERROR_TEMPLATE = new ControlTemplate("") {
private static final @NonNull ControlTemplate ERROR_TEMPLATE = new ControlTemplate("") {
@Override
public int getTemplateType() {
return TYPE_ERROR;
@@ -73,10 +75,9 @@ public abstract class ControlTemplate {
@Retention(RetentionPolicy.SOURCE)
@IntDef({
TYPE_ERROR,
TYPE_NONE,
TYPE_NO_TEMPLATE,
TYPE_TOGGLE,
TYPE_RANGE,
TYPE_THUMBNAIL,
TYPE_TOGGLE_RANGE,
TYPE_TEMPERATURE,
TYPE_STATELESS
@@ -84,14 +85,14 @@ public abstract class ControlTemplate {
public @interface TemplateType {}
/**
* Type identifier of {@link #ERROR_TEMPLATE}.
* Type identifier of the template returned by {@link #getErrorTemplate()}.
*/
public static final @TemplateType int TYPE_ERROR = -1;
/**
* Type identifier of {@link ControlTemplate#NO_TEMPLATE}.
* Type identifier of {@link ControlTemplate#getNoTemplateObject}.
*/
public static final @TemplateType int TYPE_NONE = 0;
public static final @TemplateType int TYPE_NO_TEMPLATE = 0;
/**
* Type identifier of {@link ToggleTemplate}.
@@ -103,11 +104,6 @@ public abstract class ControlTemplate {
*/
public static final @TemplateType int TYPE_RANGE = 2;
/**
* Type identifier of {@link ThumbnailTemplate}.
*/
public static final @TemplateType int TYPE_THUMBNAIL = 3;
/**
* Type identifier of {@link ToggleRangeTemplate}.
*/
@@ -191,15 +187,13 @@ public abstract class ControlTemplate {
return new ToggleTemplate(bundle);
case TYPE_RANGE:
return new RangeTemplate(bundle);
case TYPE_THUMBNAIL:
return new ThumbnailTemplate(bundle);
case TYPE_TOGGLE_RANGE:
return new ToggleRangeTemplate(bundle);
case TYPE_TEMPERATURE:
return new TemperatureControlTemplate(bundle);
case TYPE_STATELESS:
return new StatelessTemplate(bundle);
case TYPE_NONE:
case TYPE_NO_TEMPLATE:
return NO_TEMPLATE;
case TYPE_ERROR:
default:
@@ -210,4 +204,27 @@ public abstract class ControlTemplate {
return ERROR_TEMPLATE;
}
}
/**
* @return a singleton {@link ControlTemplate} used for indicating an error in unparceling.
*/
@NonNull
public static ControlTemplate getErrorTemplate() {
return ERROR_TEMPLATE;
}
/**
* Get a singleton {@link ControlTemplate} that has no features.
*
* This template has no distinctive field, not even an identifier. Used for a {@link Control}
* that accepts no type of input, or when there is no known state.
*
* @return a singleton {@link ControlTemplate} to indicate no specific template is used by
* this {@link Control}
*/
@NonNull
public static ControlTemplate getNoTemplateObject() {
return NO_TEMPLATE;
}
}

View File

@@ -60,16 +60,34 @@ public final class TemperatureControlTemplate extends ControlTemplate {
private static final int NUM_MODES = 6;
/**
* Use when the current or active mode of the device is not known
*/
public static final @Mode int MODE_UNKNOWN = 0;
/**
* Indicates that the current or active mode of the device is off.
*/
public static final @Mode int MODE_OFF = 1;
/**
* Indicates that the current or active mode of the device is set to heat.
*/
public static final @Mode int MODE_HEAT = 2;
/**
* Indicates that the current or active mode of the device is set to cool.
*/
public static final @Mode int MODE_COOL = 3;
/**
* Indicates that the current or active mode of the device is set to heat-cool.
*/
public static final @Mode int MODE_HEAT_COOL = 4;
/**
* Indicates that the current or active mode of the device is set to eco.
*/
public static final @Mode int MODE_ECO = 5;
/**
@@ -85,10 +103,29 @@ public final class TemperatureControlTemplate extends ControlTemplate {
})
public @interface ModeFlag {}
/**
* Flag to indicate that the device supports off mode.
*/
public static final int FLAG_MODE_OFF = 1 << MODE_OFF;
/**
* Flag to indicate that the device supports heat mode.
*/
public static final int FLAG_MODE_HEAT = 1 << MODE_HEAT;
/**
* Flag to indicate that the device supports cool mode.
*/
public static final int FLAG_MODE_COOL = 1 << MODE_COOL;
/**
* Flag to indicate that the device supports heat-cool mode.
*/
public static final int FLAG_MODE_HEAT_COOL = 1 << MODE_HEAT_COOL;
/**
* Flag to indicate that the device supports eco mode.
*/
public static final int FLAG_MODE_ECO = 1 << MODE_ECO;
private static final int ALL_FLAGS =
FLAG_MODE_OFF |

View File

@@ -1,98 +0,0 @@
/*
* 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.templates;
import android.annotation.NonNull;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.service.controls.Control;
import com.android.internal.util.Preconditions;
/**
* A template for a {@link Control} that displays an image.
*/
public final class ThumbnailTemplate extends ControlTemplate {
private static final @TemplateType int TYPE = TYPE_THUMBNAIL;
private static final String KEY_ICON = "key_icon";
private static final String KEY_CONTENT_DESCRIPTION = "key_content_description";
private final @NonNull Icon mThumbnail;
private final @NonNull CharSequence mContentDescription;
/**
* @param templateId the identifier for this template object
* @param thumbnail an image to display on the {@link Control}
* @param contentDescription a description of the image for accessibility.
*/
public ThumbnailTemplate(@NonNull String templateId, @NonNull Icon thumbnail,
@NonNull CharSequence contentDescription) {
super(templateId);
Preconditions.checkNotNull(thumbnail);
Preconditions.checkNotNull(contentDescription);
mThumbnail = thumbnail;
mContentDescription = contentDescription;
}
/**
* @param b
* @hide
*/
ThumbnailTemplate(Bundle b) {
super(b);
mThumbnail = b.getParcelable(KEY_ICON);
mContentDescription = b.getCharSequence(KEY_CONTENT_DESCRIPTION, "");
}
/**
* The {@link Icon} (image) displayed by this template.
*/
@NonNull
public Icon getThumbnail() {
return mThumbnail;
}
/**
* The description of the image returned by {@link ThumbnailTemplate#getThumbnail()}
*/
@NonNull
public CharSequence getContentDescription() {
return mContentDescription;
}
/**
* @return {@link ControlTemplate#TYPE_THUMBNAIL}
*/
@Override
public int getTemplateType() {
return TYPE;
}
/**
* @return
* @hide
*/
@Override
@NonNull
Bundle getDataBundle() {
Bundle b = super.getDataBundle();
b.putObject(KEY_ICON, mThumbnail);
b.putObject(KEY_CONTENT_DESCRIPTION, mContentDescription);
return b;
}
}

View File

@@ -55,16 +55,6 @@ public class ControlActionTest {
assertTrue(fromParcel instanceof FloatAction);
}
@Test
public void testUnparcelingCorrectClass_multiFloat() {
ControlAction toParcel = new MultiFloatAction(TEST_ID, new float[] {0f, 1f});
ControlAction fromParcel = parcelAndUnparcel(toParcel);
assertEquals(ControlAction.TYPE_MULTI_FLOAT, fromParcel.getActionType());
assertTrue(fromParcel instanceof MultiFloatAction);
}
@Test
public void testUnparcelingCorrectClass_mode() {
ControlAction toParcel = new ModeAction(TEST_ID, 1);

View File

@@ -102,16 +102,6 @@ public class ControlTemplateTest {
new RangeTemplate(TEST_ID, 0, 2, 1, -1, "%f");
}
@Test
public void testUnparcelingCorrectClass_thumbnail() {
ControlTemplate toParcel = new ThumbnailTemplate(TEST_ID, mIcon, TEST_ACTION_DESCRIPTION);
ControlTemplate fromParcel = parcelAndUnparcel(toParcel);
assertEquals(ControlTemplate.TYPE_THUMBNAIL, fromParcel.getTemplateType());
assertTrue(fromParcel instanceof ThumbnailTemplate);
}
@Test
public void testUnparcelingCorrectClass_toggleRange() {
ControlTemplate toParcel = new ToggleRangeTemplate(TEST_ID, mControlButton,

View File

@@ -25,7 +25,6 @@ import android.service.controls.Control
import android.service.controls.actions.ControlAction
import android.service.controls.templates.ControlTemplate
import android.service.controls.templates.TemperatureControlTemplate
import android.service.controls.templates.ThumbnailTemplate
import android.service.controls.templates.ToggleRangeTemplate
import android.service.controls.templates.ToggleTemplate
import android.util.Log
@@ -125,7 +124,6 @@ class ControlViewHolder(
template is ToggleTemplate -> ToggleBehavior::class
template is ToggleRangeTemplate -> ToggleRangeBehavior::class
template is TemperatureControlTemplate -> TemperatureControlBehavior::class
template is ThumbnailTemplate -> StaticBehavior::class
else -> DefaultBehavior::class
}
}

View File

@@ -1,67 +0,0 @@
/*
* 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.systemui.controls.ui
import android.graphics.drawable.ClipDrawable
import android.graphics.drawable.LayerDrawable
import android.service.controls.Control
import android.service.controls.templates.ThumbnailTemplate
import com.android.systemui.R
import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL
/**
* Used for controls that cannot be interacted with. Information is presented to the user
* but no actions can be taken. If using a ThumbnailTemplate, the background image will
* be changed.
*/
class StaticBehavior() : Behavior {
lateinit var control: Control
lateinit var cvh: ControlViewHolder
override fun initialize(cvh: ControlViewHolder) {
this.cvh = cvh
}
override fun bind(cws: ControlWithState) {
this.control = cws.control!!
cvh.status.setText(control.getStatusText())
val ld = cvh.layout.getBackground() as LayerDrawable
val clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable
clipLayer.setLevel(MAX_LEVEL)
cvh.setEnabled(true)
cvh.applyRenderInfo(RenderInfo.lookup(control.getDeviceType(), true))
val template = control.getControlTemplate()
if (template is ThumbnailTemplate) {
cvh.bgExecutor.execute {
// clear the default tinting in favor of only using alpha
val drawable = template.getThumbnail().loadDrawable(cvh.context)
drawable.setTintList(null)
drawable.setAlpha((0.45 * 255).toInt())
cvh.uiExecutor.execute {
val radius = cvh.context.getResources()
.getDimensionPixelSize(R.dimen.control_corner_radius).toFloat()
clipLayer.setDrawable(CornerDrawable(drawable, radius))
}
}
}
}
}