1 /*
2  * Copyright (C) 2018 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.systemui.plugins;
18 
19 import android.graphics.Color;
20 import android.graphics.Rect;
21 import android.view.View;
22 import android.widget.ImageView;
23 
24 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
25 import com.android.systemui.plugins.annotations.DependsOn;
26 import com.android.systemui.plugins.annotations.ProvidesInterface;
27 
28 /**
29  * Dispatches events to {@link DarkReceiver}s about changes in darkness, tint area and dark
30  * intensity. Accessible through {@link PluginDependency}
31  */
32 @ProvidesInterface(version = DarkIconDispatcher.VERSION)
33 @DependsOn(target = DarkReceiver.class)
34 public interface DarkIconDispatcher {
35     int VERSION = 1;
36 
37     /**
38      * Sets the dark area so {@link #applyDark} only affects the icons in the specified area.
39      *
40      * @param r the area in which icons should change its tint, in logical screen
41      *                 coordinates
42      */
setIconsDarkArea(Rect r)43     void setIconsDarkArea(Rect r);
44 
45     /**
46      * Adds a receiver to receive callbacks onDarkChanged
47      */
addDarkReceiver(DarkReceiver receiver)48     void addDarkReceiver(DarkReceiver receiver);
49 
50     /**
51      * Adds a receiver to receive callbacks onDarkChanged
52      */
addDarkReceiver(ImageView imageView)53     void addDarkReceiver(ImageView imageView);
54 
55     /**
56      * Must have been previously been added through one of the addDarkReceive methods above.
57      */
removeDarkReceiver(DarkReceiver object)58     void removeDarkReceiver(DarkReceiver object);
59 
60     /**
61      * Must have been previously been added through one of the addDarkReceive methods above.
62      */
removeDarkReceiver(ImageView object)63     void removeDarkReceiver(ImageView object);
64 
65     /**
66      * Used to reapply darkness on an object, must have previously been added through
67      * addDarkReceiver.
68       */
applyDark(DarkReceiver object)69     void applyDark(DarkReceiver object);
70 
71     int DEFAULT_ICON_TINT = Color.WHITE;
72     Rect sTmpRect = new Rect();
73     int[] sTmpInt2 = new int[2];
74 
75     /**
76      * @return the tint to apply to view depending on the desired tint color and
77      *         the screen tintArea in which to apply that tint
78      */
getTint(Rect tintArea, View view, int color)79     static int getTint(Rect tintArea, View view, int color) {
80         if (isInArea(tintArea, view)) {
81             return color;
82         } else {
83             return DEFAULT_ICON_TINT;
84         }
85     }
86 
87     /**
88      * @return the dark intensity to apply to view depending on the desired dark
89      *         intensity and the screen tintArea in which to apply that intensity
90      */
getDarkIntensity(Rect tintArea, View view, float intensity)91     static float getDarkIntensity(Rect tintArea, View view, float intensity) {
92         if (isInArea(tintArea, view)) {
93             return intensity;
94         } else {
95             return 0f;
96         }
97     }
98 
99     /**
100      * @return true if more than half of the view area are in area, false
101      *         otherwise
102      */
isInArea(Rect area, View view)103     static boolean isInArea(Rect area, View view) {
104         if (area.isEmpty()) {
105             return true;
106         }
107         sTmpRect.set(area);
108         view.getLocationOnScreen(sTmpInt2);
109         int left = sTmpInt2[0];
110 
111         int intersectStart = Math.max(left, area.left);
112         int intersectEnd = Math.min(left + view.getWidth(), area.right);
113         int intersectAmount = Math.max(0, intersectEnd - intersectStart);
114 
115         boolean coversFullStatusBar = area.top <= 0;
116         boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
117         return majorityOfWidth && coversFullStatusBar;
118     }
119 
120     /**
121      * Receives a callback on darkness changes
122      */
123     @ProvidesInterface(version = DarkReceiver.VERSION)
124     interface DarkReceiver {
125         int VERSION = 1;
onDarkChanged(Rect area, float darkIntensity, int tint)126         void onDarkChanged(Rect area, float darkIntensity, int tint);
127     }
128 }
129