Merge "Add capabilities to android.hardware.lights.Light." into sc-dev

This commit is contained in:
Chris Ye
2021-05-24 17:34:58 +00:00
committed by Android (Google) Code Review
9 changed files with 207 additions and 112 deletions

View File

@@ -18989,12 +18989,15 @@ package android.hardware.lights {
method @NonNull public String getName();
method public int getOrdinal();
method public int getType();
method public boolean hasBrightnessControl();
method public boolean hasRgbControl();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.lights.Light> CREATOR;
field public static final int LIGHT_TYPE_INPUT_PLAYER_ID = 10002; // 0x2712
field public static final int LIGHT_TYPE_INPUT_RGB = 10003; // 0x2713
field public static final int LIGHT_TYPE_INPUT_SINGLE = 10001; // 0x2711
field public static final int LIGHT_CAPABILITY_BRIGHTNESS = 1; // 0x1
field public static final int LIGHT_CAPABILITY_RGB = 0; // 0x0
field public static final int LIGHT_TYPE_INPUT = 10001; // 0x2711
field public static final int LIGHT_TYPE_MICROPHONE = 8; // 0x8
field public static final int LIGHT_TYPE_PLAYER_ID = 10002; // 0x2712
}
public final class LightState implements android.os.Parcelable {
@@ -19026,7 +19029,7 @@ package android.hardware.lights {
public final class LightsRequest {
method @NonNull public java.util.List<android.hardware.lights.LightState> getLightStates();
method @NonNull public java.util.List<java.lang.Integer> getLights();
method @NonNull public java.util.Map<java.lang.Integer,android.hardware.lights.LightState> getLightsAndStates();
method @NonNull public java.util.Map<android.hardware.lights.Light,android.hardware.lights.LightState> getLightsAndStates();
}
public static final class LightsRequest.Builder {

View File

@@ -1204,6 +1204,10 @@ package android.hardware.input {
package android.hardware.lights {
public final class Light implements android.os.Parcelable {
method public int getCapabilities();
}
public abstract class LightsManager {
method @NonNull public abstract android.hardware.lights.LightsManager.LightsSession openSession(int);
}

View File

@@ -19,6 +19,7 @@ package android.hardware.lights;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -41,36 +42,52 @@ public final class Light implements Parcelable {
/**
* Type for lights that indicate a monochrome color LED light.
*/
public static final int LIGHT_TYPE_INPUT_SINGLE = 10001;
public static final int LIGHT_TYPE_INPUT = 10001;
/**
* Type for lights that indicate a group of LED lights representing player ID.
* Player ID lights normally present on game controllers are lights that consist of a row of
* Type for lights that indicate a group of LED lights representing player id.
* Player id lights normally present on game controllers are lights that consist of a row of
* LEDs.
* During multi-player game, the player ID for the current game controller is represented by
* During multi-player game, the player id for the current game controller is represented by
* one of the LED that is lit according to its position in the row.
*/
public static final int LIGHT_TYPE_INPUT_PLAYER_ID = 10002;
public static final int LIGHT_TYPE_PLAYER_ID = 10002;
/**
* Type for lights that indicate a color LED light.
* Capability for lights that could adjust its LED brightness. If the capability is not present
* the led can only be turned either on or off.
*/
public static final int LIGHT_TYPE_INPUT_RGB = 10003;
public static final int LIGHT_CAPABILITY_BRIGHTNESS = 1 << 0;
/**
* Capability for lights that has red, green and blue LEDs to control the light's color.
*/
public static final int LIGHT_CAPABILITY_RGB = 0 << 1;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"LIGHT_TYPE_"},
value = {
LIGHT_TYPE_INPUT_PLAYER_ID,
LIGHT_TYPE_INPUT_SINGLE,
LIGHT_TYPE_INPUT_RGB,
LIGHT_TYPE_MICROPHONE,
LIGHT_TYPE_INPUT,
LIGHT_TYPE_PLAYER_ID,
})
public @interface LightType {}
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(flag = true, prefix = {"LIGHT_CAPABILITY_"},
value = {
LIGHT_CAPABILITY_BRIGHTNESS,
LIGHT_CAPABILITY_RGB,
})
public @interface LightCapability {}
private final int mId;
private final String mName;
private final int mOrdinal;
private final int mType;
private final String mName;
private final int mCapabilities;
/**
* Creates a new light with the given data.
@@ -78,7 +95,7 @@ public final class Light implements Parcelable {
* @hide
*/
public Light(int id, int ordinal, int type) {
this(id, ordinal, type, "Light");
this(id, "Light", ordinal, type, 0);
}
/**
@@ -86,27 +103,30 @@ public final class Light implements Parcelable {
*
* @hide
*/
public Light(int id, int ordinal, int type, String name) {
public Light(int id, String name, int ordinal, int type, int capabilities) {
mId = id;
mName = name;
mOrdinal = ordinal;
mType = type;
mName = name;
mCapabilities = capabilities;
}
private Light(@NonNull Parcel in) {
mId = in.readInt();
mName = in.readString();
mOrdinal = in.readInt();
mType = in.readInt();
mName = in.readString();
mCapabilities = in.readInt();
}
/** Implement the Parcelable interface */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mId);
dest.writeString(mName);
dest.writeInt(mOrdinal);
dest.writeInt(mType);
dest.writeString(mName);
dest.writeInt(mCapabilities);
}
/** Implement the Parcelable interface */
@@ -131,7 +151,8 @@ public final class Light implements Parcelable {
public boolean equals(@Nullable Object obj) {
if (obj instanceof Light) {
Light light = (Light) obj;
return mId == light.mId && mOrdinal == light.mOrdinal && mType == light.mType;
return mId == light.mId && mOrdinal == light.mOrdinal && mType == light.mType
&& mCapabilities == light.mCapabilities;
}
return false;
}
@@ -143,7 +164,8 @@ public final class Light implements Parcelable {
@Override
public String toString() {
return "[Name=" + mName + " Id=" + mId + " Type=" + mType + " Ordinal=" + mOrdinal + "]";
return "[Name=" + mName + " Id=" + mId + " Type=" + mType + " Capabilities="
+ mCapabilities + " Ordinal=" + mOrdinal + "]";
}
/**
@@ -177,7 +199,35 @@ public final class Light implements Parcelable {
/**
* Returns the logical type of the light.
*/
public @LightsManager.LightType int getType() {
public @LightType int getType() {
return mType;
}
/**
* Returns the capabilities of the light.
* @hide
*/
@TestApi
public @LightCapability int getCapabilities() {
return mCapabilities;
}
/**
* Check whether the light has led brightness control.
*
* @return True if the hardware can control the led brightness, otherwise false.
*/
public boolean hasBrightnessControl() {
return (mCapabilities & LIGHT_CAPABILITY_BRIGHTNESS) == LIGHT_CAPABILITY_BRIGHTNESS;
}
/**
* Check whether the light has RGB led control.
*
* @return True if the hardware can control the RGB led, otherwise false.
*/
public boolean hasRgbControl() {
return (mCapabilities & LIGHT_CAPABILITY_RGB) == LIGHT_CAPABILITY_RGB;
}
}

View File

@@ -43,7 +43,7 @@ public final class LightState implements Parcelable {
* of RBG color or monochrome color.
*
* @param color the desired color and intensity in ARGB format.
* @deprecated this has been replaced with {@link android.hardware.lights.LightState#forColor }
* @deprecated this has been replaced with {@link android.hardware.lights.LightState.Builder }
* @hide
*/
@Deprecated
@@ -54,8 +54,8 @@ public final class LightState implements Parcelable {
/**
* Creates a new LightState with the desired color and intensity, and the player Id.
* Player Id will only be applied on Light type
* {@link android.hardware.lights.Light#LIGHT_TYPE_INPUT_PLAYER_ID}
* Player Id will only be applied on Light with type
* {@link android.hardware.lights.Light#LIGHT_TYPE_PLAYER_ID}
*
* @param color the desired color and intensity in ARGB format.
* @hide
@@ -94,8 +94,8 @@ public final class LightState implements Parcelable {
}
/**
* Set the desired player id of the LightState Builder, for a light of type
* {@link android.hardware.lights.Light#LIGHT_TYPE_INPUT_PLAYER_ID}.
* Set the desired player id of the LightState Builder, for a light with type
* {@link android.hardware.lights.Light#LIGHT_TYPE_PLAYER_ID}.
*
* @param playerId the desired player id.
* @return The {@link LightState.Builder} object contains the player id.
@@ -134,15 +134,16 @@ public final class LightState implements Parcelable {
/**
* Returns the color and intensity associated with this LightState.
* @return the color and intensity in ARGB format. The A channel is ignored. return 0 when
* calling LightsManager.getLightState with LIGHT_TYPE_INPUT_PLAYER_ID.
* calling LightsManager.getLightState with
* {@link android.hardware.lights.Light#LIGHT_TYPE_PLAYER_ID}.
*/
public @ColorInt int getColor() {
return mColor;
}
/**
* Returns the player ID associated with this LightState for Light type
* {@link android.hardware.lights.Light#LIGHT_TYPE_INPUT_PLAYER_ID},
* Returns the player ID associated with this LightState for Light with type
* {@link android.hardware.lights.Light#LIGHT_TYPE_PLAYER_ID},
* or 0 for other types.
* @return the player ID.
*/

View File

@@ -18,12 +18,10 @@ package android.hardware.lights;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.util.SparseArray;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -34,58 +32,48 @@ import java.util.Map;
public final class LightsRequest {
/** Visible to {@link LightsManager.Session}. */
final int[] mLightIds;
/** Visible to {@link LightsManager.Session}. */
final LightState[] mLightStates;
final Map<Light, LightState> mRequests = new HashMap<>();
final List<Integer> mLightIds = new ArrayList<>();
final List<LightState> mLightStates = new ArrayList<>();
/**
* Can only be constructed via {@link LightsRequest.Builder#build()}.
*/
private LightsRequest(SparseArray<LightState> changes) {
final int n = changes.size();
mLightIds = new int[n];
mLightStates = new LightState[n];
for (int i = 0; i < n; i++) {
mLightIds[i] = changes.keyAt(i);
mLightStates[i] = changes.valueAt(i);
private LightsRequest(Map<Light, LightState> requests) {
mRequests.putAll(requests);
List<Light> lights = new ArrayList<Light>(mRequests.keySet());
for (int i = 0; i < lights.size(); i++) {
final Light light = lights.get(i);
mLightIds.add(i, light.getId());
mLightStates.add(i, mRequests.get(light));
}
}
/**
* Get a list of Light as ids. The ids will returned in same order as the lights passed
* in Builder.
* Get a list of Light as ids.
*
* @return List of light ids
* @return List of light ids in the request.
*/
public @NonNull List<Integer> getLights() {
List<Integer> lightList = new ArrayList<Integer>(mLightIds.length);
for (int i = 0; i < mLightIds.length; i++) {
lightList.add(mLightIds[i]);
}
return lightList;
return mLightIds;
}
/**
* Get a list of LightState. The states will be returned in same order as the light states
* passed in Builder.
* Get a list of LightState. The states will be returned in same order as the light ids
* returned by {@link #getLights()}.
*
* @return List of light states
*/
public @NonNull List<LightState> getLightStates() {
return Arrays.asList(mLightStates);
return mLightStates;
}
/**
* Get a map of light ids and states. The map will contain all the light ids as keys and
* Get a map of lights and states. The map will contain all the lights as keys and
* the corresponding LightState requested as values.
*/
public @NonNull Map<Integer, LightState> getLightsAndStates() {
Map<Integer, LightState> map = new HashMap<>();
for (int i = 0; i < mLightIds.length; i++) {
map.put(mLightIds[i], mLightStates[i]);
}
return map;
public @NonNull Map<Light, LightState> getLightsAndStates() {
return mRequests;
}
/**
@@ -93,8 +81,7 @@ public final class LightsRequest {
*/
public static final class Builder {
private final SparseArray<LightState> mChanges = new SparseArray<>();
final Map<Light, LightState> mChanges = new HashMap<>();
/**
* Overrides the color and intensity of a given light.
*
@@ -104,7 +91,7 @@ public final class LightsRequest {
public @NonNull Builder addLight(@NonNull Light light, @NonNull LightState state) {
Preconditions.checkNotNull(light);
Preconditions.checkNotNull(state);
mChanges.put(light.getId(), state);
mChanges.put(light, state);
return this;
}
@@ -129,7 +116,7 @@ public final class LightsRequest {
*/
public @NonNull Builder clearLight(@NonNull Light light) {
Preconditions.checkNotNull(light);
mChanges.put(light.getId(), null);
mChanges.put(light, null);
return this;
}

View File

@@ -163,7 +163,17 @@ public final class SystemLightsManager extends LightsManager {
Preconditions.checkNotNull(request);
if (!mClosed) {
try {
mService.setLightStates(getToken(), request.mLightIds, request.mLightStates);
List<Integer> idList = request.getLights();
List<LightState> stateList = request.getLightStates();
int[] ids = new int[idList.size()];
for (int i = 0; i < idList.size(); i++) {
ids[i] = idList.get(i);
}
LightState[] states = new LightState[stateList.size()];
for (int i = 0; i < stateList.size(); i++) {
states[i] = stateList.get(i);
}
mService.setLightStates(getToken(), ids, states);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -23,6 +23,8 @@ import static com.google.common.truth.Truth.assertThat;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -128,9 +130,12 @@ public class InputDeviceLightsManagerTest {
assertNotNull(device);
Light[] mockedLights = {
new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_SINGLE),
new Light(2 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
new Light(3 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_PLAYER_ID)
new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_BRIGHTNESS),
new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB),
new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
0 /* capabilities */)
};
mockLights(mockedLights);
@@ -146,10 +151,14 @@ public class InputDeviceLightsManagerTest {
assertNotNull(device);
Light[] mockedLights = {
new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
new Light(2 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
new Light(3 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
new Light(4 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB)
new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB),
new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB),
new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB),
new Light(4 /* id */, "Light4", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB)
};
mockLights(mockedLights);
@@ -194,9 +203,12 @@ public class InputDeviceLightsManagerTest {
assertNotNull(device);
Light[] mockedLights = {
new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_PLAYER_ID),
new Light(2 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_SINGLE),
new Light(3 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_RGB),
new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_PLAYER_ID,
0 /* capabilities */),
new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB | Light.LIGHT_CAPABILITY_BRIGHTNESS),
new Light(3 /* id */, "Light3", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_BRIGHTNESS)
};
mockLights(mockedLights);
@@ -226,24 +238,43 @@ public class InputDeviceLightsManagerTest {
verify(mIInputManagerMock).closeLightSession(eq(DEVICE_ID), eq(token));
}
@Test
public void testLightCapabilities() throws Exception {
Light light = new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
Light.LIGHT_CAPABILITY_RGB | Light.LIGHT_CAPABILITY_BRIGHTNESS);
assertThat(light.getType()).isEqualTo(Light.LIGHT_TYPE_INPUT);
assertThat(light.getCapabilities()).isEqualTo(Light.LIGHT_CAPABILITY_RGB
| Light.LIGHT_CAPABILITY_BRIGHTNESS);
assertTrue(light.hasBrightnessControl());
assertTrue(light.hasRgbControl());
}
@Test
public void testLightsRequest() throws Exception {
Light light = new Light(1 /* id */, 0 /* ordinal */, Light.LIGHT_TYPE_INPUT_PLAYER_ID);
LightState state = new LightState(0xf1);
LightsRequest request = new Builder().addLight(light, state).build();
Light light1 = new Light(1 /* id */, "Light1", 0 /* ordinal */, Light.LIGHT_TYPE_INPUT,
0 /* capabilities */);
Light light2 = new Light(2 /* id */, "Light2", 0 /* ordinal */, Light.LIGHT_TYPE_PLAYER_ID,
0 /* capabilities */);
LightState state1 = new LightState(0xf1);
LightState state2 = new LightState(0xf2, PLAYER_ID);
LightsRequest request = new Builder().addLight(light1, state1)
.addLight(light2, state2).build();
// Covers the LightsRequest.getLights
assertThat(request.getLights().size()).isEqualTo(1);
assertThat(request.getLights().size()).isEqualTo(2);
assertThat(request.getLights().get(0)).isEqualTo(1);
assertThat(request.getLights().get(1)).isEqualTo(2);
// Covers the LightsRequest.getLightStates
assertThat(request.getLightStates().size()).isEqualTo(1);
assertThat(request.getLightStates().get(0)).isEqualTo(state);
assertThat(request.getLightStates().size()).isEqualTo(2);
assertThat(request.getLightStates().get(0)).isEqualTo(state1);
assertThat(request.getLightStates().get(1)).isEqualTo(state2);
// Covers the LightsRequest.getLightsAndStates
assertThat(request.getLightsAndStates().size()).isEqualTo(1);
assertThat(request.getLightsAndStates().containsKey(1)).isTrue();
assertThat(request.getLightsAndStates().get(1)).isEqualTo(state);
assertThat(request.getLightsAndStates().size()).isEqualTo(2);
assertThat(request.getLightsAndStates().containsKey(light1)).isTrue();
assertThat(request.getLightsAndStates().get(light1)).isEqualTo(state1);
assertThat(request.getLightsAndStates().get(light2)).isEqualTo(state2);
}
}

View File

@@ -2479,15 +2479,12 @@ public class InputManagerService extends IInputManager.Stub
Slog.d(TAG, "setLightStateInternal device " + deviceId + " light " + light
+ "lightState " + lightState);
}
if (light.getType() == Light.LIGHT_TYPE_INPUT_PLAYER_ID) {
if (light.getType() == Light.LIGHT_TYPE_PLAYER_ID) {
nativeSetLightPlayerId(mPtr, deviceId, light.getId(), lightState.getPlayerId());
} else if (light.getType() == Light.LIGHT_TYPE_INPUT_SINGLE
|| light.getType() == Light.LIGHT_TYPE_INPUT_RGB) {
} else {
// Set ARGB format color to input device light
// Refer to https://developer.android.com/reference/kotlin/android/graphics/Color
nativeSetLightColor(mPtr, deviceId, light.getId(), lightState.getColor());
} else {
Slog.e(TAG, "setLightStates for unsupported light type " + light.getType());
}
}

View File

@@ -160,9 +160,10 @@ static struct {
static struct {
jclass clazz;
jmethodID constructor;
jfieldID lightTypeSingle;
jfieldID lightTypeInput;
jfieldID lightTypePlayerId;
jfieldID lightTypeRgb;
jfieldID lightCapabilityBrightness;
jfieldID lightCapabilityRgb;
} gLightClassInfo;
static struct {
@@ -1996,25 +1997,34 @@ static jobject nativeGetLights(JNIEnv* env, jclass clazz, jlong ptr, jint device
continue;
}
jint jTypeId = 0;
if (lightInfo->type == InputDeviceLightType::SINGLE) {
jTypeId =
env->GetStaticIntField(gLightClassInfo.clazz, gLightClassInfo.lightTypeSingle);
} else if (lightInfo->type == InputDeviceLightType::PLAYER_ID) {
jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightTypePlayerId);
jint jTypeId =
env->GetStaticIntField(gLightClassInfo.clazz, gLightClassInfo.lightTypeInput);
jint jCapability = 0;
if (lightInfo->type == InputDeviceLightType::MONO) {
jCapability = env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityBrightness);
} else if (lightInfo->type == InputDeviceLightType::RGB ||
lightInfo->type == InputDeviceLightType::MULTI_COLOR) {
jTypeId = env->GetStaticIntField(gLightClassInfo.clazz, gLightClassInfo.lightTypeRgb);
jCapability =
env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityBrightness) |
env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightCapabilityRgb);
} else if (lightInfo->type == InputDeviceLightType::PLAYER_ID) {
jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
gLightClassInfo.lightTypePlayerId);
} else {
ALOGW("Unknown light type %d", lightInfo->type);
continue;
}
ScopedLocalRef<jobject>
lightObj(env,
env->NewObject(gLightClassInfo.clazz, gLightClassInfo.constructor,
(jint)lightInfo->id, (jint)lightInfo->ordinal, jTypeId,
env->NewStringUTF(lightInfo->name.c_str())));
ScopedLocalRef<jobject> lightObj(env,
env->NewObject(gLightClassInfo.clazz,
gLightClassInfo.constructor,
static_cast<jint>(lightInfo->id),
env->NewStringUTF(lightInfo->name.c_str()),
static_cast<jint>(lightInfo->ordinal),
jTypeId, jCapability));
// Add light object to list
env->CallBooleanMethod(jLights, gArrayListClassInfo.add, lightObj.get());
}
@@ -2540,15 +2550,17 @@ int register_android_server_InputManager(JNIEnv* env) {
FIND_CLASS(gLightClassInfo.clazz, "android/hardware/lights/Light");
gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
GET_METHOD_ID(gLightClassInfo.constructor, gLightClassInfo.clazz, "<init>",
"(IIILjava/lang/String;)V");
"(ILjava/lang/String;III)V");
gLightClassInfo.clazz = jclass(env->NewGlobalRef(gLightClassInfo.clazz));
gLightClassInfo.lightTypeSingle =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT_SINGLE", "I");
gLightClassInfo.lightTypeInput =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT", "I");
gLightClassInfo.lightTypePlayerId =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT_PLAYER_ID", "I");
gLightClassInfo.lightTypeRgb =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_INPUT_RGB", "I");
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_PLAYER_ID", "I");
gLightClassInfo.lightCapabilityBrightness =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_CAPABILITY_BRIGHTNESS", "I");
gLightClassInfo.lightCapabilityRgb =
env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_CAPABILITY_RGB", "I");
// ArrayList
FIND_CLASS(gArrayListClassInfo.clazz, "java/util/ArrayList");