1 /* 2 * Copyright 2023 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.privacysandbox.ads.adservices.adselection 18 19 import android.annotation.SuppressLint 20 import android.os.Build 21 import android.os.ext.SdkExtensions 22 import android.util.Log 23 import android.view.InputEvent 24 import androidx.annotation.IntDef 25 import androidx.annotation.RequiresExtension 26 import androidx.annotation.RestrictTo 27 import androidx.privacysandbox.ads.adservices.common.ExperimentalFeatures 28 import androidx.privacysandbox.ads.adservices.internal.AdServicesInfo 29 30 /** 31 * Represent input parameters to the reportImpression API. 32 * 33 * @param adSelectionId An ID unique only to a device user that identifies a successful ad 34 * selection. 35 * @param eventKey An event key, the type of ad event to be reported. 36 * @param eventData The ad event data 37 * @param reportingDestinations The bitfield of reporting destinations to report to (buyer, seller, 38 * or both). 39 * @param inputEvent The input event associated with the user interaction. 40 */ 41 @OptIn(ExperimentalFeatures.Ext10OptIn::class) 42 @ExperimentalFeatures.Ext8OptIn 43 class ReportEventRequest 44 @JvmOverloads 45 public constructor( 46 val adSelectionId: Long, 47 val eventKey: String, 48 val eventData: String, 49 @ReportingDestination val reportingDestinations: Int, 50 @property:ExperimentalFeatures.Ext10OptIn val inputEvent: InputEvent? = null 51 ) { 52 init { 53 require( 54 0 < reportingDestinations && 55 reportingDestinations <= 56 (FLAG_REPORTING_DESTINATION_SELLER or FLAG_REPORTING_DESTINATION_BUYER) <lambda>null57 ) { 58 "Invalid reporting destinations bitfield." 59 } 60 } 61 62 /** Checks whether two [ReportImpressionRequest] objects contain the same information. */ equalsnull63 override fun equals(other: Any?): Boolean { 64 if (this === other) return true 65 if (other !is ReportEventRequest) return false 66 return this.adSelectionId == other.adSelectionId && 67 this.eventKey == other.eventKey && 68 this.eventData == other.eventData && 69 this.reportingDestinations == other.reportingDestinations && 70 this.inputEvent == other.inputEvent 71 } 72 73 /** Returns the hash of the [ReportImpressionRequest] object's data. */ hashCodenull74 override fun hashCode(): Int { 75 var hash = adSelectionId.hashCode() 76 hash = 31 * hash + eventKey.hashCode() 77 hash = 31 * hash + eventData.hashCode() 78 hash = 31 * hash + reportingDestinations.hashCode() 79 hash = 31 * hash + inputEvent.hashCode() 80 return hash 81 } 82 83 /** Overrides the toString method. */ toStringnull84 override fun toString(): String { 85 return "ReportEventRequest: adSelectionId=$adSelectionId, eventKey=$eventKey, " + 86 "eventData=$eventData, reportingDestinations=$reportingDestinations" + 87 "inputEvent=$inputEvent" 88 } 89 90 @RestrictTo(RestrictTo.Scope.LIBRARY) 91 @Retention(AnnotationRetention.SOURCE) 92 @IntDef( 93 flag = true, 94 value = 95 [ 96 Companion.FLAG_REPORTING_DESTINATION_SELLER, 97 Companion.FLAG_REPORTING_DESTINATION_BUYER 98 ] 99 ) 100 annotation class ReportingDestination 101 102 companion object { 103 const val FLAG_REPORTING_DESTINATION_SELLER: Int = 104 android.adservices.adselection.ReportEventRequest.FLAG_REPORTING_DESTINATION_SELLER 105 const val FLAG_REPORTING_DESTINATION_BUYER: Int = 106 android.adservices.adselection.ReportEventRequest.FLAG_REPORTING_DESTINATION_BUYER 107 } 108 109 @SuppressLint("NewApi") 110 @RestrictTo(RestrictTo.Scope.LIBRARY) 111 @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 8) 112 @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9) convertToAdServicesnull113 internal fun convertToAdServices(): android.adservices.adselection.ReportEventRequest { 114 if ( 115 AdServicesInfo.adServicesVersion() >= 10 || AdServicesInfo.extServicesVersionS() >= 10 116 ) { 117 return Ext10Impl.convertReportEventRequest(this) 118 } 119 return Ext8Impl.convertReportEventRequest(this) 120 } 121 122 @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 10) 123 @RequiresExtension(extension = Build.VERSION_CODES.S, version = 10) 124 private class Ext10Impl private constructor() { 125 companion object { convertReportEventRequestnull126 fun convertReportEventRequest( 127 request: ReportEventRequest 128 ): android.adservices.adselection.ReportEventRequest { 129 return android.adservices.adselection.ReportEventRequest.Builder( 130 request.adSelectionId, 131 request.eventKey, 132 request.eventData, 133 request.reportingDestinations 134 ) 135 .setInputEvent(request.inputEvent) 136 .build() 137 } 138 } 139 } 140 141 @RequiresExtension(extension = SdkExtensions.AD_SERVICES, version = 8) 142 @RequiresExtension(extension = Build.VERSION_CODES.S, version = 9) 143 private class Ext8Impl private constructor() { 144 companion object { convertReportEventRequestnull145 fun convertReportEventRequest( 146 request: ReportEventRequest 147 ): android.adservices.adselection.ReportEventRequest { 148 request.inputEvent?.let { 149 Log.w( 150 "ReportEventRequest", 151 "inputEvent is ignored. Min version to use inputEvent is API 31 ext 10" 152 ) 153 } 154 return android.adservices.adselection.ReportEventRequest.Builder( 155 request.adSelectionId, 156 request.eventKey, 157 request.eventData, 158 request.reportingDestinations 159 ) 160 .build() 161 } 162 } 163 } 164 } 165