Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d88649d authored by DingYong's avatar DingYong Committed by Josep del Rio
Browse files

Add mic mute keyboard led. (1/2)

Change-Id: Ie3ddd04853bb3471bb60cefd037d5244733046c4
Test: Built, presubmit
parent 16f8e169
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -64,6 +64,12 @@ public final class Light implements Parcelable {
     */
     */
    public static final int LIGHT_TYPE_KEYBOARD_BACKLIGHT = 10003;
    public static final int LIGHT_TYPE_KEYBOARD_BACKLIGHT = 10003;


    /**
     * Type for keyboard microphone mute light.
     * @hide
     */
    public static final int LIGHT_TYPE_KEYBOARD_MIC_MUTE = 10004;

    /**
    /**
     * Capability for lights that could adjust its LED brightness. If the capability is not present
     * 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.
     * the LED can only be turned either on or off.
@@ -92,6 +98,7 @@ public final class Light implements Parcelable {
            LIGHT_TYPE_INPUT,
            LIGHT_TYPE_INPUT,
            LIGHT_TYPE_PLAYER_ID,
            LIGHT_TYPE_PLAYER_ID,
            LIGHT_TYPE_KEYBOARD_BACKLIGHT,
            LIGHT_TYPE_KEYBOARD_BACKLIGHT,
            LIGHT_TYPE_KEYBOARD_MIC_MUTE,
        })
        })
    public @interface LightType {}
    public @interface LightType {}


+7 −0
Original line number Original line Diff line number Diff line
@@ -319,6 +319,9 @@ public class InputManagerService extends IInputManager.Stub
    // Manages Sticky modifier state
    // Manages Sticky modifier state
    private final StickyModifierStateController mStickyModifierStateController;
    private final StickyModifierStateController mStickyModifierStateController;


    // Manages Keyboard microphone mute led
    private final KeyboardLedController mKeyboardLedController;

    // Manages Keyboard modifier keys remapping
    // Manages Keyboard modifier keys remapping
    private final KeyRemapper mKeyRemapper;
    private final KeyRemapper mKeyRemapper;


@@ -468,6 +471,8 @@ public class InputManagerService extends IInputManager.Stub
                        injector.getLooper(), injector.getUEventManager())
                        injector.getLooper(), injector.getUEventManager())
                : new KeyboardBacklightControllerInterface() {};
                : new KeyboardBacklightControllerInterface() {};
        mStickyModifierStateController = new StickyModifierStateController();
        mStickyModifierStateController = new StickyModifierStateController();
        mKeyboardLedController = new KeyboardLedController(mContext, injector.getLooper(),
                mNative);
        mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
        mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
        mPointerIconCache = new PointerIconCache(mContext, mNative);
        mPointerIconCache = new PointerIconCache(mContext, mNative);


@@ -582,6 +587,7 @@ public class InputManagerService extends IInputManager.Stub
        mKeyboardLayoutManager.systemRunning();
        mKeyboardLayoutManager.systemRunning();
        mBatteryController.systemRunning();
        mBatteryController.systemRunning();
        mKeyboardBacklightController.systemRunning();
        mKeyboardBacklightController.systemRunning();
        mKeyboardLedController.systemRunning();
        mKeyRemapper.systemRunning();
        mKeyRemapper.systemRunning();
        mPointerIconCache.systemRunning();
        mPointerIconCache.systemRunning();
    }
    }
@@ -2164,6 +2170,7 @@ public class InputManagerService extends IInputManager.Stub
        dumpDisplayInputPropertiesValues(ipw);
        dumpDisplayInputPropertiesValues(ipw);
        mBatteryController.dump(ipw);
        mBatteryController.dump(ipw);
        mKeyboardBacklightController.dump(ipw);
        mKeyboardBacklightController.dump(ipw);
        mKeyboardLedController.dump(ipw);
    }
    }


    private void dumpAssociations(IndentingPrintWriter pw) {
    private void dumpAssociations(IndentingPrintWriter pw) {
+171 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2024 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.server.input;

import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.hardware.SensorPrivacyManager;
import android.hardware.SensorPrivacyManager.Sensors;
import android.hardware.input.InputManager;
import android.hardware.lights.Light;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.util.IndentingPrintWriter;
import android.util.SparseArray;
import android.view.InputDevice;

import java.io.PrintWriter;
import java.util.Objects;

/**
 * This class is used to control the light of keyboard.
 */
public final class KeyboardLedController implements InputManager.InputDeviceListener {

    private static final String TAG = KeyboardLedController.class.getSimpleName();
    private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
    private static final int MSG_UPDATE_MIC_MUTE_LED_STATE = 2;

    private final Context mContext;
    private final Handler mHandler;
    private final NativeInputManagerService mNative;
    private final SparseArray<InputDevice> mKeyboardsWithMicMuteLed = new SparseArray<>();
    @NonNull
    private InputManager mInputManager;
    @NonNull
    private SensorPrivacyManager mSensorPrivacyManager;
    @NonNull
    private AudioManager mAudioManager;
    private BroadcastReceiver mMicrophoneMuteChangedIntentReceiver =
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    Message msg =  Message.obtain(mHandler, MSG_UPDATE_MIC_MUTE_LED_STATE);
                    mHandler.sendMessage(msg);
                }
            };

    KeyboardLedController(Context context, Looper looper,
            NativeInputManagerService nativeService) {
        mContext = context;
        mNative = nativeService;
        mHandler = new Handler(looper, this::handleMessage);
    }

    private boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_UPDATE_EXISTING_DEVICES:
                for (int deviceId : (int[]) msg.obj) {
                    onInputDeviceAdded(deviceId);
                }
                return true;
            case MSG_UPDATE_MIC_MUTE_LED_STATE:
                updateMicMuteLedState();
                return true;
        }
        return false;
    }

    private void updateMicMuteLedState() {
        // We determine if the microphone is muted by querying both the hardware state of the
        // microphone and the microphone sensor privacy hardware and sensor toggles
        boolean isMicrophoneMute = mAudioManager.isMicrophoneMute()
                || mSensorPrivacyManager.areAnySensorPrivacyTogglesEnabled(Sensors.MICROPHONE);
        int color = isMicrophoneMute ? Color.WHITE : Color.TRANSPARENT;
        for (int i = 0; i < mKeyboardsWithMicMuteLed.size(); i++) {
            InputDevice device = mKeyboardsWithMicMuteLed.valueAt(i);
            if (device != null) {
                int deviceId = device.getId();
                Light light = getKeyboardMicMuteLight(device);
                if (light != null) {
                    mNative.setLightColor(deviceId, light.getId(), color);
                }
            }
        }
    }

    private Light getKeyboardMicMuteLight(InputDevice device) {
        for (Light light : device.getLightsManager().getLights()) {
            if (light.getType() == Light.LIGHT_TYPE_KEYBOARD_MIC_MUTE
                    && light.hasBrightnessControl()) {
                return light;
            }
        }
        return null;
    }

    /** Called when the system is ready for us to start third-party code. */
    public void systemRunning() {
        mSensorPrivacyManager = Objects.requireNonNull(
                mContext.getSystemService(SensorPrivacyManager.class));
        mInputManager = Objects.requireNonNull(mContext.getSystemService(InputManager.class));
        mAudioManager = Objects.requireNonNull(mContext.getSystemService(AudioManager.class));
        mInputManager.registerInputDeviceListener(this, mHandler);
        Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
                mInputManager.getInputDeviceIds());
        mHandler.sendMessage(msg);
        mContext.registerReceiverAsUser(
                mMicrophoneMuteChangedIntentReceiver,
                UserHandle.ALL,
                new IntentFilter(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED),
                null,
                mHandler);
    }

    @Override
    public void onInputDeviceAdded(int deviceId) {
        onInputDeviceChanged(deviceId);
    }

    @Override
    public void onInputDeviceRemoved(int deviceId) {
        mKeyboardsWithMicMuteLed.remove(deviceId);
    }

    @Override
    public void onInputDeviceChanged(int deviceId) {
        InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
        if (inputDevice == null) {
            return;
        }
        if (getKeyboardMicMuteLight(inputDevice) != null) {
            mKeyboardsWithMicMuteLed.put(deviceId, inputDevice);
            Message msg = Message.obtain(mHandler, MSG_UPDATE_MIC_MUTE_LED_STATE);
            mHandler.sendMessage(msg);
        }
    }

    /** Dump the diagnostic information */
    public void dump(PrintWriter pw) {
        IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
        ipw.println(TAG + ": " + mKeyboardsWithMicMuteLed.size() + " keyboard mic mute lights");
        ipw.increaseIndent();
        for (int i = 0; i < mKeyboardsWithMicMuteLed.size(); i++) {
            InputDevice inputDevice = mKeyboardsWithMicMuteLed.valueAt(i);
            ipw.println(i + " " + inputDevice.getName() + ": "
                    + getKeyboardMicMuteLight(inputDevice).toString());
        }
        ipw.decreaseIndent();
    }
}
+6 −0
Original line number Original line Diff line number Diff line
@@ -178,6 +178,7 @@ static struct {
    jfieldID lightTypeInput;
    jfieldID lightTypeInput;
    jfieldID lightTypePlayerId;
    jfieldID lightTypePlayerId;
    jfieldID lightTypeKeyboardBacklight;
    jfieldID lightTypeKeyboardBacklight;
    jfieldID lightTypeKeyboardMicMute;
    jfieldID lightCapabilityBrightness;
    jfieldID lightCapabilityBrightness;
    jfieldID lightCapabilityColorRgb;
    jfieldID lightCapabilityColorRgb;
} gLightClassInfo;
} gLightClassInfo;
@@ -2444,6 +2445,9 @@ static jobject nativeGetLights(JNIEnv* env, jobject nativeImplObj, jint deviceId
        } else if (lightInfo.type == InputDeviceLightType::KEYBOARD_BACKLIGHT) {
        } else if (lightInfo.type == InputDeviceLightType::KEYBOARD_BACKLIGHT) {
            jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
            jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
                                             gLightClassInfo.lightTypeKeyboardBacklight);
                                             gLightClassInfo.lightTypeKeyboardBacklight);
        } else if (lightInfo.type == InputDeviceLightType::KEYBOARD_MIC_MUTE) {
            jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
                                             gLightClassInfo.lightTypeKeyboardMicMute);
        } else {
        } else {
            ALOGW("Unknown light type %d", lightInfo.type);
            ALOGW("Unknown light type %d", lightInfo.type);
            continue;
            continue;
@@ -3176,6 +3180,8 @@ int register_android_server_InputManager(JNIEnv* env) {
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_PLAYER_ID", "I");
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_PLAYER_ID", "I");
    gLightClassInfo.lightTypeKeyboardBacklight =
    gLightClassInfo.lightTypeKeyboardBacklight =
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_KEYBOARD_BACKLIGHT", "I");
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_KEYBOARD_BACKLIGHT", "I");
    gLightClassInfo.lightTypeKeyboardMicMute =
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_TYPE_KEYBOARD_MIC_MUTE", "I");
    gLightClassInfo.lightCapabilityBrightness =
    gLightClassInfo.lightCapabilityBrightness =
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_CAPABILITY_BRIGHTNESS", "I");
            env->GetStaticFieldID(gLightClassInfo.clazz, "LIGHT_CAPABILITY_BRIGHTNESS", "I");
    gLightClassInfo.lightCapabilityColorRgb =
    gLightClassInfo.lightCapabilityColorRgb =
+2 −1
Original line number Original line Diff line number Diff line
@@ -30,7 +30,7 @@ android_test {
        "androidx.test.rules",
        "androidx.test.rules",
        "androidx.test.runner",
        "androidx.test.runner",
        "androidx.test.uiautomator_uiautomator",
        "androidx.test.uiautomator_uiautomator",
        "servicestests-utils",
        "compatibility-device-util-axt",
        "flag-junit",
        "flag-junit",
        "frameworks-base-testutils",
        "frameworks-base-testutils",
        "hamcrest-library",
        "hamcrest-library",
@@ -38,6 +38,7 @@ android_test {
        "mockito-target-minus-junit4",
        "mockito-target-minus-junit4",
        "platform-test-annotations",
        "platform-test-annotations",
        "services.core.unboosted",
        "services.core.unboosted",
        "servicestests-utils",
        "testables",
        "testables",
        "testng",
        "testng",
        "truth",
        "truth",
Loading