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.privacysandbox.ondevicepersonalization.client
18 
19 import android.adservices.ondevicepersonalization.SurfacePackageToken
20 import android.annotation.SuppressLint
21 import android.content.Context
22 import android.os.Build
23 import android.os.IBinder
24 import android.os.ext.SdkExtensions
25 import android.view.SurfaceControlViewHost
26 
27 /**
28  * OnDevicePersonalizationManager provides APIs for apps to load an
29  * [IsolatedService][android.adservices.ondevicepersonalization.IsolatedService] in an isolated
30  * process and interact with it.
31  *
32  * An app can request an
33  * [IsolatedService][android.adservices.ondevicepersonalization.IsolatedService] to generate content
34  * for display within an [SurfaceView][android.view.SurfaceView] within the app's view hierarchy,
35  * and also write persistent results to on-device storage which can be consumed by Federated
36  * Analytics for cross-device statistical analysis or by Federated Learning for model training. The
37  * displayed content and the persistent output are both not directly accessible by the calling app.
38  */
39 abstract class OnDevicePersonalizationManager internal constructor() {
40     /**
41      * Executes an [IsolatedService][android.adservices.ondevicepersonalization.IsolatedService] in
42      * the OnDevicePersonalization sandbox bound to an isolated process. Upon execution completion,
43      * the returned response object contains tokens that can be subsequently used to display results
44      * in a [SurfaceView][android.view.SurfaceView] within the calling app. If the service returned
45      * a [RenderingConfig][android.adservices.ondevicepersonalization.RenderingConfig] to be
46      * displayed, [ExecuteInIsolatedServiceResponse.surfacePackageToken] can be used in a subsequent
47      * [requestSurfacePackage] call to display the result in a view. The SurfacePackageToken may be
48      * null to indicate that no output is expected to be displayed for this request.
49      *
50      * @param executeInIsolatedServiceRequest
51      * @return [ExecuteInIsolatedServiceResponse]
52      * @throws android.adservices.ondevicepersonalization.OnDevicePersonalizationException If
53      *   execution of the handler fails with an error code.
54      * @throws android.content.pm.PackageManager.NameNotFoundException On older versions if the
55      *   handler package is not installed or does not have a valid ODP manifest
56      * @throws ClassNotFoundException On older versions if the handler class is not found.
57      */
executeInIsolatedServicenull58     abstract suspend fun executeInIsolatedService(
59         executeInIsolatedServiceRequest: ExecuteInIsolatedServiceRequest
60     ): ExecuteInIsolatedServiceResponse
61 
62     /**
63      * Requests a [SurfacePackage][android.view.SurfaceControlViewHost.SurfacePackage] to be
64      * inserted into a [SurfaceView][android.view.SurfaceView] inside the calling app.
65      *
66      * @param surfacePackageToken a reference to a [SurfacePackageToken] returned by a prior call to
67      *   [executeInIsolatedService].
68      * @param surfaceViewHostToken the hostToken of the [SurfaceView][android.view.SurfaceView],
69      *   which is returned by [android.view.SurfaceView.getHostToken] after the
70      *   [SurfaceView][android.view.SurfaceView] has been added to the view hierarchy.
71      * @param displayId the integer ID of the logical display on which to display the
72      *   [SurfaceControlViewHost.SurfacePackage], returned by Context.getDisplay().getDisplayId().
73      * @param width the width of the [SurfaceControlViewHost.SurfacePackage] in pixels.
74      * @param height the height of the [SurfaceControlViewHost.SurfacePackage] in pixels.
75      * @return A surface package containing a [View][android.view.View] with the content from a
76      *   result of a prior call to [executeInIsolatedService] running in the OnDevicePersonalization
77      *   sandbox.
78      * @throws android.adservices.ondevicepersonalization.OnDevicePersonalizationException if
79      *   execution of the handler fails with an error code.
80      */
81     abstract suspend fun requestSurfacePackage(
82         surfacePackageToken: SurfacePackageToken,
83         surfaceViewHostToken: IBinder,
84         displayId: Int,
85         width: Int,
86         height: Int
87     ): SurfaceControlViewHost.SurfacePackage
88 
89     companion object {
90         /**
91          * Creates [OnDevicePersonalizationManager].
92          *
93          * @return OnDevicePersonalizationManager object. If the device is running an incompatible
94          *   build, the value returned is `null`.
95          */
96         @SuppressLint("NewApi")
97         @JvmStatic
98         fun obtain(context: Context): OnDevicePersonalizationManager? {
99             return if (adServicesVersion() >= 12) {
100                 OnDevicePersonalizationManagerAPI33Ext12Impl(context)
101             } else {
102                 null
103             }
104         }
105 
106         private fun adServicesVersion(): Int {
107             return if (Build.VERSION.SDK_INT >= 33) {
108                 SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES)
109             } else {
110                 0
111             }
112         }
113     }
114 }
115