1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.tv.settings.system;
18
19import com.android.tv.settings.dialog.old.Action;
20import com.android.tv.settings.dialog.old.ActionFragment;
21import com.android.tv.settings.dialog.old.ActionAdapter;
22
23import com.android.tv.settings.BaseSettingsActivity;
24import com.android.tv.settings.ActionBehavior;
25import com.android.tv.settings.ActionKey;
26import com.android.tv.settings.R;
27import com.android.tv.settings.util.SettingsHelper;
28
29import android.view.accessibility.CaptioningManager;
30
31import android.provider.Settings;
32
33import android.os.Bundle;
34import android.content.ContentResolver;
35import android.content.Context;
36import android.content.res.Resources;
37import android.content.res.TypedArray;
38import android.text.TextUtils;
39import android.util.Log;
40
41import java.util.ArrayList;
42import java.util.Arrays;
43import java.util.Locale;
44import java.text.Collator;
45
46public class CaptionSetupActivity extends BaseSettingsActivity implements ActionAdapter.Listener,
47                                  ActionAdapter.OnFocusListener {
48
49    private static final String TAG = "CaptionSetupActivity";
50    private static final boolean DEBUG = false;
51
52    private Resources mResources;
53    private SettingsHelper mHelper;
54    private boolean mDisplayEnabled;
55    private String mNone;
56
57    private String mLanguage;
58    private String mLanguageName;
59    private String[] mLanguageLocales;
60    private String[] mLanguageNames;
61
62    private String mTextSize;
63    private String mTextSizeName;
64    private String[] mTextSizes;
65    private String[] mTextSizeNames;
66
67    private String mStyle;
68    private String mStyleName;
69    private String[] mStyles;
70    private String[] mStyleNames;
71
72    private String mFontFamily;
73    private String mFontFamilyName;
74    private String[] mFontFamilies;
75    private String[] mFontFamilyNames;
76
77    private int[] mColorResIds;
78    private int[] mColorRGBs;
79    private String[] mColorNames;
80
81    private int mTextColor;
82    private String mTextColorName;
83
84    private String mEdgeType;
85    private String mEdgeTypeName;
86    private String[] mEdgeTypes;
87    private String[] mEdgeTypeNames;
88
89    private int mEdgeColor;
90    private String mEdgeColorName;
91
92    private int mBackgroundColor;
93    private String mBackgroundColorName;
94
95    private String mBackgroundOpacity;
96    private String mBackgroundOpacityName;
97    private String[] mOpacities;
98    private String[] mOpacityNames;
99
100    private String mTextOpacity;
101    private String mTextOpacityName;
102
103    private boolean mWindowEnabled;
104    private int mWindowColor;
105    private String mWindowColorName;
106
107    private String mWindowOpacity;
108    private String mWindowOpacityName;
109
110    private CaptioningManager mCaptioningManager;
111
112    @Override
113    protected void onCreate(Bundle savedInstanceState) {
114        mResources = getResources();
115        mHelper = new SettingsHelper(this);
116        mActions = new ArrayList<Action>();
117        mCaptioningManager = (CaptioningManager) getSystemService(Context.CAPTIONING_SERVICE);
118
119        mStyles = getIntArrayAsStringArray(R.array.captioning_preset_selector_values);
120
121        mStyleNames = mResources.getStringArray(R.array.captioning_preset_selector_titles);
122
123        mTextSizes = mResources.getStringArray(R.array.captioning_font_size_selector_values);
124        mTextSizeNames = mResources.getStringArray(R.array.captioning_font_size_selector_titles);
125
126        getLanguages();
127
128        mFontFamilies = mResources.getStringArray(R.array.captioning_typeface_selector_values);
129        mFontFamilyNames = mResources.getStringArray(R.array.captioning_typeface_selector_titles);
130
131        getColorSelection();
132
133        mEdgeTypes = getIntArrayAsStringArray (R.array.captioning_edge_type_selector_values);
134        mEdgeTypeNames = mResources.getStringArray(R.array.captioning_edge_type_selector_titles);
135
136        mOpacities = getIntArrayAsStringArray(R.array.captioning_opacity_selector_values);
137        mOpacityNames = mResources.getStringArray(R.array.captioning_opacity_selector_titles);
138
139        mNone = mResources.getString(R.string.accessibility_none);
140
141        getCaptionSettings ();
142
143        super.onCreate(savedInstanceState);
144
145        mContentFragment = CaptionPreviewFragment.newInstance();
146        setContentFragment (mContentFragment);
147    }
148
149    private String[] getIntArrayAsStringArray(int resourceId) {
150        int[] a = mResources.getIntArray(resourceId);
151        String[] s = new String[a.length];
152        for (int i = 0; i < a.length; ++i)
153            s[i] = String.valueOf(a[i]);
154        return s;
155    }
156
157    private void getColorSelection() {
158        // Load the resource ids of the selectable colors.
159        TypedArray ar =
160            getApplicationContext().getResources().obtainTypedArray
161                (R.array.captioning_color_selector_ids);
162        int len = ar.length();
163        mColorResIds = new int [len];
164        for (int i = 0; i < len; ++i)
165            mColorResIds [i] = ar.getResourceId(i, 0);
166        ar.recycle();
167        // Load the RGB values of the colors.
168        mColorRGBs = new int[len];
169        for (int i = 0; i < len; ++i)
170            mColorRGBs[i] = mResources.getColor(mColorResIds[i]) & 0xffffff;
171        // Initialize the color names that will be displayed to the user.
172        String[] colorNames = mResources.getStringArray(R.array.captioning_color_selector_titles);
173        mColorNames = new String[len];
174        for (int i = 0; i < colorNames.length; ++i) {
175            mColorNames[i] = colorNames[i];
176        }
177        for (int i = colorNames.length; i < len; ++i) {
178            mColorNames[i] = String.format("#%06X", mColorRGBs[i]);
179        }
180    }
181
182    private String getColorName(int color) {
183        for (int x = 0; x < mColorRGBs.length; ++x)
184            if (mColorRGBs[x] == color)
185                return mColorNames[x];
186        return "";
187    }
188
189    private void getCaptionSettings() {
190
191        mDisplayEnabled = mCaptioningManager.isEnabled();
192
193        mLanguage = mCaptioningManager.getRawLocale();
194        if (mLanguage != null)
195            mLanguageName = getLanguageName(mLanguage);
196
197        mTextSize = getClosestValue(mCaptioningManager.getFontScale(), mTextSizes);
198        mTextSizeName = getTextSizeName(mTextSize);
199
200        int style = mCaptioningManager.getRawUserStyle();
201        mStyle = String.valueOf (style);
202        mStyleName = getStyleName(mStyle);
203
204        if (style == CaptioningManager.CaptionStyle.PRESET_CUSTOM) {
205            getCustomCaptionStyle();
206        }
207    }
208
209    private String getClosestValue(float value, String[] values) {
210        int ndx = -1;
211        float delta = 0;
212        for (int i = 0; i < values.length; ++i) {
213            float d = Math.abs(value - Float.parseFloat(values [i]));
214            if (ndx == -1 || d < delta) {
215                ndx = i;
216                delta = d;
217            }
218        }
219        if (ndx == -1) {
220            return "";
221        } else {
222            return values [ndx];
223        }
224    }
225
226    private void getCustomCaptionStyle() {
227        CaptioningManager.CaptionStyle cs = mCaptioningManager.getUserStyle();
228
229        mFontFamily = cs.mRawTypeface;
230        mFontFamilyName = getFontFamilyName(mFontFamily);
231
232        mTextColor = cs.foregroundColor & 0xffffff;
233        mTextColorName = getColorName(mTextColor);
234
235        mTextOpacity = getClosestValue(cs.foregroundColor | 0xffffff, mOpacities);
236        mTextOpacityName = getOpacityName(mTextOpacity);
237
238        mEdgeType = Integer.toString (cs.edgeType);
239        mEdgeTypeName = getEdgeTypeName(mEdgeType);
240
241        mEdgeColor = cs.edgeColor & 0xffffff;
242        mEdgeColorName = getColorName(mEdgeColor);
243
244        mBackgroundColor = cs.backgroundColor & 0xffffff;
245        mBackgroundColorName = getColorName(mBackgroundColor);
246
247        mBackgroundOpacity = getClosestValue(cs.backgroundColor | 0xffffff, mOpacities);
248        mBackgroundOpacityName = getOpacityName(mBackgroundOpacity);
249
250        mWindowEnabled = cs.hasWindowColor() && (cs.windowColor & 0xff000000) != 0;
251        mWindowColor = cs.windowColor & 0xffffff;
252        if (mWindowEnabled) {
253            mWindowColorName = getColorName(mWindowColor);
254        } else {
255            mWindowColorName = mNone;
256        }
257        mWindowOpacity = getClosestValue(cs.windowColor | 0xffffff, mOpacities);
258        if (mWindowEnabled) {
259            mWindowOpacityName = getOpacityName(mWindowOpacity);
260        } else {
261            mWindowOpacityName = mNone;
262        }
263    }
264
265    private void colorsToActions(int selectedColor) {
266        mActions.clear();
267        for (int i = 0; i < mColorResIds.length; ++i) {
268            mActions.add(
269                new Action.Builder().key(Integer.toString(mColorRGBs[i]))
270                                    .drawableResource(mColorResIds[i])
271                                    .title(mColorNames[i])
272                                    .checked(selectedColor == mColorRGBs[i]).build());
273        }
274    }
275
276    @Override
277    protected void refreshActionList() {
278        if(mContentFragment instanceof CaptionPreviewFragment) {
279            ((CaptionPreviewFragment)mContentFragment).resetLivePreview();
280        }
281        mActions.clear();
282        switch ((ActionType) mState) {
283            case CAPTIONS_OVERVIEW:
284                int statusResource = mDisplayEnabled ?
285                        R.string.captions_display_on : R.string.captions_display_off;
286                mActions.add(ActionType.CAPTIONS_DISPLAY.toAction(
287                             mResources, mResources.getString(statusResource)));
288                mActions.add(ActionType.CAPTIONS_CONFIGURE.toAction(mResources,
289                             mResources.getString(R.string.display_options)));
290                break;
291            case CAPTIONS_DISPLAY:
292                mActions.add(ActionBehavior.ON.toAction(ActionBehavior.getOnKey(
293                             ActionType.CAPTIONS_DISPLAY.name()), mResources, mDisplayEnabled));
294                mActions.add(ActionBehavior.OFF.toAction(ActionBehavior.getOffKey(
295                             ActionType.CAPTIONS_DISPLAY.name()), mResources, ! mDisplayEnabled));
296                break;
297            case CAPTIONS_CONFIGURE:
298                mActions.add(ActionType.CAPTIONS_LANGUAGE.toAction(mResources, mLanguageName));
299                mActions.add(ActionType.CAPTIONS_TEXTSIZE.toAction(mResources, mTextSizeName));
300                mActions.add(ActionType.CAPTIONS_CAPTIONSTYLE.toAction(mResources, mStyleName));
301                break;
302            case CAPTIONS_TEXTSIZE:
303                mActions = Action.createActionsFromArrays(mTextSizes, mTextSizeNames);
304                for (Action action : mActions) {
305                    action.setChecked(action.getKey().equals(mTextSize));
306                }
307                break;
308            case CAPTIONS_CAPTIONSTYLE:
309                mActions = Action.createActionsFromArrays(mStyles, mStyleNames);
310                for (Action action : mActions) {
311                    action.setChecked(action.getKey().equals(mStyle));
312                }
313                break;
314            case CAPTIONS_CUSTOMOPTIONS:
315                mActions.add(ActionType.CAPTIONS_FONTFAMILY.toAction(mResources, mFontFamilyName));
316                mActions.add(ActionType.CAPTIONS_TEXTCOLOR.toAction(mResources, mTextColorName));
317                mActions.add(ActionType.CAPTIONS_TEXTOPACITY.toAction(mResources,
318                        mTextOpacityName));
319                mActions.add(ActionType.CAPTIONS_EDGETYPE.toAction(mResources, mEdgeTypeName));
320                mActions.add(ActionType.CAPTIONS_EDGECOLOR.toAction(mResources, mEdgeColorName));
321                mActions.add(ActionType.CAPTIONS_BACKGROUNDCOLOR.toAction(mResources,
322                               mBackgroundColorName));
323                mActions.add(ActionType.CAPTIONS_BACKGROUNDOPACITY.toAction(mResources,
324                               mBackgroundOpacityName));
325                mActions.add(ActionType.CAPTIONS_WINDOWCOLOR.toAction(mResources,
326                        mWindowColorName));
327                mActions.add(ActionType.CAPTIONS_WINDOWOPACITY.toAction(mResources,
328                        mWindowOpacityName, mWindowEnabled));
329                break;
330            case CAPTIONS_LANGUAGE:
331                mActions = Action.createActionsFromArrays(mLanguageLocales, mLanguageNames);
332                for (Action action : mActions) {
333                    action.setChecked(action.getKey().equals(mLanguage));
334                }
335                break;
336            case CAPTIONS_FONTFAMILY:
337                mActions = Action.createActionsFromArrays(mFontFamilies, mFontFamilyNames);
338                for (Action action : mActions) {
339                    action.setChecked(action.getKey().equals(mFontFamily));
340                }
341                break;
342            case CAPTIONS_TEXTCOLOR:
343                colorsToActions(mTextColor);
344                break;
345            case CAPTIONS_TEXTOPACITY:
346                mActions = Action.createActionsFromArrays(mOpacities, mOpacityNames);
347                for (Action action : mActions) {
348                    action.setChecked(action.getKey().equals(mTextOpacity));
349                }
350                break;
351            case CAPTIONS_EDGETYPE:
352                mActions = Action.createActionsFromArrays(mEdgeTypes, mEdgeTypeNames);
353               for (Action action : mActions) {
354                    action.setChecked(action.getKey().equals(mEdgeType));
355                }
356                break;
357            case CAPTIONS_EDGECOLOR:
358                colorsToActions(mEdgeColor);
359                break;
360            case CAPTIONS_BACKGROUNDCOLOR:
361                colorsToActions(mBackgroundColor);
362                break;
363            case CAPTIONS_BACKGROUNDOPACITY:
364                mActions = Action.createActionsFromArrays(mOpacities, mOpacityNames);
365                for (Action action : mActions) {
366                    action.setChecked(action.getKey().equals(mBackgroundOpacity));
367                }
368                break;
369            case CAPTIONS_WINDOWCOLOR:
370                mActions.clear();
371                mActions.add(
372                    new Action.Builder().key(mNone)
373                                        .drawableResource(mColorResIds[1])
374                                        .title(mNone)
375                                        .checked(!mWindowEnabled).build());
376                for (int i = 0; i < mColorResIds.length; ++i) {
377                    mActions.add(
378                        new Action.Builder().key(Integer.toString(mColorRGBs[i]))
379                                            .drawableResource(mColorResIds[i])
380                                            .title(mColorNames[i])
381                                            .checked(mWindowEnabled && mWindowColor ==
382                                                    mColorRGBs[i]).build());
383                }
384                break;
385            case CAPTIONS_WINDOWOPACITY:
386                mActions = Action.createActionsFromArrays(mOpacities, mOpacityNames);
387                for (Action action : mActions) {
388                    action.setChecked(action.getKey().equals(mWindowOpacity));
389                }
390                break;
391        }
392    }
393
394    @Override
395    protected void updateView() {
396        refreshActionList();
397        mActionFragment = ActionFragment.newInstance(mActions);
398        setActionFragment (mActionFragment);
399    }
400
401    @Override
402    public void onActionFocused(Action action) {
403        final String key = action.getKey();
404        switch ((ActionType) mState) {
405            case CAPTIONS_LANGUAGE:
406                if(mContentFragment instanceof CaptionPreviewFragment) {
407                    ((CaptionPreviewFragment)mContentFragment).
408                        livePreviewLanguage(key);
409                }
410                break;
411            case CAPTIONS_TEXTSIZE:
412                if(mContentFragment instanceof CaptionPreviewFragment) {
413                    ((CaptionPreviewFragment)mContentFragment).
414                        livePreviewFontScale(Float.parseFloat(key));
415                }
416                break;
417            case CAPTIONS_CAPTIONSTYLE:
418                if(mContentFragment instanceof CaptionPreviewFragment) {
419                    ((CaptionPreviewFragment)mContentFragment).
420                        livePreviewCaptionStyle(Integer.parseInt(key));
421                }
422                break;
423            case CAPTIONS_FONTFAMILY:
424                if(mContentFragment instanceof CaptionPreviewFragment) {
425                    ((CaptionPreviewFragment)mContentFragment).
426                        livePreviewFontFamily(key);
427                }
428                break;
429            case CAPTIONS_TEXTCOLOR:
430                if(mContentFragment instanceof CaptionPreviewFragment) {
431                    ((CaptionPreviewFragment)mContentFragment).
432                        livePreviewTextColor(Integer.parseInt(key));
433                }
434                break;
435            case CAPTIONS_TEXTOPACITY:
436                if(mContentFragment instanceof CaptionPreviewFragment) {
437                    ((CaptionPreviewFragment)mContentFragment).
438                        livePreviewTextOpacity(key);
439                }
440                break;
441            case CAPTIONS_EDGETYPE:
442                if(mContentFragment instanceof CaptionPreviewFragment) {
443                    ((CaptionPreviewFragment)mContentFragment).
444                        livePreviewEdgeType(Integer.parseInt(key));
445                }
446                break;
447            case CAPTIONS_EDGECOLOR:
448                if(mContentFragment instanceof CaptionPreviewFragment) {
449                    ((CaptionPreviewFragment)mContentFragment).
450                        livePreviewEdgeColor(Integer.parseInt(key));
451                }
452                break;
453            case CAPTIONS_BACKGROUNDCOLOR:
454                if(mContentFragment instanceof CaptionPreviewFragment) {
455                    ((CaptionPreviewFragment)mContentFragment).
456                        livePreviewBackgroundColor(Integer.parseInt(key));
457                }
458                break;
459            case CAPTIONS_BACKGROUNDOPACITY:
460                if(mContentFragment instanceof CaptionPreviewFragment) {
461                    ((CaptionPreviewFragment)mContentFragment).
462                        livePreviewBackgroundOpacity(key);
463                }
464                break;
465            case CAPTIONS_WINDOWCOLOR:
466                if(mContentFragment instanceof CaptionPreviewFragment) {
467                    if (TextUtils.equals(key, mNone)) {
468                        ((CaptionPreviewFragment)mContentFragment).
469                            livePreviewWindowColorNone();
470                    } else {
471                        ((CaptionPreviewFragment)mContentFragment).
472                            livePreviewWindowColor(Integer.parseInt(key));
473                    }
474                }
475                break;
476            case CAPTIONS_WINDOWOPACITY:
477                if(mContentFragment instanceof CaptionPreviewFragment) {
478                    ((CaptionPreviewFragment)mContentFragment).
479                        livePreviewWindowOpacity(key);
480                }
481                break;
482        }
483    }
484
485    @Override
486    public void onActionClicked(Action action) {
487        final String key = action.getKey();
488        switch ((ActionType) mState) {
489            case CAPTIONS_LANGUAGE:
490                setLanguage(key);
491                goBack();
492                break;
493            case CAPTIONS_TEXTSIZE:
494                setTextSize(key);
495                goBack();
496                break;
497            case CAPTIONS_CAPTIONSTYLE:
498                setStyle(key);
499                if (Integer.parseInt(key) == CaptioningManager.CaptionStyle.PRESET_CUSTOM) {
500                    setState(ActionType.CAPTIONS_CUSTOMOPTIONS, true);
501                } else {
502                    goBack();
503                }
504                break;
505            case CAPTIONS_FONTFAMILY:
506                setFontFamily(key);
507                goBack();
508                break;
509            case CAPTIONS_TEXTCOLOR:
510                setTextColor(key);
511                goBack();
512                break;
513            case CAPTIONS_TEXTOPACITY:
514                setTextOpacity(key);
515                goBack();
516                break;
517            case CAPTIONS_EDGETYPE:
518                setEdgeType(key);
519                goBack();
520                break;
521            case CAPTIONS_EDGECOLOR:
522                setEdgeColor(key);
523                goBack();
524                break;
525            case CAPTIONS_BACKGROUNDCOLOR:
526                setBackgroundColor(key);
527                goBack();
528                break;
529            case CAPTIONS_BACKGROUNDOPACITY:
530                setBackgroundOpacity(key);
531                goBack();
532                break;
533            case CAPTIONS_WINDOWCOLOR:
534                setWindowColor(key);
535                goBack();
536                break;
537            case CAPTIONS_WINDOWOPACITY:
538                setWindowOpacity(key);
539                goBack();
540                break;
541            default:
542                ActionKey<ActionType, ActionBehavior> actionKey =
543                    new ActionKey<ActionType, ActionBehavior>(
544                        ActionType.class, ActionBehavior.class, action.getKey());
545                final ActionType type = actionKey.getType();
546                final ActionBehavior behavior = actionKey.getBehavior();
547                if (behavior == null) {
548                    return;
549                }
550                switch (behavior) {
551                    case ON:
552                        setProperty(true);
553                        break;
554                    case OFF:
555                        setProperty(false);
556                        break;
557                    case INIT:
558                        setState(type, true);
559                        break;
560                }
561                break;
562        }
563    }
564
565    @Override
566    protected Object getInitialState() {
567        return ActionType.CAPTIONS_OVERVIEW;
568    }
569
570    @Override
571    protected void setProperty(boolean enable) {
572        switch ((ActionType) mState) {
573            case CAPTIONS_DISPLAY:
574                setEnabled(enable);
575                break;
576        }
577        goBack();
578    }
579
580    private String getTextSizeName(String textSize) {
581        for (int i = 0; i < mTextSizes.length; ++i) {
582            if (mTextSizes [i] == textSize) {
583                return mTextSizeNames [i];
584            }
585        }
586        return "";
587    }
588
589    private String getStyleName(String style) {
590        for (int i = 0; i < mStyles.length; ++i) {
591            if (mStyles [i] == style) {
592                return mStyleNames [i];
593            }
594        }
595        return "";
596    }
597
598    private void setEnabled(boolean enabled) {
599        mDisplayEnabled = enabled;
600        final ContentResolver cr = getContentResolver();
601        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
602                               enabled ? 1 : 0);
603    }
604
605    private void setStyle(String style) {
606        mStyle = style;
607        mStyleName = getStyleName(style);
608        final ContentResolver cr = getContentResolver();
609        int s = Integer.parseInt(style);
610        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, s);
611        if (s == CaptioningManager.CaptionStyle.PRESET_CUSTOM) {
612            getCustomCaptionStyle();
613        }
614        if(mContentFragment instanceof CaptionPreviewFragment) {
615            ((CaptionPreviewFragment)mContentFragment).refreshPreviewText();
616        }
617    }
618
619    private void setTextSize(String textSize) {
620        mTextSize = textSize;
621        mTextSizeName = getTextSizeName(textSize);
622        final ContentResolver cr = getContentResolver();
623        Settings.Secure.putFloat(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE,
624                                 Float.parseFloat(textSize));
625    }
626
627    private void setLanguage(String language) {
628        mLanguage = language;
629        mLanguageName = getLanguageName(language);
630        final ContentResolver cr = getContentResolver();
631        Settings.Secure.putString(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_LOCALE, language);
632    }
633
634    private void setFontFamily(String fontFamily) {
635        mFontFamily = fontFamily;
636        mFontFamilyName = getFontFamilyName(fontFamily);
637        final ContentResolver cr = getContentResolver();
638        Settings.Secure.putString(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE,
639                                  fontFamily);
640    }
641
642    private void setTextColor(String textColor) {
643        mTextColor = Integer.parseInt(textColor);
644        mTextColorName = getColorName(mTextColor);
645        updateCaptioningTextColor();
646    }
647
648    private void setTextOpacity(String textOpacity) {
649        mTextOpacity = textOpacity;
650        mTextOpacityName = getOpacityName(textOpacity);
651        updateCaptioningTextColor();
652    }
653
654    private void updateCaptioningTextColor() {
655        int opacity = Integer.parseInt(mTextOpacity) & 0xff000000;
656        final ContentResolver cr = getContentResolver();
657        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR,
658                                opacity | mTextColor);
659    }
660
661    private void setWindowColor(String windowColor) {
662        if (TextUtils.equals(windowColor, mNone)) {
663            mWindowEnabled = false;
664            mWindowColorName = mNone;
665            mWindowOpacityName = mNone;
666        } else {
667            mWindowEnabled = true;
668            mWindowColor = Integer.parseInt(windowColor);
669            mWindowColorName = getColorName(mWindowColor);
670            mWindowOpacityName = getOpacityName(mWindowOpacity);
671        }
672        updateCaptioningWindowColor();
673    }
674
675    private void setWindowOpacity(String windowOpacity) {
676        mWindowOpacity = windowOpacity;
677        mWindowOpacityName = getOpacityName(windowOpacity);
678        updateCaptioningWindowColor();
679    }
680
681    private void updateCaptioningWindowColor() {
682        int opacity = mWindowEnabled ? Integer.parseInt(mWindowOpacity) & 0xff000000 : 0;
683        final ContentResolver cr = getContentResolver();
684        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
685                                opacity | mWindowColor);
686    }
687
688    private void setEdgeType(String edgeType) {
689        mEdgeType = edgeType;
690        mEdgeTypeName = getEdgeTypeName(edgeType);
691        final ContentResolver cr = getContentResolver();
692        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_TYPE,
693                                Integer.parseInt(edgeType));
694    }
695
696    private void setEdgeColor(String edgeColor) {
697        mEdgeColor = Integer.parseInt(edgeColor);
698        mEdgeColorName = getColorName(mEdgeColor);
699        final ContentResolver cr = getContentResolver();
700        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_EDGE_COLOR,
701                                0xff000000 | mEdgeColor);
702    }
703
704    private void updateCaptioningBackgroundColor() {
705        int opacity = Integer.parseInt(mBackgroundOpacity) & 0xff000000;
706        final ContentResolver cr = getContentResolver();
707        Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR,
708                                opacity | mBackgroundColor);
709    }
710
711    private void setBackgroundColor(String backgroundColor) {
712        mBackgroundColor = Integer.parseInt(backgroundColor);
713        mBackgroundColorName = getColorName(mBackgroundColor);
714        updateCaptioningBackgroundColor();
715    }
716
717    private void setBackgroundOpacity(String backgroundOpacity) {
718        mBackgroundOpacity = backgroundOpacity;
719        mBackgroundOpacityName = getOpacityName(backgroundOpacity);
720        updateCaptioningBackgroundColor();
721    }
722
723    private String getLanguageName(String mLanaguage) {
724        for (int i = 0; i < mLanguageLocales.length; ++i) {
725            if (mLanguage.equals(mLanguageLocales [i])) {
726                return mLanguageNames [i];
727            }
728        }
729        return "";
730    }
731
732    private static String getDisplayName(
733            Locale l, String[] specialLocaleCodes, String[] specialLocaleNames) {
734        String code = l.toString();
735        for (int i = 0; i < specialLocaleCodes.length; i++) {
736            if (specialLocaleCodes[i].equals(code)) {
737                return specialLocaleNames[i];
738            }
739        }
740        return l.getDisplayName(l);
741    }
742
743    private String getFontFamilyName(String fontFamily) {
744        int x = indexOf(mFontFamilies, fontFamily);
745        if (x == -1) {
746            return "";
747        } else {
748            return mFontFamilyNames [x];
749        }
750    }
751
752    private String getOpacityName(String opacity) {
753        int x = indexOf(mOpacities, opacity);
754        if (x == -1) {
755            return "";
756        } else {
757            return mOpacityNames [x];
758        }
759    }
760
761    private int indexOf(String[] a, String s) {
762        if (s != null) {
763            for (int i = 0; i < a.length; ++i) {
764                if (s.equals(a [i])) {
765                    return i;
766                }
767            }
768        }
769        return -1;
770    }
771
772    private String getEdgeTypeName(String edgeType) {
773        int x = indexOf(mEdgeTypes, edgeType);
774        if (x == -1) {
775            return "";
776        } else {
777            return mEdgeTypeNames [x];
778        }
779    }
780
781    private static class LocaleInfo implements Comparable<LocaleInfo> {
782        private static final Collator sCollator = Collator.getInstance();
783
784        public String label;
785        public Locale locale;
786
787        public LocaleInfo(String label, Locale locale) {
788            this.label = label;
789            this.locale = locale;
790        }
791
792        @Override
793        public String toString() {
794            return label;
795        }
796
797        @Override
798        public int compareTo(LocaleInfo another) {
799            return sCollator.compare(this.label, another.label);
800        }
801    }
802
803    private void getLanguages() {
804        final String[] systemLocales = Resources.getSystem().getAssets().getLocales();
805        Arrays.sort(systemLocales);
806
807        final Context context = getApplicationContext();
808        final Resources resources = context.getResources();
809        final String[] specialLocaleCodes = resources.getStringArray(
810                com.android.internal.R.array.special_locale_codes);
811        final String[] specialLocaleNames = resources.getStringArray(
812                com.android.internal.R.array.special_locale_names);
813
814        int finalSize = 0;
815
816        final int origSize = systemLocales.length;
817        final LocaleInfo[] localeInfos = new LocaleInfo[origSize];
818        for (int i = 0; i < origSize; i++) {
819            final String localeStr = systemLocales[i];
820            final Locale locale = Locale.forLanguageTag(localeStr.replace('_', '-'));
821            // "und" means undefined.
822            if ("und".equals(locale.getLanguage()) || locale.getLanguage().isEmpty() ||
823                    locale.getCountry().isEmpty()) {
824                continue;
825            }
826
827            if (finalSize == 0) {
828                localeInfos[finalSize++] =
829                       new LocaleInfo(locale.getDisplayLanguage(locale), locale);
830            } else {
831                // check previous entry:
832                // same lang and a country -> upgrade to full name and
833                // insert ours with full name
834                // diff lang -> insert ours with lang-only name
835                final LocaleInfo previous = localeInfos[finalSize - 1];
836                if (previous.locale.getLanguage().equals(locale.getLanguage())
837                        && !previous.locale.getLanguage().equals("zz")) {
838                    previous.label = getDisplayName(
839                            localeInfos[finalSize - 1].locale, specialLocaleCodes,
840                            specialLocaleNames);
841                    localeInfos[finalSize++] = new LocaleInfo(getDisplayName(locale,
842                            specialLocaleCodes, specialLocaleNames), locale);
843                } else {
844                    final String displayName;
845                    if (localeStr.equals("zz_ZZ")) {
846                        displayName = "[Developer] Accented English";
847                    } else if (localeStr.equals("zz_ZY")) {
848                        displayName = "[Developer] Fake Bi-Directional";
849                    } else {
850                        displayName = locale.getDisplayLanguage(locale);
851                    }
852                    localeInfos[finalSize++] = new LocaleInfo(displayName, locale);
853                }
854            }
855        }
856
857        mLanguageLocales = new String [finalSize];
858        mLanguageNames = new String [finalSize];
859
860        Arrays.sort(localeInfos, 0, finalSize);
861        for (int i = 0; i < finalSize; i++) {
862            final LocaleInfo info = localeInfos[i];
863            mLanguageLocales[i] = info.locale.toString();
864            mLanguageNames[i] = info.toString();
865        }
866    }
867}
868
869