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