失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > -11-12 Android 11 长按按键进入恢复出厂设置的实现方法-PhoneWindowManager里面用发广播的模式

-11-12 Android 11 长按按键进入恢复出厂设置的实现方法-PhoneWindowManager里面用发广播的模式

时间:2021-02-21 17:31:58

相关推荐

-11-12 Android 11 长按按键进入恢复出厂设置的实现方法-PhoneWindowManager里面用发广播的模式

一、kernel部分主要发按键信息到android上层。

diff --git a/kernel/drivers/misc/key/reset_key.c b/kernel-4.14/drivers/misc/key/reset_key.cindex 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.txtindex 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.javaindex 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.xmlindex 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.klindex 28be888fe0c..fa461d22ca2 100644--- a/frameworks/base/data/keyboards/Generic.kl+++ b/frameworks/base/data/keyboards/Generic.kl@@ -87,7 +87,7 @@ key 64 F6key 65 F7key 66 F8key 67 F9-key 68 F10+key 68 FACTORY_RESETkey 69 NUM_LOCKkey 70 SCROLL_LOCKkey 71 NUMPAD_7diff --git a/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java b/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.javaindex 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 upprivate 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.hindex 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.hindex 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) 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**/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;@Overridepublic void onReceive(final Context context, final Intent intent) {if (intent.getAction().equals(Intent.ACTION_REMOTE_INTENT)) {if (!"".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") {@Overridepublic 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);}@Overrideprotected void onPreExecute() {mProgressDialog.setIndeterminate(true);mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);mProgressDialog.setMessage(mContext.getText(R.string.progress_erasing));mProgressDialog.show();}@Overrideprotected Void doInBackground(Void... params) {Slog.w(TAG, "Wiping adoptable disks");if (mWipeExternalStorage) {StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);sm.wipeAdoptableDisks();}return null;}@Overrideprotected void onPostExecute(Void result) {mProgressDialog.dismiss();mChainedTask.start();}}}

五、长按相应的按键后,机器会重启进入恢复出厂设置,看log,又相应的打印。

如果觉得《-11-12 Android 11 长按按键进入恢复出厂设置的实现方法-PhoneWindowManager里面用发广播的模式》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。