/*
* Copyright 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 androidx.wear.input.testing;
import android.content.Context;
import android.graphics.PointF;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.wear.input.WearableButtonsProvider;
import com.google.android.wearable.input.WearableInputDevice;
import java.util.Map;
/**
* A {@link WearableButtonsProvider} suitable for use in tests.
*
* <p>This allows for explicitly specifying which buttons are available for testing, and their
* coordinates. It is intended to be used by passing in a map, mapping between the button keycode
* (typically in the set {@link android.view.KeyEvent#KEYCODE_STEM_PRIMARY}, {@link
* android.view.KeyEvent#KEYCODE_STEM_1}, {@link android.view.KeyEvent#KEYCODE_STEM_2}, or {@link
* android.view.KeyEvent#KEYCODE_STEM_3}) and the location of the button. Take the following
* example:
*
* <pre>
* Map<Integer, TestWearableButtonLocation> buttons = new HashMap<>();
* buttons.put(KEYCODE_STEM_1, new TestWearableButtonLocation(100, 100);
*
* TestWearableButtonsProvider provider = new TestWearableButtonsProvider(buttons);
*
* WearableButtons.setWearableButtonsProvider(provider);
* </pre>
*/
public class TestWearableButtonsProvider implements WearableButtonsProvider {
/**
* Class describing the location of a button on a wearable device. This has two forms; it can
* either store the absolute location of the button, or store both the absolute location of the
* button, and the absolute location when the screen is rotated through 180 degrees.
*/
public static class TestWearableButtonLocation {
private final PointF mLocation;
private final PointF mRotatedLocation;
/**
* Build a button location, with just the default button location.
*
* @param x X coordinate of the button.
* @param y Y coordinate of the button.
*/
public TestWearableButtonLocation(float x, float y) {
mLocation = new PointF(x, y);
mRotatedLocation = null;
}
/**
* Build a button location, with both the default button location, and the location when the
* device is rotated through 180 degrees.
*
* @param x X coordinate of the button.
* @param y Y coordinate of the button.
* @param rotatedX X coordinate of the button when the device is rotated.
* @param rotatedY Y coordinate of the button when the device is rotated.
*/
public TestWearableButtonLocation(float x, float y, float rotatedX, float rotatedY) {
mLocation = new PointF(x, y);
mRotatedLocation = new PointF(rotatedX, rotatedY);
}
/**
* Get the location of this button.
*
* @return A point specifying the location of this button.
*/
@NonNull
public PointF getLocation() {
return mLocation;
}
/**
* Get the location of this button when the device is rotated.
*
* @return A point specifying the location of this button when the device is rotated.
*/
@Nullable
public PointF getRotatedLocation() {
return mRotatedLocation;
}
}
private final Map<Integer, TestWearableButtonLocation> mButtons;
/**
* Build a button provider, which will respond with the provided set of buttons.
*
* @param buttons The buttons returned by this provider.
*/
public TestWearableButtonsProvider(@NonNull Map<Integer, TestWearableButtonLocation> buttons) {
mButtons = buttons;
}
@NonNull
@Override
public Bundle getButtonInfo(@NonNull Context context, int keycode) {
Bundle bundle = new Bundle();
TestWearableButtonLocation location = mButtons.get(keycode);
if (location != null) {
bundle.putFloat(WearableInputDevice.X_KEY, location.getLocation().x);
bundle.putFloat(WearableInputDevice.Y_KEY, location.getLocation().y);
if (location.getRotatedLocation() != null) {
bundle.putFloat(WearableInputDevice.X_KEY_ROTATED, location.getRotatedLocation().x);
bundle.putFloat(WearableInputDevice.Y_KEY_ROTATED, location.getRotatedLocation().y);
}
}
return bundle;
}
@Nullable
@Override
public int[] getAvailableButtonKeyCodes(@NonNull Context context) {
int[] keys = new int[mButtons.size()];
int i = 0;
for (Integer keycode : mButtons.keySet()) {
keys[i++] = keycode;
}
return keys;
}
}