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