1 /* 2 * Copyright (C) 2023 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.telephony.statslib; 18 19 import android.app.StatsManager; 20 import android.content.Context; 21 import android.util.Log; 22 import android.util.StatsEvent; 23 24 import java.util.ArrayList; 25 import java.util.HashMap; 26 import java.util.List; 27 import java.util.concurrent.Executor; 28 29 /** 30 * StatsLibPulledAtomCallback class 31 * 32 * <p>This class registers to statsd. Called once a day for this class pull stat to send to statsd. 33 */ 34 class StatsLibPulledAtomCallback implements StatsManager.StatsPullAtomCallback { 35 36 private static final String LOG_TAG = StatsLibPulledAtomCallback.class.getSimpleName(); 37 private static final boolean DBG = true; 38 private static final StatsManager.PullAtomMetadata POLICY_PULL_DAILY = 39 new StatsManager.PullAtomMetadata.Builder() 40 .setCoolDownMillis(5L) 41 .setTimeoutMillis(2L) 42 .build(); 43 private final StatsManager mStatsManager; 44 private final StatsLibStorage mStatsLibStorage; 45 private final HashMap<Integer, PulledCallback> mRegisteredCallback; 46 47 /** 48 * Constructor of StatsLibPulledAtomCallback 49 * 50 * @param context Context 51 */ StatsLibPulledAtomCallback(Context context)52 StatsLibPulledAtomCallback(Context context) { 53 mRegisteredCallback = new HashMap<>(); 54 mStatsLibStorage = new StatsLibStorage(context); 55 mStatsManager = context.getSystemService(StatsManager.class); 56 log("created StatsLibPulledAtomCallback."); 57 } 58 59 /** get a StatsLibStorage, which stores pulled atoms */ getStatsLibStorage()60 StatsLibStorage getStatsLibStorage() { 61 return mStatsLibStorage; 62 } 63 log(String s)64 private void log(String s) { 65 if (DBG) Log.d(LOG_TAG, s); 66 } 67 68 /** 69 * Register a callback 70 * 71 * @param atomTag The tag of the atom for this puller callback. 72 */ registerAtom(int atomTag)73 void registerAtom(int atomTag) { 74 registerAtom(atomTag, new EmptyCallback()); 75 } 76 77 /** 78 * Register a callback 79 * 80 * @param atomTag The tag of the atom for this puller callback. 81 */ registerAtom(int atomTag, PulledCallback callback)82 void registerAtom(int atomTag, PulledCallback callback) { 83 if (!mRegisteredCallback.containsKey(atomTag)) { 84 mStatsLibStorage.init(atomTag); 85 mStatsLibStorage.loadFromFile(atomTag); 86 mStatsManager.setPullAtomCallback( 87 atomTag, POLICY_PULL_DAILY, new MetricExecutor(), this); 88 mRegisteredCallback.put(atomTag, callback); 89 } 90 } 91 92 /** 93 * is registered a callback 94 * 95 * @param atomTag The tag of the atom for this puller callback. 96 */ isRegisteredAtom(int atomTag)97 boolean isRegisteredAtom(int atomTag) { 98 return mRegisteredCallback.containsKey(atomTag); 99 } 100 101 /** 102 * Register a callback 103 * 104 * @param atomTag The tag of the atom for this puller callback. 105 */ unregisterAtom(int atomTag)106 void unregisterAtom(int atomTag) { 107 if (mRegisteredCallback.containsKey(atomTag)) { 108 mStatsManager.clearPullAtomCallback(atomTag); 109 mRegisteredCallback.remove(atomTag); 110 mStatsLibStorage.saveToFile(atomTag); 111 } 112 } 113 114 @Override onPullAtom(int atomTag, List<StatsEvent> data)115 public int onPullAtom(int atomTag, List<StatsEvent> data) { 116 log("onPullAtom: atomTag:" + atomTag); 117 AtomsPulled[] arrayPulled = getStatsLibStorage().popPulledAtoms(atomTag); 118 for (AtomsPulled pulled : arrayPulled) { 119 final StatsEvent.Builder builder = StatsEvent.newBuilder(); 120 builder.setAtomId(pulled.getStatsId()); 121 pulled.build(builder); 122 data.add(builder.build()); 123 } 124 125 PulledCallback callback = mRegisteredCallback.get(atomTag); 126 if (callback == null) { 127 return StatsManager.PULL_SUCCESS; 128 } 129 List<AtomsPulled> list = new ArrayList<>(); 130 callback.onPulledCallback(atomTag, list); 131 for (AtomsPulled pulled : list) { 132 final StatsEvent.Builder builder = StatsEvent.newBuilder(); 133 builder.setAtomId(pulled.getStatsId()); 134 pulled.build(builder); 135 data.add(builder.build()); 136 } 137 138 return StatsManager.PULL_SUCCESS; 139 } 140 141 private static class MetricExecutor implements Executor { 142 @Override execute(Runnable command)143 public void execute(Runnable command) { 144 command.run(); 145 } 146 147 @Override toString()148 public String toString() { 149 return "METRIC_EXECUTOR"; 150 } 151 } 152 153 static class EmptyCallback implements PulledCallback { onPulledCallback(int atomTag, List<AtomsPulled> data)154 public void onPulledCallback(int atomTag, List<AtomsPulled> data) {} 155 } 156 } 157