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