public interface ClockPlugin extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_CLOCK";
- int VERSION = 4;
+ int VERSION = 5;
/**
* Get the name of the clock face.
}
/**
+ * Returns the preferred Y position of the clock.
+ *
+ * @param totalHeight Height of the parent container.
+ * @return preferred Y position.
+ */
+ int getPreferredY(int totalHeight);
+
+ /**
* Allows the plugin to clean up resources when no longer needed.
*
* Called when the view previously created by {@link ClockPlugin#getView()} has been detached
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <TextClock
- android:id="@+id/digital_clock"
- android:paddingStart="20dp"
- android:layout_marginTop="72dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top|left"
- android:textSize="44dp"
- android:letterSpacing="0.05"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:elegantTextHeight="false"
- />
<com.android.keyguard.clock.ImageClock
android:id="@+id/analog_clock"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <TextClock
- android:id="@+id/digital_clock"
- android:paddingStart="20dp"
- android:layout_marginTop="72dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="top|left"
- android:textSize="44dp"
- android:letterSpacing="0.05"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:elegantTextHeight="false"
- />
<com.android.keyguard.clock.ImageClock
android:id="@+id/analog_clock"
android:layout_width="wrap_content"
}
/**
+ * Returns the preferred Y position of the clock.
+ *
+ * @param totalHeight Height of the parent container.
+ * @return preferred Y position.
+ */
+ int getPreferredY(int totalHeight) {
+ if (mClockPlugin != null) {
+ return mClockPlugin.getPreferredY(totalHeight);
+ } else {
+ return totalHeight / 2;
+ }
+ }
+
+ /**
* Refresh the time of the clock, due to either time tick broadcast or doze time tick alarm.
*/
public void refresh() {
return mClockView.getTextSize();
}
+ /**
+ * Returns the preferred Y position of the clock.
+ *
+ * @param totalHeight The height available to position the clock.
+ * @return Y position of clock.
+ */
+ public int getClockPreferredY(int totalHeight) {
+ return mClockView.getPreferredY(totalHeight);
+ }
+
private void updateLogoutView() {
if (mLogoutView == null) {
return;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.Style;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextClock;
* Custom clock shown on AOD screen and behind stack scroller on lock.
*/
private ClockLayout mBigClockView;
- private TextClock mDigitalClock;
private ImageClock mAnalogClock;
/**
private TextClock mLockClock;
/**
- * Controller for transition to dark state.
- */
- private CrossFadeDarkController mDarkController;
-
- /**
* Create a BubbleClockController instance.
*
* @param res Resources contains title and thumbnail.
private void createViews() {
mBigClockView = (ClockLayout) mLayoutInflater.inflate(R.layout.analog_clock, null);
mAnalogClock = mBigClockView.findViewById(R.id.analog_clock);
- mDigitalClock = mBigClockView.findViewById(R.id.digital_clock);
mView = mLayoutInflater.inflate(R.layout.digital_clock, null);
mLockClock = mView.findViewById(R.id.lock_screen_clock);
- mLockClock.setVisibility(View.GONE);
-
- mDarkController = new CrossFadeDarkController(mDigitalClock, mLockClock);
+ final int textSize = mResources.getDimensionPixelSize(R.dimen.widget_title_font_size);
+ mLockClock.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
@Override
public void onDestroyView() {
mBigClockView = null;
- mDigitalClock = null;
mAnalogClock = null;
mView = null;
mLockClock = null;
- mDarkController = null;
}
@Override
}
@Override
+ public int getPreferredY(int totalHeight) {
+ return totalHeight / 4;
+ }
+
+ @Override
public void setStyle(Style style) {}
@Override
- public void setTextColor(int color) {
- mLockClock.setTextColor(color);
- }
+ public void setTextColor(int color) { }
@Override
public void setColorPalette(boolean supportsDarkText, int[] colorPalette) {
return;
}
final int length = colorPalette.length;
- mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 5)]);
+ mLockClock.setTextColor(colorPalette[Math.max(0, length - 2)]);
mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 5)],
colorPalette[Math.max(0, length - 2)]);
}
public void onTimeTick() {
mAnalogClock.onTimeChanged();
mBigClockView.onTimeChanged();
- mDigitalClock.refresh();
mLockClock.refresh();
}
@Override
- public void setDarkAmount(float darkAmount) {
- mDarkController.setDarkAmount(darkAmount);
- }
+ public void setDarkAmount(float darkAmount) { }
@Override
public void onTimeZoneChanged(TimeZone timeZone) {
@Override
public boolean shouldShowStatusArea() {
- return false;
+ return true;
}
}
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Paint.Style;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextClock;
* Custom clock shown on AOD screen and behind stack scroller on lock.
*/
private ClockLayout mView;
- private TextClock mDigitalClock;
private ImageClock mAnalogClock;
/**
private TextClock mLockClock;
/**
- * Controller for transition to dark state.
- */
- private CrossFadeDarkController mDarkController;
-
- /**
* Create a BubbleClockController instance.
*
* @param res Resources contains title and thumbnail.
private void createViews() {
mView = (ClockLayout) mLayoutInflater.inflate(R.layout.bubble_clock, null);
- mDigitalClock = (TextClock) mView.findViewById(R.id.digital_clock);
mAnalogClock = (ImageClock) mView.findViewById(R.id.analog_clock);
mLockClockContainer = mLayoutInflater.inflate(R.layout.digital_clock, null);
mLockClock = (TextClock) mLockClockContainer.findViewById(R.id.lock_screen_clock);
- mLockClock.setVisibility(View.GONE);
-
- mDarkController = new CrossFadeDarkController(mDigitalClock, mLockClock);
+ final int textSize = mResources.getDimensionPixelSize(R.dimen.widget_title_font_size);
+ mLockClock.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
}
@Override
public void onDestroyView() {
mView = null;
- mDigitalClock = null;
mAnalogClock = null;
mLockClockContainer = null;
mLockClock = null;
- mDarkController = null;
}
@Override
}
@Override
+ public int getPreferredY(int totalHeight) {
+ return totalHeight / 4;
+ }
+
+ @Override
public void setStyle(Style style) {}
@Override
- public void setTextColor(int color) {
- mLockClock.setTextColor(color);
- }
+ public void setTextColor(int color) { }
@Override
public void setColorPalette(boolean supportsDarkText, int[] colorPalette) {
return;
}
final int length = colorPalette.length;
- mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 6)]);
+ mLockClock.setTextColor(colorPalette[Math.max(0, length - 3)]);
mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 6)],
colorPalette[Math.max(0, length - 3)]);
}
@Override
- public void setDarkAmount(float darkAmount) {
- mDarkController.setDarkAmount(darkAmount);
- }
+ public void setDarkAmount(float darkAmount) { }
@Override
public void onTimeTick() {
mAnalogClock.onTimeChanged();
mView.onTimeChanged();
- mDigitalClock.refresh();
mLockClock.refresh();
}
@Override
public boolean shouldShowStatusArea() {
- return false;
+ return true;
}
}
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
-import android.widget.FrameLayout.LayoutParams;
import com.android.keyguard.R;
/**
* Clock face views.
*/
- private View mDigitalClock;
private View mAnalogClock;
/**
- * Pixel shifting amplitidues used to prevent screen burn-in.
+ * Pixel shifting amplitudes used to prevent screen burn-in.
*/
private int mBurnInPreventionOffsetX;
private int mBurnInPreventionOffsetY;
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mDigitalClock = findViewById(R.id.digital_clock);
mAnalogClock = findViewById(R.id.analog_clock);
// Get pixel shifting X, Y amplitudes from resources.
final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
- mBurnInPreventionOffsetY;
- // Put digital clock in two left corner of the screen.
- if (mDigitalClock != null) {
- LayoutParams params = (LayoutParams) mDigitalClock.getLayoutParams();
- mDigitalClock.setX(offsetX + params.leftMargin);
- mDigitalClock.setY(offsetY + params.topMargin);
- }
-
// Put the analog clock in the middle of the screen.
if (mAnalogClock != null) {
mAnalogClock.setX(Math.max(0f, 0.5f * (getWidth() - mAnalogClock.getWidth()))
}
@Override
+ public int getPreferredY(int totalHeight) {
+ return totalHeight / 2;
+ }
+
+ @Override
public void setStyle(Style style) {}
@Override
* If the shelf should be visible when the device is in ambient mode (dozing.)
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setShowDarkShelf(boolean showDarkShelf) {
- mShowDarkShelf = showDarkShelf;
+ public void showDarkShelf() {
+ mShowDarkShelf = true;
}
private void updateDarkShelfVisibility() {
if (mStatusBarStateController.isDozing()
&& mStatusBarComponent.getPanel().hasCustomClock()) {
state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
- state &= ~DISABLE_NOTIFICATION_ICONS;
}
return state;
import android.content.res.Resources;
import android.util.MathUtils;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
private int mKeyguardStatusHeight;
/**
+ * Preferred Y position of clock.
+ */
+ private int mClockPreferredY;
+
+ /**
* Height of notification stack: Sum of height of each notification.
*/
private int mNotificationStackHeight;
}
public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
- float panelExpansion, int parentHeight, int keyguardStatusHeight, float dark,
- boolean secure, float emptyDragAmount) {
+ float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
+ float dark, boolean secure, float emptyDragAmount) {
mMinTopMargin = minTopMargin + mContainerTopPadding;
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
mPanelExpansion = panelExpansion;
mHeight = parentHeight;
mKeyguardStatusHeight = keyguardStatusHeight;
+ mClockPreferredY = clockPreferredY;
mDarkAmount = dark;
mCurrentlySecure = secure;
mEmptyDragAmount = emptyDragAmount;
return mHeight / 2 - mKeyguardStatusHeight - mClockNotificationsMargin;
}
+ private int getPreferredClockY() {
+ return mClockPreferredY - mKeyguardStatusHeight - mClockNotificationsMargin;
+ }
+
/**
* Vertically align the clock and the shade in the available space considering only
* a percentage of the clock height defined by {@code CLOCK_HEIGHT_WEIGHT}.
private int getClockY() {
// Dark: Align the bottom edge of the clock at about half of the screen:
- float clockYDark = getMaxClockY() + burnInPreventionOffsetY();
+ float clockYDark = getPreferredClockY() + burnInPreventionOffsetY();
clockYDark = MathUtils.max(0, clockYDark);
float clockYRegular = getExpandedClockPosition();
private int mUnlockMoveDistance;
private float mEmptyDragAmount;
- private KeyguardClockPositionAlgorithm mClockPositionAlgorithm =
+ private final KeyguardClockPositionAlgorithm mClockPositionAlgorithm =
new KeyguardClockPositionAlgorithm();
- private KeyguardClockPositionAlgorithm.Result mClockPositionResult =
+ private final KeyguardClockPositionAlgorithm.Result mClockPositionResult =
new KeyguardClockPositionAlgorithm.Result();
private boolean mIsExpanding;
} else {
int totalHeight = getHeight();
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
+ int clockPreferredY = mKeyguardStatusView.getClockPreferredY(totalHeight);
mClockPositionAlgorithm.setup(
mStatusBarMinHeight,
totalHeight - bottomPadding,
getExpandedFraction(),
totalHeight,
mKeyguardStatusView.getHeight(),
+ clockPreferredY,
mInterpolatedDarkAmount,
mStatusBar.isKeyguardCurrentlySecure(),
mEmptyDragAmount);
mDozing = dozing;
mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation);
if (mDozing) {
- mNotificationStackScroller.setShowDarkShelf(!hasCustomClock());
+ mNotificationStackScroller.showDarkShelf();
}
mKeyguardBottomArea.setDozing(mDozing, animate);
}
@Test
- public void setDarkAmount_fadeIn() {
+ public void setDarkAmount_AOD() {
ViewGroup smallClockFrame = (ViewGroup) mClockController.getView();
View smallClock = smallClockFrame.getChildAt(0);
// WHEN dark amount is set to AOD
mClockController.setDarkAmount(1f);
- // THEN small clock should not be shown.
- assertThat(smallClock.getVisibility()).isEqualTo(View.GONE);
+ // THEN small clock should be shown.
+ assertThat(smallClock.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
- public void setTextColor_setDigitalClock() {
+ public void setColorPalette_setDigitalClock() {
ViewGroup smallClock = (ViewGroup) mClockController.getView();
- // WHEN text color is set
- mClockController.setTextColor(42);
+ // WHEN color palette is set
+ mClockController.setColorPalette(true, new int[]{42});
// THEN child of small clock should have text color set.
TextView digitalClock = (TextView) smallClock.getChildAt(0);
assertThat(digitalClock.getCurrentTextColor()).isEqualTo(42);
}
@Test
- public void setDarkAmount_fadeIn() {
+ public void setDarkAmount_AOD() {
ViewGroup smallClockFrame = (ViewGroup) mClockController.getView();
View smallClock = smallClockFrame.getChildAt(0);
// WHEN dark amount is set to AOD
mClockController.setDarkAmount(1f);
// THEN small clock should not be shown.
- assertThat(smallClock.getVisibility()).isEqualTo(View.GONE);
+ assertThat(smallClock.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
- public void setTextColor_setDigitalClock() {
+ public void setColorPalette_setDigitalClock() {
ViewGroup smallClock = (ViewGroup) mClockController.getView();
// WHEN text color is set
- mClockController.setTextColor(42);
+ mClockController.setColorPalette(true, new int[]{42});
// THEN child of small clock should have text color set.
TextView digitalClock = (TextView) smallClock.getChildAt(0);
assertThat(digitalClock.getCurrentTextColor()).isEqualTo(42);
public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
private static final int SCREEN_HEIGHT = 2000;
+ private static final int PREFERRED_CLOCK_Y = SCREEN_HEIGHT / 2;
private static final int EMPTY_MARGIN = 0;
private static final int EMPTY_HEIGHT = 0;
private static final boolean SECURE_LOCKED = false;
private void positionClock() {
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
- mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mDark, SECURE_LOCKED,
- ZERO_DRAG);
+ mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, PREFERRED_CLOCK_Y, mDark,
+ SECURE_LOCKED, ZERO_DRAG);
mClockPositionAlgorithm.run(mClockPosition);
}
}
mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
InOrder inOrder = inOrder(mNotificationStackScrollLayout, mStatusBarStateController);
inOrder.verify(mNotificationStackScrollLayout).setDark(eq(true), eq(true), eq(null));
- inOrder.verify(mNotificationStackScrollLayout).setShowDarkShelf(eq(true));
+ inOrder.verify(mNotificationStackScrollLayout).showDarkShelf();
inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
}
public void testSetDozing_showsDarkShelfWithDefaultClock() {
when(mKeyguardStatusView.hasCustomClock()).thenReturn(false);
mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
- verify(mNotificationStackScrollLayout).setShowDarkShelf(eq(true));
+ verify(mNotificationStackScrollLayout).showDarkShelf();
}
@Test
- public void testSetDozing_hidesDarkShelfWhenCustomClock() {
+ public void testSetDozing_showsDarkShelfWhenCustomClock() {
when(mKeyguardStatusView.hasCustomClock()).thenReturn(true);
mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
- verify(mNotificationStackScrollLayout).setShowDarkShelf(eq(false));
+ verify(mNotificationStackScrollLayout).showDarkShelf();
}
@Test