1 /*
2  * Copyright (C) 2022 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.ondevicepersonalization.services.policyengine.api
18 
19 import com.android.internal.annotations.VisibleForTesting;
20 
21 import com.android.libraries.pcc.chronicle.analysis.DefaultChronicleContext
22 import com.android.libraries.pcc.chronicle.analysis.DefaultPolicySet
23 import com.android.libraries.pcc.chronicle.analysis.impl.ChroniclePolicyEngine
24 import com.android.libraries.pcc.chronicle.api.ConnectionProvider
25 import com.android.libraries.pcc.chronicle.api.flags.Flags
26 import com.android.libraries.pcc.chronicle.api.flags.FlagsReader
27 import com.android.libraries.pcc.chronicle.api.integration.DefaultChronicle
28 import com.android.libraries.pcc.chronicle.api.integration.DefaultDataTypeDescriptorSet
29 import com.android.libraries.pcc.chronicle.api.policy.DefaultPolicyConformanceCheck
30 import com.android.libraries.pcc.chronicle.api.policy.Policy
31 import com.android.libraries.pcc.chronicle.util.TypedMap
32 import com.android.ondevicepersonalization.services.policyengine.data.impl.UserDataConnectionProvider
33 import com.android.ondevicepersonalization.services.policyengine.policy.DataIngressPolicy
34 import kotlinx.coroutines.flow.MutableStateFlow
35 import kotlinx.coroutines.flow.StateFlow
36 
37 /** [ChronicleManager] instance that connects to the Chronicle backend. */
38 class ChronicleManager private constructor (
39     private val connectionProviders: Set<ConnectionProvider>,
40     private val policies: Set<Policy>,
41     private val connectionContext: TypedMap = TypedMap()
42 ) {
43     private val flags = MutableStateFlow(Flags())
44     private val flagsReader: FlagsReader = object : FlagsReader {
45         override val config: StateFlow<Flags> = this@ChronicleManager.flags
46     }
47 
48     val chronicle = DefaultChronicle(
49         chronicleContext =
50             DefaultChronicleContext(
51                 connectionProviders = connectionProviders,
52                 processorNodes = emptySet(),
53                 policySet = DefaultPolicySet(policies),
54                 dataTypeDescriptorSet =
55                     DefaultDataTypeDescriptorSet(
<lambda>null56                     connectionProviders.map { it.dataType.descriptor }.toSet()
57                 ),
58                 connectionContext = connectionContext
59             ),
60         policyEngine = ChroniclePolicyEngine(),
61         config =
62             DefaultChronicle.Config(
63                 policyMode = DefaultChronicle.Config.PolicyMode.STRICT,
64                 policyConformanceCheck = DefaultPolicyConformanceCheck()
65             ),
66         flags = flagsReader
67     )
68 
69     companion object {
70         @JvmField
71         @Volatile
72         @VisibleForTesting
73         var instance: ChronicleManager? = null
74 
75         @JvmOverloads
76         @JvmStatic
getInstancenull77         fun getInstance() =
78             instance
79                 ?: synchronized(this) {
80                     // double-checked locking
81                     instance
82                         ?: ChronicleManager(
83                                 setOf(UserDataConnectionProvider()),
84                                 setOf(DataIngressPolicy.NPA_DATA_POLICY),
85                                 TypedMap()).also{ instance = it }
86                 }
87     }
88 
<lambda>null89     fun failNewConnections(failNewConnections: Boolean) = updateFlags {
90         it.copy(failNewConnections = failNewConnections)
91     }
92 
updateFlagsnull93     private inline fun updateFlags(block: (Flags) -> Flags) {
94         do {
95             val before = flags.value
96             val after = block(before)
97         } while (!flags.compareAndSet(before, after))
98     }
99 }
100