1 /*
2  * Copyright 2024 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 androidx.core.backported.fixes
18 
19 import android.os.Build
20 
21 /**
22  * Reports the status of a known issue on this device.
23  *
24  * @param resolver a function that takes a [KnownIssue] and returns its [Status] on this device.
25  *   This parameter is only used for testing. In normal flows, the empty constructor should be used.
26  */
27 internal class BackportedFixManager(private val resolver: StatusResolver) {
28     /** Creates a BackportedFixManager object using the default lookup strategy. */
29     public constructor() :
30         this(
31             // TODO b/381267367 - Use Build.getBackportedFixStatus in when available.
32             resolver = SystemPropertyResolver()
33         )
34 
35     /**
36      * Is the known issue fixed on this device.
37      *
38      * @param ki The known issue to check.
39      */
isFixednull40     internal fun isFixed(ki: KnownIssue): Boolean {
41         return when (getStatus(ki)) {
42             Status.Unknown -> false
43             Status.Fixed -> true
44             Status.NotApplicable -> true
45             Status.NotFixed -> false
46         }
47     }
48 
49     /**
50      * The status of a known issue on this device.
51      *
52      * @param ki The known issue to check.
53      */
getStatusnull54     internal fun getStatus(ki: KnownIssue): Status {
55         return when (ki) {
56             // If the known issue needs special handling,
57             // like when an issue only applies
58             // to certain devices then call a method named after the issue id or using
59             // a precondition names after the issue id.
60             //
61             // Issues are individually listed and use inline functions to make it easy for
62             // the compiler to remove unused code.
63 
64             // keep-sorted start
65 
66             KnownIssue.KI_372917199 -> preconditionResolution(::pre372917199, ki)
67 
68             // keep-sorted end
69             else -> defaultResolution(ki)
70         }
71     }
72 
preconditionResolutionnull73     private inline fun preconditionResolution(precondition: () -> Boolean, ki: KnownIssue): Status {
74         if (precondition.invoke()) {
75             return defaultResolution(ki)
76         }
77         return Status.NotApplicable
78     }
79 
defaultResolutionnull80     private fun defaultResolution(ki: KnownIssue): Status {
81         return resolver.invoke(ki)
82     }
83 
pre372917199null84     private fun pre372917199(): Boolean {
85         return (Build.BRAND.equals("robolectric"))
86     }
87 }
88 
89 /** Function that takes a [KnownIssue] and returns its [Status] on this device. */
90 internal typealias StatusResolver = (KnownIssue) -> Status
91