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.security.state.provider 18 19 import androidx.security.state.SecurityPatchState 20 import java.text.SimpleDateFormat 21 import java.util.Date 22 import java.util.Objects 23 import kotlinx.serialization.KSerializer 24 import kotlinx.serialization.Serializable 25 import kotlinx.serialization.descriptors.PrimitiveKind 26 import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor 27 import kotlinx.serialization.descriptors.SerialDescriptor 28 import kotlinx.serialization.encoding.Decoder 29 import kotlinx.serialization.encoding.Encoder 30 31 private object DateSerializer : KSerializer<Date> { 32 override val descriptor: SerialDescriptor = 33 PrimitiveSerialDescriptor("Date", PrimitiveKind.STRING) 34 35 private val dateFormat: SimpleDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") 36 serializenull37 override fun serialize(encoder: Encoder, value: Date): Unit = 38 encoder.encodeString(dateFormat.format(value)) 39 40 override fun deserialize(decoder: Decoder): Date = dateFormat.parse(decoder.decodeString())!! 41 } 42 43 @Serializable 44 internal class SerializableUpdateInfo( 45 private val uri: String, 46 private val component: String, 47 private val securityPatchLevel: String, 48 @Serializable(with = DateSerializer::class) private val publishedDate: Date 49 ) { 50 internal fun toUpdateInfo(): UpdateInfo = 51 UpdateInfo(uri, component, securityPatchLevel, publishedDate) 52 } 53 54 /** Represents information about an available update for a component. */ 55 public class UpdateInfo( 56 /** Uri of the content provider from OTA update client serving update information data. */ 57 public val uri: String, 58 /** Component for which the update information is provided. */ 59 public val component: String, 60 /** 61 * Security patch level of the available update ready to be applied by the reporting client. Use 62 * [SecurityPatchState.getComponentSecurityPatchLevel] method to get encapsulated value. 63 */ 64 public val securityPatchLevel: String, 65 /** Date when the available update was published. */ 66 public val publishedDate: Date 67 ) { 68 toSerializableUpdateInfonull69 internal fun toSerializableUpdateInfo(): SerializableUpdateInfo = 70 SerializableUpdateInfo(uri, component, securityPatchLevel, publishedDate) 71 72 /** 73 * Returns a string representation of the update information. 74 * 75 * @return A string that describes the update details. 76 */ 77 public override fun toString(): String = 78 "UpdateInfo(" + 79 "uri=$uri, component=$component, SPL=$securityPatchLevel, date=$publishedDate)" 80 81 /** 82 * Compares this UpdateInfo with another object for equality. 83 * 84 * @param other The object to compare with this instance. 85 * @return true if the other object is an instance of UpdateInfo and all properties match, false 86 * otherwise. 87 */ 88 public override fun equals(other: Any?): Boolean = 89 other is UpdateInfo && 90 uri == other.uri && 91 component == other.component && 92 securityPatchLevel == other.securityPatchLevel && 93 publishedDate == other.publishedDate 94 95 /** 96 * Provides a hash code for an UpdateInfo object. 97 * 98 * @return A hash code produced by the properties of the update info. 99 */ 100 public override fun hashCode(): Int = 101 Objects.hash(uri, component, securityPatchLevel, publishedDate) 102 103 /** Builder class for creating an instance of UpdateInfo. */ 104 public class Builder { 105 @set:JvmSynthetic private var uri: String = "" 106 @set:JvmSynthetic private var component: String = "" 107 @set:JvmSynthetic private var securityPatchLevel: String = "" 108 @set:JvmSynthetic private var publishedDate: Date = Date(0) // 1970-01-01 109 110 /** 111 * Sets the URI of the update. 112 * 113 * @param uri The URI to set. 114 * @return The builder instance for chaining. 115 */ 116 public fun setUri(uri: String): Builder = apply { this.uri = uri } 117 118 /** 119 * Sets the component associated with the update. 120 * 121 * @param component The component to set. 122 * @return The builder instance for chaining. 123 */ 124 public fun setComponent(component: String): Builder = apply { this.component = component } 125 126 /** 127 * Sets the security patch level of the update. 128 * 129 * @param securityPatchLevel The security patch level to set. 130 * @return The builder instance for chaining. 131 */ 132 public fun setSecurityPatchLevel(securityPatchLevel: String): Builder = apply { 133 this.securityPatchLevel = securityPatchLevel 134 } 135 136 /** 137 * Sets the publication date of the update. 138 * 139 * @param publishedDate The date to set. 140 * @return The builder instance for chaining. 141 */ 142 public fun setPublishedDate(publishedDate: Date): Builder = apply { 143 this.publishedDate = publishedDate 144 } 145 146 /** 147 * Builds and returns an UpdateInfo object. 148 * 149 * @return The constructed UpdateInfo. 150 */ 151 public fun build(): UpdateInfo = 152 UpdateInfo(uri, component, securityPatchLevel, publishedDate) 153 } 154 } 155