1 /*
2  * Copyright (C) 2022 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.usage;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.util.ArrayMap;
22 import android.util.ArraySet;
23 import android.util.LongArrayQueue;
24 import android.util.TimeUtils;
25 
26 import com.android.internal.util.IndentingPrintWriter;
27 
28 class UserBroadcastEvents {
29     /**
30      * Contains the mapping of targetPackage -> {BroadcastEvent} data.
31      * Here targetPackage refers to the package receiving the broadcast and BroadcastEvent objects
32      * corresponding to each broadcast it is receiving.
33      */
34     private ArrayMap<String, ArraySet<BroadcastEvent>> mBroadcastEvents = new ArrayMap();
35 
getBroadcastEvents(@onNull String packageName)36     @Nullable ArraySet<BroadcastEvent> getBroadcastEvents(@NonNull String packageName) {
37         return mBroadcastEvents.get(packageName);
38     }
39 
getOrCreateBroadcastEvents( @onNull String packageName)40     @NonNull ArraySet<BroadcastEvent> getOrCreateBroadcastEvents(
41             @NonNull String packageName) {
42         ArraySet<BroadcastEvent> broadcastEvents = mBroadcastEvents.get(packageName);
43         if (broadcastEvents == null) {
44             broadcastEvents = new ArraySet<>();
45             mBroadcastEvents.put(packageName, broadcastEvents);
46         }
47         return broadcastEvents;
48     }
49 
onPackageRemoved(@onNull String packageName)50     void onPackageRemoved(@NonNull String packageName) {
51         mBroadcastEvents.remove(packageName);
52     }
53 
onUidRemoved(int uid)54     void onUidRemoved(int uid) {
55         clear(uid);
56     }
57 
clear(int uid)58     void clear(int uid) {
59         for (int i = mBroadcastEvents.size() - 1; i >= 0; --i) {
60             final ArraySet<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
61             for (int j = broadcastEvents.size() - 1; j >= 0; --j) {
62                 if (broadcastEvents.valueAt(j).getSourceUid() == uid) {
63                     broadcastEvents.removeAt(j);
64                 }
65             }
66         }
67     }
68 
dump(@onNull IndentingPrintWriter ipw)69     void dump(@NonNull IndentingPrintWriter ipw) {
70         for (int i = 0; i < mBroadcastEvents.size(); ++i) {
71             final String packageName = mBroadcastEvents.keyAt(i);
72             final ArraySet<BroadcastEvent> broadcastEvents = mBroadcastEvents.valueAt(i);
73             ipw.println(packageName + ":");
74             ipw.increaseIndent();
75             if (broadcastEvents.size() == 0) {
76                 ipw.println("<empty>");
77             } else {
78                 for (int j = 0; j < broadcastEvents.size(); ++j) {
79                     final BroadcastEvent broadcastEvent = broadcastEvents.valueAt(j);
80                     ipw.println(broadcastEvent);
81                     ipw.increaseIndent();
82                     final LongArrayQueue timestampsMs = broadcastEvent.getTimestampsMs();
83                     for (int timestampIdx = 0; timestampIdx < timestampsMs.size(); ++timestampIdx) {
84                         if (timestampIdx > 0) {
85                             ipw.print(',');
86                         }
87                         final long timestampMs = timestampsMs.get(timestampIdx);
88                         TimeUtils.formatDuration(timestampMs, ipw);
89                     }
90                     ipw.println();
91                     ipw.decreaseIndent();
92                 }
93             }
94             ipw.decreaseIndent();
95         }
96     }
97 }
98