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 android.adservices.ondevicepersonalization;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertThrows;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.adservices.ondevicepersonalization.aidl.IExecuteCallback;
24 import android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationManagingService;
25 import android.adservices.ondevicepersonalization.aidl.IRegisterMeasurementEventCallback;
26 import android.adservices.ondevicepersonalization.aidl.IRequestSurfacePackageCallback;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.net.Uri;
30 import android.os.Bundle;
31 import android.os.IBinder;
32 import android.os.RemoteException;
33 import android.os.SystemClock;
34 import android.util.Log;
35 
36 import androidx.test.core.app.ApplicationProvider;
37 import androidx.test.ext.junit.runners.AndroidJUnit4;
38 
39 import com.android.federatedcompute.internal.util.AbstractServiceBinder;
40 import com.android.ondevicepersonalization.testing.utils.ResultReceiver;
41 
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 
45 import java.util.concurrent.Executor;
46 import java.util.concurrent.Executors;
47 
48 @RunWith(AndroidJUnit4.class)
49 public final class OnDevicePersonalizationSystemEventManagerTest {
50     private static final String TAG = "OnDevicePersonalizationManagerTest";
51     private static final String KEY_OP = "op";
52     private Context mContext = ApplicationProvider.getApplicationContext();
53     private TestServiceBinder mTestBinder = new TestServiceBinder(
54             IOnDevicePersonalizationManagingService.Stub.asInterface(new TestService()));
55     private OnDevicePersonalizationSystemEventManager mManager =
56             new OnDevicePersonalizationSystemEventManager(mContext, mTestBinder);
57 
58     @Test
testnotifyMeasurementEventSuccess()59     public void testnotifyMeasurementEventSuccess() throws Exception {
60         var receiver = new ResultReceiver<Void>();
61         mManager.notifyMeasurementEvent(
62                 new MeasurementWebTriggerEventParams.Builder(
63                         Uri.parse("http://ok"),
64                         "com.example.browser",
65                         ComponentName.createRelative("com.example", ".Example"))
66                             .build(),
67                 Executors.newSingleThreadExecutor(),
68                 receiver);
69         assertTrue(receiver.isSuccess());
70         assertFalse(receiver.isError());
71     }
72 
73     @Test
testnotifyMeasurementEventError()74     public void testnotifyMeasurementEventError() throws Exception {
75         var receiver = new ResultReceiver<Void>();
76         mManager.notifyMeasurementEvent(
77                 new MeasurementWebTriggerEventParams.Builder(
78                         Uri.parse("http://error"),
79                         "com.example.browser",
80                         ComponentName.createRelative("com.example", ".Example"))
81                             .build(),
82                 Executors.newSingleThreadExecutor(),
83                 receiver);
84         assertFalse(receiver.isSuccess());
85         assertTrue(receiver.isError());
86     }
87 
88     @Test
testnotifyMeasurementEventPropagatesIae()89     public void testnotifyMeasurementEventPropagatesIae() throws Exception {
90         assertThrows(
91                 IllegalArgumentException.class,
92                 () -> mManager.notifyMeasurementEvent(
93                         new MeasurementWebTriggerEventParams.Builder(
94                             Uri.parse("http://iae"),
95                             "com.example.browser",
96                             ComponentName.createRelative("com.example", ".Example"))
97                                 .build(),
98                         Executors.newSingleThreadExecutor(),
99                         new ResultReceiver<Void>()));
100     }
101 
102     @Test
testnotifyMeasurementEventPropagatesNpe()103     public void testnotifyMeasurementEventPropagatesNpe() throws Exception {
104         assertThrows(
105                 NullPointerException.class,
106                 () -> mManager.notifyMeasurementEvent(
107                         new MeasurementWebTriggerEventParams.Builder(
108                             Uri.parse("http://npe"),
109                             "com.example.browser",
110                             ComponentName.createRelative("com.example", ".Example"))
111                                 .build(),
112                         Executors.newSingleThreadExecutor(),
113                         new ResultReceiver<Void>()));
114     }
115 
116     @Test
testnotifyMeasurementEventCatchesExceptions()117     public void testnotifyMeasurementEventCatchesExceptions() throws Exception {
118         var receiver = new ResultReceiver<Void>();
119         mManager.notifyMeasurementEvent(
120                 new MeasurementWebTriggerEventParams.Builder(
121                         Uri.parse("http://ise"),
122                         "com.example.browser",
123                         ComponentName.createRelative("com.example", ".Example"))
124                             .build(),
125                 Executors.newSingleThreadExecutor(),
126                 receiver);
127         assertFalse(receiver.isSuccess());
128         assertTrue(receiver.isError());
129         assertTrue(receiver.getException() instanceof IllegalStateException);
130     }
131 
132     class TestService extends IOnDevicePersonalizationManagingService.Stub {
133         @Override
getVersion()134         public String getVersion() {
135             return "1.0";
136         }
137 
138         @Override
execute( String callingPackageName, ComponentName handler, Bundle params, CallerMetadata metadata, IExecuteCallback callback)139         public void execute(
140                 String callingPackageName,
141                 ComponentName handler,
142                 Bundle params,
143                 CallerMetadata metadata,
144                 IExecuteCallback callback) {
145             throw new UnsupportedOperationException();
146         }
147 
148         @Override
requestSurfacePackage( String surfacePackageToken, IBinder hostToken, int displayId, int width, int height, CallerMetadata metadata, IRequestSurfacePackageCallback callback)149         public void requestSurfacePackage(
150                 String surfacePackageToken,
151                 IBinder hostToken,
152                 int displayId,
153                 int width,
154                 int height,
155                 CallerMetadata metadata,
156                 IRequestSurfacePackageCallback callback) {
157             throw new UnsupportedOperationException();
158         }
159 
160         @Override
registerMeasurementEvent( int eventType, Bundle params, CallerMetadata metadata, IRegisterMeasurementEventCallback callback)161         public void registerMeasurementEvent(
162                 int eventType,
163                 Bundle params,
164                 CallerMetadata metadata,
165                 IRegisterMeasurementEventCallback callback) {
166             try {
167                 MeasurementWebTriggerEventParamsParcel wtparams = params.getParcelable(
168                         Constants.EXTRA_MEASUREMENT_WEB_TRIGGER_PARAMS,
169                         MeasurementWebTriggerEventParamsParcel.class);
170                 String url = wtparams.getDestinationUrl().toString();
171                 if (url.equals("http://error")) {
172                     callback.onError(Constants.STATUS_INTERNAL_ERROR,
173                             new CalleeMetadata.Builder().setCallbackInvokeTimeMillis(
174                                     SystemClock.elapsedRealtime()).build());
175                 } else if (url.equals("http://iae")) {
176                     throw new IllegalArgumentException();
177                 } else if (url.equals("http://npe")) {
178                     throw new NullPointerException();
179                 } else if (url.equals("http://ise")) {
180                     throw new IllegalStateException();
181                 } else {
182                     callback.onSuccess(
183                             new CalleeMetadata.Builder().setCallbackInvokeTimeMillis(
184                                     SystemClock.elapsedRealtime()).build());
185                 }
186             } catch (RemoteException e) {
187                 Log.e(TAG, "callback error", e);
188             }
189         }
190 
191         @Override
logApiCallStats( String sdkPackageName, int apiName, long latencyMillis, long rpcCallLatencyMillis, long rpcReturnLatencyMillis, int responseCode)192         public void logApiCallStats(
193                 String sdkPackageName,
194                 int apiName,
195                 long latencyMillis,
196                 long rpcCallLatencyMillis,
197                 long rpcReturnLatencyMillis,
198                 int responseCode) {
199         }
200     }
201 
202     class TestServiceBinder
203             extends AbstractServiceBinder<IOnDevicePersonalizationManagingService> {
204         private final IOnDevicePersonalizationManagingService mService;
TestServiceBinder(IOnDevicePersonalizationManagingService service)205         TestServiceBinder(IOnDevicePersonalizationManagingService service) {
206             mService = service;
207         }
208 
209         @Override
getService(Executor executor)210         public IOnDevicePersonalizationManagingService getService(Executor executor) {
211             return mService;
212         }
213 
214         @Override
unbindFromService()215         public void unbindFromService() {}
216     }
217 }
218