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.test; 18 19 import android.adservices.ondevicepersonalization.DownloadCompletedInput; 20 import android.adservices.ondevicepersonalization.DownloadCompletedOutput; 21 import android.adservices.ondevicepersonalization.EventInput; 22 import android.adservices.ondevicepersonalization.EventLogRecord; 23 import android.adservices.ondevicepersonalization.EventOutput; 24 import android.adservices.ondevicepersonalization.ExecuteInput; 25 import android.adservices.ondevicepersonalization.ExecuteOutput; 26 import android.adservices.ondevicepersonalization.IsolatedServiceException; 27 import android.adservices.ondevicepersonalization.IsolatedWorker; 28 import android.adservices.ondevicepersonalization.KeyValueStore; 29 import android.adservices.ondevicepersonalization.RenderInput; 30 import android.adservices.ondevicepersonalization.RenderOutput; 31 import android.adservices.ondevicepersonalization.RenderingConfig; 32 import android.adservices.ondevicepersonalization.RequestLogRecord; 33 import android.adservices.ondevicepersonalization.TrainingExampleRecord; 34 import android.adservices.ondevicepersonalization.TrainingExamplesInput; 35 import android.adservices.ondevicepersonalization.TrainingExamplesOutput; 36 import android.adservices.ondevicepersonalization.WebTriggerInput; 37 import android.adservices.ondevicepersonalization.WebTriggerOutput; 38 import android.annotation.NonNull; 39 import android.content.ContentValues; 40 import android.os.OutcomeReceiver; 41 import android.os.PersistableBundle; 42 import android.util.Log; 43 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.List; 47 import java.util.Objects; 48 import java.util.Set; 49 50 // TODO(b/249345663) Move this class and related manifest to separate APK for more realistic testing 51 public class TestPersonalizationHandler implements IsolatedWorker { 52 public static final String TAG = "TestPersonalizationHandler"; 53 54 /** Bundle key that mimics a timeout in {@link #onExecute}. */ 55 public static final String TIMEOUT_KEY = "timeout_key"; 56 57 private final KeyValueStore mRemoteData; 58 TestPersonalizationHandler(KeyValueStore remoteData)59 TestPersonalizationHandler(KeyValueStore remoteData) { 60 mRemoteData = remoteData; 61 } 62 63 @Override onDownloadCompleted( DownloadCompletedInput input, OutcomeReceiver<DownloadCompletedOutput, IsolatedServiceException> receiver)64 public void onDownloadCompleted( 65 DownloadCompletedInput input, 66 OutcomeReceiver<DownloadCompletedOutput, IsolatedServiceException> receiver) { 67 try { 68 Log.d(TAG, "Starting filterData."); 69 Log.d(TAG, "Data keys: " + input.getDownloadedContents().keySet()); 70 71 Log.d(TAG, "Existing keyExtra: " + Arrays.toString(mRemoteData.get("keyExtra"))); 72 Log.d(TAG, "Existing keySet: " + mRemoteData.keySet()); 73 74 List<String> keysToRetain = getFilteredKeys(input.getDownloadedContents()); 75 keysToRetain.add("keyExtra"); 76 // Get the keys to keep from the downloaded data 77 DownloadCompletedOutput result = 78 new DownloadCompletedOutput.Builder().setRetainedKeys(keysToRetain).build(); 79 receiver.onResult(result); 80 } catch (Exception e) { 81 Log.e(TAG, "Error occurred in onDownload", e); 82 } 83 } 84 85 @Override onExecute( @onNull ExecuteInput input, @NonNull OutcomeReceiver<ExecuteOutput, IsolatedServiceException> receiver)86 public void onExecute( 87 @NonNull ExecuteInput input, 88 @NonNull OutcomeReceiver<ExecuteOutput, IsolatedServiceException> receiver) { 89 Log.d(TAG, "onExecute() started."); 90 PersistableBundle inputBundle = input.getAppParams(); 91 if (inputBundle != null && inputBundle.getBoolean("timeout_key", false)) { 92 Log.d(TAG, "onExecute() skipped."); 93 return; 94 } 95 Log.d(TAG, "onExecute() continuing."); 96 ContentValues logData = new ContentValues(); 97 logData.put("id", "bid1"); 98 logData.put("pr", 5.0); 99 ExecuteOutput result = 100 new ExecuteOutput.Builder() 101 .setRequestLogRecord(new RequestLogRecord.Builder().addRow(logData).build()) 102 .setRenderingConfig(new RenderingConfig.Builder().addKey("bid1").build()) 103 .addEventLogRecord( 104 new EventLogRecord.Builder() 105 .setData(logData) 106 .setRequestLogRecord( 107 new RequestLogRecord.Builder() 108 .addRow(logData) 109 .addRow(logData) 110 .setRequestId(1) 111 .build()) 112 .setType(1) 113 .setRowIndex(1) 114 .build()) 115 .setOutputData(new byte[] {1, 2, 3}) 116 .build(); 117 receiver.onResult(result); 118 } 119 120 @Override onRender( @onNull RenderInput input, @NonNull OutcomeReceiver<RenderOutput, IsolatedServiceException> receiver)121 public void onRender( 122 @NonNull RenderInput input, 123 @NonNull OutcomeReceiver<RenderOutput, IsolatedServiceException> receiver) { 124 Log.d(TAG, "onRender() started."); 125 RenderOutput result = 126 new RenderOutput.Builder() 127 .setContent( 128 "<p>RenderResult: " 129 + String.join(",", input.getRenderingConfig().getKeys()) 130 + "<p>") 131 .build(); 132 receiver.onResult(result); 133 } 134 135 @Override onEvent( @onNull EventInput input, @NonNull OutcomeReceiver<EventOutput, IsolatedServiceException> receiver)136 public void onEvent( 137 @NonNull EventInput input, 138 @NonNull OutcomeReceiver<EventOutput, IsolatedServiceException> receiver) { 139 Log.d(TAG, "onEvent() started."); 140 long longValue = 0; 141 if (input.getParameters() != null) { 142 longValue = input.getParameters().getLong("x"); 143 } 144 ContentValues logData = new ContentValues(); 145 logData.put("x", longValue); 146 EventOutput result = 147 new EventOutput.Builder() 148 .setEventLogRecord( 149 new EventLogRecord.Builder() 150 .setType(1) 151 .setRowIndex(0) 152 .setData(logData) 153 .build()) 154 .build(); 155 Log.d(TAG, "onEvent() result: " + result.toString()); 156 receiver.onResult(result); 157 } 158 getFilteredKeys(KeyValueStore data)159 private List<String> getFilteredKeys(KeyValueStore data) { 160 Set<String> filteredKeys = data.keySet(); 161 Log.d(TAG, "key3 size: " + Objects.requireNonNull(data.get("key3")).length); 162 filteredKeys.remove("key3"); 163 return new ArrayList<>(filteredKeys); 164 } 165 166 @Override onTrainingExamples( @onNull TrainingExamplesInput input, @NonNull OutcomeReceiver<TrainingExamplesOutput, IsolatedServiceException> receiver)167 public void onTrainingExamples( 168 @NonNull TrainingExamplesInput input, 169 @NonNull OutcomeReceiver<TrainingExamplesOutput, IsolatedServiceException> receiver) { 170 Log.d(TAG, "onTrainingExamples() started."); 171 Log.d(TAG, "Population name: " + input.getPopulationName()); 172 Log.d(TAG, "Task name: " + input.getTaskName()); 173 174 List<TrainingExampleRecord> exampleRecordList = new ArrayList<>(); 175 TrainingExampleRecord record1 = 176 new TrainingExampleRecord.Builder() 177 .setTrainingExample(new byte[] {10}) 178 .setResumptionToken("token1".getBytes()) 179 .build(); 180 TrainingExampleRecord record2 = 181 new TrainingExampleRecord.Builder() 182 .setTrainingExample(new byte[] {20}) 183 .setResumptionToken("token2".getBytes()) 184 .build(); 185 exampleRecordList.add(record1); 186 exampleRecordList.add(record2); 187 188 TrainingExamplesOutput output = 189 new TrainingExamplesOutput.Builder() 190 .setTrainingExampleRecords(exampleRecordList) 191 .build(); 192 receiver.onResult(output); 193 } 194 195 @Override onWebTrigger( @onNull WebTriggerInput input, @NonNull OutcomeReceiver<WebTriggerOutput, IsolatedServiceException> receiver)196 public void onWebTrigger( 197 @NonNull WebTriggerInput input, 198 @NonNull OutcomeReceiver<WebTriggerOutput, IsolatedServiceException> receiver) { 199 Log.d(TAG, "onWebTrigger() started."); 200 ContentValues logData = new ContentValues(); 201 logData.put("id", "trig1"); 202 logData.put("val", 10.0); 203 WebTriggerOutput output = 204 new WebTriggerOutput.Builder() 205 .addEventLogRecord( 206 new EventLogRecord.Builder() 207 .setData(logData) 208 .setRequestLogRecord( 209 new RequestLogRecord.Builder() 210 .addRow(logData) 211 .addRow(logData) 212 .setRequestId(1) 213 .build()) 214 .setType(10) 215 .setRowIndex(1) 216 .build()) 217 .build(); 218 receiver.onResult(output); 219 } 220 } 221