1 /*
2  * Copyright (C) 2020 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.am;
18 
19 import static org.junit.Assert.assertTrue;
20 
21 import android.content.Context;
22 import android.os.Handler;
23 import android.os.HandlerThread;
24 import android.os.Process;
25 
26 import androidx.test.InstrumentationRegistry;
27 import androidx.test.runner.AndroidJUnit4;
28 
29 import com.android.server.power.stats.BatteryStatsImpl;
30 
31 import org.junit.After;
32 import org.junit.Before;
33 import org.junit.Ignore;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 
37 import java.util.concurrent.CountDownLatch;
38 import java.util.concurrent.TimeUnit;
39 import java.util.concurrent.atomic.AtomicBoolean;
40 
41 @RunWith(AndroidJUnit4.class)
42 public final class BatteryStatsServiceTest {
43 
44     private BatteryStatsService mBatteryStatsService;
45     private HandlerThread mBgThread;
46 
47     @Before
setUp()48     public void setUp() {
49         final Context context = InstrumentationRegistry.getContext();
50         mBgThread = new HandlerThread("bg thread");
51         mBgThread.start();
52         mBatteryStatsService = new BatteryStatsService(context,
53                 context.getCacheDir(), new Handler(mBgThread.getLooper()));
54     }
55 
56     @After
tearDown()57     public void tearDown() {
58         mBatteryStatsService.shutdown();
59         mBgThread.quitSafely();
60     }
61 
62     @Test
63     @Ignore("b/180015146")
testAwaitCompletion()64     public void testAwaitCompletion() throws Exception {
65         final CountDownLatch readyLatch = new CountDownLatch(2);
66         final CountDownLatch startLatch = new CountDownLatch(1);
67         final CountDownLatch testLatch = new CountDownLatch(1);
68         final AtomicBoolean quiting = new AtomicBoolean(false);
69         final AtomicBoolean finished = new AtomicBoolean(false);
70         final int uid = Process.myUid();
71         final Thread noteThread = new Thread(() -> {
72             final int maxIterations = 1000;
73             final int eventCode = 12345;
74             final String eventName = "placeholder";
75             final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
76 
77             readyLatch.countDown();
78             try {
79                 startLatch.await();
80             } catch (InterruptedException e) {
81             }
82 
83             for (int i = 0; i < maxIterations && !quiting.get(); i++) {
84                 synchronized (stats) {
85                     mBatteryStatsService.noteEvent(eventCode, eventName, uid);
86                 }
87             }
88             finished.set(true);
89         });
90         final Thread waitThread = new Thread(() -> {
91             readyLatch.countDown();
92             try {
93                 startLatch.await();
94             } catch (InterruptedException e) {
95             }
96 
97             do {
98                 mBatteryStatsService.takeUidSnapshot(uid);
99             } while (!finished.get() && !quiting.get());
100 
101             if (!quiting.get()) {
102                 // do one more to ensure we've cleared the queue
103                 mBatteryStatsService.takeUidSnapshot(uid);
104             }
105 
106             testLatch.countDown();
107         });
108         noteThread.start();
109         waitThread.start();
110         readyLatch.await();
111         startLatch.countDown();
112 
113         try {
114             assertTrue("Timed out in waiting for the completion of battery event handling",
115                     testLatch.await(10 * 1000, TimeUnit.MILLISECONDS));
116         } finally {
117             quiting.set(true);
118             noteThread.interrupt();
119             noteThread.join(1000);
120             waitThread.interrupt();
121             waitThread.join(1000);
122         }
123     }
124 }
125