• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 
17 package com.android.settings.accessibility;
18 
19 import static com.android.settings.accessibility.FlashNotificationsUtil.ACTION_FLASH_NOTIFICATION_START_PREVIEW;
20 import static com.android.settings.accessibility.FlashNotificationsUtil.ACTION_FLASH_NOTIFICATION_STOP_PREVIEW;
21 import static com.android.settings.accessibility.FlashNotificationsUtil.DEFAULT_SCREEN_FLASH_COLOR;
22 import static com.android.settings.accessibility.FlashNotificationsUtil.EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR;
23 import static com.android.settings.accessibility.FlashNotificationsUtil.EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE;
24 import static com.android.settings.accessibility.FlashNotificationsUtil.TYPE_LONG_PREVIEW;
25 
26 import android.app.Dialog;
27 import android.content.Intent;
28 import android.graphics.Color;
29 import android.os.Bundle;
30 import android.view.View;
31 
32 import androidx.annotation.ColorInt;
33 import androidx.annotation.NonNull;
34 import androidx.annotation.Nullable;
35 import androidx.appcompat.app.AlertDialog;
36 import androidx.fragment.app.DialogFragment;
37 
38 import com.android.settings.R;
39 
40 import java.util.Timer;
41 import java.util.TimerTask;
42 import java.util.function.Consumer;
43 
44 /**
45  * DialogFragment for Screen flash notification color picker.
46  */
47 public class ScreenFlashNotificationColorDialogFragment extends DialogFragment implements
48         ColorSelectorLayout.OnCheckedChangeListener {
49 
50     private static final int PREVIEW_LONG_TIME_MS = 5000;
51     private static final int BETWEEN_STOP_AND_START_DELAY_MS = 250;
52     private static final int MARGIN_FOR_STOP_DELAY_MS = 100;
53 
54     @ColorInt
55     private int mCurrentColor = Color.TRANSPARENT;
56     private Consumer<Integer> mConsumer;
57 
58     private Timer mTimer = null;
59     private Boolean mIsPreview = false;
60 
getInstance(int initialColor, Consumer<Integer> colorConsumer)61     static ScreenFlashNotificationColorDialogFragment getInstance(int initialColor,
62             Consumer<Integer> colorConsumer) {
63         final ScreenFlashNotificationColorDialogFragment result =
64                 new ScreenFlashNotificationColorDialogFragment();
65         result.mCurrentColor = initialColor;
66         result.mConsumer = colorConsumer != null ? colorConsumer : i -> {
67         };
68         return result;
69     }
70 
71     @NonNull
72     @Override
onCreateDialog(@ullable Bundle savedInstanceState)73     public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
74         final View dialogView = getLayoutInflater().inflate(R.layout.layout_color_selector_dialog,
75                 null);
76 
77         final ColorSelectorLayout colorSelectorLayout = dialogView.findViewById(
78                 R.id.color_selector_preference);
79         if (colorSelectorLayout != null) {
80             colorSelectorLayout.setOnCheckedChangeListener(this);
81             colorSelectorLayout.setCheckedColor(mCurrentColor);
82         }
83 
84         final AlertDialog createdDialog = new AlertDialog.Builder(getContext())
85                 .setView(dialogView)
86                 .setTitle(R.string.screen_flash_notification_color_title)
87                 .setNeutralButton(R.string.flash_notifications_preview, null)
88                 .setNegativeButton(R.string.color_selector_dialog_cancel, (dialog, which) -> {
89                 })
90                 .setPositiveButton(R.string.color_selector_dialog_done, (dialog, which) -> {
91                     mCurrentColor = colorSelectorLayout.getCheckedColor(DEFAULT_SCREEN_FLASH_COLOR);
92                     mConsumer.accept(mCurrentColor);
93                 })
94                 .create();
95         createdDialog.setOnShowListener(
96                 dialogInterface -> createdDialog.getButton(AlertDialog.BUTTON_NEUTRAL)
97                         .setOnClickListener(v -> showColor()));
98 
99         return createdDialog;
100     }
101 
102     @Override
onPause()103     public void onPause() {
104         super.onPause();
105         cancelPreviewTask();
106     }
107 
108     @Override
onCheckedChanged(ColorSelectorLayout group)109     public void onCheckedChanged(ColorSelectorLayout group) {
110         mCurrentColor = group.getCheckedColor(DEFAULT_SCREEN_FLASH_COLOR);
111         if (mIsPreview) {
112             showColor();
113         }
114     }
115 
showColor()116     private void showColor() {
117         int startDelay = 0;
118 
119         synchronized (this) {
120             if (mTimer != null) mTimer.cancel();
121 
122             mTimer = new Timer();
123             if (mIsPreview) {
124                 mTimer.schedule(getStopTask(), 0);
125                 startDelay = BETWEEN_STOP_AND_START_DELAY_MS;
126             }
127             mTimer.schedule(getStartTask(), startDelay);
128             mTimer.schedule(getStopTask(),
129                     startDelay + PREVIEW_LONG_TIME_MS + MARGIN_FOR_STOP_DELAY_MS);
130         }
131     }
132 
getStartTask()133     private TimerTask getStartTask() {
134         return new TimerTask() {
135             @Override
136             public void run() {
137                 synchronized (this) {
138                     startPreviewLocked();
139                 }
140             }
141         };
142     }
143 
144     private TimerTask getStopTask() {
145         return new TimerTask() {
146             @Override
147             public void run() {
148                 synchronized (this) {
149                     stopPreviewLocked();
150                 }
151             }
152         };
153     }
154 
155     private void cancelPreviewTask() {
156         synchronized (this) {
157             if (mTimer != null) mTimer.cancel();
158             stopPreviewLocked();
159         }
160     }
161 
162     private void startPreviewLocked() {
163         if (getContext() == null) return;
164 
165         mIsPreview = true;
166         Intent intent = new Intent(ACTION_FLASH_NOTIFICATION_START_PREVIEW);
167         intent.putExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_TYPE, TYPE_LONG_PREVIEW);
168         intent.putExtra(EXTRA_FLASH_NOTIFICATION_PREVIEW_COLOR, mCurrentColor);
169         getContext().sendBroadcast(intent);
170     }
171 
172     private void stopPreviewLocked() {
173         if (getContext() == null) return;
174 
175         Intent stopIntent = new Intent(ACTION_FLASH_NOTIFICATION_STOP_PREVIEW);
176         getContext().sendBroadcast(stopIntent);
177         mIsPreview = false;
178     }
179 }
180