SystemUI---双击电源键打开Camera(重启第一次无法启动相机)

src/com/android/keyguard/KeyguardSecurityContainerController.java

        if (finish) {
            mSecurityCallback.finish(strongAuth, targetUserId);
            Log.d(TAG, "finish ");
        }
        if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish() - return finish = " + finish) ;
        
        /* add by *** for not allowed open camera begin*/
        if (finish) {
            SystemProperties.set("sys.keyguard_open","1");
        }
        /* add by *** for not allowed open camera begin*/

        return finish;
    }

src/com/android/systemui/statusbar/phone/StatusBar.java

    @Override
    public void onCameraLaunchGestureDetected(int source) {
        mLastCameraLaunchSource = source;
        /* add by *** for not allowed open camera begin*/
        if ("0".equals(SystemProperties.get("sys.keyguard_open","0"))) {
            return;
        } else {
            Slog.d(TAG, "The camera is not allowed to start because it has never been unlocked");
        }
        /* add by **** for not allowed open camera end*/

        if (isGoingToSleep()) {
            if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
            mLaunchCameraOnFinishedGoingToSleep = true;
            return;
        }

分析双击电源键打开相机的流程:

找到电源按键上报的代码:

base/services/core/java/com/android/server/policy/PhoneWindowManager.java

关键函数:

在这两个函数中处理,注意可能被重写导致不在PhoneWindowManager.java中出现

1)interceptKeyBeforeDispatching

2)interceptKeyBeforeQueueing

处理流程:

base/services/core/java/com/android/server/policy/PhoneWindowManager.java

interceptKeyBeforeQueueing->
handleKeyGesture->
mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched);

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {

......
        if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
            Log.d(TAG,"handleKeyGesture +000");
            handleKeyGesture(event, interactiveAndOn);
        }
......
}

/*********************************************************************************/
    private void handleKeyGesture(KeyEvent event, boolean interactive) {
......
        if (event.getKeyCode() == KEYCODE_POWER && event.getAction() == KeyEvent.ACTION_DOWN) {
            mPowerKeyHandled = handleCameraGesture(event, interactive);
            if (mPowerKeyHandled) {
                // handled by camera gesture.
                mSingleKeyGestureDetector.reset();
                return;
            }
        }

        mSingleKeyGestureDetector.interceptKey(event, interactive);
    }

/********************************************************************************/
    // The camera gesture will be detected by GestureLauncherService.
    private boolean handleCameraGesture(KeyEvent event, boolean interactive) {
        // camera gesture.
......
        final boolean intercept =
                mGestureLauncherService.interceptPowerKeyDown(event, interactive, outLaunched);
......
    }

/********************************************************************************/

base/services/core/java/com/android/server/GestureLauncherService.java

interceptPowerKeyDown->

handleCameraGesture->

onCameraLaunchGestureDetected

    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
            MutableBoolean outLaunched) {
.......

        if (launchCamera) {
            Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval="
                    + powerTapInterval + "ms");
            launchCamera = handleCameraGesture(false /* useWakelock */,
                    StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
            if (launchCamera) {
                mMetricsLogger.action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE,
                        (int) powerTapInterval);
                mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER);
            }
        } else if (launchEmergencyGesture) {
            Slog.i(TAG, "Emergency gesture detected, launching.");
            launchEmergencyGesture = handleEmergencyGesture();
            mUiEventLogger.log(GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER);
        }
.......
    }

/*********************************************************************************/
    @VisibleForTesting
    boolean handleCameraGesture(boolean useWakelock, int source) {
......
            if (useWakelock) {
                // Make sure we don't sleep too early
                mWakeLock.acquire(500L);
            }
            StatusBarManagerInternal service = LocalServices.getService(
                    StatusBarManagerInternal.class);
            service.onCameraLaunchGestureDetected(source);
            return true;
......
    }

base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java

        @Override
        public void onCameraLaunchGestureDetected(int source) {
            if (mBar != null) {
                try {
                    mBar.onCameraLaunchGestureDetected(source);
                } catch (RemoteException e) {
                }
            }
        }

base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

    @Override
    public void onCameraLaunchGestureDetected(int source) {
        mLastCameraLaunchSource = source;
        // Slog.e(TAG,  Log.getStackTraceString(new Throwable()));
        /* add by zhoujian for not allowed open camera begin*/
        if ("0".equals(SystemProperties.get("sys.keyguard_open","0"))) {
            return;
        } else {
            Slog.e(TAG, "The camera is allowed to start because it has been unlocked");
        }
        /* add by zhoujian for not allowed open camera end*/

        if (isGoingToSleep()) {
            if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
            mLaunchCameraOnFinishedGoingToSleep = true;
            return;
        }
        if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
            if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now");
            return;
        }
        if (!mDeviceInteractive) {
            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH,
                    "com.android.systemui:CAMERA_GESTURE");
        }
        vibrateForCameraGesture();

        if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
            Log.v(TAG, "Camera launch");
            /// M: ALPS05974700 Fix the screen desplay white while double click power key
            mCameraLaunchPowerDouble = true;
            mKeyguardUpdateMonitor.onCameraLaunched();//屏蔽人脸或者指纹解锁
        }

        if (!mStatusBarKeyguardViewManager.isShowing()) {
            final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext);
            startActivityDismissingKeyguard(cameraIntent,
                    false /* onlyProvisioned */, true /* dismissShade */,
                    true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0,
                    null /* animationController */);
        } else {

            if (!mDeviceInteractive) {
                // Avoid flickering of the scrim when we instant launch the camera and the bouncer
                // comes on.
                mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
            }

            if (isWakingUpOrAwake()) {
                if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera aaa");
                if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
                    mStatusBarKeyguardViewManager.reset(true /* hide */);
                }
                // M: Mtk add for fix unresponse when swipe lock and occluded.
                if (!mStatusBarKeyguardViewManager.isSecure()
                        && mStatusBarKeyguardViewManager.isOccluded()) {
                    Slog.d(TAG, "Non-Secure unlock, no need to launch camera");
                    return;
                }

                mNotificationPanelViewController.launchCamera(
                        mDeviceInteractive /* animate */, source);//启动相机

                updateScrimController();
            } else {
                // We need to defer the camera launch until the screen comes on, since otherwise
                // we will dismiss us too early since we are waiting on an activity to be drawn and
                // incorrectly get notified because of the screen on event (which resumes and pauses
                // some activities)
                if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on");
                mLaunchCameraWhenFinishedWaking = true;
            }
        }
    }

startActivityDismissingKeyguard()

    private void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
            final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
            final Callback callback, int flags,
            @Nullable ActivityLaunchAnimator.Controller animationController) {
        Slog.e(TAG,  Log.getStackTraceString(new Throwable())); 

        if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;

        final boolean willLaunchResolverActivity =
                mActivityIntentHelper.wouldLaunchResolverActivity(intent,
                        mLockscreenUserManager.getCurrentUserId());

        boolean animate =
                animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
                        true /* isActivityIntent */);
        ActivityLaunchAnimator.Controller animController =
                animate ? wrapAnimationController(animationController, dismissShade) : null;

        // If we animate, we will dismiss the shade only once the animation is done. This is taken
        // care of by the StatusBarLaunchAnimationController.
        boolean dismissShadeDirectly = dismissShade && animController == null;

        Runnable runnable = () -> {
            mAssistManagerLazy.get().hideAssist();
            intent.setFlags(
                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.addFlags(flags);
            int[] result = new int[]{ActivityManager.START_CANCELED};

            mActivityLaunchAnimator.startIntentWithAnimation(animController,
                    animate, intent.getPackage(), (adapter) -> {
                        ActivityOptions options = new ActivityOptions(
                                getActivityOptions(mDisplayId, adapter));
                        options.setDisallowEnterPictureInPictureWhileLaunching(
                                disallowEnterPictureInPictureWhileLaunching);
                        if (CameraIntents.isInsecureCameraIntent(intent)) {
                            // Normally an activity will set it's requested rotation
                            // animation on its window. However when launching an activity
                            // causes the orientation to change this is too late. In these cases
                            // the default animation is used. This doesn't look good for
                            // the camera (as it rotates the camera contents out of sync
                            // with physical reality). So, we ask the WindowManager to
                            // force the crossfade animation if an orientation change
                            // happens to occur during the launch.
                            options.setRotationAnimationHint(
                                    WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
                        }
                        if (intent.getAction() == Settings.Panel.ACTION_VOLUME) {
                            // Settings Panel is implemented as activity(not a dialog), so
                            // underlying app is paused and may enter picture-in-picture mode
                            // as a result.
                            // So we need to disable picture-in-picture mode here
                            // if it is volume panel.
                            options.setDisallowEnterPictureInPictureWhileLaunching(true);
                        }

                        try {
                            result[0] = ActivityTaskManager.getService().startActivityAsUser(
                                    null, mContext.getBasePackageName(),
                                    mContext.getAttributionTag(),
                                    intent,
                                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                                    null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
                                    options.toBundle(), UserHandle.CURRENT.getIdentifier());
                        } catch (RemoteException e) {
                            Log.w(TAG, "Unable to start activity", e);
                        }
                        return result[0];
                    });

            if (callback != null) {
                callback.onActivityStarted(result[0]);
            }
        };
        Runnable cancelRunnable = () -> {
            if (callback != null) {
                callback.onActivityStarted(ActivityManager.START_CANCELED);
            }
        };
        executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
                willLaunchResolverActivity, true /* deferred */, animate);
    }

src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java

launchCamera->launchAffordance

    public void launchCamera(boolean animate, int source) {
        if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
            mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
        } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
            mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
        } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) {
            mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER;
        } else {

            // Default.
            mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
        }

        // If we are launching it when we are occluded already we don't want it to animate,
        // nor setting these flags, since the occluded state doesn't change anymore, hence it's
        // never reset.
        Log.d(TAG, "launchCamera +++");
        if (!isFullyCollapsed()) {
            setLaunchingAffordance(true);//启动动画????
        } else {
            animate = false;
        }
        mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
        mAffordanceHelper.launchAffordance(
                animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
    }

src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java

......

### 如何使用Python编写爬虫抓取B番剧视频 #### 环境准备 为了顺利进行数据采集工作,建议先准备好开发环境。推荐使用 Python 3.x 版本并安装必要的第三方库,如 `requests` 和 `BeautifulSoup4` 或者更为强大的框架如 Scrapy 来简化网页解析过程[^2]。 #### 编写基础爬虫脚本 下面是一个简单的例子来获取 B 上某个特定页面的内容: ```python import requests from bs4 import BeautifulSoup def fetch_page(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', } response = requests.get(url, headers=headers) if response.status_code == 200: soup = BeautifulSoup(response.text, "html.parser") return soup else: raise Exception(f"Failed to load page {url}") ``` 此函数会返回给定 URL 页面经过解析后的 HTML 文档对象模型(DOM),可以用来定位所需的信息节点。 #### 抓取具体信息 对于番剧来说,通常需要关注的是标题、播放量、弹幕数量等基本信息。可以通过观察目标网结构找到这些元素对应的标签名称及其属性值,在上述 DOM 中查找相应位置的数据项。例如: ```python soup = fetch_page('https://www.bilibili.com/anime') titles = [item.string.strip() for item in soup.select('.title')] play_counts = [int(item['data-play']) for item in soup.select('.play')] danmu_counts = [int(item['data-danmaku']) for item in soup.select('.danmaku')] ``` 这里假设 `.title`, `[data-play]`, `[data-danmaku]` 是实际存在的 CSS Selectors 表达式用于匹配到相应的HTML元素。 #### 处理分页或多级页面链接 如果要访问多个列表页或是深入某条记录下的子页面,则需注意构建合理的URL模式,并循环调用之前定义好的请求方法完成遍历操作。比如当遇到带有参数化的路径时(如 `/anime?page=1`),可通过改变查询字符串中的数值实现翻页效果;而对于详情页而言,则可能涉及到正则表达式的运用以提取出完整的跳转地址。 #### 数据存储方式的选择 考虑到后期可能会对所获资料做进一步加工处理甚至建立小型数据库供其他应用读取,因此合理规划好本地缓存机制非常重要。可以选择 CSV 文件作为临时载体保存原始文本串形式的结果集,也可以考虑采用 SQLite 这样的轻型关系型数据库管理系统来进行持久化管理。 #### 遵守robots协议与道德准则 在实施任何网络爬行活动前都应该仔细阅读目标点发布的 robots.txt 文件了解允许范围内的行为边界,同时尊重版权方利益不滥用自动化工具干扰正常服务秩序。另外还需特别留意个人信息保护法规的要求以免触犯法律风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值