7
7
import android .util .Log ;
8
8
import androidx .annotation .GuardedBy ;
9
9
import androidx .annotation .VisibleForTesting ;
10
+ import com .bumptech .glide .util .Util ;
10
11
import java .io .File ;
11
12
import java .util .Arrays ;
13
+ import java .util .concurrent .atomic .AtomicBoolean ;
12
14
13
15
/**
14
16
* State and constants for interacting with {@link android.graphics.Bitmap.Config#HARDWARE} on
15
17
* Android O+.
16
18
*/
17
19
public final class HardwareConfigState {
20
+ private static final String TAG = "HardwareConfig" ;
21
+
18
22
/**
19
23
* Force the state to wait until a call to allow hardware Bitmaps to be used when they'd otherwise
20
24
* be eligible to work around a framework issue pre Q that can cause a native crash when
21
25
* allocating a hardware Bitmap in this specific circumstance. See b/126573603#comment12 for
22
26
* details.
23
27
*/
24
- private static final boolean BLOCK_HARDWARE_BITMAPS_BY_DEFAULT =
28
+ private static final boolean BLOCK_HARDWARE_BITMAPS_WHEN_GL_CONTEXT_MIGHT_NOT_BE_INITIALIZED =
25
29
Build .VERSION .SDK_INT < Build .VERSION_CODES .Q ;
26
30
27
31
/**
@@ -87,7 +91,13 @@ public final class HardwareConfigState {
87
91
@ GuardedBy ("this" )
88
92
private boolean isFdSizeBelowHardwareLimit = true ;
89
93
90
- private volatile boolean areHardwareBitmapsUnblocked ;
94
+ /**
95
+ * Only mutated on the main thread. Read by any number of background threads concurrently.
96
+ *
97
+ * <p>Defaults to {@code false} because we need to wait for the GL context to be initialized and
98
+ * it defaults to not initialized (https://b.corp.google.com/issues/126573603#comment12).
99
+ */
100
+ private final AtomicBoolean isHardwareConfigAllowedByAppState = new AtomicBoolean (false );
91
101
92
102
public static HardwareConfigState getInstance () {
93
103
if (instance == null ) {
@@ -112,31 +122,77 @@ public static HardwareConfigState getInstance() {
112
122
}
113
123
}
114
124
115
- public void unblockHardwareBitmaps () {
116
- areHardwareBitmapsUnblocked = true ;
125
+ public synchronized void blockHardwareBitmaps () {
126
+ Util .assertMainThread ();
127
+ isHardwareConfigAllowedByAppState .set (false );
128
+ }
129
+
130
+ public synchronized void unblockHardwareBitmaps () {
131
+ Util .assertMainThread ();
132
+ isHardwareConfigAllowedByAppState .set (true );
117
133
}
118
134
119
135
public boolean isHardwareConfigAllowed (
120
136
int targetWidth ,
121
137
int targetHeight ,
122
138
boolean isHardwareConfigAllowed ,
123
139
boolean isExifOrientationRequired ) {
124
- if (!isHardwareConfigAllowed
125
- || !isHardwareConfigAllowedByDeviceModel
126
- || Build .VERSION .SDK_INT < Build .VERSION_CODES .O
127
- || areHardwareBitmapsBlockedByAppState ()
128
- || isExifOrientationRequired ) {
140
+ if (!isHardwareConfigAllowed ) {
141
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
142
+ Log .v (TAG , "Hardware config disallowed by caller" );
143
+ }
144
+ return false ;
145
+ }
146
+ if (!isHardwareConfigAllowedByDeviceModel ) {
147
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
148
+ Log .v (TAG , "Hardware config disallowed by device model" );
149
+ }
150
+ return false ;
151
+ }
152
+ if (Build .VERSION .SDK_INT < Build .VERSION_CODES .O ) {
153
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
154
+ Log .v (TAG , "Hardware config disallowed by sdk" );
155
+ }
156
+ return false ;
157
+ }
158
+ if (areHardwareBitmapsBlockedByAppState ()) {
159
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
160
+ Log .v (TAG , "Hardware config disallowed by app state" );
161
+ }
162
+ return false ;
163
+ }
164
+ if (isExifOrientationRequired ) {
165
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
166
+ Log .v (TAG , "Hardware config disallowed because exif orientation is required" );
167
+ }
168
+ return false ;
169
+ }
170
+ if (targetWidth < minHardwareDimension ) {
171
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
172
+ Log .v (TAG , "Hardware config disallowed because width is too small" );
173
+ }
174
+ return false ;
175
+ }
176
+ if (targetHeight < minHardwareDimension ) {
177
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
178
+ Log .v (TAG , "Hardware config disallowed because height is too small" );
179
+ }
180
+ return false ;
181
+ }
182
+ // Make sure to call isFdSizeBelowHardwareLimit last because it has side affects.
183
+ if (!isFdSizeBelowHardwareLimit ()) {
184
+ if (Log .isLoggable (TAG , Log .VERBOSE )) {
185
+ Log .v (TAG , "Hardware config disallowed because there are insufficient FDs" );
186
+ }
129
187
return false ;
130
188
}
131
189
132
- return targetWidth >= minHardwareDimension
133
- && targetHeight >= minHardwareDimension
134
- // Make sure to call isFdSizeBelowHardwareLimit last because it has side affects.
135
- && isFdSizeBelowHardwareLimit ();
190
+ return true ;
136
191
}
137
192
138
193
private boolean areHardwareBitmapsBlockedByAppState () {
139
- return BLOCK_HARDWARE_BITMAPS_BY_DEFAULT && !areHardwareBitmapsUnblocked ;
194
+ return BLOCK_HARDWARE_BITMAPS_WHEN_GL_CONTEXT_MIGHT_NOT_BE_INITIALIZED
195
+ && !isHardwareConfigAllowedByAppState .get ();
140
196
}
141
197
142
198
@ TargetApi (Build .VERSION_CODES .O )
0 commit comments