diff options
-rw-r--r-- | api/current.txt | 22 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 6 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 11 | ||||
-rw-r--r-- | core/java/android/provider/Settings.java | 35 | ||||
-rw-r--r-- | core/java/android/view/accessibility/CaptioningManager.java | 300 |
5 files changed, 294 insertions, 80 deletions
diff --git a/api/current.txt b/api/current.txt index 8d71796..f508c0a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5957,6 +5957,7 @@ package android.content { field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20 field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth"; field public static final java.lang.String CAMERA_SERVICE = "camera"; + field public static final java.lang.String CAPTIONING_SERVICE = "captioning"; field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard"; field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity"; field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2 @@ -21253,6 +21254,7 @@ package android.provider { field public static final java.lang.String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS"; field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS"; field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS"; + field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS"; field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS"; field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS"; field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS"; @@ -28963,15 +28965,15 @@ package android.view.accessibility { } public class CaptioningManager { - ctor public CaptioningManager(); - method public static final float getFontSize(android.content.ContentResolver); - method public static final java.util.Locale getLocale(android.content.ContentResolver); - method public static final boolean isEnabled(android.content.ContentResolver); - field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS"; + method public void addCaptioningStateChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener); + method public final float getFontScale(); + method public final java.util.Locale getLocale(); + method public android.view.accessibility.CaptioningManager.CaptionStyle getUserStyle(); + method public final boolean isEnabled(); + method public void removeCaptioningStateChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener); } public static final class CaptioningManager.CaptionStyle { - method public static android.view.accessibility.CaptioningManager.CaptionStyle defaultUserStyle(android.content.ContentResolver); method public android.graphics.Typeface getTypeface(); field public static final int EDGE_TYPE_DROP_SHADOW = 2; // 0x2 field public static final int EDGE_TYPE_NONE = 0; // 0x0 @@ -28982,6 +28984,14 @@ package android.view.accessibility { field public final int foregroundColor; } + public abstract class CaptioningManager.CaptioningChangeListener { + ctor public CaptioningManager.CaptioningChangeListener(); + method public void onEnabledChanged(boolean); + method public void onFontScaleChanged(float); + method public void onLocaleChanged(java.util.Locale); + method public void onUserStyleChanged(android.view.accessibility.CaptioningManager.CaptionStyle); + } + } package android.view.animation { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index cdec399..f10290d 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -105,6 +105,7 @@ import android.view.ContextThemeWrapper; import android.view.Display; import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.CaptioningManager; import android.view.inputmethod.InputMethodManager; import android.view.textservice.TextServicesManager; import android.accounts.AccountManager; @@ -307,6 +308,11 @@ class ContextImpl extends Context { return AccessibilityManager.getInstance(ctx); }}); + registerService(CAPTIONING_SERVICE, new ServiceFetcher() { + public Object getService(ContextImpl ctx) { + return new CaptioningManager(ctx); + }}); + registerService(ACCOUNT_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(ACCOUNT_SERVICE); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index cd1f87b..2ff9182 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2011,6 +2011,17 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a + * {@link android.view.accessibility.CaptioningManager} for obtaining + * captioning properties and listening for changes in captioning + * preferences. + * + * @see #getSystemService + * @see android.view.accessibility.CaptioningManager + */ + public static final String CAPTIONING_SERVICE = "captioning"; + + /** + * Use with {@link #getSystemService} to retrieve a * {@link android.app.NotificationManager} for controlling keyguard. * * @see #getSystemService diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 802bedf..31817cc 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -690,6 +690,19 @@ public final class Settings { public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.NOTIFICATION_LISTENER_SETTINGS"; + /** + * Activity Action: Show settings for video captioning. + * <p> + * In some cases, a matching Activity may not exist, so ensure you safeguard + * against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS"; + // End of Intent actions for Settings /** @@ -3588,7 +3601,7 @@ public final class Settings { * <li>{@link #ACCESSIBILITY_CAPTIONING_EDGE_COLOR} * <li>{@link #ACCESSIBILITY_CAPTIONING_EDGE_TYPE} * <li>{@link #ACCESSIBILITY_CAPTIONING_TYPEFACE} - * <li>{@link #ACCESSIBILITY_CAPTIONING_FONT_SIZE} + * <li>{@link #ACCESSIBILITY_CAPTIONING_FONT_SCALE} * </ul> * * @hide @@ -3610,9 +3623,8 @@ public final class Settings { * Integer property that specifies the preset style for captions, one * of: * <ul> - * <li>{@link android.view.accessibility.CaptioningManager#PRESET_WHITE_ON_BLACK} - * <li>{@link android.view.accessibility.CaptioningManager#PRESET_BLACK_ON_WHITE} - * <li>{@link android.view.accessibility.CaptioningManager#PRESET_CUSTOM} + * <li>{@link android.view.accessibility.CaptioningManager.CaptionStyle#PRESET_CUSTOM} + * <li>a valid index of {@link android.view.accessibility.CaptioningManager.CaptionStyle#PRESETS} * </ul> * * @see java.util.Locale#toString @@ -3644,9 +3656,9 @@ public final class Settings { /** * Integer property that specifes the edge type for captions, one of: * <ul> - * <li>{@link android.view.accessibility.CaptioningManager#EDGE_TYPE_NONE} - * <li>{@link android.view.accessibility.CaptioningManager#EDGE_TYPE_OUTLINE} - * <li>{@link android.view.accessibility.CaptioningManager#EDGE_TYPE_DROP_SHADOWED} + * <li>{@link android.view.accessibility.CaptioningManager.CaptionStyle#EDGE_TYPE_NONE} + * <li>{@link android.view.accessibility.CaptioningManager.CaptionStyle#EDGE_TYPE_OUTLINE} + * <li>{@link android.view.accessibility.CaptioningManager.CaptionStyle#EDGE_TYPE_DROP_SHADOW} * </ul> * * @see #ACCESSIBILITY_CAPTIONING_EDGE_COLOR @@ -3682,13 +3694,12 @@ public final class Settings { "accessibility_captioning_typeface"; /** - * Integer point property that specifies font size for captions in - * scaled pixels (sp). + * Floating point property that specifies font scaling for captions. * * @hide */ - public static final String ACCESSIBILITY_CAPTIONING_FONT_SIZE = - "accessibility_captioning_font_size"; + public static final String ACCESSIBILITY_CAPTIONING_FONT_SCALE = + "accessibility_captioning_font_scale"; /** * The timout for considering a press to be a long press in milliseconds. @@ -4327,7 +4338,7 @@ public final class Settings { ACCESSIBILITY_CAPTIONING_EDGE_TYPE, ACCESSIBILITY_CAPTIONING_EDGE_COLOR, ACCESSIBILITY_CAPTIONING_TYPEFACE, - ACCESSIBILITY_CAPTIONING_FONT_SIZE, + ACCESSIBILITY_CAPTIONING_FONT_SCALE, TTS_USE_DEFAULTS, TTS_DEFAULT_RATE, TTS_DEFAULT_PITCH, diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java index b1be24c..d4c6abe 100644 --- a/core/java/android/view/accessibility/CaptioningManager.java +++ b/core/java/android/view/accessibility/CaptioningManager.java @@ -17,58 +17,77 @@ package android.view.accessibility; 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 preferred video captioning state and + * Contains methods for accessing and monitoring preferred video captioning state and visual * properties. + * <p> + * To obtain a handle to the captioning manager, do the following: + * <p> + * <code> + * <pre>CaptioningManager captioningManager = + * (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);</pre> + * </code> */ public class CaptioningManager { - /** - * Activity Action: Show settings for video captioning. - * <p> - * In some cases, a matching Activity may not exist, so ensure you safeguard - * against this. - * <p> - * Input: Nothing. - * <p> - * Output: Nothing. - */ - public static final String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS"; + /** 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; - private static final int DEFAULT_ENABLED = 0; - private static final float DEFAULT_FONT_SIZE = 24; + + /** Default scaling value for caption fonts. */ + private static final float DEFAULT_FONT_SCALE = 1; + + private final ArrayList<CaptioningChangeListener> + mListeners = new ArrayList<CaptioningChangeListener>(); + private final Handler mHandler = new Handler(); + + private final ContentResolver mContentResolver; + + /** + * Creates a new captioning manager for the specified context. + * + * @hide + */ + public CaptioningManager(Context context) { + mContentResolver = context.getContentResolver(); + } /** - * @param cr Resolver to access the database with. - * @return The user's preferred caption enabled state. + * @return the user's preferred captioning enabled state */ - public static final boolean isEnabled(ContentResolver cr) { - return Secure.getInt(cr, Secure.ACCESSIBILITY_CAPTIONING_ENABLED, DEFAULT_ENABLED) == 1; + public final boolean isEnabled() { + return Secure.getInt( + mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_ENABLED, DEFAULT_ENABLED) == 1; } /** - * @param cr Resolver to access the database with. - * @return The raw locale string for the user's preferred caption language. + * @return the raw locale string for the user's preferred captioning + * language * @hide */ - public static final String getRawLocale(ContentResolver cr) { - return Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_LOCALE); + public final String getRawLocale() { + return Secure.getString(mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_LOCALE); } /** - * @param cr Resolver to access the database with. - * @return The locale for the user's preferred caption language, or null if - * not specified. + * @return the locale for the user's preferred captioning language, or null + * if not specified */ - public static final Locale getLocale(ContentResolver cr) { - final String rawLocale = getRawLocale(cr); + public final Locale getLocale() { + final String rawLocale = getRawLocale(); if (!TextUtils.isEmpty(rawLocale)) { final String[] splitLocale = rawLocale.split("_"); switch (splitLocale.length) { @@ -85,14 +104,151 @@ public class CaptioningManager { } /** - * @param cr Resolver to access the database with. - * @return The user's preferred font size for video captions, or 0 if not - * specified. + * @return the user's preferred font scaling factor for video captions, or 1 if not + * specified */ - public static final float getFontSize(ContentResolver cr) { - return Secure.getFloat(cr, Secure.ACCESSIBILITY_CAPTIONING_FONT_SIZE, DEFAULT_FONT_SIZE); + public final float getFontScale() { + return Secure.getFloat( + mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, DEFAULT_FONT_SCALE); + } + + /** + * @return the raw preset number, or the first preset if not specified + * @hide + */ + public int getRawUserStyle() { + return Secure.getInt( + mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_PRESET, DEFAULT_PRESET); + } + + /** + * @return the user's preferred visual properties for captions as a + * {@link CaptionStyle}, or the default style if not specified + */ + public CaptionStyle getUserStyle() { + final int preset = getRawUserStyle(); + if (preset == CaptionStyle.PRESET_CUSTOM) { + return CaptionStyle.getCustomStyle(mContentResolver); + } + + return CaptionStyle.PRESETS[preset]; + } + + /** + * Adds a listener for changes in the user's preferred captioning enabled + * state and visual properties. + * + * @param listener the listener to add + */ + public void addCaptioningStateChangeListener(CaptioningChangeListener listener) { + synchronized (mListeners) { + if (mListeners.isEmpty()) { + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE); + registerObserver(Secure.ACCESSIBILITY_CAPTIONING_LOCALE); + } + + mListeners.add(listener); + } + } + + private void registerObserver(String key) { + mContentResolver.registerContentObserver(Secure.getUriFor(key), false, mContentObserver); + } + + /** + * Removes a listener previously added using + * {@link #addCaptioningStateChangeListener}. + * + * @param listener the listener to remove + */ + public void removeCaptioningStateChangeListener(CaptioningChangeListener listener) { + synchronized (mListeners) { + mListeners.remove(listener); + + if (mListeners.isEmpty()) { + mContentResolver.unregisterContentObserver(mContentObserver); + } + } + } + + private void notifyEnabledChanged() { + final boolean enabled = isEnabled(); + synchronized (mListeners) { + for (CaptioningChangeListener listener : mListeners) { + listener.onEnabledChanged(enabled); + } + } + } + + private void notifyUserStyleChanged() { + final CaptionStyle userStyle = getUserStyle(); + synchronized (mListeners) { + for (CaptioningChangeListener listener : mListeners) { + listener.onUserStyleChanged(userStyle); + } + } } + private void notifyLocaleChanged() { + final Locale locale = getLocale(); + synchronized (mListeners) { + for (CaptioningChangeListener listener : mListeners) { + listener.onLocaleChanged(locale); + } + } + } + + private void notifyFontScaleChanged() { + final float fontScale = getFontScale(); + synchronized (mListeners) { + for (CaptioningChangeListener listener : mListeners) { + listener.onFontScaleChanged(fontScale); + } + } + } + + private final ContentObserver mContentObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange, Uri uri) { + final String uriPath = uri.getPath(); + final String name = uriPath.substring(uriPath.lastIndexOf('/') + 1); + if (Secure.ACCESSIBILITY_CAPTIONING_ENABLED.equals(name)) { + notifyEnabledChanged(); + } else if (Secure.ACCESSIBILITY_CAPTIONING_LOCALE.equals(name)) { + notifyLocaleChanged(); + } else if (Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE.equals(name)) { + notifyFontScaleChanged(); + } else { + // We only need a single callback when multiple style properties + // change in rapid succession. + mHandler.removeCallbacks(mStyleChangedRunnable); + mHandler.post(mStyleChangedRunnable); + } + } + }; + + /** + * Runnable posted when user style properties change. This is used to + * prevent unnecessary change notifications when multiple properties change + * in rapid succession. + */ + private final Runnable mStyleChangedRunnable = new Runnable() { + @Override + public void run() { + notifyUserStyleChanged(); + } + }; + + /** + * Specifies visual properties for video captions, including foreground and + * background colors, edge properties, and typeface. + */ public static final class CaptionStyle { private static final CaptionStyle WHITE_ON_BLACK; private static final CaptionStyle BLACK_ON_WHITE; @@ -155,8 +311,8 @@ public class CaptioningManager { } /** - * @return The preferred {@link Typeface} for video captions, or null if - * not specified. + * @return the preferred {@link Typeface} for video captions, or null if + * not specified */ public Typeface getTypeface() { if (mParsedTypeface == null && !TextUtils.isEmpty(mRawTypeface)) { @@ -168,41 +324,20 @@ public class CaptioningManager { /** * @hide */ - public static int getRawPreset(ContentResolver cr) { - return Secure.getInt(cr, Secure.ACCESSIBILITY_CAPTIONING_PRESET, DEFAULT_PRESET); - } - - /** - * @param cr Resolver to access the database with. - * @return The user's preferred caption style. - */ - public static CaptionStyle defaultUserStyle(ContentResolver cr) { - final int preset = getRawPreset(cr); - if (preset == PRESET_CUSTOM) { - return getCustomStyle(cr); - } - - return PRESETS[preset]; - } - - /** - * @hide - */ public static CaptionStyle getCustomStyle(ContentResolver cr) { + final CaptionStyle defStyle = CaptionStyle.DEFAULT_CUSTOM; final int foregroundColor = Secure.getInt( - cr, Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, - DEFAULT_CUSTOM.foregroundColor); - final int backgroundColor = Secure.getInt(cr, - Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, - DEFAULT_CUSTOM.backgroundColor); + 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, DEFAULT_CUSTOM.edgeType); + cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, defStyle.edgeType); final int edgeColor = Secure.getInt( - cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, DEFAULT_CUSTOM.edgeColor); + cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, defStyle.edgeColor); String rawTypeface = Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE); if (rawTypeface == null) { - rawTypeface = DEFAULT_CUSTOM.mRawTypeface; + rawTypeface = defStyle.mRawTypeface; } return new CaptionStyle( @@ -226,4 +361,45 @@ public class CaptioningManager { DEFAULT_CUSTOM = WHITE_ON_BLACK; } } + + /** + * Listener for changes in captioning properties, including enabled state + * and user style preferences. + */ + public 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(CaptionStyle userStyle) { + } + + /** + * Called when the captioning locale changes. + * + * @param locale the preferred captioning locale + * @see CaptioningManager#getLocale() + */ + public void onLocaleChanged(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) { + } + } } |