锁屏状态下NFC不可用

锁屏状态下NFC不可用

1. Description

在工厂测试软件中,需要对nfc进行测试。
1. 开机启动后,直接进入工厂测试软件中
2. 运行到nfc测试用例时,发现该测试用例不能成功的检测到nfc
3. 退出工厂测试软件,进入setttings->connected devices->打开nfc开关,继续验证nfc,发现是OK的。
4. 在回到工厂测试软件中nfc测试用例,nfc测试又变为ok。

2. Analysis

经过分析发现,在开机启动后,直接进入工厂测试软件时,设备是在锁屏后才进入工厂测试软件的。这就导致当前设备是锁屏的状态,而工厂测试软件又将该锁屏界面给覆盖了,所有导致在进行nfc测试用例时,nfc是打不开的。
然后问题就转为在进行工厂软件测试时,通过该软件自动解锁后在进行nfc测试用例。
然后网上查看相关资料发现,在NfcService.java中其实是可以修改NFC最小enable状态的,对应的属性为:

// minimum screen state that enables NFC polling
static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;

而属性 NFC_POLLING_MODE分别有一下几种状态可以使用:

  • SCREEN_STATE_OFF黑屏状态

  • SCREEN_STATE_ON_LOCKED屏幕亮了,但是是锁屏状态

  • SCREEN_STATE_ON_UNLOCKED 屏幕亮了,并且是解锁状态

因此该问题可以有4种方式解决:

  1. 在framework层进行修改,将属性 NFC_POLLING_MODE设为SCREEN_STATE_ON_LOCKED,这样即使在锁屏状态下,nfc还是可以enable的。

  2. 在nfc本身的测试用例中,加入解锁的逻辑,具体如下所示:

    public static void wakeUpAndUnlock(Context context) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    boolean screenOn = pm.isScreenOn();
    if (!screenOn) {
    PowerManager.WakeLock mWakeLock = pm.newWakeLock(
    PowerManager.ACQUIRE_CAUSES_WAKEUP
    | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "RunInWakeUp");
    mWakeLock.acquire(10000);
    mWakeLock.setReferenceCounted(false);
    mWakeLock.release();
    }
    KeyguardManager keyguardManager = (KeyguardManager)context.getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardManager.KeyguardLock keyguardLock = keyguardManager
    .newKeyguardLock("unLock");
    keyguardLock.reenableKeyguard();
    keyguardLock.disableKeyguard();
    }

  3. 还可以使用settings中的关闭锁屏功能的逻辑,即在整个版本中不锁屏(这个修改其实影响比较大,因为它是针对整个系统的,如果一直不让系统锁屏,功耗方面就是第一个大问题)。

    <!-- Is the lock-screen disabled for new users by default -->
    <bool name="config_disableLockscreenByDefault">false</bool>

    如果将配置文件中config_disableLockscreenByDefault的值改为true,则在熄屏后默认不进行锁屏。
    但是直接在此处改,不管编译什么版本都是会变成熄屏后默认不进行锁屏的逻辑,而当前的需求只是在工厂版本需要这个功能,那就可以在framework层动态修改。
  4. 在锁屏的时候让锁屏界面不显示,需要修改文件framework/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java和文件frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java,具体修改如下。
    /**KeyguardViewMediator.java文件
     * Enable the keyguard if the settings are appropriate.
     */
    private void doKeyguardLocked(Bundle options) {
        if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {
            // Don't show keyguard during half-booted cryptkeeper stage.
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because booting to cryptkeeper");
            return;
        }

        // if another app is disabling us, don't show
        if (!mExternallyEnabled) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");

            // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes
            // for an occasional ugly flicker in this situation:
            // 1) receive a call with the screen on (no keyguard) or make a call
            // 2) screen times out
            // 3) user hits key to turn screen back on
            // instead, we reenable the keyguard when we know the screen is off and the call
            // ends (see the broadcast receiver below)
            // TODO: clean this up when we have better support at the window manager level
            // for apps that wish to be on top of the keyguard
            return;
        }

        // if the keyguard is already showing, don't bother
        if (mStatusBarKeyguardViewManager.isShowing()) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
            resetStateLocked();
            return;
        }

        // In split system user mode, we never unlock system user.
        if (!mustNotUnlockCurrentUser()
                || !mUpdateMonitor.isDeviceProvisioned()) {

            // if the setup wizard hasn't run yet, don't show
            final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
            final boolean absent = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(ABSENT));
            final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
            final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
                    || ((absent || disabled) && requireSim);

            if (!lockedOrMissing && shouldWaitForProvisioning()) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
                        + " and the sim is not locked or missing");
                return;
            }

            boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
            if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
                    && !lockedOrMissing && !forceShow) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
                return;
            }

            if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
                if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
                // Without this, settings is not enabled until the lock screen first appears
                setShowingLocked(false);
                hideLocked();
                return;
            }
        }
/*modify for nfc function ,not showing lockscreen*/
      if (SystemProperties.getBoolean("ro.dev.MMITest", false)){
          Log.d(TAG, "doKeyguard: Jrdminisw mode, not showing lockscreen ");
          return ;
       }
/*modify   return before lock device screen*/
        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
        showLocked(options);
    }


//PhoneWindowManager.java文件
    public void systemReady() {
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
       /*modify for nfc function ,not verify SystemReady is MMITest version*/
         if (!SystemProperties.getBoolean("ro.dev.MMITest", false)) {
             // mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
              mKeyguardDelegate.onSystemReady();
          }
        /*modify for nfc function */
        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
        if (mVrManagerInternal != null) {
            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
        }
        readCameraLensCoverState();
        updateUiMode();
        synchronized (mLock) {
            updateOrientationListenerLp();
            mSystemReady = true;
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateSettings();
                }
            });
            // If this happens, for whatever reason, systemReady came later than systemBooted.
            // And keyguard should be already bound from systemBooted
            if (mSystemBooted) {
                mKeyguardDelegate.onBootCompleted();
            }
        }

        mSystemGestures.systemReady();
        mImmersiveModeConfirmation.systemReady();
    }

3. Solution

最后解决方法还是选择了第三种,对文件frameworks/base/core/java/com/android/internal/widget/LockPatternUtils.java具体修改如下:

    /**
     * Determine if LockScreen is disabled for the current user. This is used to decide whether
     * LockScreen is shown after reboot or after screen timeout / short press on power.
     *
     * @return true if lock screen is disabled
     */
    public boolean isLockScreenDisabled(int userId) {
        if (isSecure(userId)) {
            return false;
        }
        boolean disabledByDefault = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_disableLockscreenByDefault);
/*modify for nfc , disable Lockscreen ByDefault */
        Log.d(TAG, "hello,disabledByDefault is : "+disabledByDefault);
        if (SystemProperties.getBoolean("ro.dev.MMITest", false)){
            Log.d(TAG, "hello,dev.t2m.MMITest is true,disable Lockscreen By Default is:"+!disabledByDefault);
            disabledByDefault = !disabledByDefault;
        }
/*modify for nfc , disable Lockscreen ByDefault*/
        boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
        UserInfo userInfo = getUserManager().getUserInfo(userId);
        boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null
                && userInfo.isDemo();
        return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
                || (disabledByDefault && !isSystemUser)
                || isDemoUser;
    }

4. Summary

这个问题最根本的点其实就是锁屏下nfc不可用导致的,只要找到这个点,解起来方法还是比较多的,然后就是需要注意区分cu版本和工厂测试版本,在进行修改的时候,不能影响cu版本的正常逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值