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