• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.alarmmanager.cts;
18 
19 import android.util.Log;
20 import android.util.LongArray;
21 
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.ObjectInputStream;
27 import java.io.ObjectOutputStream;
28 import java.util.Arrays;
29 
30 /**
31  * This class is a lightweight wrapper to store app-global history of events persisted to disk.
32  * For this test app, this is used exclusively to record alarm events to facilitate
33  * pending quota calculations. But this stores only timestamps, and so can be used to record any
34  * kind of events.
35  * This deliberately goes against the principle of test-case isolation, but quotas are managed per
36  * app which makes them impossible to test without persisting some state across test-cases.
37  */
38 public class PersistableEventHistory {
39     private static final String TAG = PersistableEventHistory.class.getSimpleName();
40 
41     final LongArray mHistory;
42     final File mFile;
43 
PersistableEventHistory(File file)44     PersistableEventHistory(File file) {
45         mFile = file;
46         mHistory = (file.exists() ? readFromFile() : new LongArray());
47     }
48 
readFromFile()49     synchronized LongArray readFromFile() {
50         try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(mFile))) {
51             final long[] restored = (long[]) in.readObject();
52             Log.i(TAG, "Loaded existing event history " + Arrays.toString(restored)
53                     + " from " + mFile.getName());
54             return LongArray.wrap(restored);
55         } catch (Exception e) {
56             throw new RuntimeException("Could not load event history from " + mFile.getName(), e);
57         }
58     }
59 
saveToFile()60     synchronized void saveToFile() {
61         final long[] historyArray = mHistory.toArray();
62         Log.i(TAG, "Saving event history " + Arrays.toString(historyArray)
63                 + " to " + mFile.getName());
64 
65         try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(mFile))) {
66             out.writeObject(historyArray);
67         } catch (IOException e) {
68             throw new RuntimeException("Could not save event history to " + mFile.getName(), e);
69         }
70     }
71 
getNthLastEventTime(int n)72     synchronized long getNthLastEventTime(int n) {
73         if (n <= 0 || n > mHistory.size()) {
74             return 0;
75         }
76         return mHistory.get(mHistory.size() - n);
77     }
78 
recordLatestEvent(long timeOfReceipt)79     synchronized void recordLatestEvent(long timeOfReceipt) {
80         if (mHistory.size() == 0 || mHistory.get(mHistory.size() - 1) < timeOfReceipt) {
81             mHistory.add(timeOfReceipt);
82             saveToFile();
83         }
84     }
85 
dump(String prefix)86     synchronized void dump(String prefix) {
87         Log.i(TAG, prefix + ": " + Arrays.toString(mHistory.toArray()));
88     }
89 }
90