admin管理员组文章数量:1660331
一、kernel部分主要发按键信息到android上层。
diff --git a/kernel/drivers/misc/key/reset_key.c b/kernel-4.14/drivers/misc/key/reset_key.c
index 127319a29fa..8d954fc28c5 100755
--- a/kernel/drivers/misc/key/reset_key.c
+++ b/kernel/drivers/misc/key/reset_key.c
@@ -12,12 +12,14 @@
#include <linux/jiffies.h>
#include <linux/reset.h>
#include <linux/reboot.h>
-
+#include <linux/input.h>
+#include <linux/miscdevice.h>
struct reset_key {
struct device_node *nd;
int reset_gpio;
unsigned int irq;
struct delayed_work rest_work;
+ struct input_dev *reset_key_dev ;
};
struct reset_key key;
@@ -28,39 +30,53 @@ struct file_operations reset_key_fops = {
struct miscdevice reset_key_misc = {
.minor = MISC_DYNAMIC_MINOR,
- .name = "reset_key",
- .fops = &reset_key_fops,
+ .name = "reset_key",
+ .fops = &reset_key_fops,
};
void rest_work_func(struct work_struct *work)
{
- int value = 0;
-
+ int value = 0 ;
+ static int key_is_down = 0;
+ disable_irq(key.irq);
value = gpio_get_value(key.reset_gpio);
- printk("[%s] value = %d\n",__func__,value);
+ printk(" [%s] value = %d irq=%d\n",__func__,value,key.irq);
if(1 == value)
{
// orderly_reboot();
- kernel_restart(NULL);
+ // kernel_restart(NULL);
// 重置
// reset_control_reset(struct reset_control *rstc);
- irq_set_irq_type(key.irq,IRQF_TRIGGER_FALLING);
+ // test_temp = irq_set_irq_type(key.irq,IRQ_TYPE_LEVEL_LOW);
+ if(key_is_down){
+ input_report_key(key.reset_key_dev, KEY_F10, 0);
+ input_sync(key.reset_key_dev);
+ }
+ key_is_down = 0;
printk("[%s] if value = %d\n",__func__,value);
}
else
{
// orderly_reboot();
- irq_set_irq_type(key.irq,IRQF_TRIGGER_RISING);
+ // test_temp = irq_set_irq_type(key.irq,IRQ_TYPE_LEVEL_HIGH);
+ if(key_is_down == 0){
+ input_report_key(key.reset_key_dev, KEY_F10, 1);
+ input_sync(key.reset_key_dev);
+ key_is_down = 1;
+ }
+
printk("[%s] else value = %d\n",__func__,value);
}
+ enable_irq(key.irq);
// orderly_reboot();
}
irqreturn_t reset_key_irq_handler(int data, void *arg)
{
- schedule_delayed_work(&key.rest_work,msecs_to_jiffies(20));
+ schedule_delayed_work(&key.rest_work, msecs_to_jiffies(50));
+
// schedule_work 结构体名不一样
return IRQ_HANDLED;
}
@@ -93,14 +109,15 @@ int reset_key_probe(struct platform_device *dev)
printk("gpio_request failed\n");
return -1;
}
-
+gpio_direction_input(key.reset_gpio);
// INIT_WORK(&key.rest_work,rest_work_func);
INIT_DELAYED_WORK(&key.rest_work,rest_work_func);
//中断注册 中断下文用工作队列
key.irq = irq_of_parse_and_map(key.nd,0);
- ret = request_irq(key.irq,reset_key_irq_handler,IRQF_TRIGGER_FALLING,
+ ret = request_irq(key.irq,reset_key_irq_handler,IRQ_TYPE_EDGE_BOTH,
"reset_key_irq", NULL);
+ //gpio_set_debounce(key.reset_gpio, 10 * 1000);
if(ret < 0)
{
printk("request_irq failed\n");
@@ -115,6 +132,14 @@ int reset_key_probe(struct platform_device *dev)
printk("misc_register failed\n");
return -1;
}
+ key.reset_key_dev = input_allocate_device();
+ key.reset_key_dev->name = "reset-key";
+ __set_bit(EV_KEY, key.reset_key_dev->evbit);
+ __set_bit(KEY_F10, key.reset_key_dev->keybit);
+ ret = input_register_device(key.reset_key_dev);
+ if(ret){
+ printk("key.reset_key_dev register input err!\n");
+ }
//定时器 可以使用函数来消抖
return 0;
}
--
2.25.1
二、frameworks里面PhoneWindowManager.java接收kernel 上传上来的按键信息,然后发广播进行恢复出厂设置。核心是发广播。用event.getDownTime()和 event.getEventTime()计算按键的时间。
三、frameworks里面处理按键的部分的代码如下:
---
frameworks/base/api/test-current.txt | 2 +-
.../base/core/java/android/view/KeyEvent.java | 4 +++-
frameworks/base/core/res/res/values/attrs.xml | 1 +
frameworks/base/data/keyboards/Generic.kl | 2 +-
.../server/policy/PhoneWindowManager.java | 19 +++++++++++++++++++
frameworks/native/include/android/keycodes.h | 4 +++-
.../native/include/input/InputEventLabels.h | 1 +
7 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/frameworks/base/api/test-current.txt b/frameworks/base/api/test-current.txt
index 539aaa0a5fa..cff226972b1 100644
--- a/frameworks/base/api/test-current.txt
+++ b/frameworks/base/api/test-current.txt
@@ -5125,7 +5125,7 @@ package android.view {
public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {
method public static String actionToString(int);
method public final void setDisplayId(int);
- field public static final int LAST_KEYCODE = 289; // 0x121
+ field public static final int LAST_KEYCODE = 290; // 0x122
}
public final class KeyboardShortcutGroup implements android.os.Parcelable {
diff --git a/frameworks/base/core/java/android/view/KeyEvent.java b/frameworks/base/core/java/android/view/KeyEvent.java
index f1bc5ee216b..7a8e81486f2 100644
--- a/frameworks/base/core/java/android/view/KeyEvent.java
+++ b/frameworks/base/core/java/android/view/KeyEvent.java
@@ -826,12 +826,14 @@ public class KeyEvent extends InputEvent implements Parcelable {
public static final int KEYCODE_PROFILE_SWITCH = 288;
/** @hide */
public static final int KEYCODE_SCREEN_SHOT = 289;
+ /** @hide */
+ public static final int KEYCODE_FACTORY_RESET = 290;
/**
* Integer value of the last KEYCODE. Increases as new keycodes are added to KeyEvent.
* @hide
*/
@TestApi
- public static final int LAST_KEYCODE = KEYCODE_SCREEN_SHOT;
+ public static final int LAST_KEYCODE = KEYCODE_FACTORY_RESET;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
diff --git a/frameworks/base/core/res/res/values/attrs.xml b/frameworks/base/core/res/res/values/attrs.xml
index cfad781a8e6..0aeb8bb7726 100644
--- a/frameworks/base/core/res/res/values/attrs.xml
+++ b/frameworks/base/core/res/res/values/attrs.xml
@@ -1927,6 +1927,7 @@
<enum name="KEYCODE_THUMBS_DOWN" value="287" />
<enum name="KEYCODE_PROFILE_SWITCH" value="288" />
<enum name="KEYCODE_SCREEN_SHOT" value="289" />
+ <enum name="KEYCODE_FACTORY_RESET" value="290" />
</attr>
<!-- ***************************************************************** -->
diff --git a/frameworks/base/data/keyboards/Generic.kl b/frameworks/base/data/keyboards/Generic.kl
index 28be888fe0c..fa461d22ca2 100644
--- a/frameworks/base/data/keyboards/Generic.kl
+++ b/frameworks/base/data/keyboards/Generic.kl
@@ -87,7 +87,7 @@ key 64 F6
key 65 F7
key 66 F8
key 67 F9
-key 68 F10
+key 68 FACTORY_RESET
key 69 NUM_LOCK
key 70 SCROLL_LOCK
key 71 NUMPAD_7
diff --git a/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f0db3107b72..c8675119557 100644
--- a/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -577,6 +577,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mScreenshotChordPowerKeyTriggered;
private long mScreenshotChordPowerKeyTime;
private long mScreenshotDownKeyTime;
+ private static final long FACTORY_RESET_DELAY_MILLIS = 8*1000;
+ private long mFactoryResetDownKeyTime;
+ private long mFactoryResetEventKeyTime;
+ private long mFactoryResetEndkeyTime;
// Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up
private int mRingerToggleChord = VOLUME_HUSH_OFF;
@@ -1358,6 +1362,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
}
}
+
+ private void factoryReset(){
+ long endKeyTime = mFactoryResetEventKeyTime - mFactoryResetDownKeyTime;
+ if(endKeyTime >= FACTORY_RESET_DELAY_MILLIS){
+ Intent intent = new Intent("android.intent.action.MASTER_CLEAR");
+ intent.setPackage("android");
+ mContext.sendBroadcast(intent);
+ }
+ }
private void interceptAccessibilityShortcutChord() {
if (mAccessibilityShortcutController.isAccessibilityShortcutAvailable(isKeyguardLocked())
&& mScreenshotChordVolumeDownKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered
@@ -3722,6 +3735,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
break;
}
+ case KeyEvent.KEYCODE_FACTORY_RESET:{
+ mFactoryResetDownKeyTime = event.getDownTime();
+ mFactoryResetEventKeyTime = event.getEventTime();
+ factoryReset();
+ break;
+ }
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
diff --git a/frameworks/native/include/android/keycodes.h b/frameworks/native/include/android/keycodes.h
index 9061eeeba95..9d9944e7087 100644
--- a/frameworks/native/include/android/keycodes.h
+++ b/frameworks/native/include/android/keycodes.h
@@ -778,7 +778,9 @@ enum {
* May be consumed by system to switch current viewer profile. */
AKEYCODE_PROFILE_SWITCH = 288,
/** @hide */
- AKEYCODE_SCREEN_SHOT = 289
+ AKEYCODE_SCREEN_SHOT = 289,
+ /** @hide */
+ AKEYCODE_FACTORY_RESET = 290
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
};
diff --git a/frameworks/native/include/input/InputEventLabels.h b/frameworks/native/include/input/InputEventLabels.h
index 0891d00a84d..5773a829e1b 100644
--- a/frameworks/native/include/input/InputEventLabels.h
+++ b/frameworks/native/include/input/InputEventLabels.h
@@ -329,6 +329,7 @@ static const InputEventLabel KEYCODES[] = {
DEFINE_KEYCODE(THUMBS_DOWN),
DEFINE_KEYCODE(PROFILE_SWITCH),
DEFINE_KEYCODE(SCREEN_SHOT),
+ DEFINE_KEYCODE(FACTORY_RESET),
{ nullptr, 0 }
--
2.25.1
四、收到广播后进入恢复出厂设置
1、\frameworks\base\core\res\AndroidManifest.xml
2、frameworks\base\services\core\java\com\android\server\MasterClearReceiver.java
/*
* Copyright (C) 2008 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/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;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.RecoverySystem;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.view.WindowManager;
import com.android.internal.R;
import java.io.IOException;
public class MasterClearReceiver extends BroadcastReceiver {
private static final String TAG = "MasterClear";
private boolean mWipeExternalStorage;
private boolean mWipeEsims;
@Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {
if (!"google".equals(intent.getStringExtra("from"))) {
Slog.w(TAG, "Ignoring master clear request -- not from trusted server.");
return;
}
}
if (Intent.ACTION_MASTER_CLEAR.equals(intent.getAction())) {
Slog.w(TAG, "The request uses the deprecated Intent#ACTION_MASTER_CLEAR, "
+ "Intent#ACTION_FACTORY_RESET should be used instead.");
}
if (intent.hasExtra(Intent.EXTRA_FORCE_MASTER_CLEAR)) {
Slog.w(TAG, "The request uses the deprecated Intent#EXTRA_FORCE_MASTER_CLEAR, "
+ "Intent#EXTRA_FORCE_FACTORY_RESET should be used instead.");
}
final String factoryResetPackage = context
.getString(com.android.internal.R.string.config_factoryResetPackage);
if (Intent.ACTION_FACTORY_RESET.equals(intent.getAction())
&& !TextUtils.isEmpty(factoryResetPackage)) {
intent.setPackage(factoryResetPackage).setComponent(null);
context.sendBroadcastAsUser(intent, UserHandle.SYSTEM);
return;
}
final boolean shutdown = intent.getBooleanExtra("shutdown", false);
final String reason = intent.getStringExtra(Intent.EXTRA_REASON);
mWipeExternalStorage = intent.getBooleanExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false);
mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false);
final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)
|| intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);
Slog.w(TAG, "!!! FACTORY RESET !!!");
// The reboot call is blocking, so we need to do it on another thread.
Thread thr = new Thread("Reboot") {
@Override
public void run() {
try {
RecoverySystem
.rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims);
Log.wtf(TAG, "Still running after master clear?!");
} catch (IOException e) {
Slog.e(TAG, "Can't perform master clear/factory reset", e);
} catch (SecurityException e) {
Slog.e(TAG, "Can't perform master clear/factory reset", e);
}
}
};
if (mWipeExternalStorage) {
// thr will be started at the end of this task.
new WipeDataTask(context, thr).execute();
} else {
thr.start();
}
}
private class WipeDataTask extends AsyncTask<Void, Void, Void> {
private final Thread mChainedTask;
private final Context mContext;
private final ProgressDialog mProgressDialog;
public WipeDataTask(Context context, Thread chainedTask) {
mContext = context;
mChainedTask = chainedTask;
mProgressDialog = new ProgressDialog(context);
}
@Override
protected void onPreExecute() {
mProgressDialog.setIndeterminate(true);
mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));
mProgressDialog.show();
}
@Override
protected Void doInBackground(Void... params) {
Slog.w(TAG, "Wiping adoptable disks");
if (mWipeExternalStorage) {
StorageManager sm = (StorageManager) mContext.getSystemService(
Context.STORAGE_SERVICE);
sm.wipeAdoptableDisks();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mProgressDialog.dismiss();
mChainedTask.start();
}
}
}
五、长按相应的按键后,机器会重启进入恢复出厂设置,看log,又相应的打印。
本文标签: 按键模式方法PhoneWindowManagerandroid
版权声明:本文标题:2021-11-12 Android 11 长按按键进入恢复出厂设置的实现方法-PhoneWindowManager里面用发广播的模式 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1729860219a1215603.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论