/* * Copyright (C) 2013 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 android.view.accessibility; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; import android.os.Handler; import android.provider.Settings.Secure; import android.text.TextUtils; import java.util.ArrayList; import java.util.Locale; /** * Contains methods for accessing and monitoring preferred video captioning state and visual * properties. *
* To obtain a handle to the captioning manager, do the following: *
*
*
*/
public class CaptioningManager {
/** Default captioning enabled value. */
private static final int DEFAULT_ENABLED = 0;
/** Default style preset as an index into {@link CaptionStyle#PRESETS}. */
private static final int DEFAULT_PRESET = 0;
/** Default scaling value for caption fonts. */
private static final float DEFAULT_FONT_SCALE = 1;
private final ArrayListCaptioningManager captioningManager =
* (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
*
*
*/
public final int edgeType;
/**
* The preferred edge color for video captions, if using an edge type
* other than {@link #EDGE_TYPE_NONE}.
*/
public final int edgeColor;
/** The preferred window color for video captions. */
public final int windowColor;
/**
* @hide
*/
public final String mRawTypeface;
private final boolean mHasForegroundColor;
private final boolean mHasBackgroundColor;
private final boolean mHasEdgeType;
private final boolean mHasEdgeColor;
private final boolean mHasWindowColor;
/** Lazily-created typeface based on the raw typeface string. */
private Typeface mParsedTypeface;
private CaptionStyle(int foregroundColor, int backgroundColor, int edgeType, int edgeColor,
int windowColor, String rawTypeface) {
mHasForegroundColor = hasColor(foregroundColor);
mHasBackgroundColor = hasColor(backgroundColor);
mHasEdgeType = edgeType != EDGE_TYPE_UNSPECIFIED;
mHasEdgeColor = hasColor(edgeColor);
mHasWindowColor = hasColor(windowColor);
// Always use valid colors, even when no override is specified, to
// ensure backwards compatibility with apps targeting KitKat MR2.
this.foregroundColor = mHasForegroundColor ? foregroundColor : Color.WHITE;
this.backgroundColor = mHasBackgroundColor ? backgroundColor : Color.BLACK;
this.edgeType = mHasEdgeType ? edgeType : EDGE_TYPE_NONE;
this.edgeColor = mHasEdgeColor ? edgeColor : Color.BLACK;
this.windowColor = mHasWindowColor ? windowColor : COLOR_NONE_OPAQUE;
mRawTypeface = rawTypeface;
}
/**
* Returns whether a packed color indicates a non-default value.
*
* @param packedColor the packed color value
* @return {@code true} if a non-default value is specified
* @hide
*/
public static boolean hasColor(int packedColor) {
// Matches the color packing code from Settings. "Default" packed
// colors are indicated by zero alpha and non-zero red/blue. The
// cached alpha value used by Settings is stored in green.
return (packedColor >>> 24) != 0 || (packedColor & 0xFFFF00) == 0;
}
/**
* Applies a caption style, overriding any properties that are specified
* in the overlay caption.
*
* @param overlay The style to apply
* @return A caption style with the overlay style applied
* @hide
*/
@NonNull
public CaptionStyle applyStyle(@NonNull CaptionStyle overlay) {
final int newForegroundColor = overlay.hasForegroundColor() ?
overlay.foregroundColor : foregroundColor;
final int newBackgroundColor = overlay.hasBackgroundColor() ?
overlay.backgroundColor : backgroundColor;
final int newEdgeType = overlay.hasEdgeType() ?
overlay.edgeType : edgeType;
final int newEdgeColor = overlay.hasEdgeColor() ?
overlay.edgeColor : edgeColor;
final int newWindowColor = overlay.hasWindowColor() ?
overlay.windowColor : windowColor;
final String newRawTypeface = overlay.mRawTypeface != null ?
overlay.mRawTypeface : mRawTypeface;
return new CaptionStyle(newForegroundColor, newBackgroundColor, newEdgeType,
newEdgeColor, newWindowColor, newRawTypeface);
}
/**
* @return {@code true} if the user has specified a background color
* that should override the application default, {@code false}
* otherwise
*/
public boolean hasBackgroundColor() {
return mHasBackgroundColor;
}
/**
* @return {@code true} if the user has specified a foreground color
* that should override the application default, {@code false}
* otherwise
*/
public boolean hasForegroundColor() {
return mHasForegroundColor;
}
/**
* @return {@code true} if the user has specified an edge type that
* should override the application default, {@code false}
* otherwise
*/
public boolean hasEdgeType() {
return mHasEdgeType;
}
/**
* @return {@code true} if the user has specified an edge color that
* should override the application default, {@code false}
* otherwise
*/
public boolean hasEdgeColor() {
return mHasEdgeColor;
}
/**
* @return {@code true} if the user has specified a window color that
* should override the application default, {@code false}
* otherwise
*/
public boolean hasWindowColor() {
return mHasWindowColor;
}
/**
* @return the preferred {@link Typeface} for video captions, or null if
* not specified
*/
@Nullable
public Typeface getTypeface() {
if (mParsedTypeface == null && !TextUtils.isEmpty(mRawTypeface)) {
mParsedTypeface = Typeface.create(mRawTypeface, Typeface.NORMAL);
}
return mParsedTypeface;
}
/**
* @hide
*/
@NonNull
public static CaptionStyle getCustomStyle(ContentResolver cr) {
final CaptionStyle defStyle = CaptionStyle.DEFAULT_CUSTOM;
final int foregroundColor = Secure.getInt(
cr, Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, defStyle.foregroundColor);
final int backgroundColor = Secure.getInt(
cr, Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, defStyle.backgroundColor);
final int edgeType = Secure.getInt(
cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, defStyle.edgeType);
final int edgeColor = Secure.getInt(
cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, defStyle.edgeColor);
final int windowColor = Secure.getInt(
cr, Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, defStyle.windowColor);
String rawTypeface = Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
if (rawTypeface == null) {
rawTypeface = defStyle.mRawTypeface;
}
return new CaptionStyle(foregroundColor, backgroundColor, edgeType, edgeColor,
windowColor, rawTypeface);
}
static {
WHITE_ON_BLACK = new CaptionStyle(Color.WHITE, Color.BLACK, EDGE_TYPE_NONE,
Color.BLACK, COLOR_NONE_OPAQUE, null);
BLACK_ON_WHITE = new CaptionStyle(Color.BLACK, Color.WHITE, EDGE_TYPE_NONE,
Color.BLACK, COLOR_NONE_OPAQUE, null);
YELLOW_ON_BLACK = new CaptionStyle(Color.YELLOW, Color.BLACK, EDGE_TYPE_NONE,
Color.BLACK, COLOR_NONE_OPAQUE, null);
YELLOW_ON_BLUE = new CaptionStyle(Color.YELLOW, Color.BLUE, EDGE_TYPE_NONE,
Color.BLACK, COLOR_NONE_OPAQUE, null);
UNSPECIFIED = new CaptionStyle(COLOR_UNSPECIFIED, COLOR_UNSPECIFIED,
EDGE_TYPE_UNSPECIFIED, COLOR_UNSPECIFIED, COLOR_UNSPECIFIED, null);
// The ordering of these cannot change since we store the index
// directly in preferences.
PRESETS = new CaptionStyle[] {
WHITE_ON_BLACK, BLACK_ON_WHITE, YELLOW_ON_BLACK, YELLOW_ON_BLUE, UNSPECIFIED
};
DEFAULT_CUSTOM = WHITE_ON_BLACK;
DEFAULT = WHITE_ON_BLACK;
}
}
/**
* Listener for changes in captioning properties, including enabled state
* and user style preferences.
*/
public static abstract class CaptioningChangeListener {
/**
* Called when the captioning enabled state changes.
*
* @param enabled the user's new preferred captioning enabled state
*/
public void onEnabledChanged(boolean enabled) {}
/**
* Called when the captioning user style changes.
*
* @param userStyle the user's new preferred style
* @see CaptioningManager#getUserStyle()
*/
public void onUserStyleChanged(@NonNull CaptionStyle userStyle) {}
/**
* Called when the captioning locale changes.
*
* @param locale the preferred captioning locale, or {@code null} if not specified
* @see CaptioningManager#getLocale()
*/
public void onLocaleChanged(@Nullable Locale locale) {}
/**
* Called when the captioning font scaling factor changes.
*
* @param fontScale the preferred font scaling factor
* @see CaptioningManager#getFontScale()
*/
public void onFontScaleChanged(float fontScale) {}
}
}