Android 11 ANR

平台

     R K 3568 + A n d r o i d 11 RK3568 + Android 11 RK3568+Android11

概述

官方的说明
    如果 Android 应用的界面线程处于阻塞状态的时间过长,会触发“应用无响应”(ANR) 错误。如果应用位于前台,系统会向用户显示一个对话框,ANR 对话框会为用户提供强制退出应用的选项。

    ANR 处理流程

  • 首先, 3个ANR的时间定义:
        通过调试: adb shell dumpsys input中查看窗口信息的dispatchingTimeout, 不同的窗口可能是不一样的, 这得看实际的时间设定, 如下3个值都设置为5秒, 那显示的都为5秒.

App如Launhcer:
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

	//当前的超时设置为5's
    public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;

SystemUI的导航栏和状态栏:
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

///
//  这个时间关联到的是:                         //
///
    // Default input dispatching timeout in nanoseconds.
    static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
       h.dispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;

frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
constexpr std::chrono::nanoseconds DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5s;
  • 第二, 字符串定义(frameworks/base/core/res 目录下):
    <string name="anr_activity_application" msgid="8121716632960340680">"<xliff:g id="APPLICATION">%2$s</xliff:g>没有响应"</string>
    <string name="anr_activity_process" msgid="3477362583767128667">"<xliff:g id="ACTIVITY">%1$s</xliff:g>没有响应"</string>
    <string name="anr_application_process" msgid="4978772139461676184">"<xliff:g id="APPLICATION">%1$s</xliff:g>没有响应"</string>
    <string name="anr_process" msgid="1664277165911816067">"进程“<xliff:g id="PROCESS">%1$s</xliff:g>”没有响应"</string>
    <string name="force_close" msgid="9035203496368973803">"确定"</string>
    <string name="report" msgid="2149194372340349521">"报告"</string>
    <string name="wait" msgid="7765985809494033348">"等待"</string>

时序

InputDispatcher com_android_server_input_InputManagerService InputManagerService InputManagerCallback ActivityRecord ActivityManagerService$LocalService ActivityManagerService AnrHelper AnrHelper.AnrConsumerThread AnrHelper.AnrRecord appNotResponding ProcessRecord AppErrors dispatchOnce(处理输入事件) processAnrsLocked(检测到ANR后) onAnrLocked notifyAnr notifyAnr notifyANR notifyANRInner keyDispatchingTimedOut inputDispatchingTimedOut inputDispatchingTimedOut appNotResponding run appNotResponding appNotResponding mUiHandler.sendMessage(SHOW_NOT_RESPONDING_UI_MSG) handleShowAnrUi InputDispatcher com_android_server_input_InputManagerService InputManagerService InputManagerCallback ActivityRecord ActivityManagerService$LocalService ActivityManagerService AnrHelper AnrHelper.AnrConsumerThread AnrHelper.AnrRecord appNotResponding ProcessRecord AppErrors

关键代码

frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

void InputDispatcher::doNotifyAnrLockedInterruptible(CommandEntry* commandEntry) {
    sp<IBinder> token =
            commandEntry->inputChannel ? commandEntry->inputChannel->getConnectionToken() : nullptr;
    mLock.unlock();

    const nsecs_t timeoutExtension =
            mPolicy->notifyAnr(commandEntry->inputApplicationHandle, token, commandEntry->reason);

    mLock.lock();

    if (timeoutExtension > 0) {
        extendAnrTimeoutsLocked(commandEntry->inputApplicationHandle, token, timeoutExtension);
    } else {
        // stop waking up for events in this connection, it is already not responding
        sp<Connection> connection = getConnectionLocked(token);
        if (connection == nullptr) {
            return;
        }
        cancelEventsForAnrLocked(connection);
    }
}

void InputDispatcher::onAnrLocked(const sp<Connection>& connection) {
    // Since we are allowing the policy to extend the timeout, maybe the waitQueue
    // is already healthy again. Don't raise ANR in this situation
    if (connection->waitQueue.empty()) {
        ALOGI("Not raising ANR because the connection %s has recovered",
              connection->inputChannel->getName().c_str());
        return;
    }
    /**
     * The "oldestEntry" is the entry that was first sent to the application. That entry, however,
     * may not be the one that caused the timeout to occur. One possibility is that window timeout
     * has changed. This could cause newer entries to time out before the already dispatched
     * entries. In that situation, the newest entries caused ANR. But in all likelihood, the app
     * processes the events linearly. So providing information about the oldest entry seems to be
     * most useful.
     */
    DispatchEntry* oldestEntry = *connection->waitQueue.begin();
    const nsecs_t currentWait = now() - oldestEntry->deliveryTime;
    std::string reason =
            android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s",
                                        connection->inputChannel->getName().c_str(),
                                        ns2ms(currentWait),
                                        oldestEntry->eventEntry->getDescription().c_str());

    updateLastAnrStateLocked(getWindowHandleLocked(connection->inputChannel->getConnectionToken()),
                             reason);
    std::unique_ptr<CommandEntry> commandEntry =
            std::make_unique<CommandEntry>(&InputDispatcher::doNotifyAnrLockedInterruptible);
    commandEntry->inputApplicationHandle = nullptr;
    commandEntry->inputChannel = connection->inputChannel;
    commandEntry->reason = std::move(reason);
    postCommandLocked(std::move(commandEntry));
}

/**
 * Check if any of the connections' wait queues have events that are too old.
 * If we waited for events to be ack'ed for more than the window timeout, raise an ANR.
 * Return the time at which we should wake up next.
 */
nsecs_t InputDispatcher::processAnrsLocked() {
    const nsecs_t currentTime = now();
    nsecs_t nextAnrCheck = LONG_LONG_MAX;
    // Check if we are waiting for a focused window to appear. Raise ANR if waited too long
    if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
        if (currentTime >= *mNoFocusedWindowTimeoutTime) {
            onAnrLocked(mAwaitedFocusedApplication);
            mAwaitedFocusedApplication.clear();
            return LONG_LONG_MIN;
        } else {
            // Keep waiting
            const nsecs_t millisRemaining = ns2ms(*mNoFocusedWindowTimeoutTime - currentTime);
            ALOGW("Still no focused window. Will drop the event in %" PRId64 "ms", millisRemaining);
            nextAnrCheck = *mNoFocusedWindowTimeoutTime;
        }
    }

    // Check if any connection ANRs are due
    nextAnrCheck = std::min(nextAnrCheck, mAnrTracker.firstTimeout());
    if (currentTime < nextAnrCheck) { // most likely scenario
        return nextAnrCheck;          // everything is normal. Let's check again at nextAnrCheck
    }

    // If we reached here, we have an unresponsive connection.
    sp<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
    if (connection == nullptr) {
        ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
        return nextAnrCheck;
    }
    connection->responsive = false;
    // Stop waking up for this unresponsive connection
    mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken());
	//ANR触发位置
    onAnrLocked(connection);
    return LONG_LONG_MIN;
}

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();

        // Run a dispatch loop if there are no pending commands.
        // The dispatch loop might enqueue commands to run afterwards.
        if (!haveCommandsLocked()) {
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        // Run all pending commands if there are any.
        // If any commands were run then force the next poll to wake up immediately.
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }

        // If we are still waiting for ack on some events,
        // we might have to wake up earlier to check if an app is anr'ing.
        const nsecs_t nextAnrCheck = processAnrsLocked();
        nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);

        // We are about to enter an infinitely long sleep, because we have no commands or
        // pending or queued events
        if (nextWakeupTime == LONG_LONG_MAX) {
            mDispatcherEnteredIdle.notify_all();
        }
    } // release lock

    // Wait for callback or timeout or wake.  (make sure we round up, not down)
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis);
}

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

nsecs_t NativeInputManager::notifyAnr(const sp<InputApplicationHandle>& inputApplicationHandle,
                                      const sp<IBinder>& token, const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
    ALOGD("notifyANR");
#endif
    ATRACE_CALL();

    JNIEnv* env = jniEnv();
    ScopedLocalFrame localFrame(env);

    jobject inputApplicationHandleObj =
            getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);

    jobject tokenObj = javaObjectForIBinder(env, token);
    jstring reasonObj = env->NewStringUTF(reason.c_str());

    jlong newTimeout = env->CallLongMethod(mServiceObj,
            gServiceClassInfo.notifyANR, inputApplicationHandleObj, tokenObj,
                 reasonObj);
    if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
        newTimeout = 0; // abort dispatch
    } else {
        assert(newTimeout >= 0);
    }
    return newTimeout;
}


    GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
            "notifyANR",
            "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java


    // Native callback.
    private long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token,
            String reason) {
        return mWindowManagerCallbacks.notifyANR(inputApplicationHandle,
                token, reason);
    }

frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java

    /**
     * Notifies the window manager about an application that is not responding.
     * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
     *
     * Called by the InputManager.
     */
    @Override
    public long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token,
            String reason) {
        final long startTime = SystemClock.uptimeMillis();
        try {
            return notifyANRInner(inputApplicationHandle, token, reason);
        } finally {
            // Log the time because the method is called from InputDispatcher thread. It shouldn't
            // take too long that may affect input response time.
            Slog.d(TAG_WM, "notifyANR took " + (SystemClock.uptimeMillis() - startTime) + "ms");
        }
    }

    private long notifyANRInner(InputApplicationHandle inputApplicationHandle, IBinder token,
            String reason) {
        ActivityRecord activity = null;
        WindowState windowState = null;
        boolean aboveSystem = false;
        int windowPid = INVALID_PID;

        preDumpIfLockTooSlow();

        //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
        synchronized (mService.mGlobalLock) {

            // Check if we can blame a window
            if (token != null) {
                windowState = mService.mInputToWindowMap.get(token);
                if (windowState != null) {
                    activity = windowState.mActivityRecord;
                    windowPid = windowState.mSession.mPid;
                    // Figure out whether this window is layered above system windows.
                    // We need to do this here to help the activity manager know how to
                    // layer its ANR dialog.
                    aboveSystem = isWindowAboveSystem(windowState);
                }
            }

            // Check if we can blame an embedded window
            if (token != null && windowState == null) {
                EmbeddedWindow embeddedWindow = mService.mEmbeddedWindowController.get(token);
                if (embeddedWindow != null) {
                    windowPid = embeddedWindow.mOwnerPid;
                    WindowState hostWindowState = embeddedWindow.mHostWindowState;
                    if (hostWindowState == null) {
                        // The embedded window has no host window and we cannot easily determine
                        // its z order. Try to place the anr dialog as high as possible.
                        aboveSystem = true;
                    } else {
                        aboveSystem = isWindowAboveSystem(hostWindowState);
                    }
                }
            }

            // Check if we can blame an activity. If we don't have an activity to blame, pull out
            // the token passed in via input application handle. This can happen if there are no
            // focused windows but input dispatcher knows the focused app.
            if (activity == null && inputApplicationHandle != null) {
                activity = ActivityRecord.forTokenLocked(inputApplicationHandle.token);
            }

            if (windowState != null) {
                Slog.i(TAG_WM, "Input event dispatching timed out "
                        + "sending to " + windowState.mAttrs.getTitle()
                        + ".  Reason: " + reason);
            } else if (activity != null) {
                Slog.i(TAG_WM, "Input event dispatching timed out "
                        + "sending to application " + activity.stringName
                        + ".  Reason: " + reason);
            } else {
                Slog.i(TAG_WM, "Input event dispatching timed out "
                        + ".  Reason: " + reason);
            }

            mService.saveANRStateLocked(activity, windowState, reason);
        }

        // All the calls below need to happen without the WM lock held since they call into AM.
        mService.mAtmInternal.saveANRState(reason);

        if (activity != null && activity.appToken != null) {
            // Notify the activity manager about the timeout and let it decide whether
            // to abort dispatching or keep waiting.
            final boolean abort = activity.keyDispatchingTimedOut(reason, windowPid);
            if (!abort) {
                // The activity manager declined to abort dispatching.
                // Wait a bit longer and timeout again later.
                return activity.mInputDispatchingTimeoutNanos;
            }
        } else if (windowState != null || windowPid != INVALID_PID) {
            // Notify the activity manager about the timeout and let it decide whether
            // to abort dispatching or keep waiting.
            long timeout = mService.mAmInternal.inputDispatchingTimedOut(windowPid, aboveSystem,
                    reason);
            if (timeout >= 0) {
                // The activity manager declined to abort dispatching.
                // Wait a bit longer and timeout again later.
                return timeout * 1000000L; // nanoseconds
            }
        }
        return 0; // abort dispatching
    }


frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
        if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires permission " + FILTER_EVENTS);
        }
        ProcessRecord proc;
        long timeout;
        synchronized (this) {
            synchronized (mPidsSelfLocked) {
                proc = mPidsSelfLocked.get(pid);
            }
            timeout = proc != null ? proc.getInputDispatchingTimeout() : KEY_DISPATCHING_TIMEOUT_MS;
        }

        if (inputDispatchingTimedOut(proc, null, null, null, null, aboveSystem, reason)) {
            return -1;
        }

        return timeout;
    }

    final class UiHandler extends Handler {
        //Ignored....
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SHOW_ERROR_UI_MSG: {
                    mAppErrors.handleShowAppErrorUi(msg);
                    ensureBootCompleted();
                } break;
                case SHOW_NOT_RESPONDING_UI_MSG: {
                    mAppErrors.handleShowAnrUi(msg);
                    ensureBootCompleted();
                } break;
        //Ignored .....
     }

frameworks/base/services/core/java/com/android/server/am/AnrHelper.java

    void appNotResponding(ProcessRecord anrProcess, String annotation) {
        appNotResponding(anrProcess, null /* activityShortComponentName */, null /* aInfo */,
                null /* parentShortComponentName */, null /* parentProcess */,
                false /* aboveSystem */, annotation);
    }

    void appNotResponding(ProcessRecord anrProcess, String activityShortComponentName,
            ApplicationInfo aInfo, String parentShortComponentName,
            WindowProcessController parentProcess, boolean aboveSystem, String annotation) {
        synchronized (mAnrRecords) {
            mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,
                    parentShortComponentName, parentProcess, aboveSystem, annotation));
        }
        startAnrConsumerIfNeeded();
    }

    private void startAnrConsumerIfNeeded() {
        if (mRunning.compareAndSet(false, true)) {
            new AnrConsumerThread().start();
        }
    }

frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java

    void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
            String parentShortComponentName, WindowProcessController parentProcess,
            boolean aboveSystem, String annotation, boolean onlyDumpSelf) {
        //Ignored...

            // mUiHandler can be null if the AMS is constructed with injector only. This will only
            // happen in tests.
            if (mService.mUiHandler != null) {
                // Bring up the infamous App Not Responding dialog
                Message msg = Message.obtain();
                msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
                msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);

                mService.mUiHandler.sendMessage(msg);
            }
        }
    }
    
class ErrorDialogControlle
        //AppErrors 调用
        void showAnrDialogs(AppNotRespondingDialog.Data data) {
            List<Context> contexts = getDisplayContexts(isSilentAnr() /* lastUsedOnly */);
            mAnrDialogs = new ArrayList<>();
            for (int i = contexts.size() - 1; i >= 0; i--) {
                final Context c = contexts.get(i);
                mAnrDialogs.add(new AppNotRespondingDialog(mService, c, data));
            }
            mService.mUiHandler.post(() -> {
                List<AppNotRespondingDialog> dialogs;
                synchronized (mService) {
                    dialogs = mAnrDialogs;
                }
                if (dialogs != null) {
                    forAllDialogs(dialogs, Dialog::show);
                }
            });
        }

frameworks/base/services/core/java/com/android/server/am/AppErrors.java

    void handleShowAnrUi(Message msg) {
        List<VersionedPackage> packageList = null;
        synchronized (mService) {
            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
            final ProcessRecord proc = data.proc;
            if (proc == null) {
                Slog.e(TAG, "handleShowAnrUi: proc is null");
                return;
            }
            if (!proc.isPersistent()) {
                packageList = proc.getPackageListWithVersionCode();
            }
            if (proc.getDialogController().hasAnrDialogs()) {
                Slog.e(TAG, "App already has anr dialog: " + proc);
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.ALREADY_SHOWING);
                return;
            }

            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
            if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
                proc.getDialogController().showAnrDialogs(data);
                //Ignored .....
   }

frameworks/base/services/core/java/com/android/server/am/AppNotRespondingDialog.java
对话框的代码就省略吧.

至此, 显示ANR对话框的流程走完
 


InputDispatcher中窗口句柄

SurfaceFlinger InputManager InputDispatcher updateInputFlinger updateInputWindowInfo setInputWindows setInputWindowsLocked SurfaceFlinger InputManager InputDispatcher

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::updateInputFlinger() {
    ATRACE_CALL();
    if (!mInputFlinger) {
        return;
    }

    if (mVisibleRegionsDirty || mInputInfoChanged) {
        mInputInfoChanged = false;
        updateInputWindowInfo();
    } else if (mInputWindowCommands.syncInputWindows) {
        // If the caller requested to sync input windows, but there are no
        // changes to input windows, notify immediately.
        setInputWindowsFinished();
    }

    mInputWindowCommands.clear();
}

void SurfaceFlinger::updateInputWindowInfo() {
    std::vector<InputWindowInfo> inputHandles;

    mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
        if (layer->needsInputInfo()) {
            // When calculating the screen bounds we ignore the transparent region since it may
            // result in an unwanted offset.
            inputHandles.push_back(layer->fillInputInfo());
        }
    });

    mInputFlinger->setInputWindows(inputHandles,
                                   mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener
                                                                         : nullptr);
}

frameworks/native/services/inputflinger/InputManager.cpp

void InputManager::setInputWindows(const std::vector<InputWindowInfo>& infos,
        const sp<ISetInputWindowsListener>& setInputWindowsListener) {
    std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> handlesPerDisplay;

    std::vector<sp<InputWindowHandle>> handles;
    for (const auto& info : infos) {
        handlesPerDisplay.emplace(info.displayId, std::vector<sp<InputWindowHandle>>());
        handlesPerDisplay[info.displayId].push_back(new BinderWindowHandle(info));
    }
    mDispatcher->setInputWindows(handlesPerDisplay);

    if (setInputWindowsListener) {
        setInputWindowsListener->onSetInputWindowsFinished();
    }
}

frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

///
//  通过InputManagerService 添加窗口句柄        //
///
/** 
 * Called from InputManagerService, update window handle list by displayId that can receive input.
 * A window handle contains information about InputChannel, Touch Region, Types, Focused,...
 * If set an empty list, remove all handles from the specific display.
 * For focused handle, check if need to change and send a cancel event to previous one.
 * For removed handle, check if need to send a cancel event if already in touch.
 */
void InputDispatcher::setInputWindowsLocked(){
	updateWindowHandlesForDisplayLocked...
}
///
//   更新mWindowHandlesByDisplay中            //
///
void InputDispatcher::updateWindowHandlesForDisplayLocked(
        const std::vector<sp<InputWindowHandle>>& inputWindowHandles, int32_t displayId) {
    //Ignored.....
    // Insert or replace
    mWindowHandlesByDisplay[displayId] = newHandles;
}

///
//  从mWindowHandlesByDisplay中查询当前窗口     //
///
sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
        const sp<IBinder>& windowHandleToken) const {
    if (windowHandleToken == nullptr) {
        return nullptr;
    }

    for (auto& it : mWindowHandlesByDisplay) {
        const std::vector<sp<InputWindowHandle>> windowHandles = it.second;
        for (const sp<InputWindowHandle>& windowHandle : windowHandles) {
            if (windowHandle->getToken() == windowHandleToken) {
                return windowHandle;
            }
        }
    }
    return nullptr;
}

nsecs_t InputDispatcher::getDispatchingTimeoutLocked(const sp<IBinder>& token) {
    sp<InputWindowHandle> window = getWindowHandleLocked(token);
    if (window != nullptr) {
        return window->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT).count();
    }
    return DEFAULT_INPUT_DISPATCHING_TIMEOUT.count();
}

frameworks/base/services/core/java/com/android/server/wm/WindowProcessController.java

    public long getInputDispatchingTimeout() {
        synchronized (mAtm.mGlobalLock) {
            return isInstrumenting() || isUsingWrapper()
                    ? INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS : KEY_DISPATCHING_TIMEOUT_MS;
        }
    }

frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java

    public long getInputDispatchingTimeout() {
        return mWindowProcessController.getInputDispatchingTimeout();
    }

扩展

编译及替换

#编译
mmm frameworks/native/services/inputflinger/ -j2

#替换
adb push out/target/product/rk3566_r/system/bin/inputflinger /system/bin/
adb push out/target/product/rk3566_r/system/lib/libinputflinger.so /system/lib/
adb push out/target/product/rk3566_r/system/lib64/libinputflinger.so /system/lib64/

调试: adb shell dumpsys input

      0: name='Window{57ce99a u0 NavigationBar0}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x21840068, type=0x000007e3, frame=[0,752][1280,800], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[0,752][1280,800], inputFeatures=0x00000000, ownerPid=614, ownerUid=10119, dispatchingTimeout=7000ms
      1: name='Window{61c1033 u0 StatusBar}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x81800408, type=0x000007d0, frame=[0,0][1280,24], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[0,0][1280,24], inputFeatures=0x00000000, ownerPid=614, ownerUid=10119, dispatchingTimeout=7000ms
      2: name='Window{e0e47c4 u0 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=true, hasWallpaper=true, visible=true, canReceiveKeys=true, flags=0x81910120, type=0x00000001, frame=[0,0][1280,800], globalScale=1.000000, windowScale=(1.000000,1.000000), touchableRegion=[0,0][1280,800], inputFeatures=0x00000000, ownerPid=1039, ownerUid=10121, dispatchingTimeout=15000ms
      3: name='Window{bbadc9c u0 com.android.systemui.ImageWallpaper}', displayId=0, portalToDisplayId=-1, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x00014318, type=0x000007dd, frame=[-64,-304][1344,1104], globalScale=1.000000, windowScale=(0.909091,0.909091), touchableRegion=[-64,-304][1344,1104], inputFeatures=0x00000000, ownerPid=614, ownerUid=10119, dispatchingTimeout=7000ms

参考

ANR
Android ANR:原理分析及解决办法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值