1 /* 2 * Copyright (C) 2017 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; 18 19 import static junit.framework.Assert.*; 20 import static org.mockito.Mockito.*; 21 22 import android.hardware.health.V2_0.IHealth; 23 import android.hidl.manager.V1_0.IServiceManager; 24 import android.hidl.manager.V1_0.IServiceNotification; 25 import android.os.RemoteException; 26 import android.support.test.filters.SmallTest; 27 import android.test.AndroidTestCase; 28 import android.util.Slog; 29 30 import java.util.Arrays; 31 import java.util.Collection; 32 import java.util.NoSuchElementException; 33 34 import org.junit.runner.RunWith; 35 import org.mockito.ArgumentMatcher; 36 import org.mockito.Mock; 37 import org.mockito.MockitoAnnotations; 38 import org.mockito.Spy; 39 import org.mockito.invocation.InvocationOnMock; 40 41 42 public class BatteryServiceTest extends AndroidTestCase { 43 44 @Mock IServiceManager mMockedManager; 45 @Mock IHealth mMockedHal; 46 @Mock IHealth mMockedHal2; 47 48 @Mock BatteryService.HealthServiceWrapper.Callback mCallback; 49 @Mock BatteryService.HealthServiceWrapper.IServiceManagerSupplier mManagerSupplier; 50 @Mock BatteryService.HealthServiceWrapper.IHealthSupplier mHealthServiceSupplier; 51 BatteryService.HealthServiceWrapper mWrapper; 52 53 private static final String HEALTHD = BatteryService.HealthServiceWrapper.INSTANCE_HEALTHD; 54 private static final String VENDOR = BatteryService.HealthServiceWrapper.INSTANCE_VENDOR; 55 56 @Override setUp()57 public void setUp() { 58 MockitoAnnotations.initMocks(this); 59 } 60 61 @Override tearDown()62 public void tearDown() { 63 if (mWrapper != null) 64 mWrapper.getHandlerThread().quitSafely(); 65 } 66 isOneOf(Collection<T> collection)67 public static <T> ArgumentMatcher<T> isOneOf(Collection<T> collection) { 68 return new ArgumentMatcher<T>() { 69 @Override public boolean matches(T e) { 70 return collection.contains(e); 71 } 72 @Override public String toString() { 73 return collection.toString(); 74 } 75 }; 76 } 77 78 private void initForInstances(String... instanceNamesArr) throws Exception { 79 final Collection<String> instanceNames = Arrays.asList(instanceNamesArr); 80 doAnswer((invocation) -> { 81 // technically, preexisting is ignored by 82 // BatteryService.HealthServiceWrapper.Notification, but still call it correctly. 83 sendNotification(invocation, true); 84 sendNotification(invocation, true); 85 sendNotification(invocation, false); 86 return null; 87 }).when(mMockedManager).registerForNotifications( 88 eq(IHealth.kInterfaceName), 89 argThat(isOneOf(instanceNames)), 90 any(IServiceNotification.class)); 91 92 doReturn(mMockedManager).when(mManagerSupplier).get(); 93 doReturn(mMockedHal) // init calls this 94 .doReturn(mMockedHal) // notification 1 95 .doReturn(mMockedHal) // notification 2 96 .doReturn(mMockedHal2) // notification 3 97 .doThrow(new RuntimeException("Should not call getService for more than 4 times")) 98 .when(mHealthServiceSupplier).get(argThat(isOneOf(instanceNames))); 99 100 mWrapper = new BatteryService.HealthServiceWrapper(); 101 } 102 103 private void waitHandlerThreadFinish() throws Exception { 104 for (int i = 0; i < 5; i++) { 105 if (!mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks()) { 106 return; 107 } 108 Thread.sleep(300); 109 } 110 assertFalse(mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks()); 111 } 112 113 private static void sendNotification(InvocationOnMock invocation, boolean preexisting) 114 throws Exception { 115 ((IServiceNotification)invocation.getArguments()[2]).onRegistration( 116 IHealth.kInterfaceName, 117 (String)invocation.getArguments()[1], 118 preexisting); 119 } 120 121 @SmallTest 122 public void testWrapPreferVendor() throws Exception { 123 initForInstances(VENDOR, HEALTHD); 124 mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier); 125 waitHandlerThreadFinish(); 126 verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR)); 127 verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString()); 128 verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(VENDOR)); 129 } 130 131 @SmallTest 132 public void testUseHealthd() throws Exception { 133 initForInstances(HEALTHD); 134 mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier); 135 waitHandlerThreadFinish(); 136 verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(HEALTHD)); 137 verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString()); 138 verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(HEALTHD)); 139 } 140 141 @SmallTest 142 public void testNoService() throws Exception { 143 initForInstances("unrelated"); 144 try { 145 mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier); 146 fail("Expect NoSuchElementException"); 147 } catch (NoSuchElementException ex) { 148 // expected 149 } 150 } 151 } 152