summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/volume
diff options
context:
space:
mode:
authorJohn Spurlock <jspurlock@google.com>2014-11-30 16:26:19 -0500
committerJohn Spurlock <jspurlock@google.com>2014-12-08 11:00:57 -0500
commit530052a2fe3b6a6a4246ce28ab0ced647fe7f470 (patch)
treea54342518eb9b94bf43b49fb50d2db1771463436 /packages/SystemUI/src/com/android/systemui/volume
parent78a7357787406220c4c2459f8d25a0175ac98347 (diff)
downloadframeworks_base-530052a2fe3b6a6a4246ce28ab0ced647fe7f470.zip
frameworks_base-530052a2fe3b6a6a4246ce28ab0ced647fe7f470.tar.gz
frameworks_base-530052a2fe3b6a6a4246ce28ab0ced647fe7f470.tar.bz2
Zen: New behavior for built-in downtime + nextalarm conditions.
- Downtime: Allow user to enter downtime early, offer as an end condition four hours before downtime starts. Available in either none or priority, regardless of settings configuration. - Downtime: Always exit before next alarm if zen=none. - Downtime: Make more like any other condition provider, remove special status (mostly). - Downtime: New auto-triggering rules, allow triggering after a manual condition ends, once. - Decouple NextAlarm + Downtime providers, allow them to offer their conditions at the same time. - Downtime/NextAlarm: Update conditions if they change while being requested, even if unsubscribed. - Make all three built-in condition providers optional, via config. - New internal helper for runtime config. - Don't follow changes to next alarm, consider the condition false. - Isolate downtime calendar logic into separate class (for testing). - Allow a:bb -> a:bb as a valid downtime range (all day). - Volume dialog: configuration establishes maximum number of visible conditions, including built-ins. - Zen mode panel: avoid widget updates during layout transition. - Zen mode panel: move controller callers to background thread. - Zen mode panel: hide/show/rebind rows instead of adding/removing. - ZenLog: Add downtime autotrigger results. - Volume panel: Smarter refresh on ringer/zen changes. Bug: 16373455 Change-Id: I4f801018ddb0beb6eb9fa03a81c79f7949888a3f
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/volume')
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java325
2 files changed, 276 insertions, 84 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index d3a8fc0..acdcfc1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -124,8 +124,7 @@ public class VolumePanel extends Handler implements DemoMode {
private static final int MSG_ZEN_MODE_AVAILABLE_CHANGED = 13;
private static final int MSG_USER_ACTIVITY = 14;
private static final int MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED = 15;
- private static final int MSG_ZEN_MODE_CHANGED = 16;
- private static final int MSG_INTERNAL_RINGER_MODE_CHANGED = 17;
+ private static final int MSG_INTERNAL_RINGER_MODE_CHANGED = 16;
// Pseudo stream type for master volume
private static final int STREAM_MASTER = -100;
@@ -511,6 +510,9 @@ public class VolumePanel extends Handler implements DemoMode {
pw.println();
}
}
+ if (mZenPanel != null) {
+ mZenPanel.dump(fd, pw, args);
+ }
}
private void initZenModePanel() {
@@ -723,7 +725,7 @@ public class VolumePanel extends Handler implements DemoMode {
mSliderPanel.addView(active.group);
mActiveStreamType = activeStreamType;
active.group.setVisibility(View.VISIBLE);
- updateSlider(active);
+ updateSlider(active, true /*forceReloadIcon*/);
updateTimeoutDelay();
updateZenPanelVisible();
}
@@ -799,11 +801,12 @@ public class VolumePanel extends Handler implements DemoMode {
}
/** Update the mute and progress state of a slider */
- private void updateSlider(StreamControl sc) {
+ private void updateSlider(StreamControl sc, boolean forceReloadIcon) {
updateSliderProgress(sc, -1);
final boolean muted = isMuted(sc.streamType);
- // Force reloading the image resource
- sc.icon.setImageDrawable(null);
+ if (forceReloadIcon) {
+ sc.icon.setImageDrawable(null);
+ }
updateSliderIcon(sc, muted);
updateSliderEnabled(sc, muted, false);
updateSliderSuppressor(sc);
@@ -907,11 +910,18 @@ public class VolumePanel extends Handler implements DemoMode {
}
}
- public void updateStates() {
+ private void updateStates() {
final int count = mSliderPanel.getChildCount();
for (int i = 0; i < count; i++) {
StreamControl sc = (StreamControl) mSliderPanel.getChildAt(i).getTag();
- updateSlider(sc);
+ updateSlider(sc, true /*forceReloadIcon*/);
+ }
+ }
+
+ private void updateActiveSlider() {
+ final StreamControl active = mStreamControls.get(mActiveStreamType);
+ if (active != null) {
+ updateSlider(active, false /*forceReloadIcon*/);
}
}
@@ -1449,12 +1459,11 @@ public class VolumePanel extends Handler implements DemoMode {
break;
}
- case MSG_ZEN_MODE_CHANGED:
case MSG_RINGER_MODE_CHANGED:
case MSG_INTERNAL_RINGER_MODE_CHANGED:
case MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED: {
if (isShowing()) {
- updateStates();
+ updateActiveSlider();
}
break;
}
@@ -1563,10 +1572,6 @@ public class VolumePanel extends Handler implements DemoMode {
mNotificationEffectsSuppressor = mZenController.getEffectsSuppressor();
sendEmptyMessage(MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED);
}
-
- public void onZenChanged(int zen) {
- sendEmptyMessage(MSG_ZEN_MODE_CHANGED);
- }
};
private final MediaController.Callback mMediaControllerCb = new MediaController.Callback() {
@@ -1591,6 +1596,7 @@ public class VolumePanel extends Handler implements DemoMode {
public void start(StreamControl sc) {
if (sc == null) throw new IllegalArgumentException();
+ if (LOGD) Log.d(mTag, "Secondary icon animation start");
if (mTarget != null) {
cancel();
}
@@ -1643,6 +1649,7 @@ public class VolumePanel extends Handler implements DemoMode {
@Override
public void run() {
if (mTarget == null) return;
+ if (LOGD) Log.d(mTag, "Secondary icon animation complete, show notification slider");
mAudioManager.forceVolumeControlStream(StreamResources.NotificationStream.streamType);
mAudioManager.adjustStreamVolume(StreamResources.NotificationStream.streamType,
AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 6ed24e0..e250ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -17,13 +17,16 @@
package com.android.systemui.volume;
import android.animation.LayoutTransition;
+import android.animation.LayoutTransition.TransitionListener;
import android.app.ActivityManager;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -32,6 +35,7 @@ import android.provider.Settings.Global;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
@@ -50,6 +54,8 @@ import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Objects;
@@ -67,8 +73,7 @@ public class ZenModePanel extends LinearLayout {
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
private static final int FOREVER_CONDITION_INDEX = 0;
- private static final int TIME_CONDITION_INDEX = 1;
- private static final int FIRST_CONDITION_INDEX = 2;
+ private static final int COUNTDOWN_CONDITION_INDEX = 1;
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -81,6 +86,10 @@ public class ZenModePanel extends LinearLayout {
private final int mSubheadColor;
private final Interpolator mInterpolator;
private final int mMaxConditions;
+ private final int mMaxOptionalConditions;
+ private final boolean mCountdownConditionSupported;
+ private final int mFirstConditionIndex;
+ private final TransitionHelper mTransitionHelper = new TransitionHelper();
private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
@@ -98,7 +107,7 @@ public class ZenModePanel extends LinearLayout {
private String mExitConditionText;
private int mBucketIndex = -1;
private boolean mExpanded;
- private boolean mHidden = false;
+ private boolean mHidden;
private int mSessionZen;
private int mAttachedZen;
private boolean mAttached;
@@ -117,11 +126,30 @@ public class ZenModePanel extends LinearLayout {
mSubheadColor = res.getColor(R.color.qs_subhead);
mInterpolator = AnimationUtils.loadInterpolator(mContext,
com.android.internal.R.interpolator.fast_out_slow_in);
+ mCountdownConditionSupported = NotificationManager.from(mContext)
+ .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH);
+ final int countdownDelta = mCountdownConditionSupported ? 1 : 0;
+ mFirstConditionIndex = COUNTDOWN_CONDITION_INDEX + countdownDelta;
+ final int minConditions = 1 /*forever*/ + countdownDelta;
mMaxConditions = MathUtils.constrain(res.getInteger(R.integer.zen_mode_max_conditions),
- 1, 100);
+ minConditions, 100);
+ mMaxOptionalConditions = mMaxConditions - minConditions;
if (DEBUG) Log.d(mTag, "new ZenModePanel");
}
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("ZenModePanel state:");
+ pw.print(" mCountdownConditionSupported="); pw.println(mCountdownConditionSupported);
+ pw.print(" mMaxConditions="); pw.println(mMaxConditions);
+ pw.print(" mRequestingConditions="); pw.println(mRequestingConditions);
+ pw.print(" mAttached="); pw.println(mAttached);
+ pw.print(" mHidden="); pw.println(mHidden);
+ pw.print(" mExpanded="); pw.println(mExpanded);
+ pw.print(" mSessionZen="); pw.println(mSessionZen);
+ pw.print(" mAttachedZen="); pw.println(mAttachedZen);
+ mTransitionHelper.dump(fd, pw, args);
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -135,6 +163,9 @@ public class ZenModePanel extends LinearLayout {
Global.ZEN_MODE_OFF);
mZenButtons.setCallback(mZenButtonsCallback);
+ final ViewGroup zenButtonsContainer = (ViewGroup) findViewById(R.id.zen_buttons_container);
+ zenButtonsContainer.setLayoutTransition(newLayoutTransition(null));
+
mZenSubhead = findViewById(R.id.zen_subhead);
mZenSubheadCollapsed = (TextView) findViewById(R.id.zen_subhead_collapsed);
@@ -159,15 +190,22 @@ public class ZenModePanel extends LinearLayout {
Interaction.register(mMoreSettings, mInteractionCallback);
mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
- setLayoutTransition(newLayoutTransition());
+ for (int i = 0; i < mMaxConditions; i++) {
+ mZenConditions.addView(mInflater.inflate(R.layout.zen_mode_condition, this, false));
+ }
+
+ setLayoutTransition(newLayoutTransition(mTransitionHelper));
}
- private LayoutTransition newLayoutTransition() {
+ private LayoutTransition newLayoutTransition(TransitionListener listener) {
final LayoutTransition transition = new LayoutTransition();
transition.disableTransitionType(LayoutTransition.DISAPPEARING);
transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
- transition.setInterpolator(LayoutTransition.APPEARING, mInterpolator);
+ transition.disableTransitionType(LayoutTransition.APPEARING);
transition.setInterpolator(LayoutTransition.CHANGE_APPEARING, mInterpolator);
+ if (listener != null) {
+ transition.addTransitionListener(listener);
+ }
return transition;
}
@@ -175,11 +213,11 @@ public class ZenModePanel extends LinearLayout {
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (DEBUG) Log.d(mTag, "onAttachedToWindow");
- ((ViewGroup) getParent()).setLayoutTransition(newLayoutTransition());
mAttached = true;
mAttachedZen = getSelectedZen(-1);
mSessionZen = mAttachedZen;
- mSessionExitCondition = copy(mExitCondition);
+ mTransitionHelper.clear();
+ setSessionExitCondition(copy(mExitCondition));
refreshExitConditionText();
updateWidgets();
setRequestingConditions(!mHidden);
@@ -193,9 +231,16 @@ public class ZenModePanel extends LinearLayout {
mAttached = false;
mAttachedZen = -1;
mSessionZen = -1;
- mSessionExitCondition = null;
+ setSessionExitCondition(null);
setExpanded(false);
setRequestingConditions(false);
+ mTransitionHelper.clear();
+ }
+
+ private void setSessionExitCondition(Condition condition) {
+ if (Objects.equals(condition, mSessionExitCondition)) return;
+ if (DEBUG) Log.d(mTag, "mSessionExitCondition=" + getConditionId(condition));
+ mSessionExitCondition = condition;
}
public void setHidden(boolean hidden) {
@@ -228,12 +273,17 @@ public class ZenModePanel extends LinearLayout {
}
/** Start or stop requesting relevant zen mode exit conditions */
- private void setRequestingConditions(boolean requesting) {
+ private void setRequestingConditions(final boolean requesting) {
if (mRequestingConditions == requesting) return;
if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
mRequestingConditions = requesting;
if (mController != null) {
- mController.requestConditions(mRequestingConditions);
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ mController.requestConditions(requesting);
+ }
+ });
}
if (mRequestingConditions) {
mTimeCondition = parseExistingTimeCondition(mExitCondition);
@@ -248,7 +298,7 @@ public class ZenModePanel extends LinearLayout {
mConditions = null; // reset conditions
handleUpdateConditions();
} else {
- mZenConditions.removeAllViews();
+ hideAllConditions();
}
}
@@ -259,7 +309,7 @@ public class ZenModePanel extends LinearLayout {
mSessionZen = getSelectedZen(-1);
handleUpdateZen(mController.getZen());
if (DEBUG) Log.d(mTag, "init mExitCondition=" + mExitCondition);
- mZenConditions.removeAllViews();
+ hideAllConditions();
mController.addCallback(mZenCallback);
}
@@ -270,6 +320,7 @@ public class ZenModePanel extends LinearLayout {
private void setExitCondition(Condition exitCondition) {
if (Objects.equals(mExitCondition, exitCondition)) return;
mExitCondition = exitCondition;
+ if (DEBUG) Log.d(mTag, "mExitCondition=" + getConditionId(mExitCondition));
refreshExitConditionText();
updateWidgets();
}
@@ -290,7 +341,7 @@ public class ZenModePanel extends LinearLayout {
final String forever = mContext.getString(com.android.internal.R.string.zen_mode_forever);
if (mExitCondition == null) {
mExitConditionText = forever;
- } else if (ZenModeConfig.isValidCountdownConditionId(mExitCondition.id)) {
+ } else if (isCountdown(mExitCondition)) {
final Condition condition = parseExistingTimeCondition(mExitCondition);
mExitConditionText = condition != null ? condition.summary : forever;
} else {
@@ -316,6 +367,24 @@ public class ZenModePanel extends LinearLayout {
}
mZenButtons.setSelectedValue(zen);
updateWidgets();
+ handleUpdateConditions();
+ if (mExpanded) {
+ final Condition selected = getSelectedCondition();
+ if (!Objects.equals(mExitCondition, selected)) {
+ select(selected);
+ }
+ }
+ }
+
+ private Condition getSelectedCondition() {
+ final int N = getVisibleConditions();
+ for (int i = 0; i < N; i++) {
+ final ConditionTag tag = getConditionTagAt(i);
+ if (tag != null && tag.rb.isChecked()) {
+ return tag.condition;
+ }
+ }
+ return null;
}
private int getSelectedZen(int defValue) {
@@ -324,6 +393,10 @@ public class ZenModePanel extends LinearLayout {
}
private void updateWidgets() {
+ if (mTransitionHelper.isTransitioning()) {
+ mTransitionHelper.pendingUpdateWidgets();
+ return;
+ }
final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
final boolean zenOff = zen == Global.ZEN_MODE_OFF;
final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
@@ -371,7 +444,7 @@ public class ZenModePanel extends LinearLayout {
}
private Condition[] trimConditions(Condition[] conditions) {
- if (conditions == null || conditions.length <= mMaxConditions) {
+ if (conditions == null || conditions.length <= mMaxOptionalConditions) {
// no need to trim
return conditions;
}
@@ -384,33 +457,34 @@ public class ZenModePanel extends LinearLayout {
break;
}
}
- final Condition[] rt = Arrays.copyOf(conditions, mMaxConditions);
- if (found >= mMaxConditions) {
+ final Condition[] rt = Arrays.copyOf(conditions, mMaxOptionalConditions);
+ if (found >= mMaxOptionalConditions) {
// found after the first N, promote to the end of the first N
- rt[mMaxConditions - 1] = conditions[found];
+ rt[mMaxOptionalConditions - 1] = conditions[found];
}
return rt;
}
private void handleUpdateConditions() {
+ if (mTransitionHelper.isTransitioning()) {
+ mTransitionHelper.pendingUpdateConditions();
+ return;
+ }
final int conditionCount = mConditions == null ? 0 : mConditions.length;
if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
- for (int i = mZenConditions.getChildCount() - 1; i >= FIRST_CONDITION_INDEX; i--) {
- mZenConditions.removeViewAt(i);
- }
// forever
bind(null, mZenConditions.getChildAt(FOREVER_CONDITION_INDEX));
// countdown
- bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
+ if (mCountdownConditionSupported) {
+ bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
+ }
// provider conditions
- boolean foundDowntime = false;
for (int i = 0; i < conditionCount; i++) {
- bind(mConditions[i], mZenConditions.getChildAt(FIRST_CONDITION_INDEX + i));
- foundDowntime |= isDowntime(mConditions[i]);
+ bind(mConditions[i], mZenConditions.getChildAt(mFirstConditionIndex + i));
}
- // ensure downtime exists, if active
- if (isDowntime(mSessionExitCondition) && !foundDowntime) {
- bind(mSessionExitCondition, null);
+ // hide the rest
+ for (int i = mZenConditions.getChildCount() - 1; i > mFirstConditionIndex + conditionCount; i--) {
+ mZenConditions.getChildAt(i).setVisibility(GONE);
}
// ensure something is selected
if (mExpanded) {
@@ -418,78 +492,101 @@ public class ZenModePanel extends LinearLayout {
}
}
- private static boolean isDowntime(Condition c) {
- return ZenModeConfig.isValidDowntimeConditionId(getConditionId(c));
- }
-
private ConditionTag getConditionTagAt(int index) {
return (ConditionTag) mZenConditions.getChildAt(index).getTag();
}
+ private int getVisibleConditions() {
+ int rt = 0;
+ final int N = mZenConditions.getChildCount();
+ for (int i = 0; i < N; i++) {
+ rt += mZenConditions.getChildAt(i).getVisibility() == VISIBLE ? 1 : 0;
+ }
+ return rt;
+ }
+
+ private void hideAllConditions() {
+ final int N = mZenConditions.getChildCount();
+ for (int i = 0; i < N; i++) {
+ mZenConditions.getChildAt(i).setVisibility(GONE);
+ }
+ }
+
private void ensureSelection() {
// are we left without anything selected? if so, set a default
- if (mZenConditions.getChildCount() == 0) return;
- for (int i = 0; i < mZenConditions.getChildCount(); i++) {
- if (getConditionTagAt(i).rb.isChecked()) {
- if (DEBUG) Log.d(mTag, "Not selecting a default, checked="
- + getConditionTagAt(i).condition);
+ final int visibleConditions = getVisibleConditions();
+ if (visibleConditions == 0) return;
+ for (int i = 0; i < visibleConditions; i++) {
+ final ConditionTag tag = getConditionTagAt(i);
+ if (tag != null && tag.rb.isChecked()) {
+ if (DEBUG) Log.d(mTag, "Not selecting a default, checked=" + tag.condition);
return;
}
}
+ final ConditionTag foreverTag = getConditionTagAt(FOREVER_CONDITION_INDEX);
+ if (foreverTag == null) return;
if (DEBUG) Log.d(mTag, "Selecting a default");
final int favoriteIndex = mPrefs.getMinuteIndex();
- if (favoriteIndex == -1) {
- getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
+ if (favoriteIndex == -1 || !mCountdownConditionSupported) {
+ foreverTag.rb.setChecked(true);
} else {
mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[favoriteIndex], ActivityManager.getCurrentUser());
mBucketIndex = favoriteIndex;
- bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
- getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true);
+ bind(mTimeCondition, mZenConditions.getChildAt(COUNTDOWN_CONDITION_INDEX));
+ getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
}
}
private void handleExitConditionChanged(Condition exitCondition) {
setExitCondition(exitCondition);
if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitCondition);
- final int N = mZenConditions.getChildCount();
+ final int N = getVisibleConditions();
for (int i = 0; i < N; i++) {
final ConditionTag tag = getConditionTagAt(i);
- tag.rb.setChecked(sameConditionId(tag.condition, mExitCondition));
+ if (tag != null) {
+ if (sameConditionId(tag.condition, mExitCondition)) {
+ bind(exitCondition, mZenConditions.getChildAt(i));
+ }
+ }
}
}
- private void bind(final Condition condition, View convertView) {
+ private boolean isCountdown(Condition c) {
+ return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
+ }
+
+ private void bind(final Condition condition, final View row) {
final boolean enabled = condition == null || condition.state == Condition.STATE_TRUE;
- final View row;
- if (convertView == null) {
- row = mInflater.inflate(R.layout.zen_mode_condition, this, false);
- if (DEBUG) Log.d(mTag, "Adding new condition view for: " + condition);
- mZenConditions.addView(row);
- } else {
- row = convertView;
- }
final ConditionTag tag =
row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();
row.setTag(tag);
+ final boolean first = tag.rb == null;
if (tag.rb == null) {
tag.rb = (RadioButton) row.findViewById(android.R.id.checkbox);
}
tag.condition = condition;
+ final Uri conditionId = getConditionId(tag.condition);
+ if (DEBUG) Log.d(mTag, "bind i=" + mZenConditions.indexOfChild(row) + " first=" + first
+ + " condition=" + conditionId);
tag.rb.setEnabled(enabled);
- if ((mSessionExitCondition != null || mAttachedZen != Global.ZEN_MODE_OFF)
- && sameConditionId(mSessionExitCondition, tag.condition)) {
- tag.rb.setChecked(true);
+ final boolean checked = (mSessionExitCondition != null
+ || mAttachedZen != Global.ZEN_MODE_OFF)
+ && (sameConditionId(mSessionExitCondition, tag.condition)
+ || isCountdown(mSessionExitCondition) && isCountdown(tag.condition));
+ if (checked != tag.rb.isChecked()) {
+ if (DEBUG) Log.d(mTag, "bind checked=" + checked + " condition=" + conditionId);
+ tag.rb.setChecked(checked);
}
tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mExpanded && isChecked) {
- if (DEBUG) Log.d(mTag, "onCheckedChanged " + tag.condition);
- final int N = mZenConditions.getChildCount();
+ if (DEBUG) Log.d(mTag, "onCheckedChanged " + conditionId);
+ final int N = getVisibleConditions();
for (int i = 0; i < N; i++) {
- ConditionTag childTag = getConditionTagAt(i);
- if (childTag == tag) continue;
+ final ConditionTag childTag = getConditionTagAt(i);
+ if (childTag == null || childTag == tag) continue;
childTag.rb.setChecked(false);
}
select(tag.condition);
@@ -547,8 +644,10 @@ public class ZenModePanel extends LinearLayout {
}
});
- final long time = ZenModeConfig.tryParseCountdownConditionId(getConditionId(tag.condition));
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
if (time > 0) {
+ button1.setVisibility(VISIBLE);
+ button2.setVisibility(VISIBLE);
if (mBucketIndex > -1) {
button1.setEnabled(mBucketIndex > 0);
button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
@@ -563,16 +662,17 @@ public class ZenModePanel extends LinearLayout {
button1.setAlpha(button1.isEnabled() ? 1f : .5f);
button2.setAlpha(button2.isEnabled() ? 1f : .5f);
} else {
- button1.setVisibility(View.GONE);
- button2.setVisibility(View.GONE);
+ button1.setVisibility(GONE);
+ button2.setVisibility(GONE);
}
// wire up interaction callbacks for newly-added condition rows
- if (convertView == null) {
+ if (first) {
Interaction.register(tag.rb, mInteractionCallback);
Interaction.register(tag.lines, mInteractionCallback);
Interaction.register(button1, mInteractionCallback);
Interaction.register(button2, mInteractionCallback);
}
+ row.setVisibility(VISIBLE);
}
private void announceConditionSelection(ConditionTag tag) {
@@ -629,18 +729,23 @@ public class ZenModePanel extends LinearLayout {
announceConditionSelection(tag);
}
- private void select(Condition condition) {
+ private void select(final Condition condition) {
if (DEBUG) Log.d(mTag, "select " + condition);
if (mController != null) {
- mController.setExitCondition(condition);
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ mController.setExitCondition(condition);
+ }
+ });
}
setExitCondition(condition);
if (condition == null) {
mPrefs.setMinuteIndex(-1);
- } else if (ZenModeConfig.isValidCountdownConditionId(condition.id) && mBucketIndex != -1) {
+ } else if (isCountdown(condition) && mBucketIndex != -1) {
mPrefs.setMinuteIndex(mBucketIndex);
}
- mSessionExitCondition = copy(condition);
+ setSessionExitCondition(copy(condition));
}
private void fireMoreSettings() {
@@ -784,10 +889,15 @@ public class ZenModePanel extends LinearLayout {
private final SegmentedButtons.Callback mZenButtonsCallback = new SegmentedButtons.Callback() {
@Override
- public void onSelected(Object value) {
+ public void onSelected(final Object value) {
if (value != null && mZenButtons.isShown()) {
if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + value);
- mController.setZen((Integer) value);
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ mController.setZen((Integer) value);
+ }
+ });
}
}
@@ -803,4 +913,79 @@ public class ZenModePanel extends LinearLayout {
fireInteraction();
}
};
+
+ private final class TransitionHelper implements TransitionListener, Runnable {
+ private final ArraySet<View> mTransitioningViews = new ArraySet<View>();
+
+ private boolean mTransitioning;
+ private boolean mPendingUpdateConditions;
+ private boolean mPendingUpdateWidgets;
+
+ public void clear() {
+ mTransitioningViews.clear();
+ mPendingUpdateConditions = mPendingUpdateWidgets = false;
+ }
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(" TransitionHelper state:");
+ pw.print(" mPendingUpdateConditions="); pw.println(mPendingUpdateConditions);
+ pw.print(" mPendingUpdateWidgets="); pw.println(mPendingUpdateWidgets);
+ pw.print(" mTransitioning="); pw.println(mTransitioning);
+ pw.print(" mTransitioningViews="); pw.println(mTransitioningViews);
+ }
+
+ public void pendingUpdateConditions() {
+ mPendingUpdateConditions = true;
+ }
+
+ public void pendingUpdateWidgets() {
+ mPendingUpdateWidgets = true;
+ }
+
+ public boolean isTransitioning() {
+ return !mTransitioningViews.isEmpty();
+ }
+
+ @Override
+ public void startTransition(LayoutTransition transition,
+ ViewGroup container, View view, int transitionType) {
+ mTransitioningViews.add(view);
+ updateTransitioning();
+ }
+
+ @Override
+ public void endTransition(LayoutTransition transition,
+ ViewGroup container, View view, int transitionType) {
+ mTransitioningViews.remove(view);
+ updateTransitioning();
+ }
+
+ @Override
+ public void run() {
+ if (DEBUG) Log.d(mTag, "TransitionHelper run"
+ + " mPendingUpdateWidgets=" + mPendingUpdateWidgets
+ + " mPendingUpdateConditions=" + mPendingUpdateConditions);
+ if (mPendingUpdateWidgets) {
+ updateWidgets();
+ }
+ if (mPendingUpdateConditions) {
+ handleUpdateConditions();
+ }
+ mPendingUpdateWidgets = mPendingUpdateConditions = false;
+ }
+
+ private void updateTransitioning() {
+ final boolean transitioning = isTransitioning();
+ if (mTransitioning == transitioning) return;
+ mTransitioning = transitioning;
+ if (DEBUG) Log.d(mTag, "TransitionHelper mTransitioning=" + mTransitioning);
+ if (!mTransitioning) {
+ if (mPendingUpdateConditions || mPendingUpdateWidgets) {
+ mHandler.post(this);
+ } else {
+ mPendingUpdateConditions = mPendingUpdateWidgets = false;
+ }
+ }
+ }
+ }
}