143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette/*
243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * Copyright (C) 2013 The Android Open Source Project
343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette *
443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * Licensed under the Apache License, Version 2.0 (the "License");
543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * you may not use this file except in compliance with the License.
643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * You may obtain a copy of the License at
743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette *
843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette *      http://www.apache.org/licenses/LICENSE-2.0
943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette *
1043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * Unless required by applicable law or agreed to in writing, software
1143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * distributed under the License is distributed on an "AS IS" BASIS,
1243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * See the License for the specific language governing permissions and
1443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * limitations under the License.
1543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette */
1643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
1743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverettepackage android.view.accessibility;
1843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
1943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.content.ContentResolver;
2069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.content.Context;
2169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.database.ContentObserver;
2243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.graphics.Color;
2343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.graphics.Typeface;
2469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.net.Uri;
2569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.os.Handler;
2643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.provider.Settings.Secure;
2743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.text.TextUtils;
2843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
2969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport java.util.ArrayList;
3043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport java.util.Locale;
3143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
3243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette/**
3369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * Contains methods for accessing and monitoring preferred video captioning state and visual
3443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * properties.
3569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * <p>
3669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * To obtain a handle to the captioning manager, do the following:
3769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * <p>
3869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * <code>
3969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * <pre>CaptioningManager captioningManager =
4069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette *        (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);</pre>
4169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * </code>
4243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette */
4343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverettepublic class CaptioningManager {
4469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /** Default captioning enabled value. */
4569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private static final int DEFAULT_ENABLED = 0;
4643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
4769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /** Default style preset as an index into {@link CaptionStyle#PRESETS}. */
4843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    private static final int DEFAULT_PRESET = 0;
4969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
5069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /** Default scaling value for caption fonts. */
5169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private static final float DEFAULT_FONT_SCALE = 1;
5269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
5369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final ArrayList<CaptioningChangeListener>
5469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            mListeners = new ArrayList<CaptioningChangeListener>();
5569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final Handler mHandler = new Handler();
5669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
5769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final ContentResolver mContentResolver;
5869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
5969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
6069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Creates a new captioning manager for the specified context.
6169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *
6269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @hide
6369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
6469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public CaptioningManager(Context context) {
6569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        mContentResolver = context.getContentResolver();
6669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
6743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
6843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
6969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the user's preferred captioning enabled state
7043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
7169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public final boolean isEnabled() {
7269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return Secure.getInt(
7369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_ENABLED, DEFAULT_ENABLED) == 1;
7443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
7543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
7643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
7769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the raw locale string for the user's preferred captioning
7869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *         language
7943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     * @hide
8043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
8169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public final String getRawLocale() {
8269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return Secure.getString(mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
8343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
8443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
8543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
8669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the locale for the user's preferred captioning language, or null
8769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *         if not specified
8843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
8969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public final Locale getLocale() {
9069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final String rawLocale = getRawLocale();
9143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        if (!TextUtils.isEmpty(rawLocale)) {
9243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final String[] splitLocale = rawLocale.split("_");
9343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            switch (splitLocale.length) {
9443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                case 3:
9543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    return new Locale(splitLocale[0], splitLocale[1], splitLocale[2]);
9643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                case 2:
9743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    return new Locale(splitLocale[0], splitLocale[1]);
9843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                case 1:
9943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    return new Locale(splitLocale[0]);
10043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            }
10143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
10243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
10343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        return null;
10443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
10543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
10643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
10769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the user's preferred font scaling factor for video captions, or 1 if not
10869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *         specified
10943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
11069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public final float getFontScale() {
11169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return Secure.getFloat(
11269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, DEFAULT_FONT_SCALE);
11369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
11469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
11569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
11669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the raw preset number, or the first preset if not specified
11769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @hide
11869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
11969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public int getRawUserStyle() {
12069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return Secure.getInt(
12169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_PRESET, DEFAULT_PRESET);
12269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
12369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
12469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
12569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the user's preferred visual properties for captions as a
12669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *         {@link CaptionStyle}, or the default style if not specified
12769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
12869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public CaptionStyle getUserStyle() {
12969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final int preset = getRawUserStyle();
13069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        if (preset == CaptionStyle.PRESET_CUSTOM) {
13169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            return CaptionStyle.getCustomStyle(mContentResolver);
13269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
13369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
13469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return CaptionStyle.PRESETS[preset];
13569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
13669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
13769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
13869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Adds a listener for changes in the user's preferred captioning enabled
13969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * state and visual properties.
14069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *
14169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @param listener the listener to add
14269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
143d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette    public void addCaptioningChangeListener(CaptioningChangeListener listener) {
14469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
14569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            if (mListeners.isEmpty()) {
14669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
14769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR);
14869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR);
14969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE);
15069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR);
15169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
15269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE);
15369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
15469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
15569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
15669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            mListeners.add(listener);
15769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
15869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
15969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
16069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void registerObserver(String key) {
16169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        mContentResolver.registerContentObserver(Secure.getUriFor(key), false, mContentObserver);
16269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
16369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
16469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
16569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Removes a listener previously added using
166d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette     * {@link #addCaptioningChangeListener}.
16769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *
16869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @param listener the listener to remove
16969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
170d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette    public void removeCaptioningChangeListener(CaptioningChangeListener listener) {
17169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
17269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            mListeners.remove(listener);
17369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
17469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            if (mListeners.isEmpty()) {
17569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mContentResolver.unregisterContentObserver(mContentObserver);
17669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
17769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
17869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
17969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
18069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyEnabledChanged() {
18169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final boolean enabled = isEnabled();
18269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
18369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
18469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onEnabledChanged(enabled);
18569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
18669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
18769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
18869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
18969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyUserStyleChanged() {
19069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final CaptionStyle userStyle = getUserStyle();
19169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
19269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
19369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onUserStyleChanged(userStyle);
19469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
19569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
19643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
19743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
19869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyLocaleChanged() {
19969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final Locale locale = getLocale();
20069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
20169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
20269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onLocaleChanged(locale);
20369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
20469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
20569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
20669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
20769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyFontScaleChanged() {
20869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final float fontScale = getFontScale();
20969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
21069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
21169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onFontScaleChanged(fontScale);
21269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
21369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
21469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
21569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
21669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
21769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        @Override
21869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void onChange(boolean selfChange, Uri uri) {
21969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final String uriPath = uri.getPath();
22069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final String name = uriPath.substring(uriPath.lastIndexOf('/') + 1);
22169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            if (Secure.ACCESSIBILITY_CAPTIONING_ENABLED.equals(name)) {
22269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                notifyEnabledChanged();
22369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            } else if (Secure.ACCESSIBILITY_CAPTIONING_LOCALE.equals(name)) {
22469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                notifyLocaleChanged();
22569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            } else if (Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE.equals(name)) {
22669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                notifyFontScaleChanged();
22769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            } else {
22869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                // We only need a single callback when multiple style properties
22969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                // change in rapid succession.
23069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mHandler.removeCallbacks(mStyleChangedRunnable);
23169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mHandler.post(mStyleChangedRunnable);
23269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
23369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
23469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    };
23569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
23669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
23769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Runnable posted when user style properties change. This is used to
23869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * prevent unnecessary change notifications when multiple properties change
23969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * in rapid succession.
24069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
24169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final Runnable mStyleChangedRunnable = new Runnable() {
24269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        @Override
24369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void run() {
24469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            notifyUserStyleChanged();
24569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
24669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    };
24769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
24869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
24969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Specifies visual properties for video captions, including foreground and
25069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * background colors, edge properties, and typeface.
25169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
25243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    public static final class CaptionStyle {
25343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle WHITE_ON_BLACK;
25443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle BLACK_ON_WHITE;
25543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle YELLOW_ON_BLACK;
25643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle YELLOW_ON_BLUE;
25743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle DEFAULT_CUSTOM;
25843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
25943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** @hide */
26043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final CaptionStyle[] PRESETS;
26143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
26243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** @hide */
26343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int PRESET_CUSTOM = -1;
26443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
26543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** Edge type value specifying no character edges. */
26643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int EDGE_TYPE_NONE = 0;
26743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
26843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** Edge type value specifying uniformly outlined character edges. */
26943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int EDGE_TYPE_OUTLINE = 1;
27043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
27143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** Edge type value specifying drop-shadowed character edges. */
27243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int EDGE_TYPE_DROP_SHADOW = 2;
27343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
27443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** The preferred foreground color for video captions. */
27543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int foregroundColor;
27643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
27743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** The preferred background color for video captions. */
27843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int backgroundColor;
27943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
28043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
28143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * The preferred edge type for video captions, one of:
28243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <ul>
28343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <li>{@link #EDGE_TYPE_NONE}
28443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <li>{@link #EDGE_TYPE_OUTLINE}
28543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <li>{@link #EDGE_TYPE_DROP_SHADOW}
28643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * </ul>
28743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
28843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int edgeType;
28943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
29043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
29143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * The preferred edge color for video captions, if using an edge type
29243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * other than {@link #EDGE_TYPE_NONE}.
29343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
29443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int edgeColor;
29543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
29643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
29743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * @hide
29843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
29943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final String mRawTypeface;
30043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
30143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private Typeface mParsedTypeface;
30243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
30343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private CaptionStyle(int foregroundColor, int backgroundColor, int edgeType, int edgeColor,
30443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                String rawTypeface) {
30543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            this.foregroundColor = foregroundColor;
30643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            this.backgroundColor = backgroundColor;
30743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            this.edgeType = edgeType;
30843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            this.edgeColor = edgeColor;
30943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
31043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            mRawTypeface = rawTypeface;
31143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
31243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
31343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
31469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @return the preferred {@link Typeface} for video captions, or null if
31569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *         not specified
31643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
31743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public Typeface getTypeface() {
31843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            if (mParsedTypeface == null && !TextUtils.isEmpty(mRawTypeface)) {
31943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                mParsedTypeface = Typeface.create(mRawTypeface, Typeface.NORMAL);
32043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            }
32143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            return mParsedTypeface;
32243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
32343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
32443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
32543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * @hide
32643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
32743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static CaptionStyle getCustomStyle(ContentResolver cr) {
32869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final CaptionStyle defStyle = CaptionStyle.DEFAULT_CUSTOM;
32943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final int foregroundColor = Secure.getInt(
33069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, defStyle.foregroundColor);
33169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final int backgroundColor = Secure.getInt(
33269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, defStyle.backgroundColor);
33343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final int edgeType = Secure.getInt(
33469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, defStyle.edgeType);
33543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final int edgeColor = Secure.getInt(
33669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, defStyle.edgeColor);
33743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
33843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            String rawTypeface = Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
33943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            if (rawTypeface == null) {
34069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                rawTypeface = defStyle.mRawTypeface;
34143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            }
34243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
34343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            return new CaptionStyle(
34443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    foregroundColor, backgroundColor, edgeType, edgeColor, rawTypeface);
34543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
34643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
34743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        static {
34843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            WHITE_ON_BLACK = new CaptionStyle(
34943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    Color.WHITE, Color.BLACK, EDGE_TYPE_NONE, Color.BLACK, null);
35043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            BLACK_ON_WHITE = new CaptionStyle(
35143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    Color.BLACK, Color.WHITE, EDGE_TYPE_NONE, Color.BLACK, null);
35243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            YELLOW_ON_BLACK = new CaptionStyle(
35343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    Color.YELLOW, Color.BLACK, EDGE_TYPE_NONE, Color.BLACK, null);
35443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            YELLOW_ON_BLUE = new CaptionStyle(
35543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    Color.YELLOW, Color.BLUE, EDGE_TYPE_NONE, Color.BLACK, null);
35643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
35743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            PRESETS = new CaptionStyle[] {
35843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                    WHITE_ON_BLACK, BLACK_ON_WHITE, YELLOW_ON_BLACK, YELLOW_ON_BLUE
35943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            };
36043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
36143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            DEFAULT_CUSTOM = WHITE_ON_BLACK;
36243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
36343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
36469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
36569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
36669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Listener for changes in captioning properties, including enabled state
36769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * and user style preferences.
36869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
369d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette    public static abstract class CaptioningChangeListener {
37069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
37169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning enabled state changes.
37269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
37369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param enabled the user's new preferred captioning enabled state
37469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
37569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void onEnabledChanged(boolean enabled) {
37669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
37769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
37869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
37969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning user style changes.
38069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
38169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param userStyle the user's new preferred style
38269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @see CaptioningManager#getUserStyle()
38369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
38469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void onUserStyleChanged(CaptionStyle userStyle) {
38569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
38669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
38769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
38869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning locale changes.
38969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
39069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param locale the preferred captioning locale
39169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @see CaptioningManager#getLocale()
39269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
39369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void onLocaleChanged(Locale locale) {
39469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
39569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
39669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
39769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning font scaling factor changes.
39869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
39969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param fontScale the preferred font scaling factor
40069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @see CaptioningManager#getFontScale()
40169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
40269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void onFontScaleChanged(float fontScale) {
40369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
40469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
40543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette}
406