Merge changes from topic "native_hint" into sc-dev am: ea52c87596 am: 9533a3db22
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15326475 Change-Id: If8502e41cbc2cf88b6ed9634741e57f066ab3652
This commit is contained in:
@@ -158,7 +158,6 @@ import android.os.IBatteryPropertiesRegistrar;
|
||||
import android.os.IBinder;
|
||||
import android.os.IDumpstate;
|
||||
import android.os.IHardwarePropertiesManager;
|
||||
import android.os.IHintManager;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.IRecoverySystem;
|
||||
import android.os.ISystemUpdateManager;
|
||||
@@ -600,10 +599,7 @@ public final class SystemServiceRegistry {
|
||||
@Override
|
||||
public PerformanceHintManager createService(ContextImpl ctx)
|
||||
throws ServiceNotFoundException {
|
||||
IBinder hintBinder = ServiceManager.getServiceOrThrow(
|
||||
Context.PERFORMANCE_HINT_SERVICE);
|
||||
IHintManager hintService = IHintManager.Stub.asInterface(hintBinder);
|
||||
return new PerformanceHintManager(hintService);
|
||||
return PerformanceHintManager.create();
|
||||
}});
|
||||
|
||||
registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
|
||||
|
||||
@@ -24,24 +24,23 @@ import android.content.Context;
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/** The PerformanceHintManager allows apps to send performance hint to system. */
|
||||
@SystemService(Context.PERFORMANCE_HINT_SERVICE)
|
||||
public final class PerformanceHintManager {
|
||||
private static final String TAG = "PerformanceHintManager";
|
||||
private final IHintManager mService;
|
||||
// HAL preferred update rate
|
||||
private final long mPreferredRate;
|
||||
private final long mNativeManagerPtr;
|
||||
|
||||
/** @hide */
|
||||
public PerformanceHintManager(IHintManager service) {
|
||||
mService = service;
|
||||
try {
|
||||
mPreferredRate = mService.getHintSessionPreferredRate();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
public static PerformanceHintManager create() throws ServiceManager.ServiceNotFoundException {
|
||||
long nativeManagerPtr = nativeAcquireManager();
|
||||
if (nativeManagerPtr == 0) {
|
||||
throw new ServiceManager.ServiceNotFoundException(Context.PERFORMANCE_HINT_SERVICE);
|
||||
}
|
||||
return new PerformanceHintManager(nativeManagerPtr);
|
||||
}
|
||||
|
||||
private PerformanceHintManager(long nativeManagerPtr) {
|
||||
mNativeManagerPtr = nativeManagerPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,16 +56,13 @@ public final class PerformanceHintManager {
|
||||
*/
|
||||
@Nullable
|
||||
public Session createHintSession(@NonNull int[] tids, long initialTargetWorkDurationNanos) {
|
||||
try {
|
||||
IBinder token = new Binder();
|
||||
IHintSession session = mService.createHintSession(token, tids,
|
||||
initialTargetWorkDurationNanos);
|
||||
if (session == null) return null;
|
||||
return new Session(session, sNanoClock, mPreferredRate,
|
||||
initialTargetWorkDurationNanos);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
Preconditions.checkNotNull(tids, "tids cannot be null");
|
||||
Preconditions.checkArgumentPositive(initialTargetWorkDurationNanos,
|
||||
"the hint target duration should be positive.");
|
||||
long nativeSessionPtr = nativeCreateSession(mNativeManagerPtr, tids,
|
||||
initialTargetWorkDurationNanos);
|
||||
if (nativeSessionPtr == 0) return null;
|
||||
return new Session(nativeSessionPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +71,7 @@ public final class PerformanceHintManager {
|
||||
* @return the preferred update rate supported by device software.
|
||||
*/
|
||||
public long getPreferredUpdateRateNanos() {
|
||||
return mPreferredRate;
|
||||
return nativeGetPreferredUpdateRateNanos(mNativeManagerPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,28 +97,21 @@ public final class PerformanceHintManager {
|
||||
* <p>All timings should be in {@link SystemClock#elapsedRealtimeNanos()}.</p>
|
||||
*/
|
||||
public static class Session implements Closeable {
|
||||
private final IHintSession mSession;
|
||||
private final NanoClock mElapsedRealtimeClock;
|
||||
// Target duration for choosing update rate
|
||||
private long mTargetDurationInNanos;
|
||||
// HAL preferred update rate
|
||||
private long mPreferredRate;
|
||||
// Last update timestamp
|
||||
private long mLastUpdateTimeStamp = -1L;
|
||||
// Cached samples
|
||||
private final ArrayList<Long> mActualDurationNanos;
|
||||
private final ArrayList<Long> mTimeStampNanos;
|
||||
private long mNativeSessionPtr;
|
||||
|
||||
/** @hide */
|
||||
public Session(IHintSession session, NanoClock elapsedRealtimeClock, long preferredRate,
|
||||
long durationNanos) {
|
||||
mSession = session;
|
||||
mElapsedRealtimeClock = elapsedRealtimeClock;
|
||||
mTargetDurationInNanos = durationNanos;
|
||||
mPreferredRate = preferredRate;
|
||||
mActualDurationNanos = new ArrayList<Long>();
|
||||
mTimeStampNanos = new ArrayList<Long>();
|
||||
mLastUpdateTimeStamp = mElapsedRealtimeClock.nanos();
|
||||
public Session(long nativeSessionPtr) {
|
||||
mNativeSessionPtr = nativeSessionPtr;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
close();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,19 +122,7 @@ public final class PerformanceHintManager {
|
||||
public void updateTargetWorkDuration(long targetDurationNanos) {
|
||||
Preconditions.checkArgumentPositive(targetDurationNanos, "the hint target duration"
|
||||
+ " should be positive.");
|
||||
try {
|
||||
mSession.updateTargetWorkDuration(targetDurationNanos);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
mTargetDurationInNanos = targetDurationNanos;
|
||||
/**
|
||||
* Most of the workload is target_duration dependent, so now clear the cached samples
|
||||
* as they are most likely obsolete.
|
||||
*/
|
||||
mActualDurationNanos.clear();
|
||||
mTimeStampNanos.clear();
|
||||
mLastUpdateTimeStamp = mElapsedRealtimeClock.nanos();
|
||||
nativeUpdateTargetWorkDuration(mNativeSessionPtr, targetDurationNanos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,38 +138,7 @@ public final class PerformanceHintManager {
|
||||
public void reportActualWorkDuration(long actualDurationNanos) {
|
||||
Preconditions.checkArgumentPositive(actualDurationNanos, "the actual duration should"
|
||||
+ " be positive.");
|
||||
final long now = mElapsedRealtimeClock.nanos();
|
||||
mActualDurationNanos.add(actualDurationNanos);
|
||||
mTimeStampNanos.add(now);
|
||||
|
||||
/**
|
||||
* Use current sample to determine the rate limit. We can pick a shorter rate limit
|
||||
* if any sample underperformed, however, it could be the lower level system is slow
|
||||
* to react. So here we explicitly choose the rate limit with the latest sample.
|
||||
*/
|
||||
long rateLimit =
|
||||
actualDurationNanos > mTargetDurationInNanos ? mPreferredRate
|
||||
: 10 * mPreferredRate;
|
||||
|
||||
if (now - mLastUpdateTimeStamp <= rateLimit) {
|
||||
return;
|
||||
}
|
||||
Preconditions.checkState(mActualDurationNanos.size() == mTimeStampNanos.size());
|
||||
final int size = mActualDurationNanos.size();
|
||||
long[] actualDurationArray = new long[size];
|
||||
long[] timeStampArray = new long[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
actualDurationArray[i] = mActualDurationNanos.get(i);
|
||||
timeStampArray[i] = mTimeStampNanos.get(i);
|
||||
}
|
||||
try {
|
||||
mSession.reportActualWorkDuration(actualDurationArray, timeStampArray);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
mActualDurationNanos.clear();
|
||||
mTimeStampNanos.clear();
|
||||
mLastUpdateTimeStamp = now;
|
||||
nativeReportActualWorkDuration(mNativeSessionPtr, actualDurationNanos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,26 +147,20 @@ public final class PerformanceHintManager {
|
||||
* <p>Once called, you should not call anything else on this object.</p>
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
mSession.close();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
if (mNativeSessionPtr != 0) {
|
||||
nativeCloseSession(mNativeSessionPtr);
|
||||
mNativeSessionPtr = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The interface is to make the FakeClock for testing.
|
||||
* @hide
|
||||
*/
|
||||
public interface NanoClock {
|
||||
/** Gets the current nanosecond instant of the clock. */
|
||||
long nanos();
|
||||
}
|
||||
|
||||
private static final NanoClock sNanoClock = new NanoClock() {
|
||||
public long nanos() {
|
||||
return SystemClock.elapsedRealtimeNanos();
|
||||
}
|
||||
};
|
||||
private static native long nativeAcquireManager();
|
||||
private static native long nativeGetPreferredUpdateRateNanos(long nativeManagerPtr);
|
||||
private static native long nativeCreateSession(long nativeManagerPtr,
|
||||
int[] tids, long initialTargetWorkDurationNanos);
|
||||
private static native void nativeUpdateTargetWorkDuration(long nativeSessionPtr,
|
||||
long targetDurationNanos);
|
||||
private static native void nativeReportActualWorkDuration(long nativeSessionPtr,
|
||||
long actualDurationNanos);
|
||||
private static native void nativeCloseSession(long nativeSessionPtr);
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ cc_library_shared {
|
||||
"android_os_MemoryFile.cpp",
|
||||
"android_os_MessageQueue.cpp",
|
||||
"android_os_Parcel.cpp",
|
||||
"android_os_PerformanceHintManager.cpp",
|
||||
"android_os_SELinux.cpp",
|
||||
"android_os_ServiceManager.cpp",
|
||||
"android_os_SharedMemory.cpp",
|
||||
|
||||
@@ -144,6 +144,7 @@ extern int register_android_os_NativeHandle(JNIEnv *env);
|
||||
extern int register_android_os_ServiceManager(JNIEnv *env);
|
||||
extern int register_android_os_MessageQueue(JNIEnv* env);
|
||||
extern int register_android_os_Parcel(JNIEnv* env);
|
||||
extern int register_android_os_PerformanceHintManager(JNIEnv* env);
|
||||
extern int register_android_os_SELinux(JNIEnv* env);
|
||||
extern int register_android_os_VintfObject(JNIEnv *env);
|
||||
extern int register_android_os_VintfRuntimeInfo(JNIEnv *env);
|
||||
@@ -1523,6 +1524,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_os_SystemProperties),
|
||||
REG_JNI(register_android_os_Binder),
|
||||
REG_JNI(register_android_os_Parcel),
|
||||
REG_JNI(register_android_os_PerformanceHintManager),
|
||||
REG_JNI(register_android_os_HidlMemory),
|
||||
REG_JNI(register_android_os_HidlSupport),
|
||||
REG_JNI(register_android_os_HwBinder),
|
||||
|
||||
155
core/jni/android_os_PerformanceHintManager.cpp
Normal file
155
core/jni/android_os_PerformanceHintManager.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "PerfHint-jni"
|
||||
|
||||
#include "jni.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <nativehelper/ScopedPrimitiveArray.h>
|
||||
#include <utils/Log.h>
|
||||
#include <vector>
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
namespace {
|
||||
|
||||
struct APerformanceHintManager;
|
||||
struct APerformanceHintSession;
|
||||
|
||||
typedef APerformanceHintManager* (*APH_getManager)();
|
||||
typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
|
||||
size_t, int64_t);
|
||||
typedef int64_t (*APH_getPreferredUpdateRateNanos)(APerformanceHintManager* manager);
|
||||
typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
|
||||
typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
|
||||
typedef void (*APH_closeSession)(APerformanceHintSession* session);
|
||||
|
||||
bool gAPerformanceHintBindingInitialized = false;
|
||||
APH_getManager gAPH_getManagerFn = nullptr;
|
||||
APH_createSession gAPH_createSessionFn = nullptr;
|
||||
APH_getPreferredUpdateRateNanos gAPH_getPreferredUpdateRateNanosFn = nullptr;
|
||||
APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
|
||||
APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
|
||||
APH_closeSession gAPH_closeSessionFn = nullptr;
|
||||
|
||||
void ensureAPerformanceHintBindingInitialized() {
|
||||
if (gAPerformanceHintBindingInitialized) return;
|
||||
|
||||
void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
|
||||
LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
|
||||
|
||||
gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
|
||||
"Failed to find required symbol APerformanceHint_getManager!");
|
||||
|
||||
gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
|
||||
"Failed to find required symbol APerformanceHint_createSession!");
|
||||
|
||||
gAPH_getPreferredUpdateRateNanosFn =
|
||||
(APH_getPreferredUpdateRateNanos)dlsym(handle_,
|
||||
"APerformanceHint_getPreferredUpdateRateNanos");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_getPreferredUpdateRateNanosFn == nullptr,
|
||||
"Failed to find required symbol "
|
||||
"APerformanceHint_getPreferredUpdateRateNanos!");
|
||||
|
||||
gAPH_updateTargetWorkDurationFn =
|
||||
(APH_updateTargetWorkDuration)dlsym(handle_,
|
||||
"APerformanceHint_updateTargetWorkDuration");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_updateTargetWorkDurationFn == nullptr,
|
||||
"Failed to find required symbol "
|
||||
"APerformanceHint_updateTargetWorkDuration!");
|
||||
|
||||
gAPH_reportActualWorkDurationFn =
|
||||
(APH_reportActualWorkDuration)dlsym(handle_,
|
||||
"APerformanceHint_reportActualWorkDuration");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_reportActualWorkDurationFn == nullptr,
|
||||
"Failed to find required symbol "
|
||||
"APerformanceHint_reportActualWorkDuration!");
|
||||
|
||||
gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
|
||||
LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
|
||||
"Failed to find required symbol APerformanceHint_closeSession!");
|
||||
|
||||
gAPerformanceHintBindingInitialized = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
static jlong nativeAcquireManager(JNIEnv* env, jclass clazz) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
return reinterpret_cast<jlong>(gAPH_getManagerFn());
|
||||
}
|
||||
|
||||
static jlong nativeGetPreferredUpdateRateNanos(JNIEnv* env, jclass clazz, jlong nativeManagerPtr) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
return gAPH_getPreferredUpdateRateNanosFn(
|
||||
reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr));
|
||||
}
|
||||
|
||||
static jlong nativeCreateSession(JNIEnv* env, jclass clazz, jlong nativeManagerPtr, jintArray tids,
|
||||
jlong initialTargetWorkDurationNanos) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
if (tids == nullptr) return 0;
|
||||
std::vector<int32_t> tidsVector;
|
||||
ScopedIntArrayRO tidsArray(env, tids);
|
||||
for (size_t i = 0; i < tidsArray.size(); ++i) {
|
||||
tidsVector.push_back(static_cast<int32_t>(tidsArray[i]));
|
||||
}
|
||||
return reinterpret_cast<jlong>(
|
||||
gAPH_createSessionFn(reinterpret_cast<APerformanceHintManager*>(nativeManagerPtr),
|
||||
tidsVector.data(), tidsVector.size(),
|
||||
initialTargetWorkDurationNanos));
|
||||
}
|
||||
|
||||
static void nativeUpdateTargetWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
|
||||
jlong targetDurationNanos) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
gAPH_updateTargetWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
|
||||
targetDurationNanos);
|
||||
}
|
||||
|
||||
static void nativeReportActualWorkDuration(JNIEnv* env, jclass clazz, jlong nativeSessionPtr,
|
||||
jlong actualDurationNanos) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
gAPH_reportActualWorkDurationFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr),
|
||||
actualDurationNanos);
|
||||
}
|
||||
|
||||
static void nativeCloseSession(JNIEnv* env, jclass clazz, jlong nativeSessionPtr) {
|
||||
ensureAPerformanceHintBindingInitialized();
|
||||
gAPH_closeSessionFn(reinterpret_cast<APerformanceHintSession*>(nativeSessionPtr));
|
||||
}
|
||||
|
||||
static const JNINativeMethod gPerformanceHintMethods[] = {
|
||||
{"nativeAcquireManager", "()J", (void*)nativeAcquireManager},
|
||||
{"nativeGetPreferredUpdateRateNanos", "(J)J", (void*)nativeGetPreferredUpdateRateNanos},
|
||||
{"nativeCreateSession", "(J[IJ)J", (void*)nativeCreateSession},
|
||||
{"nativeUpdateTargetWorkDuration", "(JJ)V", (void*)nativeUpdateTargetWorkDuration},
|
||||
{"nativeReportActualWorkDuration", "(JJ)V", (void*)nativeReportActualWorkDuration},
|
||||
{"nativeCloseSession", "(J)V", (void*)nativeCloseSession},
|
||||
};
|
||||
|
||||
int register_android_os_PerformanceHintManager(JNIEnv* env) {
|
||||
return RegisterMethodsOrDie(env, "android/os/PerformanceHintManager", gPerformanceHintMethods,
|
||||
NELEM(gPerformanceHintMethods));
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
@@ -22,12 +22,6 @@ import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.os.PerformanceHintManager.Session;
|
||||
|
||||
@@ -119,93 +113,10 @@ public class PerformanceHintManagerTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRateLimitWithDurationFastEnough() throws Exception {
|
||||
FakeClock fakeClock = new FakeClock();
|
||||
Session s = new Session(mIHintSessionMock, fakeClock, RATE_1000, TARGET_166);
|
||||
|
||||
reset(mIHintSessionMock);
|
||||
fakeClock.setNow(0);
|
||||
s.updateTargetWorkDuration(TARGET_166);
|
||||
|
||||
s.reportActualWorkDuration(TARGET_166 - 1);
|
||||
s.reportActualWorkDuration(TARGET_166);
|
||||
// we should not see update as the rate should be 10X for over-perform case.
|
||||
verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
|
||||
fakeClock.incrementClock(10 * RATE_1000);
|
||||
s.reportActualWorkDuration(TARGET_166);
|
||||
verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
|
||||
fakeClock.incrementClock(1);
|
||||
s.reportActualWorkDuration(TARGET_166);
|
||||
// we should see update after rate limit
|
||||
verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
|
||||
eq(new long[] {TARGET_166 - 1, TARGET_166, TARGET_166, TARGET_166}),
|
||||
eq(new long[] {0, 0, 10 * RATE_1000, 10 * RATE_1000 + 1}));
|
||||
|
||||
reset(mIHintSessionMock);
|
||||
s.reportActualWorkDuration(TARGET_166);
|
||||
s.reportActualWorkDuration(TARGET_166 - 1);
|
||||
s.reportActualWorkDuration(TARGET_166 - 2);
|
||||
// we should not see update as the rate should be 10X for over-perform case.
|
||||
verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
|
||||
fakeClock.incrementClock(10 * RATE_1000 + 1);
|
||||
s.reportActualWorkDuration(TARGET_166);
|
||||
s.reportActualWorkDuration(TARGET_166 - 1);
|
||||
// we should see update now
|
||||
verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
|
||||
eq(new long[] {TARGET_166, TARGET_166 - 1, TARGET_166 - 2, TARGET_166}),
|
||||
eq(new long[] {10 * RATE_1000 + 1, 10 * RATE_1000 + 1, 10 * RATE_1000 + 1,
|
||||
(10 * RATE_1000 + 1) * 2}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRateLimitWithDurationTooSlow() throws Exception {
|
||||
FakeClock fakeClock = new FakeClock();
|
||||
Session s = new Session(mIHintSessionMock, fakeClock, RATE_1000, TARGET_166);
|
||||
|
||||
reset(mIHintSessionMock);
|
||||
fakeClock.setNow(0);
|
||||
s.updateTargetWorkDuration(TARGET_166);
|
||||
|
||||
verify(mIHintSessionMock, times(1)).updateTargetWorkDuration(eq(TARGET_166));
|
||||
// shouldn't update before rate limit
|
||||
s.reportActualWorkDuration(TARGET_166 + 1);
|
||||
verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
|
||||
|
||||
// shouldn't update when the time is exactly at rate limit
|
||||
fakeClock.incrementClock(RATE_1000);
|
||||
s.reportActualWorkDuration(TARGET_166 + 1);
|
||||
verify(mIHintSessionMock, never()).reportActualWorkDuration(any(), any());
|
||||
|
||||
// should be ready for sending hint
|
||||
fakeClock.incrementClock(1);
|
||||
s.reportActualWorkDuration(TARGET_166 + 1);
|
||||
verify(mIHintSessionMock, times(1)).reportActualWorkDuration(
|
||||
eq(new long[] {TARGET_166 + 1, TARGET_166 + 1, TARGET_166 + 1}),
|
||||
eq(new long[] {0 , RATE_1000, RATE_1000 + 1}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseHintSession() {
|
||||
Session s = createSession();
|
||||
assumeNotNull(s);
|
||||
s.close();
|
||||
}
|
||||
|
||||
private static class FakeClock implements PerformanceHintManager.NanoClock {
|
||||
private long mCurrentTime = 0L;
|
||||
|
||||
@Override
|
||||
public long nanos() {
|
||||
return mCurrentTime;
|
||||
}
|
||||
|
||||
public void setNow(long nanos) {
|
||||
mCurrentTime = nanos;
|
||||
}
|
||||
|
||||
public void incrementClock(long nanos) {
|
||||
mCurrentTime += nanos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user