blob: 28dc5905270edb076d17529d90ec83f945ead76b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
/*
* 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.
*/
package com.android.tv.settings.system.development.audio;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.util.Optional;
/** Stores audio recording metrics. Sends metrics updates through a callback. */
public class AudioMetrics {
private static final String TAG = "AudioMetrics";
private Optional<Long> mStartTs = Optional.empty();
private Data mData = new Data();
private final UpdateMetricsCallback mCallback;
/** Contains data to be exposed via the callback. */
public static class Data {
public Optional<Long> timeToStartReadMs = Optional.empty();
public Optional<Long> timeToValidAudioMs = Optional.empty();
public Optional<Long> emptyAudioDurationMs = Optional.empty();
public Data() {
}
public Data(Data data) {
this.timeToStartReadMs = data.timeToStartReadMs;
this.timeToValidAudioMs = data.timeToValidAudioMs;
this.emptyAudioDurationMs = data.emptyAudioDurationMs;
}
}
/** Interface for receiving metrics updates. */
public interface UpdateMetricsCallback {
/** Callback for receiving metrics updates. */
void onUpdateMetrics(AudioMetrics.Data data);
}
/**
* @param callback Callback for updates.
*/
public AudioMetrics(UpdateMetricsCallback callback) {
this.mCallback = callback;
}
/** Records the beginning of the audio recording process. */
public void start() {
mData = new Data();
mStartTs = Optional.of(System.currentTimeMillis());
updateMetrics();
}
/** Records that we have started monitoring a buffer for incoming audio data. */
public void startedReading() throws IllegalStateException {
long startTs = this.mStartTs
.orElseThrow(() -> new IllegalStateException(
"Started reading before recording started"));
long currentTs = System.currentTimeMillis();
mData = new Data(mData);
mData.timeToStartReadMs = Optional.of(currentTs - startTs);
updateMetrics();
}
/** Records that we have started receiving non-zero audio data */
public void receivedValidAudio() throws IllegalStateException {
long startTs = this.mStartTs
.orElseThrow(() -> new IllegalStateException(
"Received audio data before recording started"));
long currentTs = System.currentTimeMillis();
mData = new Data(mData);
mData.timeToValidAudioMs = Optional.of(currentTs - startTs);
updateMetrics();
}
/** Records the duration of empty audio received before valid audio */
public void setEmptyAudioDurationMs(long emptyAudioMs) {
mData = new Data(mData);
mData.emptyAudioDurationMs = Optional.of(emptyAudioMs);
updateMetrics();
}
/** Sends updated data through the callback */
private void updateMetrics() {
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(() -> mCallback.onUpdateMetrics(mData));
Log.i(TAG, String.format("Time to start reading: %s",
msTimestampToString(mData.timeToStartReadMs)));
Log.i(TAG, String.format("Time to valid audio data: %s",
msTimestampToString(mData.timeToValidAudioMs)));
Log.i(TAG, String.format("Empty audio duration: %s",
msTimestampToString(mData.emptyAudioDurationMs)));
}
/** Converts a possible timestamp in milliseconds to its string representation. */
public static String msTimestampToString(Optional<Long> optL) {
return optL.map((Long l) -> String.format("%s ms", l)).orElse("");
}
}
|