A20关机长按关机按钮提示进入安全模式

长按电源键弹出关机按钮,长按关机按钮会弹出进入安全模式的设置,进入安全模式后将中止全部的第三方APP的加载,因为咱们的系统只有本身定制的lunch,因此已经去掉系统的加载项LUNCHER2,进入安全模式后没法加载启动项而停在android界面,致使系统没法启动,为了不系统进入安全模式,只有屏蔽长按关机按钮。java

android\frameworks\base\policy\src\com\android\internal\policy\impl\GlobalActions.javaandroid

在private GlobalActionsDialog createDialog() 这个方法里定义关机界面和各类模式的选择等操做监听事件;安全

如下是长按关机按钮弹出安全模式选择的按钮监听:
ide

        dialog.getListView().setOnItemLongClickListener(
                new AdapterView.OnItemLongClickListener() {
                    @Override
                    public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
                            long id) {
                        return mAdapter.getItem(position).onLongPress();
                    }
        });post

咱们要作的就是把它改为this

dialog.getListView().setOnItemLongClickListener(null);.net

便可中止监听长按关机按钮事件,也就表面上阻止了用户选择安全模式的可能;orm

下面分析一下android4.2的安全模式:server


android\frameworks\base\core\java\android\os\SystemService.javablog

    /** Request that the init daemon start a named service. */
    public static void start(String name) {
        SystemProperties.set("ctl.start", name);
    }

关于SystemProperties.set方法参见属性设置机制:

http://blog.csdn.net/ameyume/article/details/8056492

在android\frameworks\base\core\jni\AndroidRuntime.cpp中定义了

register_android_os_SystemProperties(JNIEnv *env);

这个方法在android\frameworks\base\core\jni\android_os_SystemProperties.cpp中定义,其实是返回了此文件中的jni方法集合:

static JNINativeMethod method_table[] = {
    { "native_get", "(Ljava/lang/String;)Ljava/lang/String;",
      (void*) SystemProperties_getS },
    { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
      (void*) SystemProperties_getSS },
    { "native_get_int", "(Ljava/lang/String;I)I",
      (void*) SystemProperties_get_int },
    { "native_get_long", "(Ljava/lang/String;J)J",
      (void*) SystemProperties_get_long },
    { "native_get_boolean", "(Ljava/lang/String;Z)Z",
      (void*) SystemProperties_get_boolean },
    { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
      (void*) SystemProperties_set },
    { "native_add_change_callback", "()V",
      (void*) SystemProperties_add_change_callback },
};

这些方法是android\frameworks\base\core\java\android\os\SystemProperties.java中方法的本地实现(jni实现);

启动WindowManagerService,会调用

android\frameworks\base\services\java\com\android\server\wm\WindowManagerService.java中detectSafeMode()方法,代码以下:

    public boolean detectSafeMode() {
        if (!mInputMonitor.waitForInputDevicesReady(
                INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
            Slog.w(TAG, "Devices still not ready after waiting "
                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
                   + " milliseconds before attempting to detect safe mode.");
        }

        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
                KeyEvent.KEYCODE_MENU);
        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
                KeyEvent.KEYCODE_DPAD_CENTER);
        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
                InputManagerService.BTN_MOUSE);
        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
                KeyEvent.KEYCODE_VOLUME_DOWN);
        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
                || volumeDownState > 0;
        try {
            if (SystemProperties.getInt(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, 0) != 0) {
                mSafeMode = true;
                SystemProperties.set(ShutdownThread.REBOOT_SAFEMODE_PROPERTY, "");
            }
        } catch (IllegalArgumentException e) {
        }
        if (mSafeMode) {
            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
        } else {
            Log.i(TAG, "SAFE MODE not enabled");
        }
        mPolicy.setSafeMode(mSafeMode);
        return mSafeMode;
    }

若是监测到是安全模式将进入到安全模式;

在android\frameworks\base\services\java\com\android\server\am\ActivityManagerService.java中

    public final void enterSafeMode() {
        synchronized(this) {
            // It only makes sense to do this before the system is ready
            // and started launching other packages.
            if (!mSystemReady) {
                try {
                    AppGlobals.getPackageManager().enterSafeMode();
                } catch (RemoteException e) {
                }
            }
        }
    }
在\android\frameworks\base\services\java\com\android\server\pm\PackageManagerService.java中

    public void enterSafeMode() {
        enforceSystemOrRoot("Only the system can request entering safe mode");

        if (!mSystemReady) {
            mSafeMode = true;
        }
    }
android\frameworks\base\services\java\com\android\server\wm\WindowManagerService.java

    public void systemReady() {
        mPolicy.systemReady();
    }

最后会调用到android\frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java

   /** {@inheritDoc} */
    public void systemReady() {
        if (mKeyguardMediator != null) {
            // tell the keyguard
            mKeyguardMediator.onSystemReady();
        }
        synchronized (mLock) {
            updateOrientationListenerLp();
            mSystemReady = true;
            mHandler.post(new Runnable() {
                public void run() {
                    updateSettings();
                }
            });
        }
    }

android\frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

    public final void showSafeModeOverlay() {
        View v = LayoutInflater.from(mContext).inflate(
                com.android.internal.R.layout.safe_mode, null);
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
        lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
        lp.gravity = Gravity.BOTTOM | Gravity.START;
        lp.format = v.getBackground().getOpacity();
        lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
        ((WindowManager)mContext.getSystemService(
                Context.WINDOW_SERVICE)).addView(v, lp);
    }

android\frameworks\base\services\java\com\android\server\AppWidgetService.java

    public void systemReady(boolean safeMode) {        mSafeMode = safeMode;        mAppWidgetServices.get(0).systemReady(safeMode);        // Register for the boot completed broadcast, so we can send the        // ENABLE broacasts. If we try to send them now, they time out,        // because the system isn't ready to handle them yet.        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,                new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);        // Register for configuration changes so we can update the names        // of the widgets when the locale changes.        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,                new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED), null, null);        // Register for broadcasts about package install, etc., so we can        // update the provider list.        IntentFilter filter = new IntentFilter();        filter.addAction(Intent.ACTION_PACKAGE_ADDED);        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);        filter.addDataScheme("package");        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,                filter, null, null);        // Register for events related to sdcard installation.        IntentFilter sdFilter = new IntentFilter();        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);        sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);        mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,                sdFilter, null, null);        IntentFilter userFilter = new IntentFilter();        userFilter.addAction(Intent.ACTION_USER_REMOVED);        userFilter.addAction(Intent.ACTION_USER_STOPPING);        mContext.registerReceiver(new BroadcastReceiver() {            @Override            public void onReceive(Context context, Intent intent) {                if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {                    onUserRemoved(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,                            UserHandle.USER_NULL));                } else if (Intent.ACTION_USER_STOPPING.equals(intent.getAction())) {                    onUserStopping(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,                            UserHandle.USER_NULL));                }            }        }, userFilter);    }

相关文章
相关标签/搜索