diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index c31bb33d6a41c..c643d6708adb0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -54,8 +54,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha mQsContainer = container; mQuickQsPanel = quickPanel; mQsPanel = panel; - mQuickQsPanel.addOnLayoutChangeListener(this); - mQsPanel.addOnLayoutChangeListener(this); + container.addOnLayoutChangeListener(this); QSTileLayout tileLayout = mQsPanel.getTileLayout(); if (tileLayout instanceof PagedTileLayout) { ((PagedTileLayout) tileLayout).setPageListener(this); @@ -161,6 +160,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha @Override public void onAnimationAtStart() { + mQuickQsPanel.setVisibility(View.VISIBLE); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java index 026dd0e74a0a0..35ade580654a0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/TouchAnimator.java @@ -38,7 +38,7 @@ public class TouchAnimator { private final float mSpan; private final Interpolator mInterpolator; private final Listener mListener; - private float mLastT; + private float mLastT = -1; private TouchAnimator(Object[] targets, KeyframeSet[] keyframeSets, float startDelay, float endDelay, Interpolator interpolator, Listener listener) { @@ -56,15 +56,16 @@ public class TouchAnimator { if (mInterpolator != null) { t = mInterpolator.getInterpolation(t); } + if (t == mLastT) { + return; + } if (mListener != null) { - if (mLastT == 0 || mLastT == 1) { - if (t != mLastT) { - mListener.onAnimationStarted(); - } - } else if (t == 1) { + if (t == 1) { mListener.onAnimationAtEnd(); } else if (t == 0) { mListener.onAnimationAtStart(); + } else if (mLastT <= 0 || mLastT == 1) { + mListener.onAnimationStarted(); } mLastT = t; } @@ -114,12 +115,12 @@ public class TouchAnimator { private Listener mListener; public Builder addFloat(Object target, String property, float... values) { - add(target, KeyframeSet.ofFloat(getProperty(target, property), values)); + add(target, KeyframeSet.ofFloat(getProperty(target, property, float.class), values)); return this; } public Builder addInt(Object target, String property, int... values) { - add(target, KeyframeSet.ofInt(getProperty(target, property), values)); + add(target, KeyframeSet.ofInt(getProperty(target, property, int.class), values)); return this; } @@ -128,7 +129,7 @@ public class TouchAnimator { mValues.add(keyframeSet); } - private static Property getProperty(Object target, String property) { + private static Property getProperty(Object target, String property, Class cls) { if (target instanceof View) { switch (property) { case "translationX": @@ -151,7 +152,7 @@ public class TouchAnimator { return View.SCALE_Y; } } - return Property.of(target.getClass(), float.class, property); + return Property.of(target.getClass(), cls, property); } public Builder setStartDelay(float startDelay) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index cf5531fd3eb85..b549d5912117d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -38,7 +38,6 @@ import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; import com.android.systemui.qs.QuickQSPanel; import com.android.systemui.qs.TouchAnimator; -import com.android.systemui.qs.TouchAnimator.Listener; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback; @@ -46,7 +45,7 @@ import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.tuner.TunerService; public class QuickStatusBarHeader extends BaseStatusBarHeader implements - NextAlarmChangeCallback, OnClickListener, Listener { + NextAlarmChangeCallback, OnClickListener { private static final String TAG = "QuickStatusBarHeader"; @@ -157,7 +156,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mAnimator = new TouchAnimator.Builder() .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0) .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0) - .setListener(this) .build(); mSecondHalfAnimator = new TouchAnimator.Builder() .addFloat(mSettingsButton, "rotation", -180, 0) @@ -224,20 +222,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD); } - @Override - public void onAnimationAtStart() { - } - - @Override - public void onAnimationAtEnd() { - mHeaderQsPanel.setVisibility(View.INVISIBLE); - } - - @Override - public void onAnimationStarted() { - mHeaderQsPanel.setVisibility(View.VISIBLE); - } - private void updateAlarmVisibilities() { mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE); mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE); diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index 282560100cb44..5389c8047b26c 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -20,6 +20,8 @@ + + diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java new file mode 100644 index 0000000000000..1d81fd478b52e --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TouchAnimatorTests.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2016 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.qs; + +import android.view.View; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.qs.TouchAnimator.Listener; +import org.mockito.Mockito; + +public class TouchAnimatorTests extends SysuiTestCase { + + private Listener mTouchListener; + private View mTestView; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mTestView = new View(getContext()); + mTouchListener = Mockito.mock(Listener.class); + } + + public void testSetValueFloat() { + TouchAnimator animator = new TouchAnimator.Builder() + .addFloat(mTestView, "x", 0, 50) + .build(); + + animator.setPosition(0); + assertEquals(0f, mTestView.getX()); + + animator.setPosition(.5f); + assertEquals(25f, mTestView.getX()); + + animator.setPosition(1); + assertEquals(50f, mTestView.getX()); + } + + public void testSetValueInt() { + TouchAnimator animator = new TouchAnimator.Builder() + .addInt(mTestView, "top", 0, 50) + .build(); + + animator.setPosition(0); + assertEquals(0, mTestView.getTop()); + + animator.setPosition(.5f); + assertEquals(25, mTestView.getTop()); + + animator.setPosition(1); + assertEquals(50, mTestView.getTop()); + } + + public void testStartDelay() { + TouchAnimator animator = new TouchAnimator.Builder() + .addFloat(mTestView, "x", 0, 50) + .setStartDelay(.5f) + .build(); + + animator.setPosition(0); + assertEquals(0f, mTestView.getX()); + + animator.setPosition(.5f); + assertEquals(0f, mTestView.getX()); + + animator.setPosition(.75f); + assertEquals(25f, mTestView.getX()); + + animator.setPosition(1); + assertEquals(50f, mTestView.getX()); + } + + public void testEndDelay() { + TouchAnimator animator = new TouchAnimator.Builder() + .addFloat(mTestView, "x", 0, 50) + .setEndDelay(.5f) + .build(); + + animator.setPosition(0); + assertEquals(0f, mTestView.getX()); + + animator.setPosition(.25f); + assertEquals(25f, mTestView.getX()); + + animator.setPosition(.5f); + assertEquals(50f, mTestView.getX()); + + animator.setPosition(1); + assertEquals(50f, mTestView.getX()); + } + + public void testOnAnimationAtStartCallback() { + TouchAnimator animator = new TouchAnimator.Builder() + .setListener(mTouchListener) + .build(); + + // Called on init. + animator.setPosition(0); + verifyOnAnimationAtStart(1); + + // Not called from same state. + animator.setPosition(0); + verifyOnAnimationAtStart(1); + + // Called after starting and moving back to start. + animator.setPosition(.5f); + animator.setPosition(0); + verifyOnAnimationAtStart(2); + + // Called when move from end to end. + animator.setPosition(1); + animator.setPosition(0); + verifyOnAnimationAtStart(3); + } + + public void testOnAnimationAtEndCallback() { + TouchAnimator animator = new TouchAnimator.Builder() + .setListener(mTouchListener) + .build(); + + // Called on init. + animator.setPosition(1); + verifyOnAnimationAtEnd(1); + + // Not called from same state. + animator.setPosition(1); + verifyOnAnimationAtEnd(1); + + // Called after starting and moving back to end. + animator.setPosition(.5f); + animator.setPosition(1); + verifyOnAnimationAtEnd(2); + + // Called when move from end to end. + animator.setPosition(0); + animator.setPosition(1); + verifyOnAnimationAtEnd(3); + } + + public void testOnAnimationStartedCallback() { + TouchAnimator animator = new TouchAnimator.Builder() + .setListener(mTouchListener) + .build(); + + // Called on init. + animator.setPosition(.5f); + verifyOnAnimationStarted(1); + + // Not called from same state. + animator.setPosition(.6f); + verifyOnAnimationStarted(1); + + // Called after going to end then moving again. + animator.setPosition(1); + animator.setPosition(.5f); + verifyOnAnimationStarted(2); + + // Called after moving to start then moving again. + animator.setPosition(0); + animator.setPosition(.5f); + verifyOnAnimationStarted(3); + } + + // TODO: Add test for interpolator. + + private void verifyOnAnimationAtStart(int times) { + Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtStart(); + } + + private void verifyOnAnimationAtEnd(int times) { + Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationAtEnd(); + } + + private void verifyOnAnimationStarted(int times) { + Mockito.verify(mTouchListener, Mockito.times(times)).onAnimationStarted(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java index c4ca039fab0c4..18412519af500 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTests.java @@ -19,6 +19,9 @@ import android.content.ComponentName; import android.os.Looper; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.phone.QSTileHost; +import com.android.systemui.statusbar.policy.DataSaverController; +import com.android.systemui.statusbar.policy.HotspotController; +import com.android.systemui.statusbar.policy.NetworkController; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -34,7 +37,12 @@ public class TileServicesTests extends SysuiTestCase { protected void setUp() throws Exception { super.setUp(); mManagers = new ArrayList<>(); - QSTileHost host = new QSTileHost(mContext, null, null, null, null, null, null, null, null, + final NetworkController networkController = Mockito.mock(NetworkController.class); + Mockito.when(networkController.getDataSaverController()).thenReturn( + Mockito.mock(DataSaverController.class)); + QSTileHost host = new QSTileHost(mContext, null, null, null, null, + networkController, null, + Mockito.mock(HotspotController.class), null, null, null, null, null, null, null, null); mTileService = new TestTileServices(host, Looper.myLooper()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 5cf37670f3eac..ebd538473c1d3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -16,9 +16,6 @@ package com.android.systemui.statusbar.policy; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkCapabilities; @@ -31,14 +28,12 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; - import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.net.DataUsageController; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; - import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -47,6 +42,9 @@ import java.io.StringWriter; import java.util.ArrayList; import java.util.List; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class NetworkControllerBaseTest extends SysuiTestCase { private static final String TAG = "NetworkControllerBaseTest"; protected static final int DEFAULT_LEVEL = 2; @@ -109,6 +107,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { protected void setupNetworkController() { // For now just pretend to be the data sim, so we can test that too. mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; + when(mMockTm.getDataEnabled(mSubId)).thenReturn(true); setDefaultSubId(mSubId); setSubscriptions(mSubId); mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);