Android 8.1 修改锁屏显示时间

平台

RK3399 + Android 8.1

需求

加长锁屏显示时间, 延长用户解锁时间

补丁

|-- frameworks/base/core/res/res/values/config.xml

diff --git a/frameworks/base/core/res/res/values/config.xml b/frameworks/base/core/res/res/values/config.xml
index b81b609..c401275 100644
--- a/frameworks/base/core/res/res/values/config.xml
+++ b/frameworks/base/core/res/res/values/config.xml
@@ -1988,7 +1988,7 @@
          This value must be greater than zero, otherwise the device will immediately
          fall asleep again as soon as it is awoken.
     -->
-    <integer name="config_minimumScreenOffTimeout">10000</integer>
+    <integer name="config_minimumScreenOffTimeout">15000</integer>
 
     <!-- User activity timeout: Maximum screen dim duration in milliseconds.

由原来的10 秒延长到15秒

跟踪

|-- frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

    private void readConfigurationLocked() {
        ...
        mMinimumScreenOffTimeoutConfig = resources.getInteger(
                com.android.internal.R.integer.config_minimumScreenOffTimeout);
        ...
    }

    private void updateUserActivitySummaryLocked(long now, int dirty) {
        // Update the status of the user activity timeout timer.
        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
                | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
            mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);

            long nextTimeout = 0;
            if (mWakefulness == WAKEFULNESS_AWAKE
                    || mWakefulness == WAKEFULNESS_DREAMING
                    || mWakefulness == WAKEFULNESS_DOZING) {
                final int sleepTimeout = getSleepTimeoutLocked();
                final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
                ...

                mUserActivitySummary = 0;
                if (mLastUserActivityTime >= mLastWakeTime) {
//计算超时进入休眠时间. 
//mLastUserActivityTime最后一次操作
                    nextTimeout = mLastUserActivityTime
                            + screenOffTimeout - screenDimDuration;
                    if (now < nextTimeout) {
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                    } else {
                        nextTimeout = mLastUserActivityTime + screenOffTimeout;
                        if (now < nextTimeout) {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }
                ...
                if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtTime(msg, nextTimeout);
                }
            }
			...
        }
    }


/*
dumpsys power | grep mScreenOffTimeoutSetting
  mScreenOffTimeoutSetting=2147483647
*/
    private int getScreenOffTimeoutLocked(int sleepTimeout) {//-1
        int timeout = mScreenOffTimeoutSetting;//2147483647
        if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
            timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
        }
        if (mUserActivityTimeoutOverrideFromWindowManager >= 0) {
            timeout = (int)Math.min(timeout, mUserActivityTimeoutOverrideFromWindowManager);
        }
        if (sleepTimeout >= 0) {
            timeout = Math.min(timeout, sleepTimeout);
        }
        return Math.max(timeout, mMinimumScreenOffTimeoutConfig);
    }

	//用户长时间不操作后:
    private void handleUserActivityTimeout() { // runs on handler thread
        synchronized (mLock) {
            if (DEBUG_SPEW) {
                Slog.d(TAG, "handleUserActivityTimeout");
            }

            mDirty |= DIRTY_USER_ACTIVITY;
            updatePowerStateLocked();
        }
    }


    /**
     * Updates the global power state based on dirty bits recorded in mDirty.
     *
     * This is the main function that performs power state transitions.
     * We centralize them here so that we can recompute the power state completely
     * each time something important changes, and ensure that we do it the same
     * way each time.  The point is to gather all of the transition logic here.
     */
    private void updatePowerStateLocked() {
			...
            // Phase 2: Update display power state.
            boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

            // Phase 3: Update dream state (depends on display ready signal).
            updateDreamLocked(dirtyPhase2, displayBecameReady);

            // Phase 4: Send notifications, if needed.
            finishWakefulnessChangeIfNeededLocked();
			...
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    }

	/**
     * Determines whether to post a message to the sandman to update the dream state.
     */
    private void updateDreamLocked(int dirty, boolean displayBecameReady) {
        if ((dirty & (DIRTY_WAKEFULNESS
                | DIRTY_USER_ACTIVITY
                | DIRTY_WAKE_LOCKS
                | DIRTY_BOOT_COMPLETED
                | DIRTY_SETTINGS
                | DIRTY_IS_POWERED
                | DIRTY_STAY_ON
                | DIRTY_PROXIMITY_POSITIVE
                | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
            if (mDisplayReady) {
                scheduleSandmanLocked();
            }
        }
    }

    private void scheduleSandmanLocked() {
        if (!mSandmanScheduled) {
            mSandmanScheduled = true;
            Message msg = mHandler.obtainMessage(MSG_SANDMAN);
            msg.setAsynchronous(true);
            mHandler.sendMessage(msg);
        }
    }

	private void handleSandman() { // runs on handler thread
        // Handle preconditions.
		...
                // Doze has ended or will be stopped.  Update the power state.
                reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
                updatePowerStateLocked();
            }
        }

        // Stop dream.
        if (isDreaming) {
            mDreamManager.stopDream(false /*immediate*/);
        }
    }

    // Done dozing, drop everything and go to sleep.
    private boolean reallyGoToSleepNoUpdateLocked(long eventTime, int uid) {
        if (DEBUG_SPEW) {
            Slog.d(TAG, "reallyGoToSleepNoUpdateLocked: eventTime=" + eventTime
                    + ", uid=" + uid);
        }

        if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
                || !mBootCompleted || !mSystemReady) {
            return false;
        }

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "reallyGoToSleep");
        try {
            Slog.i(TAG, "Sleeping (uid " + uid +")...");

            setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
        return true;
    }

<think>首先,用户的问题是:“我想查找在Android 8.1系统中,使用left_button在界面无法进入拨号盘的解决方案。” 这是在询问如何解决在Android 8.1界面上使用left_button无法进入拨号盘的问题。 用户提供了几个引用,但我需要参考这些引用以及之前的对话历史。回顾系统指令: - 所有行内数学表达式必须使用$...$格式(但这里没有数学内容,所以可能不适用)。 - 独立公式使用$$...$$(同样不适用)。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识。 用户提供的引用是: - 引用[1]: 关于Android输入类型,如number、phone等。 - 引用[2]: 关于onFocusChanged()方法处理焦点改变。 - 引用[3]: 关于使用layer-list定义形状,如圆角边框。 - 引用[4]: 关于RadioButton单选按钮。 用户提到:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但在这个对话中,用户上一次的问题就是这个,所以没有更早的历史。我需要基于当前问题回答。 用户真正的需求是解决方案:在Android 8.1界面,使用left_button无法进入拨号盘。 作为AI,我需要提供准确的解决方案。我应该基于Android开发知识来回答。 关键点: - Android 8.1系统。 - 界面(lock screen)。 - left_button:可能指的是界面上的按钮,比如紧急拨号按钮或其他自定义按钮。 - 无法进入拨号盘:意思是点击按钮没有响应或无法打开拨号应用。 可能的解决方案: 1. 检查按钮的配置:确保按钮被正确设置为触发拨号动作。 2. 焦点处理:引用[2]提到了onFocusChanged()方法,可能焦点问题导致按钮无效。 3. UI元素:引用[3]是关于UI形状的,可能涉及按钮的可见性或可点击性。 4. 系统权限或策略:Android界面可能有安全限制,阻止直接进入拨号盘。 在Android中,界面通常限制某些操作,除非是紧急呼叫。Android 8.1可能已废弃一些旧API。 标准方法: - 在界面添加紧急拨号按钮通常是自定义或系统修改。 - 可能需要使用KeyguardManager或类似API。 步骤: 1. 确认按钮定义:在布局文件中,按钮应该有正确的onClick属性或setOnClickListener。 2. 处理点击事件:在代码中,按钮点击时调用Intent启动拨号应用。 3. 权限:Android 9及以上有更严格的限制,但Android 8.1可能支持。 特定于left_button:可能是一个自定义视图或系统视图。 参考用户提供的引用: - 引用[1]有android:inputType="phone",这用于输入框,不是按钮。 - 引用[2]是关于焦点,可能如果按钮没有焦点,无法点击。 - 引用[3]是UI美化,可能按钮不可见或覆盖。 - 引用[4]是单选按钮,不直接相关。 所以,解决方案可能聚焦于: - 确保按钮有焦点和可点击。 - 正确设置点击监听器。 - 启动拨号Intent:Intent.ACTION_DIAL。 在界面,需要处理安全上下文。 常见原因和解决: - 按钮被其他视图覆盖。 - 焦点丢失。 - 系统限制。 具体步骤: 1. 检查布局:确保left_button在布局中正确放置并设置为可点击。 2. 代码实现:在Activity或Fragment中,添加按钮点击监听器。 ```java left_button.setOnClickListener(v -> { Intent intent = new Intent(Intent.ACTION_DIAL); startActivity(intent); }); ``` 3. 焦点处理:重写onFocusChanged以确保按钮获得焦点(引用[2])。 4. 测试安全模式:界面可能需要特殊权限。在AndroidManifest.xml中添加权限,比如USE_FULL_SCREEN_INTENT或WAKE_LOCK,但可能需要系统签名。 对于系统修改,通常需要定制ROM或使用系统APP权限。 提供一般建议: - 调试按钮点击事件。 - 检查日志错误。 - 确保设备解策略允许。 最后,生成相关问题。 回答结构: 1. 清晰介绍问题。 2. 逐步提供解决方案。 3. 引用相关引用自然地添加标识。 4. 结束生成相关问题。 使用中文。 </think>### Android 8.1系统中界面left_button无法进入拨号盘的解决方案 在Android 8.1系统中,界面(lock screen)的`left_button`无法进入拨号盘的问题,通常涉及按钮配置错误、焦点处理不当或系统权限限制。这可能是由于自定义视图未正确处理点击事件、焦点丢失或系统安全策略导致。下面我将基于Android开发知识,逐步分析并提供解决方案。解决方案包括检查布局文件、代码实现、焦点处理和安全配置等步骤。参考您的引用内容(如焦点回调方法[^2]和UI元素定义[^3]),我会整合相关建议。 #### 1. **检查按钮布局和可点击性** - **问题描述**:`left_button`在布局中可能未正确定义为可点击,或者被其他视图覆盖导致事件无法触发。 - **解决方案**: - 在布局XML文件中,确保`left_button`设置了`android:clickable="true"`和`android:focusable="true"`属性。同时,使用`<layer-list>`(如引用[^3]所述)定义按钮形状时,确保视图层级正确,避免内部元素覆盖点击区域。 ```xml <!-- 示例:布局文件(如自定义视图的XML) --> <Button android:id="@+id/left_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="拨号" android:clickable="true" <!-- 确保可点击 --> android:focusable="true" <!-- 确保可获取焦点 --> android:background="@drawable/button_shape" /> <!-- 引用[^3]中的layer-list形状示例 --> ``` - 如果使用自定义形状(如引用[^3]),检查`layer-list`中的`<item>`元素是否设置了错误的边界(如`android:bottom="1dp"`),这可能导致按钮实际可点击区域缩小。调整尺寸或移除不必要的偏移。 #### 2. **实现按钮点击事件处理** - **问题描述**:`left_button`的点击监听器未正确设置或启动拨号Intent失败,导致点击无响应。 - **解决方案**: - 在Activity或Fragment代码中,为`left_button`设置`OnClickListener`,使用`Intent.ACTION_DIAL`启动拨号应用。注意:在界面启动拨号盘可能受系统限制,需要处理安全例外。 ```java // 在自定义Activity中(如KeyguardService或LockScreenActivity) Button leftButton = findViewById(R.id.left_button); leftButton.setOnClickListener(v -> { try { // 启动拨号Intent Intent dialIntent = new Intent(Intent.ACTION_DIAL); dialIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(dialIntent); } catch (SecurityException e) { // 处理权限异常(见于上下文) Log.e("LockScreen", "无法启动拨号盘: " + e.getMessage()); } }); ``` - 如果系统阻止拨号Intent(Android 8.1可能有安全策略),添加`FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS`以避免冲突。 #### 3. **处理焦点问题** - **问题描述**:界面中,`left_button`可能因焦点丢失无法响应点击(如幕唤醒时的焦点变化)。引用[^2]提到`onFocusChanged()`方法可用于处理焦点事件。 - **解决方案**: - 自定义按钮视图,重写`onFocusChanged()`以强制获取焦点并保持可点击状态。这在唤醒时特别重要。 ```java public class LockScreenButton extends androidx.appcompat.widget.AppCompatButton { public LockScreenButton(Context context) { super(context); setFocusableInTouchMode(true); // 确保触摸时可获取焦点 } @Override protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { super.onFocusChanged(focused, direction, previouslyFocusedRect); if (focused) { // 焦点获得时高亮按钮或确保可用 setBackgroundColor(Color.BLUE); // 示例:视觉反馈 } else { // 焦点丢失时恢复状态 setBackgroundResource(R.drawable.button_shape); // 引用[^3]的形状 } } } ``` - 在布局中使用此自定义按钮: ```xml <com.example.LockScreenButton android:id="@+id/left_button" android:layout_width="wrap_content" android:layout_height="wrap_content" /> ``` #### 4. **系统权限和策略调整** - **问题描述**:Android 8.1界面默认限制非紧急操作(如拨号),可能导致按钮无效。系统权限缺失或设备策略管理器(DevicePolicyManager)可能阻止此操作。 - **解决方案**: - **添加权限**:在`AndroidManifest.xml`中声明必要权限,如`USE_FULL_SCREEN_INTENT`(Android 8.1支持),但注意这需要系统级APP签名或特殊权限。 ```xml <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" /> ``` - **测试紧急拨号**:如果`left_button`设计为紧急拨号按钮,使用`Intent.ACTION_CALL_EMERGENCY`代替ACTION_DIAL(需`CALL_PHONE`权限)。但用户交互必须有明确提示。 - **调试日志**:检查Logcat输出,过滤关键字如`Keyguard`或`SecurityException`,以识别具体错误。使用`adb logcat`查看运行时信息。 #### 5. **兼容性测试和备选方案** - **Android 8.1特定注意**:此版本API较旧,确保代码兼容Oreo(API 27)。测试时,模拟状态使用`adb shell am start -a android.intent.action.MAIN -n com.android.systemui/.keyguard.KeyguardService`。 - **备选方案**:如果以上方法无效,考虑: - 使用`KeyguardManager`暂时解幕后再启动拨号(需用户认证)。 - 集成系统拨号盘组件(如`DialerFragment`),但可能需ROM定制。 ### 总结 上述步骤应能解决Android 8.1界面`left_button`无法进入拨号盘的问题。常见原因是按钮配置不当(如未设置可点击)、焦点处理缺失(引用[^2])或系统安全限制。优先检查布局和点击事件代码,确保按钮可操作。如果问题persists,检查系统日志以定位权限错误。注意:自定义功能可能需要系统签名权限,这在非root设备上受限[^1][^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值