162 lines
4.9 KiB
Java
162 lines
4.9 KiB
Java
/*
|
|
* Copyright (C) 2018 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.
|
|
*/
|
|
|
|
package com.android.internal.os;
|
|
|
|
|
|
import android.os.SystemClock;
|
|
|
|
import com.android.internal.annotations.GuardedBy;
|
|
import com.android.internal.annotations.VisibleForTesting;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* Stores the device state (e.g. charging/on battery, screen on/off) to be shared with
|
|
* the System Server telemetry services.
|
|
*
|
|
* @hide
|
|
*/
|
|
@android.ravenwood.annotation.RavenwoodKeepWholeClass
|
|
public class CachedDeviceState {
|
|
private volatile boolean mScreenInteractive;
|
|
private volatile boolean mCharging;
|
|
private final Object mStopwatchesLock = new Object();
|
|
@GuardedBy("mStopwatchLock")
|
|
private final ArrayList<TimeInStateStopwatch> mOnBatteryStopwatches = new ArrayList<>();
|
|
|
|
public CachedDeviceState() {
|
|
mCharging = true;
|
|
mScreenInteractive = false;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public CachedDeviceState(boolean isCharging, boolean isScreenInteractive) {
|
|
mCharging = isCharging;
|
|
mScreenInteractive = isScreenInteractive;
|
|
}
|
|
|
|
public void setScreenInteractive(boolean screenInteractive) {
|
|
mScreenInteractive = screenInteractive;
|
|
}
|
|
|
|
public void setCharging(boolean charging) {
|
|
if (mCharging != charging) {
|
|
mCharging = charging;
|
|
updateStopwatches(/* shouldStart= */ !charging);
|
|
}
|
|
}
|
|
|
|
private void updateStopwatches(boolean shouldStart) {
|
|
synchronized (mStopwatchesLock) {
|
|
final int size = mOnBatteryStopwatches.size();
|
|
for (int i = 0; i < size; i++) {
|
|
if (shouldStart) {
|
|
mOnBatteryStopwatches.get(i).start();
|
|
} else {
|
|
mOnBatteryStopwatches.get(i).stop();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Readonly getReadonlyClient() {
|
|
return new CachedDeviceState.Readonly();
|
|
}
|
|
|
|
/**
|
|
* Allows for only a readonly access to the device state.
|
|
*/
|
|
public class Readonly {
|
|
public boolean isCharging() {
|
|
return mCharging;
|
|
}
|
|
|
|
public boolean isScreenInteractive() {
|
|
return mScreenInteractive;
|
|
}
|
|
|
|
/** Creates a {@link TimeInStateStopwatch stopwatch} that tracks the time on battery. */
|
|
public TimeInStateStopwatch createTimeOnBatteryStopwatch() {
|
|
synchronized (mStopwatchesLock) {
|
|
final TimeInStateStopwatch stopwatch = new TimeInStateStopwatch();
|
|
mOnBatteryStopwatches.add(stopwatch);
|
|
if (!mCharging) {
|
|
stopwatch.start();
|
|
}
|
|
return stopwatch;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Tracks the time the device spent in a given state. */
|
|
public class TimeInStateStopwatch implements AutoCloseable {
|
|
private final Object mLock = new Object();
|
|
@GuardedBy("mLock")
|
|
private long mStartTimeMillis;
|
|
@GuardedBy("mLock")
|
|
private long mTotalTimeMillis;
|
|
|
|
/** Returns the time in state since the last call to {@link TimeInStateStopwatch#reset}. */
|
|
public long getMillis() {
|
|
synchronized (mLock) {
|
|
return mTotalTimeMillis + elapsedTime();
|
|
}
|
|
}
|
|
|
|
/** Resets the time in state to 0 without stopping the timer if it's started. */
|
|
public void reset() {
|
|
synchronized (mLock) {
|
|
mTotalTimeMillis = 0;
|
|
mStartTimeMillis = isRunning() ? SystemClock.elapsedRealtime() : 0;
|
|
}
|
|
}
|
|
|
|
private void start() {
|
|
synchronized (mLock) {
|
|
if (!isRunning()) {
|
|
mStartTimeMillis = SystemClock.elapsedRealtime();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void stop() {
|
|
synchronized (mLock) {
|
|
if (isRunning()) {
|
|
mTotalTimeMillis += elapsedTime();
|
|
mStartTimeMillis = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private long elapsedTime() {
|
|
return isRunning() ? SystemClock.elapsedRealtime() - mStartTimeMillis : 0;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public boolean isRunning() {
|
|
return mStartTimeMillis > 0;
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
synchronized (mStopwatchesLock) {
|
|
mOnBatteryStopwatches.remove(this);
|
|
}
|
|
}
|
|
}
|
|
}
|