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 kotlinx.coroutines.flow.MutableStateFlow 33 import kotlinx.coroutines.flow.StateFlow 34 35 /** [ChronicleManager] instance that connects to the Chronicle backend. */ 36 class ChronicleManager private constructor ( 37 private val connectionProviders: Set<ConnectionProvider>, 38 private val policies: Set<Policy>, 39 private val connectionContext: TypedMap = TypedMap() 40 ) { 41 private val flags = MutableStateFlow(Flags()) 42 private val flagsReader: FlagsReader = object : FlagsReader { 43 override val config: StateFlow<Flags> = this@ChronicleManager.flags 44 } 45 46 val chronicle = DefaultChronicle( 47 chronicleContext = 48 DefaultChronicleContext( 49 connectionProviders = connectionProviders, 50 processorNodes = emptySet(), 51 policySet = DefaultPolicySet(policies), 52 dataTypeDescriptorSet = 53 DefaultDataTypeDescriptorSet( <lambda>null54 connectionProviders.map { it.dataType.descriptor }.toSet() 55 ), 56 connectionContext = connectionContext 57 ), 58 policyEngine = ChroniclePolicyEngine(), 59 config = 60 DefaultChronicle.Config( 61 policyMode = DefaultChronicle.Config.PolicyMode.STRICT, 62 policyConformanceCheck = DefaultPolicyConformanceCheck() 63 ), 64 flags = flagsReader 65 ) 66 67 companion object { 68 @JvmField 69 @Volatile 70 @VisibleForTesting 71 var instance: ChronicleManager? = null 72 73 @JvmOverloads 74 @JvmStatic getInstancenull75 fun getInstance(connectionProviders: Set<ConnectionProvider>, 76 policies: Set<Policy>, 77 connectionContext: TypedMap = TypedMap()) = 78 instance 79 ?: synchronized(this) { 80 // double-checked locking 81 instance 82 ?: ChronicleManager( 83 connectionProviders, policies, connectionContext).also{ instance = it } 84 } 85 } 86 <lambda>null87 fun failNewConnections(failNewConnections: Boolean) = updateFlags { 88 it.copy(failNewConnections = failNewConnections) 89 } 90 updateFlagsnull91 private inline fun updateFlags(block: (Flags) -> Flags) { 92 do { 93 val before = flags.value 94 val after = block(before) 95 } while (!flags.compareAndSet(before, after)) 96 } 97 } 98