Merge "Touch-exploration improvements to volume dialog." into lmp-dev
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 48450dd..1a44c8c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -908,4 +908,7 @@
<!-- Indication that the current volume and other effects (vibration) are being suppressed by a third party, such as a notification listener. [CHAR LIMIT=30] -->
<string name="muted_by">Muted by <xliff:g id="third_party">%1$s</xliff:g></string>
+
+ <!-- Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. [CHAR LIMIT=20] -->
+ <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Interaction.java b/packages/SystemUI/src/com/android/systemui/volume/Interaction.java
new file mode 100644
index 0000000..46eab36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/Interaction.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 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.volume;
+
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnGenericMotionListener;
+import android.view.View.OnTouchListener;
+
+public class Interaction {
+
+ public static void register(View v, final Callback callback) {
+ v.setOnTouchListener(new OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ callback.onInteraction();
+ return false;
+ }
+ });
+ v.setOnGenericMotionListener(new OnGenericMotionListener() {
+ @Override
+ public boolean onGenericMotion(View v, MotionEvent event) {
+ callback.onInteraction();
+ return false;
+ }
+ });
+ }
+
+ public interface Callback {
+ void onInteraction();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
index 66e1e15..f7f5047 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
@@ -80,6 +80,12 @@
addView(b);
b.setTag(value);
b.setOnClickListener(mClick);
+ Interaction.register(b, new Interaction.Callback() {
+ @Override
+ public void onInteraction() {
+ fireInteraction();
+ }
+ });
}
public void updateLocale() {
@@ -96,6 +102,12 @@
}
}
+ private void fireInteraction() {
+ if (mCallback != null) {
+ mCallback.onInteraction();
+ }
+ }
+
private final View.OnClickListener mClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -103,7 +115,7 @@
}
};
- public interface Callback {
+ public interface Callback extends Interaction.Callback {
void onSelected(Object value);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index fa43f32..40bdea2 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -42,6 +42,7 @@
import android.media.session.MediaController;
import android.media.session.MediaController.PlaybackInfo;
import android.net.Uri;
+import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
@@ -400,11 +401,10 @@
| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| LayoutParams.FLAG_HARDWARE_ACCELERATED);
mView = window.findViewById(R.id.content);
- mView.setOnTouchListener(new View.OnTouchListener() {
+ Interaction.register(mView, new Interaction.Callback() {
@Override
- public boolean onTouch(View v, MotionEvent event) {
+ public void onInteraction() {
resetTimeout();
- return false;
}
});
@@ -1382,9 +1382,10 @@
}
private void resetTimeout() {
+ final boolean touchExploration = mAccessibilityManager.isTouchExplorationEnabled();
if (LOGD) Log.d(mTag, "resetTimeout at " + System.currentTimeMillis()
- + " delay=" + mTimeoutDelay);
- if (sSafetyWarning == null || !mAccessibilityManager.isTouchExplorationEnabled()) {
+ + " delay=" + mTimeoutDelay + " touchExploration=" + touchExploration);
+ if (sSafetyWarning == null || !touchExploration) {
removeMessages(MSG_TIMEOUT);
sendEmptyMessageDelayed(MSG_TIMEOUT, mTimeoutDelay);
removeMessages(MSG_USER_ACTIVITY);
@@ -1393,6 +1394,7 @@
}
private void forceTimeout(long delay) {
+ if (LOGD) Log.d(mTag, "forceTimeout delay=" + delay + " callers=" + Debug.getCallers(3));
removeMessages(MSG_TIMEOUT);
sendEmptyMessageDelayed(MSG_TIMEOUT, delay);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index c1681c7..ea431ae 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -135,20 +135,21 @@
@Override
public void onClick(View v) {
setExpanded(true);
- fireInteraction();
}
});
+ Interaction.register(mZenSubheadCollapsed, mInteractionCallback);
mZenSubheadExpanded = (TextView) findViewById(R.id.zen_subhead_expanded);
+ Interaction.register(mZenSubheadExpanded, mInteractionCallback);
mMoreSettings = findViewById(R.id.zen_more_settings);
mMoreSettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fireMoreSettings();
- fireInteraction();
}
});
+ Interaction.register(mMoreSettings, mInteractionCallback);
mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
}
@@ -444,18 +445,22 @@
childTag.rb.setChecked(false);
}
select(tag.condition);
- fireInteraction();
+ announceConditionSelection(tag);
}
}
});
- final TextView title = (TextView) row.findViewById(android.R.id.title);
- if (condition == null) {
- title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
- } else {
- title.setText(condition.summary);
+
+ if (tag.title == null) {
+ tag.title = (TextView) row.findViewById(android.R.id.title);
}
- title.setEnabled(enabled);
- title.setAlpha(enabled ? 1 : .4f);
+ if (condition == null) {
+ tag.title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
+ } else {
+ tag.title.setText(condition.summary);
+ }
+ tag.title.setEnabled(enabled);
+ tag.title.setAlpha(enabled ? 1 : .4f);
+
final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@Override
@@ -471,11 +476,10 @@
onClickTimeButton(row, tag, true /*up*/);
}
});
- title.setOnClickListener(new OnClickListener() {
+ tag.title.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tag.rb.setChecked(true);
- fireInteraction();
}
});
@@ -497,6 +501,30 @@
button1.setVisibility(View.GONE);
button2.setVisibility(View.GONE);
}
+ // wire up interaction callbacks for newly-added condition rows
+ if (convertView == null) {
+ Interaction.register(tag.rb, mInteractionCallback);
+ Interaction.register(tag.title, mInteractionCallback);
+ Interaction.register(button1, mInteractionCallback);
+ Interaction.register(button2, mInteractionCallback);
+ }
+ }
+
+ private void announceConditionSelection(ConditionTag tag) {
+ final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
+ String modeText;
+ switch(zen) {
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ modeText = mContext.getString(R.string.zen_important_interruptions);
+ break;
+ case Global.ZEN_MODE_NO_INTERRUPTIONS:
+ modeText = mContext.getString(R.string.zen_no_interruptions);
+ break;
+ default:
+ return;
+ }
+ announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText,
+ tag.title.getText()));
}
private void onClickTimeButton(View row, ConditionTag tag, boolean up) {
@@ -530,7 +558,7 @@
bind(mTimeCondition, row);
tag.rb.setChecked(true);
select(mTimeCondition);
- fireInteraction();
+ announceConditionSelection(tag);
}
private void select(Condition condition) {
@@ -611,6 +639,7 @@
// used as the view tag on condition rows
private static class ConditionTag {
RadioButton rb;
+ TextView title;
Condition condition;
}
@@ -691,5 +720,17 @@
mController.setZen((Integer) value);
}
}
+
+ @Override
+ public void onInteraction() {
+ fireInteraction();
+ }
+ };
+
+ private final Interaction.Callback mInteractionCallback = new Interaction.Callback() {
+ @Override
+ public void onInteraction() {
+ fireInteraction();
+ }
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java b/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java
index 96e2a8e..d887712 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenToast.java
@@ -31,6 +31,7 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
@@ -110,6 +111,17 @@
message.setText(text);
final ImageView icon = (ImageView) mZenToast.findViewById(android.R.id.icon);
icon.setImageResource(iconRes);
+ mZenToast.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ // noop
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mZenToast.announceForAccessibility(message.getText());
+ }
+ });
mWindowManager.addView(mZenToast, params);
final int animDuration = res.getInteger(R.integer.zen_toast_animation_duration);
final int visibleDuration = res.getInteger(R.integer.zen_toast_visible_duration);