안드로이드 휴면 프로세스의 한 가지 이해

9388 단어
1. 전원 관리는 디스플레이의 상태를 모니터링하고 화면을 끄면 휴면 절차를 시작하고native층을 호출하는 방법으로 계속 아래로 내려간다.먼저 Display PowerController에서 MSG 수신UPDATE_POWER_STATE 소식은 Display Blanker 인터페이스의 Request Display State를 일련의 리셋을 거쳤다.다음은 디스플레이 PowerCallbacks 인터페이스의 온디스플레이 StateChange 방법입니다.
        @Override
        public void onDisplayStateChange(int state) {
            // This method is only needed to support legacy display blanking behavior
            // where the display's power state is coupled to suspend or to the power HAL.
            // The order of operations matters here.
            synchronized (mLock) {
                if (mDisplayState != state) {
                    mDisplayState = state;
                    if (state == Display.STATE_OFF) {
                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
                            setHalInteractiveModeLocked(false);
                        }
                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
                            setHalAutoSuspendModeLocked(true);
                        }
                    } else {
                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
                            setHalAutoSuspendModeLocked(false);
                        }
                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
                            setHalInteractiveModeLocked(true);
                        }
                    }
                }
            }
        }

우리 회사의 방안에서는 기본적으로 결합되지 않는 방안이다.그래서 업데이트 PowerState Locked update Suspend Blocker Locked();그곳에서는 휴면 프로세스를 시작하지 않고 디스플레이 state에서change가 발생할 때 디스플레이 상태와 연결됩니다.false
    
    false

2. setHal AutoSuspend Mode Locked는 시스템이 즉시 휴면에 들어가는지 제어할 수 없습니다. 휴면에 들어가는지 깨우는지 여부는 다른native Acquire Suspend Blocker와native Release Suspend Blocker가 Suspend Blocker를 방출하는지 여부에 따라 결정됩니다.함수 이름에서 말한 바와 같이 이것은 1급 제어 스위치입니다. enable or disable, enable가 있어야 휴면을 할 수 있습니다./sys/power/state에서 응용층이 설정한 지원 가능한 휴면 모드입니다. 현재 p의gtvs버전은 항상freeze mem입니다.
static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
    if (enable) {
        android::base::Timer t;
        autosuspend_enable();
        if (t.duration() > 100ms) {
            ALOGD("Excessive delay in autosuspend_enable() while turning screen off");
        }
    } else {
        android::base::Timer t;
        autosuspend_disable();
        if (t.duration() > 100ms) {
            ALOGD("Excessive delay in autosuspend_disable() while turning screen on");
        }
    }
}
static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
    ScopedUtfChars name(env, nameStr);
    acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}

static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass /* clazz */, jstring nameStr) {
    ScopedUtfChars name(env, nameStr);
    release_wake_lock(name.c_str());
}

 
3.native Acquire Suspend Blocker와native Release Suspend Blocker.BlockSuspender aquire와release에서 이 두 jni의 함수를 호출하고 그 안에서 Hardware/libhardware 를 통과합니다legacy/power.c에 있는 두 개의 광범위한 함수 acquirewake_lock 및 releasewake_lock, 대응하는suspender의 이름을/sys/power/wake 에 쓰기lock 및/sys/power/wakeunlock 안에서 kernel이 상응하는 깨우기와 수면 동작을 모니터링합니다.이전에는 응용층이 계수의 효과일 뿐이라고 오해했다. 이 BlockSuspender는 실제로kernel이 사용자 상태에 개방된 노드를 직접 제어할 수 있다는 것을 무시했다. 처음에 봤을 때도 이 뚜렷한 PMS를 쓴 자물쇠의 위치를 찾지 못했다.
        @Override
        public void acquire() {
            synchronized (this) {
                mReferenceCount += 1;
                if (mReferenceCount == 1) {
                    if (DEBUG_SPEW) {
                        Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");
                    }
                    Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
                    nativeAcquireSuspendBlocker(mName);
                }
            }
        }

        @Override
        public void release() {
            synchronized (this) {
                mReferenceCount -= 1;
                if (mReferenceCount == 0) {
                    if (DEBUG_SPEW) {
                        Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");
                    }
                    nativeReleaseSuspendBlocker(mName);
                    Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
                } else if (mReferenceCount < 0) {
                    Slog.wtf(TAG, "Suspend blocker \"" + mName
                            + "\" was released without being acquired!", new Throwable());
                    mReferenceCount = 0;
                }
            }
        }
enum {
    ACQUIRE_PARTIAL_WAKE_LOCK = 0,
    RELEASE_WAKE_LOCK,
    OUR_FD_COUNT
};

const char * const OLD_PATHS[] = {
    "/sys/android_power/acquire_partial_wake_lock",
    "/sys/android_power/release_wake_lock",
};

const char * const NEW_PATHS[] = {
    "/sys/power/wake_lock",
    "/sys/power/wake_unlock",
};
int
acquire_wake_lock(int lock, const char* id)
{
    initialize_fds();

//    ALOGI("acquire_wake_lock lock=%d id='%s'
", lock, id); if (g_error) return g_error; int fd; ssize_t ret; if (lock != PARTIAL_WAKE_LOCK) { return -EINVAL; } fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK]; ret = write(fd, id, strlen(id)); if (ret < 0) { return -errno; } return ret; } int release_wake_lock(const char* id) { initialize_fds(); // ALOGI("release_wake_lock id='%s'
", id); if (g_error) return g_error; ssize_t len = write(g_fds[RELEASE_WAKE_LOCK], id, strlen(id)); if (len < 0) { return -errno; } return len; }

4. setHalAutoSuspendModeLocked에서 아래로 내려가면 시스템/core/libsuspend 아래로 이동합니다.enable 및 disable 최종 대응 autosuspend_wakeup_count.cpp 내 autosuspendwakeup_count_enable 및 autosuspendwakeup_count_disable 함수.이 안은 신호량을 통해 동기 스위치를 제어하는 것이고, enable는sempost Wake 열기count의 쓰기 제어,disable는semwait가 막혔습니다.enable에서mem을/sys/power/state에 쓰고sys/power/wakeupcount를 읽고 다시 써도 왜 그런지 모르겠어요.
static int autosuspend_wakeup_count_enable(void) {
    LOG(VERBOSE) << "autosuspend_wakeup_count_enable";

    int ret = autosuspend_init();
    if (ret < 0) {
        LOG(ERROR) << "autosuspend_init failed";
        return ret;
    }

    ret = sem_post(&suspend_lockout);
    if (ret < 0) {
        PLOG(ERROR) << "error changing semaphore";
    }

    LOG(VERBOSE) << "autosuspend_wakeup_count_enable done";

    return ret;
}

static int autosuspend_wakeup_count_disable(void) {
    LOG(VERBOSE) << "autosuspend_wakeup_count_disable";

    if (!autosuspend_is_init) {
        return 0;  // always successful if no thread is running yet
    }

    int ret = sem_wait(&suspend_lockout);

    if (ret < 0) {
        PLOG(ERROR) << "error changing semaphore";
    }

    LOG(VERBOSE) << "autosuspend_wakeup_count_disable done";

    return ret;
}
        LOG(VERBOSE) << "wait";
        int ret = sem_wait(&suspend_lockout);
        if (ret < 0) {
            PLOG(ERROR) << "error waiting on semaphore";
            continue;
        }

        LOG(VERBOSE) << "write " << wakeup_count << " to wakeup_count";
        if (WriteStringToFd(wakeup_count, wakeup_count_fd)) {
            LOG(VERBOSE) << "write " << sleep_state << " to " << sys_power_state;
            success = WriteStringToFd(sleep_state, state_fd);

            void (*func)(bool success) = wakeup_func;
            if (func != NULL) {
                (*func)(success);
            }
        } else {
            PLOG(ERROR) << "error writing to " << sys_power_wakeup_count;
        }

        LOG(VERBOSE) << "release sem";
        ret = sem_post(&suspend_lockout);

 
5. 위 절차에서 휴면할 때 장치 노드/sys/power/state에mem를 쓰는 작업을 완성했고kernel에 이 장치 노드에 대한 작업 함수를 등록했습니다.후속 각성원의 조건이 충족되면 휴면에 들어갈 수 있다.

좋은 웹페이지 즐겨찾기