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
19e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viveretteimport android.annotation.NonNull;
20e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viveretteimport android.annotation.Nullable;
21d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService;
2243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.content.ContentResolver;
2369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.content.Context;
2469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.database.ContentObserver;
2543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.graphics.Color;
2643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.graphics.Typeface;
2769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.net.Uri;
2869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport android.os.Handler;
2943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.provider.Settings.Secure;
3043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport android.text.TextUtils;
3143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
3269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viveretteimport java.util.ArrayList;
3343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viveretteimport java.util.Locale;
3443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
3543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette/**
3669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette * Contains methods for accessing and monitoring preferred video captioning state and visual
3743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette * properties.
3843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette */
39d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.CAPTIONING_SERVICE)
4043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverettepublic class CaptioningManager {
4169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /** Default captioning enabled value. */
4269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private static final int DEFAULT_ENABLED = 0;
4343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
4469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /** Default style preset as an index into {@link CaptionStyle#PRESETS}. */
4543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    private static final int DEFAULT_PRESET = 0;
4669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
4769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /** Default scaling value for caption fonts. */
4869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private static final float DEFAULT_FONT_SCALE = 1;
4969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
50727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette    private final ArrayList<CaptioningChangeListener> mListeners = new ArrayList<>();
5169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final ContentResolver mContentResolver;
52727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette    private final ContentObserver mContentObserver;
5369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
5469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
5569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Creates a new captioning manager for the specified context.
5669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *
5769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @hide
5869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
5969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public CaptioningManager(Context context) {
6069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        mContentResolver = context.getContentResolver();
61727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette
62727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette        final Handler handler = new Handler(context.getMainLooper());
63727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette        mContentObserver = new MyContentObserver(handler);
6469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
6543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
6643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
6769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the user's preferred captioning enabled state
6843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
6969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public final boolean isEnabled() {
7069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return Secure.getInt(
7169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_ENABLED, DEFAULT_ENABLED) == 1;
7243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
7343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
7443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
7569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the raw locale string for the user's preferred captioning
7669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *         language
7743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     * @hide
7843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
79e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette    @Nullable
8069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public final String getRawLocale() {
8169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return Secure.getString(mContentResolver, Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
8243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
8343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
8443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    /**
8569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @return the locale for the user's preferred captioning language, or null
8669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *         if not specified
8743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette     */
88e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette    @Nullable
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     */
128e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette    @NonNull
12969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    public CaptionStyle getUserStyle() {
13069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final int preset = getRawUserStyle();
13169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        if (preset == CaptionStyle.PRESET_CUSTOM) {
13269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            return CaptionStyle.getCustomStyle(mContentResolver);
13369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
13469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
13569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        return CaptionStyle.PRESETS[preset];
13669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
13769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
13869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
13969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Adds a listener for changes in the user's preferred captioning enabled
14069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * state and visual properties.
14169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *
14269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @param listener the listener to add
14369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
144e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette    public void addCaptioningChangeListener(@NonNull CaptioningChangeListener listener) {
14569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
14669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            if (mListeners.isEmpty()) {
14769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
14869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR);
14969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR);
150e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR);
15169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE);
15269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR);
15369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
15469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE);
15569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_LOCALE);
156e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                registerObserver(Secure.ACCESSIBILITY_CAPTIONING_PRESET);
15769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
15869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
15969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            mListeners.add(listener);
16069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
16169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
16269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
16369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void registerObserver(String key) {
16469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        mContentResolver.registerContentObserver(Secure.getUriFor(key), false, mContentObserver);
16569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
16669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
16769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
16869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Removes a listener previously added using
169d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette     * {@link #addCaptioningChangeListener}.
17069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     *
17169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * @param listener the listener to remove
17269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
173e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette    public void removeCaptioningChangeListener(@NonNull CaptioningChangeListener listener) {
17469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
17569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            mListeners.remove(listener);
17669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
17769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            if (mListeners.isEmpty()) {
17869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mContentResolver.unregisterContentObserver(mContentObserver);
17969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
18069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
18169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
18269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
18369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyEnabledChanged() {
18469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final boolean enabled = isEnabled();
18569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
18669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
18769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onEnabledChanged(enabled);
18869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
18969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
19069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
19169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
19269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyUserStyleChanged() {
19369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final CaptionStyle userStyle = getUserStyle();
19469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
19569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
19669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onUserStyleChanged(userStyle);
19769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
19869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
19943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
20043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
20169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyLocaleChanged() {
20269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final Locale locale = getLocale();
20369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
20469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
20569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onLocaleChanged(locale);
20669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
20769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
20869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
20969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
21069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private void notifyFontScaleChanged() {
21169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        final float fontScale = getFontScale();
21269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        synchronized (mListeners) {
21369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            for (CaptioningChangeListener listener : mListeners) {
21469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                listener.onFontScaleChanged(fontScale);
21569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
21669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
21769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
21869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
219727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette    private class MyContentObserver extends ContentObserver {
220727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette        private final Handler mHandler;
221727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette
222727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette        public MyContentObserver(Handler handler) {
223727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette            super(handler);
224727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette
225727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette            mHandler = handler;
226727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette        }
227727dcc7e6b43902edaab88e7adfb1a8b88fd482bAlan Viverette
22869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        @Override
22969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void onChange(boolean selfChange, Uri uri) {
23069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final String uriPath = uri.getPath();
23169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final String name = uriPath.substring(uriPath.lastIndexOf('/') + 1);
23269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            if (Secure.ACCESSIBILITY_CAPTIONING_ENABLED.equals(name)) {
23369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                notifyEnabledChanged();
23469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            } else if (Secure.ACCESSIBILITY_CAPTIONING_LOCALE.equals(name)) {
23569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                notifyLocaleChanged();
23669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            } else if (Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE.equals(name)) {
23769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                notifyFontScaleChanged();
23869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            } else {
23969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                // We only need a single callback when multiple style properties
24069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                // change in rapid succession.
24169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mHandler.removeCallbacks(mStyleChangedRunnable);
24269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                mHandler.post(mStyleChangedRunnable);
24369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            }
24469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
24569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    };
24669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
24769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
24869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Runnable posted when user style properties change. This is used to
24969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * prevent unnecessary change notifications when multiple properties change
25069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * in rapid succession.
25169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
25269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    private final Runnable mStyleChangedRunnable = new Runnable() {
25369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        @Override
25469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        public void run() {
25569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            notifyUserStyleChanged();
25669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        }
25769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    };
25869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
25969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
26069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Specifies visual properties for video captions, including foreground and
26169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * background colors, edge properties, and typeface.
26269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
26343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    public static final class CaptionStyle {
2647e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette        /**
2657e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * Packed value for a color of 'none' and a cached opacity of 100%.
2667e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         *
2677e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * @hide
2687e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         */
269ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette        private static final int COLOR_NONE_OPAQUE = 0x000000FF;
270ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette
2717e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette        /**
2727e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * Packed value for a color of 'default' and opacity of 100%.
2737e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         *
2747e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * @hide
2757e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         */
2767e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette        public static final int COLOR_UNSPECIFIED = 0x00FFFFFF;
277e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
27843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle WHITE_ON_BLACK;
27943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle BLACK_ON_WHITE;
28043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle YELLOW_ON_BLACK;
28143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle YELLOW_ON_BLUE;
28243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private static final CaptionStyle DEFAULT_CUSTOM;
283e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        private static final CaptionStyle UNSPECIFIED;
284e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
285e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /** The default caption style used to fill in unspecified values. @hide */
286e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public static final CaptionStyle DEFAULT;
28743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
28843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** @hide */
28943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final CaptionStyle[] PRESETS;
29043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
29143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** @hide */
29243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int PRESET_CUSTOM = -1;
29343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
294e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /** Unspecified edge type value. */
295e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public static final int EDGE_TYPE_UNSPECIFIED = -1;
296e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
29743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** Edge type value specifying no character edges. */
29843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int EDGE_TYPE_NONE = 0;
29943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
30043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** Edge type value specifying uniformly outlined character edges. */
30143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int EDGE_TYPE_OUTLINE = 1;
30243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
30343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** Edge type value specifying drop-shadowed character edges. */
30443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static final int EDGE_TYPE_DROP_SHADOW = 2;
30543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
306ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette        /** Edge type value specifying raised bevel character edges. */
307ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette        public static final int EDGE_TYPE_RAISED = 3;
308ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette
309ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette        /** Edge type value specifying depressed bevel character edges. */
310ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette        public static final int EDGE_TYPE_DEPRESSED = 4;
311ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette
31243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** The preferred foreground color for video captions. */
31343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int foregroundColor;
31443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
31543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /** The preferred background color for video captions. */
31643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int backgroundColor;
31743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
31843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
31943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * The preferred edge type for video captions, one of:
32043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <ul>
321e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * <li>{@link #EDGE_TYPE_UNSPECIFIED}
32243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <li>{@link #EDGE_TYPE_NONE}
32343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <li>{@link #EDGE_TYPE_OUTLINE}
32443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * <li>{@link #EDGE_TYPE_DROP_SHADOW}
325ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette         * <li>{@link #EDGE_TYPE_RAISED}
326ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette         * <li>{@link #EDGE_TYPE_DEPRESSED}
32743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * </ul>
32843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
32943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int edgeType;
33043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
33143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
33243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * The preferred edge color for video captions, if using an edge type
33343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * other than {@link #EDGE_TYPE_NONE}.
33443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
33543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final int edgeColor;
33643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
33755d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette        /** The preferred window color for video captions. */
33855d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette        public final int windowColor;
33955d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette
34043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
34143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * @hide
34243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
34343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public final String mRawTypeface;
34443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
345f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette        private final boolean mHasForegroundColor;
346f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette        private final boolean mHasBackgroundColor;
347f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette        private final boolean mHasEdgeType;
348f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette        private final boolean mHasEdgeColor;
349f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette        private final boolean mHasWindowColor;
350f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette
351f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette        /** Lazily-created typeface based on the raw typeface string. */
35243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private Typeface mParsedTypeface;
35343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
35443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        private CaptionStyle(int foregroundColor, int backgroundColor, int edgeType, int edgeColor,
35555d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette                int windowColor, String rawTypeface) {
3567e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            mHasForegroundColor = hasColor(foregroundColor);
3577e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            mHasBackgroundColor = hasColor(backgroundColor);
358f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            mHasEdgeType = edgeType != EDGE_TYPE_UNSPECIFIED;
3597e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            mHasEdgeColor = hasColor(edgeColor);
3607e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            mHasWindowColor = hasColor(windowColor);
361f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette
362f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            // Always use valid colors, even when no override is specified, to
363f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            // ensure backwards compatibility with apps targeting KitKat MR2.
364f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            this.foregroundColor = mHasForegroundColor ? foregroundColor : Color.WHITE;
365f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            this.backgroundColor = mHasBackgroundColor ? backgroundColor : Color.BLACK;
366f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            this.edgeType = mHasEdgeType ? edgeType : EDGE_TYPE_NONE;
367f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            this.edgeColor = mHasEdgeColor ? edgeColor : Color.BLACK;
368f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            this.windowColor = mHasWindowColor ? windowColor : COLOR_NONE_OPAQUE;
36943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
37043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            mRawTypeface = rawTypeface;
37143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
37243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
37343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
3747e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * Returns whether a packed color indicates a non-default value.
3757e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         *
3767e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * @param packedColor the packed color value
3777e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * @return {@code true} if a non-default value is specified
3787e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         * @hide
3797e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette         */
3807e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette        public static boolean hasColor(int packedColor) {
3817e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            // Matches the color packing code from Settings. "Default" packed
3827e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            // colors are indicated by zero alpha and non-zero red/blue. The
3837e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            // cached alpha value used by Settings is stored in green.
3847e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette            return (packedColor >>> 24) != 0 || (packedColor & 0xFFFF00) == 0;
3857e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette        }
3867e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette
3877e4019b7413511bb60e19d6011c80baf00e40b76Alan Viverette        /**
388e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * Applies a caption style, overriding any properties that are specified
389e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * in the overlay caption.
390e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *
391e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @param overlay The style to apply
392e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @return A caption style with the overlay style applied
393e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @hide
394e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         */
395e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        @NonNull
396e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public CaptionStyle applyStyle(@NonNull CaptionStyle overlay) {
397e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            final int newForegroundColor = overlay.hasForegroundColor() ?
398e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    overlay.foregroundColor : foregroundColor;
399e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            final int newBackgroundColor = overlay.hasBackgroundColor() ?
400e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    overlay.backgroundColor : backgroundColor;
401e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            final int newEdgeType = overlay.hasEdgeType() ?
402e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    overlay.edgeType : edgeType;
403e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            final int newEdgeColor = overlay.hasEdgeColor() ?
404e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    overlay.edgeColor : edgeColor;
405e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            final int newWindowColor = overlay.hasWindowColor() ?
406e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    overlay.windowColor : windowColor;
407e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            final String newRawTypeface = overlay.mRawTypeface != null ?
408e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    overlay.mRawTypeface : mRawTypeface;
409e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            return new CaptionStyle(newForegroundColor, newBackgroundColor, newEdgeType,
410e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    newEdgeColor, newWindowColor, newRawTypeface);
411e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        }
412e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
413e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /**
414e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @return {@code true} if the user has specified a background color
415e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         that should override the application default, {@code false}
416e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         otherwise
417e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         */
418e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public boolean hasBackgroundColor() {
419f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            return mHasBackgroundColor;
420e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        }
421e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
422e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /**
423e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @return {@code true} if the user has specified a foreground color
424e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         that should override the application default, {@code false}
425e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         otherwise
426e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         */
427e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public boolean hasForegroundColor() {
428f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            return mHasForegroundColor;
429e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        }
430e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
431e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /**
432e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @return {@code true} if the user has specified an edge type that
433e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         should override the application default, {@code false}
434e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         otherwise
435e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         */
436e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public boolean hasEdgeType() {
437f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            return mHasEdgeType;
438e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        }
439e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
440e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /**
441e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @return {@code true} if the user has specified an edge color that
442e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         should override the application default, {@code false}
443e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         otherwise
444e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         */
445e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public boolean hasEdgeColor() {
446f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            return mHasEdgeColor;
447e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        }
448e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
449e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /**
450e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @return {@code true} if the user has specified a window color that
451e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         should override the application default, {@code false}
452e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         *         otherwise
453e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         */
454e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public boolean hasWindowColor() {
455f1820064d9cfcf43e4cfd16872acca3bf5a7d94bAlan Viverette            return mHasWindowColor;
456e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        }
457e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette
458e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        /**
45969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @return the preferred {@link Typeface} for video captions, or null if
46069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *         not specified
46143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
462e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        @Nullable
46343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public Typeface getTypeface() {
46443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            if (mParsedTypeface == null && !TextUtils.isEmpty(mRawTypeface)) {
46543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette                mParsedTypeface = Typeface.create(mRawTypeface, Typeface.NORMAL);
46643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            }
46743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            return mParsedTypeface;
46843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
46943a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
47043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        /**
47143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         * @hide
47243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette         */
473e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        @NonNull
47443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        public static CaptionStyle getCustomStyle(ContentResolver cr) {
47569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final CaptionStyle defStyle = CaptionStyle.DEFAULT_CUSTOM;
47643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final int foregroundColor = Secure.getInt(
47769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR, defStyle.foregroundColor);
47869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette            final int backgroundColor = Secure.getInt(
47969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR, defStyle.backgroundColor);
48043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final int edgeType = Secure.getInt(
48169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE, defStyle.edgeType);
48243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            final int edgeColor = Secure.getInt(
48369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR, defStyle.edgeColor);
48455d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette            final int windowColor = Secure.getInt(
48555d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette                    cr, Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR, defStyle.windowColor);
48643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
48743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            String rawTypeface = Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);
48843a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            if (rawTypeface == null) {
48969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette                rawTypeface = defStyle.mRawTypeface;
49043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            }
49143a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
49255d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette            return new CaptionStyle(foregroundColor, backgroundColor, edgeType, edgeColor,
49355d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette                    windowColor, rawTypeface);
49443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
49543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
49643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        static {
49755d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette            WHITE_ON_BLACK = new CaptionStyle(Color.WHITE, Color.BLACK, EDGE_TYPE_NONE,
498ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette                    Color.BLACK, COLOR_NONE_OPAQUE, null);
49955d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette            BLACK_ON_WHITE = new CaptionStyle(Color.BLACK, Color.WHITE, EDGE_TYPE_NONE,
500ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette                    Color.BLACK, COLOR_NONE_OPAQUE, null);
50155d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette            YELLOW_ON_BLACK = new CaptionStyle(Color.YELLOW, Color.BLACK, EDGE_TYPE_NONE,
502ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette                    Color.BLACK, COLOR_NONE_OPAQUE, null);
50355d70620d9fda8afafb2fdec59757a710eec0e89Alan Viverette            YELLOW_ON_BLUE = new CaptionStyle(Color.YELLOW, Color.BLUE, EDGE_TYPE_NONE,
504ce32ea7345f0157a595b1dd4306a9a65f444d7c2Alan Viverette                    Color.BLACK, COLOR_NONE_OPAQUE, null);
505e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            UNSPECIFIED = new CaptionStyle(COLOR_UNSPECIFIED, COLOR_UNSPECIFIED,
506e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    EDGE_TYPE_UNSPECIFIED, COLOR_UNSPECIFIED, COLOR_UNSPECIFIED, null);
50743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
508e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            // The ordering of these cannot change since we store the index
509e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            // directly in preferences.
51043a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            PRESETS = new CaptionStyle[] {
511e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette                    WHITE_ON_BLACK, BLACK_ON_WHITE, YELLOW_ON_BLACK, YELLOW_ON_BLUE, UNSPECIFIED
51243a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            };
51343a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette
51443a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette            DEFAULT_CUSTOM = WHITE_ON_BLACK;
515e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette            DEFAULT = WHITE_ON_BLACK;
51643a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette        }
51743a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette    }
51869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
51969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    /**
52069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * Listener for changes in captioning properties, including enabled state
52169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     * and user style preferences.
52269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette     */
523d43daf361e993457e64eeeddab6d1a0ebc828c99Alan Viverette    public static abstract class CaptioningChangeListener {
52469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
52569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning enabled state changes.
52669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
52769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param enabled the user's new preferred captioning enabled state
52869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
529e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public void onEnabledChanged(boolean enabled) {}
53069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
53169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
53269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning user style changes.
53369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
53469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param userStyle the user's new preferred style
53569ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @see CaptioningManager#getUserStyle()
53669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
537e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public void onUserStyleChanged(@NonNull CaptionStyle userStyle) {}
53869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
53969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
54069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning locale changes.
54169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
542e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette         * @param locale the preferred captioning locale, or {@code null} if not specified
54369ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @see CaptioningManager#getLocale()
54469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
545e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public void onLocaleChanged(@Nullable Locale locale) {}
54669ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette
54769ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette        /**
54869ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * Called when the captioning font scaling factor changes.
54969ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         *
55069ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @param fontScale the preferred font scaling factor
55169ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         * @see CaptioningManager#getFontScale()
55269ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette         */
553e88aee8ad85b01229b12dbc0c3cc2f0b8b490192Alan Viverette        public void onFontScaleChanged(float fontScale) {}
55469ce69b0e1500bcf0bfa87eaf0b89ae47f552f5cAlan Viverette    }
55543a1e3d319d77c251445339bcc8f82c82b097feeAlan Viverette}
556