powerkey 到亮屏/关屏流程

/**********************************************************************************/
目标:
/**********************************************************************************/
1. 关屏模式下:按下powerKey亮屏的过程:
2. 亮屏模式下:按下powerKey 出现关机界面的过程
3. 亮屏模式下:长按键,重启的过程
4. 关屏模式下:长按键,重启的过程


/**********************************************************************************/
inputManaerService的初始化过程
frameworks/base/services/java/com/android/server/SystemServer.java
    private void startOtherServices() {
            Slog.i(TAG, "Input Manager");
            // xxx MOD:
            // inputManager = new InputManagerService(context);
            inputManager = new xxxInputManagerService(context, null);


            Slog.i(TAG, "Window Manager");
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);


            mActivityManagerService.setWindowManager(wm);


            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            inputManager.start();


            try {
                Slog.i(TAG, "Wired Accessory Manager");
                // Listen for wired headset changes
                inputManager.setWiredAccessoryCallbacks(
                        new WiredAccessoryManager(context, inputManager));
            } catch (Throwable e) {
                reportWtf("starting WiredAccessoryManager", e);
            }
}


/**********************************************************************************/
xxx/frameworks/base/services/java/com/android/server/input/xxxInputManagerService.java
public class xxxInputManagerService extends xxxBaseInputManagerService {


    private Context mContext;


    public xxxInputManagerService(Context context, Handler handler) {
        super(context, handler);
        mContext = context;
    }


    @Override
    public void start() {
        super.start();
        HandyMode.initialize(mContext, this);
    }
}


xxx/frameworks/base/services/java/com/android/server/input/xxxBaseInputManagerService.java
public class xxxBaseInputManagerService extends InputManagerService {


    public xxxBaseInputManagerService(Context context, Handler handler) {
        super(context, handler);
    }
}


/**********************************************************************************/
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
/*
 * Wraps the C++ InputManager and provides its callbacks.
 */
public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    static final String TAG = "InputManager";
    private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);
    private static native void nativeStart(long ptr);
}


/**********************************************************************************/
frameworks/base/core/java/android/hardware/input/IInputManager.aidl
/** @hide */
interface IInputManager {
    // Gets input device information.
    InputDevice getInputDevice(int deviceId);
    int[] getInputDeviceIds();
}


service的名字在那个文件定义的?
frameworks/base/core/java/android/content/Context.java
    /**
     * Use with {@link #getSystemService} to retrieve a
     * {@link android.hardware.input.InputManager} for interacting with input devices.
     *
     * @see #getSystemService
     * @see android.hardware.input.InputManager
     */
    public static final String INPUT_SERVICE = "input";


frameworks/base/core/java/android/hardware/input/


InputManagerService.java的构造函数:
    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());


        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());


        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }


    private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);




/**********************************************************************************/
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }


    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}


NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();


    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);


    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
    }
    mInteractive = true;


    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}


/**********************************************************************************/
frameworks/native/services/inputflinger/


EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
}


InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}


InputManager::InputManager(
        const sp<InputReaderInterface>& reader,
        const sp<InputDispatcherInterface>& dispatcher) :
        mReader(reader),
        mDispatcher(dispatcher) {
    initialize();
}




void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}


/**********************************************************************************/
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);


        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);


        registerPointerSpeedSettingObserver();
        registerShowTouchesSettingObserver();


        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                updatePointerSpeedFromSettings();
                updateShowTouchesFromSettings();
            }
        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);


        updatePointerSpeedFromSettings();
        updateShowTouchesFromSettings();
    }


frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);


    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}


status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);


    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);




    return OK;
}


/**********************************************************************************/
1. 关屏模式下:按下powerKey亮屏的过程
/**********************************************************************************/
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;


    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);


    { // acquire lock
        AutoMutex _l(mLock);


        if (count) {
            processEventsLocked(mEventBuffer, count);
        }


    } // release lock




    // Flush queued events out to the listener.
    mQueuedListener->flush();
}




struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};


/*
 * A raw event as retrieved from the EventHub.
 */
struct RawEvent {
    nsecs_t when;
    int32_t deviceId;
    int32_t type;
    int32_t code;
    int32_t value;
};
从input_event 转换成 raw_event: 数据成员多出了 deviceID:
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    
    struct input_event readBuffer[bufferSize];
    RawEvent* event = buffer;
            Device* device = mDevices.valueAt(deviceIndex);
            if (eventItem.events & EPOLLIN) {
                int32_t readSize = read(device->fd, readBuffer,
                        sizeof(struct input_event) * capacity);


                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
}


void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) ->
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
InputDevice* device = mDevices.valueAt(deviceIndex);
device->process(rawEvents, count);[转换为InputDevice]


void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    size_t numMappers = mMappers.size();
    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                mapper->process(rawEvent); [这里的mapper是分别处理某种类型的input event]
            }
    }
}


下面已PowerKey为例:
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EV_KEY: {
        int32_t scanCode = rawEvent->code; [所说的 scanCode 就是来着input event,rawEent的code]
        int32_t usageCode = mCurrentHidUsage;
        mCurrentHidUsage = 0;


        if (isKeyboardOrGamepadKey(scanCode)) {
            int32_t keyCode;
            uint32_t flags;
            if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
                keyCode = AKEYCODE_UNKNOWN;
                flags = 0;
            }
            processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
        }
        break;
    }



这里说的 getKeyCharacterMap and keyLayoutMap 分别是什么意思?
status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
        int32_t* outKeycode, uint32_t* outFlags) const {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);


    if (device) {
        // Check the key character map first.
        sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
        if (kcm != NULL) {
            if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
                *outFlags = 0;
                return NO_ERROR;
            }
        }


        // Check the key layout next.
        if (device->keyMap.haveKeyLayout()) {
            if (!device->keyMap.keyLayoutMap->mapKey(
                    scanCode, usageCode, outKeycode, outFlags)) {
                return NO_ERROR;
            }
        }
    }


    *outKeycode = 0;
    *outFlags = 0;
    return NAME_NOT_FOUND;
}


这里的 mapKey是那个函数实现的?最终有生成了个 keyCode?
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
    getListener()->notifyKey(&args);
}


/* Superclass of all input event argument objects */
struct NotifyArgs {
    virtual ~NotifyArgs() { }
    virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
};


数据结构有转换为 NotifyArgs
/* Describes a key event. */
struct NotifyKeyArgs : public NotifyArgs {
    nsecs_t eventTime;
    int32_t deviceId;
    uint32_t source;
    uint32_t policyFlags;
    int32_t action;
    int32_t flags;
    int32_t keyCode;
    int32_t scanCode;
    int32_t metaState;
    nsecs_t downTime;
----
}


void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    KeyEvent event;
    event.initialize(args->deviceId, args->source, args->action,
            flags, keyCode, args->scanCode, metaState, 0,
            args->downTime, args->eventTime);


    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
}


KeyEvent是个class了


mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java


    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");


void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
        uint32_t& policyFlags) {
    // Policy:
    // - Ignore untrusted events and pass them along.
    // - Ask the window manager what to do with normal events and trusted injected events.
    // - For normal events wake and brighten the screen if currently off or dim.
    bool interactive = mInteractive.load();


    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
        nsecs_t when = keyEvent->getEventTime();
        JNIEnv* env = jniEnv();
        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
        jint wmActions;
        if (keyEventObj) {
            wmActions = env->CallIntMethod(mServiceObj,
                    gServiceClassInfo.interceptKeyBeforeQueueing,
                    keyEventObj, policyFlags);
            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
                wmActions = 0;
            }
            android_view_KeyEvent_recycle(env, keyEventObj);
            env->DeleteLocalRef(keyEventObj);
        } 
        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
    }
}




frameworks/native/include/input/InputDevice.h
/*
 * Describes the characteristics and capabilities of an input device.
 */
/*
 * Describes the characteristics and capabilities of an input device.
 */
class InputDeviceInfo {
public:
    InputDeviceInfo();
    InputDeviceInfo(const InputDeviceInfo& other);
}


/**********************************************************************************/
按键处理过程


frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    // Native callback.
    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
    }


frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
    /* Provides an opportunity for the window manager policy to intercept early key
     * processing as soon as the key has been read from the device. */
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
    }



frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    /** {@inheritDoc} */
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
  }
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
        @Override // Binder call
        public void wakeUp(long eventTime, String reason, String opPackageName) {
            if (eventTime > SystemClock.uptimeMillis()) {
                throw new IllegalArgumentException("event time must not be in the future");
            }


            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);


            final int uid = Binder.getCallingUid();
            final long ident = Binder.clearCallingIdentity();
            try {
                wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
            int opUid) {
        synchronized (mLock) {
            if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
                updatePowerStateLocked();
            }
        }
    }


/**********************************************************************************/
输入设备的创建过程
/**********************************************************************************/
这和EventHub里的device有什么不同?
class EventHub : public EventHubInterface
{
    struct Device {
        Device* next;


        int fd; // may be -1 if device is virtual
        const int32_t id;
        const String8 path;
        const InputDeviceIdentifier identifier;
     }
}


KeyedVector<int32_t, Device*> mDevices;


创建EventHub对象时:mNeedToScanDevices(true)
EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
}




size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }


}


遍历路径下每个文件的方法:参考文件:
frameworks/native/services/inputflinger/EventHub.cpp的函数:status_t EventHub::scanDirLocked(const char *dirname)


/**********************************************************************************/
2. 亮屏模式下:按下powerKey 出现关机界面的过程
/**********************************************************************************/
[    5196.839152] /dev/input/event0: EV_KEY       KEY_POWER            DOWN                
[    5196.839152] /dev/input/event0: EV_SYN       SYN_REPORT           00000000            
[    5198.226475] /dev/input/event0: EV_KEY       KEY_POWER            UP 


frameworks/base/services/core/java/com/android/server/GestureLauncherService.java
    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
}


frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
        GestureLauncherService gestureService = LocalServices.getService(
                GestureLauncherService.class);
        boolean gesturedServiceIntercepted = false;
        if (gestureService != null) {
            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive);
        }
     }


frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        // Handle special keys.
        switch (keyCode) {
            case KeyEvent.KEYCODE_POWER: {
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    interceptPowerKeyDown(event, interactive);
                } else {
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 中,当幕关闭后,设备会进入睡眠模式以节省电量。在睡眠模式下,应用程序的活动将被暂停或停止。要使您的应用程序在幕关闭后继续运行并接收信息,您可以使用以下两种方法之一: 1. 使用 WakeLock WakeLock 是一种锁定机制,它允许您在设备进入睡眠模式时保持应用程序处于活动状态。这意味着您的应用程序将继续在后台运行,并且您可以接收信息、数据和通知。 使用 WakeLock 需要注意两点: - 使用 WakeLock 可能会影响设备的电池寿命。 - 不要忘记在应用程序不需要使用 WakeLock 时释放它。 以下是使用 WakeLock 的代码示例: ``` PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock"); wakeLock.acquire(); ``` 2. 使用 Foreground Service 前台服务是一种长时间运行的服务,它通常与用户正在进行的活动相关联。在运行前台服务时,应用程序将继续在后台运行,并且您可以接收信息、数据和通知。 使用前台服务需要注意: - 前台服务将显示一个通知,告诉用户应用程序正在运行。 - 前台服务将在设备的电池寿命方面产生一些影响。 以下是使用前台服务的代码示例: ``` public class MyService extends Service { private static final int NOTIFICATION_ID = 1; @Override public int onStartCommand(Intent intent, int flags, int startId) { Notification notification = new Notification.Builder(this) .setContentTitle("My App") .setContentText("Running in background") .setSmallIcon(R.drawable.icon) .build(); startForeground(NOTIFICATION_ID, notification); // Your code here return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值