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