blob: f7ee05117c06c38a6913ec7b96a35fb73dfd94f3 [file] [log] [blame]
Andy Hung06f3aba2019-12-03 16:36:42 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AudioAnalytics"
19#include <utils/Log.h>
20
21#include "AudioAnalytics.h"
22
23#include <audio_utils/clock.h> // clock conversions
24
25namespace android::mediametrics {
26
27AudioAnalytics::AudioAnalytics()
28{
29 ALOGD("%s", __func__);
Andy Hung0f7ad8c2020-01-03 13:24:34 -080030
31 // Add action to save AnalyticsState if audioserver is restarted.
32 // This triggers on an item of "audio.flinger"
33 // with a property "event" set to "AudioFlinger" (the constructor).
34 mActions.addAction(
35 "audio.flinger.event",
36 std::string("AudioFlinger"),
37 std::make_shared<AnalyticsActions::Function>(
38 [this](const std::shared_ptr<const android::mediametrics::Item> &){
39 ALOGW("Audioflinger() constructor event detected");
40 mPreviousAnalyticsState.set(std::make_shared<AnalyticsState>(
41 *mAnalyticsState.get()));
42 // Note: get returns shared_ptr temp, whose lifetime is extended
43 // to end of full expression.
44 mAnalyticsState->clear(); // TODO: filter the analytics state.
45 }));
Andy Hung06f3aba2019-12-03 16:36:42 -080046}
47
48AudioAnalytics::~AudioAnalytics()
49{
50 ALOGD("%s", __func__);
51}
52
53status_t AudioAnalytics::submit(
Ray Essickf27e9872019-12-07 06:28:46 -080054 const std::shared_ptr<const mediametrics::Item>& item, bool isTrusted)
Andy Hung06f3aba2019-12-03 16:36:42 -080055{
Andy Hung0f7ad8c2020-01-03 13:24:34 -080056 if (!startsWith(item->getKey(), "audio.")) return BAD_VALUE;
57 status_t status = mAnalyticsState->submit(item, isTrusted);
58 if (status != NO_ERROR) return status; // may not be permitted.
59
60 // Only if the item was successfully submitted (permission)
61 // do we check triggered actions.
62 checkActions(item);
63 return NO_ERROR;
Andy Hung06f3aba2019-12-03 16:36:42 -080064}
65
66std::pair<std::string, int32_t> AudioAnalytics::dump(int32_t lines) const
67{
68 std::stringstream ss;
69 int32_t ll = lines;
70
71 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -080072 auto [s, l] = mAnalyticsState->dump(ll);
Andy Hung06f3aba2019-12-03 16:36:42 -080073 ss << s;
74 ll -= l;
75 }
76 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -080077 ss << "Prior audioserver state:\n";
Andy Hung06f3aba2019-12-03 16:36:42 -080078 --ll;
79 }
80 if (ll > 0) {
Andy Hung0f7ad8c2020-01-03 13:24:34 -080081 auto [s, l] = mPreviousAnalyticsState->dump(ll);
Andy Hung06f3aba2019-12-03 16:36:42 -080082 ss << s;
83 ll -= l;
84 }
85 return { ss.str(), lines - ll };
86}
87
Andy Hung0f7ad8c2020-01-03 13:24:34 -080088void AudioAnalytics::checkActions(const std::shared_ptr<const mediametrics::Item>& item)
89{
90 auto actions = mActions.getActionsForItem(item); // internally locked.
91 // Execute actions with no lock held.
92 for (const auto& action : actions) {
93 (*action)(item);
94 }
95}
96
Andy Hung06f3aba2019-12-03 16:36:42 -080097} // namespace android