10217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk/*
20217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * Copyright (C) 2015 The Android Open Source Project
30217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk *
40217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
50217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * you may not use this file except in compliance with the License.
60217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * You may obtain a copy of the License at
70217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk *
80217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
90217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk *
100217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * Unless required by applicable law or agreed to in writing, software
110217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
120217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * See the License for the specific language governing permissions and
140217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk * limitations under the License.
150217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk */
160217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkpackage com.android.settings;
170217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
180217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.app.AlertDialog.Builder;
190217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.content.Context;
200217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.content.res.Resources;
210217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.hardware.display.DisplayManager;
220217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.hardware.display.DisplayManager.DisplayListener;
230217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.os.Handler;
240217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.os.Looper;
250217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.preference.DialogPreference;
2616a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monkimport android.preference.SwitchPreference;
270217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.util.AttributeSet;
280217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.view.Display;
290217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.view.Display.ColorTransform;
300217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.view.LayoutInflater;
310217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.view.View;
320217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.view.View.OnClickListener;
330217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.widget.Checkable;
340217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.widget.LinearLayout;
350217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport android.widget.TextView;
360217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
370217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monkimport java.util.ArrayList;
380217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
3916a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monkpublic class ColorModePreference extends SwitchPreference implements DisplayListener {
400217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
410217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    private DisplayManager mDisplayManager;
420217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    private Display mDisplay;
430217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
440217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    private int mCurrentIndex;
450217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    private ArrayList<ColorTransformDescription> mDescriptions;
460217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
470217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public ColorModePreference(Context context, AttributeSet attrs) {
480217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        super(context, attrs);
490217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        mDisplayManager = getContext().getSystemService(DisplayManager.class);
500217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
510217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
520217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public int getTransformsCount() {
530217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        return mDescriptions.size();
540217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
550217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
560217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public void startListening() {
570217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        mDisplayManager.registerDisplayListener(this, new Handler(Looper.getMainLooper()));
580217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
590217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
600217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public void stopListening() {
610217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        mDisplayManager.unregisterDisplayListener(this);
620217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
630217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
640217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    @Override
650217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public void onDisplayAdded(int displayId) {
660217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        if (displayId == Display.DEFAULT_DISPLAY) {
670217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            updateCurrentAndSupported();
680217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        }
690217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
700217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
710217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    @Override
720217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public void onDisplayChanged(int displayId) {
730217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        if (displayId == Display.DEFAULT_DISPLAY) {
740217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            updateCurrentAndSupported();
750217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        }
760217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
770217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
780217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    @Override
790217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public void onDisplayRemoved(int displayId) {
800217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
810217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
820217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    public void updateCurrentAndSupported() {
830217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        mDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
840217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
850217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        mDescriptions = new ArrayList<>();
860217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
870217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        Resources resources = getContext().getResources();
880217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        int[] transforms = resources.getIntArray(
890217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                com.android.internal.R.array.config_colorTransforms);
900217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        String[] titles = resources.getStringArray(R.array.color_mode_names);
910217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        String[] descriptions = resources.getStringArray(R.array.color_mode_descriptions);
920217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        // Map the resource information describing color transforms.
930217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        for (int i = 0; i < transforms.length; i++) {
9416a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk            if (transforms[i] != -1 && i != 1 /* Skip Natural for now. */) {
950217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                ColorTransformDescription desc = new ColorTransformDescription();
960217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                desc.colorTransform = transforms[i];
970217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                desc.title = titles[i];
980217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                desc.summary = descriptions[i];
990217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                mDescriptions.add(desc);
1000217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            }
1010217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        }
1020217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        // Match up a ColorTransform to every description.
1030217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        ColorTransform[] supportedColorTransforms = mDisplay.getSupportedColorTransforms();
1040217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        for (int i = 0; i < supportedColorTransforms.length; i++) {
1050217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            for (int j = 0; j < mDescriptions.size(); j++) {
1060217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                if (mDescriptions.get(j).colorTransform
1070217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                        == supportedColorTransforms[i].getColorTransform()
1080217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                        && mDescriptions.get(j).transform == null) {
1090217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                    mDescriptions.get(j).transform = supportedColorTransforms[i];
1100217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                    break;
1110217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                }
1120217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            }
1130217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        }
1140217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        // Remove any extras that don't have a transform for some reason.
1150217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        for (int i = 0; i < mDescriptions.size(); i++) {
1160217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            if (mDescriptions.get(i).transform == null) {
1170217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                mDescriptions.remove(i--);
1180217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            }
1190217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        }
1200217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
1210217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        ColorTransform currentTransform = mDisplay.getColorTransform();
1220217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        mCurrentIndex = -1;
1230217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        for (int i = 0; i < mDescriptions.size(); i++) {
1240217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            if (mDescriptions.get(i).colorTransform == currentTransform.getColorTransform()) {
1250217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                mCurrentIndex = i;
1260217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk                break;
1270217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk            }
1280217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        }
12916a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk        setChecked(mCurrentIndex == 1);
1300217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
1310217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
1320217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    @Override
13316a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk    protected boolean persistBoolean(boolean value) {
13416a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk        // Right now this is a switch, so we only support two modes.
13516a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk        if (mDescriptions.size() == 2) {
13616a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk            ColorTransformDescription desc = mDescriptions.get(value ? 1 : 0);
1370217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
13816a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk            mDisplay.requestColorTransform(desc.transform);
13916a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk            mCurrentIndex = mDescriptions.indexOf(desc);
14016a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk        }
1410217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
14216a8e8d1028c09abe8b083acf9da70e6d65ebb79Jason Monk        return true;
1430217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
1440217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk
1450217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    private static class ColorTransformDescription {
1460217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        private int colorTransform;
1470217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        private String title;
1480217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        private String summary;
1490217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk        private ColorTransform transform;
1500217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk    }
1510217281d33e9f76c703073a0a8f8ea565a55dae9Jason Monk}
152