• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 package com.android.server.alarm;
18 
19 import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__ALLOW_LIST;
20 import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
21 import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
22 import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
23 import static com.android.internal.util.FrameworkStatsLog.ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION;
24 import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY;
25 
26 import android.app.ActivityManager;
27 import android.app.AlarmManager;
28 import android.app.StatsManager;
29 import android.content.Context;
30 import android.os.SystemClock;
31 
32 import com.android.internal.os.BackgroundThread;
33 import com.android.internal.util.FrameworkStatsLog;
34 
35 import java.util.function.Supplier;
36 
37 /**
38  * A helper class to write logs to statsd.
39  */
40 class MetricsHelper {
41     private final Context mContext;
42     private final Object mLock;
43 
MetricsHelper(Context context, Object lock)44     MetricsHelper(Context context, Object lock) {
45         mContext = context;
46         mLock = lock;
47     }
48 
registerPuller(Supplier<AlarmStore> alarmStoreSupplier)49     void registerPuller(Supplier<AlarmStore> alarmStoreSupplier) {
50         final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
51         statsManager.setPullAtomCallback(FrameworkStatsLog.PENDING_ALARM_INFO, null,
52                 BackgroundThread.getExecutor(), (atomTag, data) -> {
53                     if (atomTag != FrameworkStatsLog.PENDING_ALARM_INFO) {
54                         throw new UnsupportedOperationException("Unknown tag" + atomTag);
55                     }
56                     final long now = SystemClock.elapsedRealtime();
57                     synchronized (mLock) {
58                         final AlarmStore alarmStore = alarmStoreSupplier.get();
59                         data.add(FrameworkStatsLog.buildStatsEvent(atomTag,
60                                 alarmStore.size(),
61                                 alarmStore.getCount(a -> a.windowLength == 0),
62                                 alarmStore.getCount(a -> a.wakeup),
63                                 alarmStore.getCount(
64                                         a -> (a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0),
65                                 alarmStore.getCount(
66                                         a -> (a.flags & AlarmManager.FLAG_PRIORITIZE) != 0),
67                                 alarmStore.getCount(a -> (a.operation != null
68                                         && a.operation.isForegroundService())),
69                                 alarmStore.getCount(
70                                         a -> (a.operation != null && a.operation.isActivity())),
71                                 alarmStore.getCount(
72                                         a -> (a.operation != null && a.operation.isService())),
73                                 alarmStore.getCount(a -> (a.listener != null)),
74                                 alarmStore.getCount(
75                                         a -> (a.getRequestedElapsed() > now + INDEFINITE_DELAY)),
76                                 alarmStore.getCount(a -> (a.repeatInterval != 0)),
77                                 alarmStore.getCount(a -> (a.alarmClock != null)),
78                                 alarmStore.getCount(a -> AlarmManagerService.isRtc(a.type))
79                         ));
80                         return StatsManager.PULL_SUCCESS;
81                     }
82                 });
83     }
84 
reasonToStatsReason(int reasonCode)85     private static int reasonToStatsReason(int reasonCode) {
86         switch (reasonCode) {
87             case Alarm.EXACT_ALLOW_REASON_ALLOW_LIST:
88                 return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__ALLOW_LIST;
89             case Alarm.EXACT_ALLOW_REASON_PERMISSION:
90                 return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__PERMISSION;
91             case Alarm.EXACT_ALLOW_REASON_COMPAT:
92                 return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__CHANGE_DISABLED;
93             case Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION:
94                 return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__POLICY_PERMISSION;
95             default:
96                 return ALARM_SCHEDULED__EXACT_ALARM_ALLOWED_REASON__NOT_APPLICABLE;
97         }
98     }
99 
pushAlarmScheduled(Alarm a, int callerProcState)100     static void pushAlarmScheduled(Alarm a, int callerProcState) {
101         FrameworkStatsLog.write(
102                 FrameworkStatsLog.ALARM_SCHEDULED,
103                 a.uid,
104                 a.windowLength == 0,
105                 a.wakeup,
106                 (a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0,
107                 a.alarmClock != null,
108                 a.repeatInterval != 0,
109                 reasonToStatsReason(a.mExactAllowReason),
110                 AlarmManagerService.isRtc(a.type),
111                 ActivityManager.processStateAmToProto(callerProcState));
112     }
113 
pushAlarmBatchDelivered( int numAlarms, int wakeups, int[] uids, int[] alarmsPerUid, int[] wakeupAlarmsPerUid)114     static void pushAlarmBatchDelivered(
115             int numAlarms, int wakeups, int[] uids, int[] alarmsPerUid, int[] wakeupAlarmsPerUid) {
116         FrameworkStatsLog.write(
117                 FrameworkStatsLog.ALARM_BATCH_DELIVERED,
118                 numAlarms,
119                 wakeups,
120                 uids,
121                 alarmsPerUid,
122                 wakeupAlarmsPerUid);
123     }
124 }
125