Fix constantly spinning hvac views

Also clean up some things w.r.t. CarFacetButtonController

Bug: 143610340
Test: manual, atest HvacControllerTest
Change-Id: Idca6f5731704da893fb530deefe2e695281c6f60
This commit is contained in:
Heemin Seog
2019-11-12 08:49:26 -08:00
parent d59786b99a
commit fb35ab5e28
6 changed files with 163 additions and 28 deletions

View File

@@ -19,36 +19,16 @@ package com.android.systemui;
import android.content.Context;
import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.navigationbar.car.CarFacetButtonController;
import javax.inject.Singleton;
import dagger.Component;
/**
* Class factory to provide car specific SystemUI components.
*/
public class CarSystemUIFactory extends SystemUIFactory {
private CarDependencyComponent mCarDependencyComponent;
@Override
protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
mCarDependencyComponent = DaggerCarSystemUIFactory_CarDependencyComponent.builder()
.contextHolder(new ContextHolder(context))
.build();
return DaggerCarSystemUIRootComponent.builder()
.contextHolder(new ContextHolder(context))
.build();
}
public CarDependencyComponent getCarDependencyComponent() {
return mCarDependencyComponent;
}
@Singleton
@Component(modules = ContextHolder.class)
public interface CarDependencyComponent {
CarFacetButtonController getCarFacetButtonController();
}
}

View File

@@ -19,6 +19,8 @@ package com.android.systemui.car;
import android.car.Car;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import java.util.ArrayList;
import java.util.List;
@@ -50,6 +52,12 @@ public class CarServiceProvider {
});
}
@VisibleForTesting
public CarServiceProvider(Context context, Car car) {
mContext = context;
mCar = car;
}
/**
* Let's other components hook into the connection to the car service. If we're already
* connected to the car service, the callback is immediately triggered.

View File

@@ -29,9 +29,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.CarSystemUIFactory;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
/**
* CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined
@@ -82,10 +80,6 @@ public class CarFacetButton extends LinearLayout {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
setupIntents(typedArray);
setupIcons(typedArray);
CarSystemUIFactory factory = SystemUIFactory.getInstance();
CarFacetButtonController carFacetButtonController = factory.getCarDependencyComponent()
.getCarFacetButtonController();
carFacetButtonController.addFacetButton(this);
}
/**

View File

@@ -43,6 +43,8 @@ import javax.inject.Singleton;
@Singleton
public class CarFacetButtonController {
private final Set<CarFacetButton> mRegisteredViews = new HashSet<>();
protected ButtonMap mButtonsByCategory = new ButtonMap();
protected ButtonMap mButtonsByPackage = new ButtonMap();
protected ButtonMap mButtonsByComponentName = new ButtonMap();
@@ -60,7 +62,11 @@ public class CarFacetButtonController {
* to get a reference to this controller via {@link com.android.systemui.Dependency}
* and self add.
*/
public void addFacetButton(CarFacetButton facetButton) {
private void addFacetButton(CarFacetButton facetButton) {
if (mRegisteredViews.contains(facetButton)) {
return;
}
String[] categories = facetButton.getCategories();
for (int i = 0; i < categories.length; i++) {
mButtonsByCategory.add(categories[i], facetButton);
@@ -74,6 +80,8 @@ public class CarFacetButtonController {
for (int i = 0; i < componentNames.length; i++) {
mButtonsByComponentName.add(componentNames[i], facetButton);
}
mRegisteredViews.add(facetButton);
}
/** Removes all buttons from the button maps. */
@@ -82,6 +90,7 @@ public class CarFacetButtonController {
mButtonsByPackage.clear();
mButtonsByComponentName.clear();
mSelectedFacetButtons.clear();
mRegisteredViews.clear();
}
/**

View File

@@ -32,10 +32,12 @@ import com.android.systemui.car.CarServiceProvider;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -49,6 +51,7 @@ public class HvacController {
public static final String TAG = "HvacController";
private final CarServiceProvider mCarServiceProvider;
private final Set<TemperatureView> mRegisteredViews = new HashSet<>();
private CarHvacManager mHvacManager;
private HashMap<HvacKey, List<TemperatureView>> mTempComponents = new HashMap<>();
@@ -112,7 +115,10 @@ public class HvacController {
/**
* Add component to list and initialize it if the connection is up.
*/
public void addHvacTextView(TemperatureView temperatureView) {
private void addHvacTextView(TemperatureView temperatureView) {
if (mRegisteredViews.contains(temperatureView)) {
return;
}
HvacKey hvacKey = new HvacKey(temperatureView.getPropertyId(), temperatureView.getAreaId());
if (!mTempComponents.containsKey(hvacKey)) {
@@ -120,6 +126,8 @@ public class HvacController {
}
mTempComponents.get(hvacKey).add(temperatureView);
initComponent(temperatureView);
mRegisteredViews.add(temperatureView);
}
private void initComponents() {
@@ -165,6 +173,7 @@ public class HvacController {
*/
public void removeAllComponents() {
mTempComponents.clear();
mRegisteredViews.clear();
}
/**

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.navigationbar.car.hvac;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.car.Car;
import android.car.hardware.hvac.CarHvacManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarServiceProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class HvacControllerTest extends SysuiTestCase {
private static final int PROPERTY_ID = 1;
private static final int AREA_ID = 1;
private static final float VALUE = 72.0f;
private HvacController mHvacController;
private CarServiceProvider mCarServiceProvider;
@Mock
private Car mCar;
@Mock
private CarHvacManager mCarHvacManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mCar.isConnected()).thenReturn(true);
when(mCar.getCarManager(Car.HVAC_SERVICE)).thenReturn(mCarHvacManager);
mCarServiceProvider = new CarServiceProvider(mContext, mCar);
mHvacController = new HvacController(mCarServiceProvider);
mHvacController.connectToCarService();
}
@Test
public void connectToCarService_registersCallback() {
verify(mCarHvacManager).registerCallback(any());
}
@Test
public void addTemperatureViewToController_usingTemperatureView_registersView() {
TemperatureTextView v = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE);
mHvacController.addTemperatureViewToController(v);
verify(v).setTemp(VALUE);
}
@Test
public void addTemperatureViewToController_usingSameTemperatureView_registersFirstView() {
TemperatureTextView v = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE);
mHvacController.addTemperatureViewToController(v);
verify(v).setTemp(VALUE);
resetTemperatureView(v, PROPERTY_ID, AREA_ID);
mHvacController.addTemperatureViewToController(v);
verify(v, never()).setTemp(VALUE);
}
@Test
public void addTemperatureViewToController_usingDifferentTemperatureView_registersBothViews() {
TemperatureTextView v1 = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE);
mHvacController.addTemperatureViewToController(v1);
verify(v1).setTemp(VALUE);
TemperatureTextView v2 = setupMockTemperatureTextView(
PROPERTY_ID + 1,
AREA_ID + 1,
VALUE + 1);
mHvacController.addTemperatureViewToController(v2);
verify(v2).setTemp(VALUE + 1);
}
@Test
public void removeAllComponents_ableToRegisterSameView() {
TemperatureTextView v = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE);
mHvacController.addTemperatureViewToController(v);
verify(v).setTemp(VALUE);
mHvacController.removeAllComponents();
resetTemperatureView(v, PROPERTY_ID, AREA_ID);
mHvacController.addTemperatureViewToController(v);
verify(v).setTemp(VALUE);
}
private TemperatureTextView setupMockTemperatureTextView(int propertyId, int areaId,
float value) {
TemperatureTextView v = mock(TemperatureTextView.class);
resetTemperatureView(v, propertyId, areaId);
when(mCarHvacManager.isPropertyAvailable(propertyId, areaId)).thenReturn(true);
when(mCarHvacManager.getFloatProperty(propertyId, areaId)).thenReturn(value);
return v;
}
private void resetTemperatureView(TemperatureTextView view, int propertyId, int areaId) {
reset(view);
when(view.getPropertyId()).thenReturn(propertyId);
when(view.getAreaId()).thenReturn(areaId);
}
}