/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.test; import android.adservices.ondevicepersonalization.DownloadCompletedInput; import android.adservices.ondevicepersonalization.DownloadCompletedOutput; import android.adservices.ondevicepersonalization.EventInput; import android.adservices.ondevicepersonalization.EventLogRecord; import android.adservices.ondevicepersonalization.EventOutput; import android.adservices.ondevicepersonalization.ExecuteInput; import android.adservices.ondevicepersonalization.ExecuteOutput; import android.adservices.ondevicepersonalization.IsolatedServiceException; import android.adservices.ondevicepersonalization.IsolatedWorker; import android.adservices.ondevicepersonalization.KeyValueStore; import android.adservices.ondevicepersonalization.RenderInput; import android.adservices.ondevicepersonalization.RenderOutput; import android.adservices.ondevicepersonalization.RenderingConfig; import android.adservices.ondevicepersonalization.RequestLogRecord; import android.adservices.ondevicepersonalization.TrainingExampleRecord; import android.adservices.ondevicepersonalization.TrainingExamplesInput; import android.adservices.ondevicepersonalization.TrainingExamplesOutput; import android.adservices.ondevicepersonalization.WebTriggerInput; import android.adservices.ondevicepersonalization.WebTriggerOutput; import android.annotation.NonNull; import android.content.ContentValues; import android.os.OutcomeReceiver; import android.os.PersistableBundle; import android.util.Log; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; // TODO(b/249345663) Move this class and related manifest to separate APK for more realistic testing public class TestPersonalizationHandler implements IsolatedWorker { public static final String TAG = "TestPersonalizationHandler"; /** Bundle key that mimics a timeout in {@link #onExecute}. */ public static final String TIMEOUT_KEY = "timeout_key"; private final KeyValueStore mRemoteData; TestPersonalizationHandler(KeyValueStore remoteData) { mRemoteData = remoteData; } @Override public void onDownloadCompleted( DownloadCompletedInput input, OutcomeReceiver receiver) { try { Log.d(TAG, "Starting filterData."); Log.d(TAG, "Data keys: " + input.getDownloadedContents().keySet()); Log.d(TAG, "Existing keyExtra: " + Arrays.toString(mRemoteData.get("keyExtra"))); Log.d(TAG, "Existing keySet: " + mRemoteData.keySet()); List keysToRetain = getFilteredKeys(input.getDownloadedContents()); keysToRetain.add("keyExtra"); // Get the keys to keep from the downloaded data DownloadCompletedOutput result = new DownloadCompletedOutput.Builder().setRetainedKeys(keysToRetain).build(); receiver.onResult(result); } catch (Exception e) { Log.e(TAG, "Error occurred in onDownload", e); } } @Override public void onExecute( @NonNull ExecuteInput input, @NonNull OutcomeReceiver receiver) { Log.d(TAG, "onExecute() started."); PersistableBundle inputBundle = input.getAppParams(); if (inputBundle != null && inputBundle.getBoolean("timeout_key", false)) { Log.d(TAG, "onExecute() skipped."); return; } Log.d(TAG, "onExecute() continuing."); ContentValues logData = new ContentValues(); logData.put("id", "bid1"); logData.put("pr", 5.0); ExecuteOutput result = new ExecuteOutput.Builder() .setRequestLogRecord(new RequestLogRecord.Builder().addRow(logData).build()) .setRenderingConfig(new RenderingConfig.Builder().addKey("bid1").build()) .addEventLogRecord( new EventLogRecord.Builder() .setData(logData) .setRequestLogRecord( new RequestLogRecord.Builder() .addRow(logData) .addRow(logData) .setRequestId(1) .build()) .setType(1) .setRowIndex(1) .build()) .setOutputData(new byte[] {1, 2, 3}) .build(); receiver.onResult(result); } @Override public void onRender( @NonNull RenderInput input, @NonNull OutcomeReceiver receiver) { Log.d(TAG, "onRender() started."); RenderOutput result = new RenderOutput.Builder() .setContent( "

RenderResult: " + String.join(",", input.getRenderingConfig().getKeys()) + "

") .build(); receiver.onResult(result); } @Override public void onEvent( @NonNull EventInput input, @NonNull OutcomeReceiver receiver) { Log.d(TAG, "onEvent() started."); long longValue = 0; if (input.getParameters() != null) { longValue = input.getParameters().getLong("x"); } ContentValues logData = new ContentValues(); logData.put("x", longValue); EventOutput result = new EventOutput.Builder() .setEventLogRecord( new EventLogRecord.Builder() .setType(1) .setRowIndex(0) .setData(logData) .build()) .build(); Log.d(TAG, "onEvent() result: " + result.toString()); receiver.onResult(result); } private List getFilteredKeys(KeyValueStore data) { Set filteredKeys = data.keySet(); Log.d(TAG, "key3 size: " + Objects.requireNonNull(data.get("key3")).length); filteredKeys.remove("key3"); return new ArrayList<>(filteredKeys); } @Override public void onTrainingExamples( @NonNull TrainingExamplesInput input, @NonNull OutcomeReceiver receiver) { Log.d(TAG, "onTrainingExamples() started."); Log.d(TAG, "Population name: " + input.getPopulationName()); Log.d(TAG, "Task name: " + input.getTaskName()); List exampleRecordList = new ArrayList<>(); TrainingExampleRecord record1 = new TrainingExampleRecord.Builder() .setTrainingExample(new byte[] {10}) .setResumptionToken("token1".getBytes()) .build(); TrainingExampleRecord record2 = new TrainingExampleRecord.Builder() .setTrainingExample(new byte[] {20}) .setResumptionToken("token2".getBytes()) .build(); exampleRecordList.add(record1); exampleRecordList.add(record2); TrainingExamplesOutput output = new TrainingExamplesOutput.Builder() .setTrainingExampleRecords(exampleRecordList) .build(); receiver.onResult(output); } @Override public void onWebTrigger( @NonNull WebTriggerInput input, @NonNull OutcomeReceiver receiver) { Log.d(TAG, "onWebTrigger() started."); ContentValues logData = new ContentValues(); logData.put("id", "trig1"); logData.put("val", 10.0); WebTriggerOutput output = new WebTriggerOutput.Builder() .addEventLogRecord( new EventLogRecord.Builder() .setData(logData) .setRequestLogRecord( new RequestLogRecord.Builder() .addRow(logData) .addRow(logData) .setRequestId(1) .build()) .setType(10) .setRowIndex(1) .build()) .build(); receiver.onResult(output); } }