<!-- 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>
--- /dev/null
+/*
+ * 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();
+ }
+}
addView(b);
b.setTag(value);
b.setOnClickListener(mClick);
+ Interaction.register(b, new Interaction.Callback() {
+ @Override
+ public void onInteraction() {
+ fireInteraction();
+ }
+ });
}
public void updateLocale() {
}
}
+ private void fireInteraction() {
+ if (mCallback != null) {
+ mCallback.onInteraction();
+ }
+ }
+
private final View.OnClickListener mClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
}
};
- public interface Callback {
+ public interface Callback extends Interaction.Callback {
void onSelected(Object value);
}
}
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;
| 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;
}
});
}
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);
}
private void forceTimeout(long delay) {
+ if (LOGD) Log.d(mTag, "forceTimeout delay=" + delay + " callers=" + Debug.getCallers(3));
removeMessages(MSG_TIMEOUT);
sendEmptyMessageDelayed(MSG_TIMEOUT, delay);
}
@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);
}
childTag.rb.setChecked(false);
}
select(tag.condition);
- fireInteraction();
+ announceConditionSelection(tag);
}
}
});
- final TextView title = (TextView) row.findViewById(android.R.id.title);
+
+ if (tag.title == null) {
+ tag.title = (TextView) row.findViewById(android.R.id.title);
+ }
if (condition == null) {
- title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
+ tag.title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
} else {
- title.setText(condition.summary);
+ tag.title.setText(condition.summary);
}
- title.setEnabled(enabled);
- title.setAlpha(enabled ? 1 : .4f);
+ 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
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();
}
});
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) {
bind(mTimeCondition, row);
tag.rb.setChecked(true);
select(mTimeCondition);
- fireInteraction();
+ announceConditionSelection(tag);
}
private void select(Condition condition) {
// used as the view tag on condition rows
private static class ConditionTag {
RadioButton rb;
+ TextView title;
Condition condition;
}
mController.setZen((Integer) value);
}
}
+
+ @Override
+ public void onInteraction() {
+ fireInteraction();
+ }
+ };
+
+ private final Interaction.Callback mInteractionCallback = new Interaction.Callback() {
+ @Override
+ public void onInteraction() {
+ fireInteraction();
+ }
};
}
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;
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);