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.android.ondevicepersonalization.services; 18 19 import static android.adservices.ondevicepersonalization.OnDevicePersonalizationPermissions.MODIFY_ONDEVICEPERSONALIZATION_STATE; 20 21 import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__API_CALLBACK_ERROR; 22 import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__API_REMOTE_EXCEPTION; 23 import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ON_DEVICE_PERSONALIZATION_ERROR; 24 import static com.android.adservices.service.stats.AdServicesStatsLog.AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__ODP; 25 26 import android.adservices.ondevicepersonalization.Constants; 27 import android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationConfigService; 28 import android.adservices.ondevicepersonalization.aidl.IOnDevicePersonalizationConfigServiceCallback; 29 import android.annotation.NonNull; 30 import android.annotation.RequiresPermission; 31 import android.content.Context; 32 import android.content.pm.PackageManager; 33 import android.ondevicepersonalization.IOnDevicePersonalizationSystemService; 34 import android.ondevicepersonalization.IOnDevicePersonalizationSystemServiceCallback; 35 import android.ondevicepersonalization.OnDevicePersonalizationSystemServiceManager; 36 import android.os.Binder; 37 import android.os.Bundle; 38 import android.os.RemoteException; 39 40 import com.android.modules.utils.build.SdkLevel; 41 import com.android.ondevicepersonalization.internal.util.LoggerFactory; 42 import com.android.ondevicepersonalization.services.data.user.RawUserData; 43 import com.android.ondevicepersonalization.services.data.user.UserDataCollector; 44 import com.android.ondevicepersonalization.services.data.user.UserPrivacyStatus; 45 import com.android.ondevicepersonalization.services.statsd.errorlogging.ClientErrorLogger; 46 47 import java.util.Objects; 48 import java.util.concurrent.Executor; 49 50 /** 51 * ODP service that modifies and persists ODP enablement status 52 */ 53 public class OnDevicePersonalizationConfigServiceDelegate 54 extends IOnDevicePersonalizationConfigService.Stub { 55 private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger(); 56 private static final String TAG = "OnDevicePersonalizationConfigServiceDelegate"; 57 private final Context mContext; 58 private static final Executor sBackgroundExecutor = 59 OnDevicePersonalizationExecutors.getBackgroundExecutor(); 60 private static final int SERVICE_NOT_IMPLEMENTED = 501; 61 OnDevicePersonalizationConfigServiceDelegate(Context context)62 public OnDevicePersonalizationConfigServiceDelegate(Context context) { 63 mContext = context; 64 } 65 66 @Override 67 @RequiresPermission(MODIFY_ONDEVICEPERSONALIZATION_STATE) setPersonalizationStatus(boolean enabled, @NonNull IOnDevicePersonalizationConfigServiceCallback callback)68 public void setPersonalizationStatus(boolean enabled, 69 @NonNull IOnDevicePersonalizationConfigServiceCallback 70 callback) { 71 if (getGlobalKillSwitch()) { 72 throw new IllegalStateException("Service skipped as the API flag is turned off."); 73 } 74 75 // Verify caller's permission 76 if (mContext.checkCallingPermission(MODIFY_ONDEVICEPERSONALIZATION_STATE) 77 != PackageManager.PERMISSION_GRANTED) { 78 throw new SecurityException( 79 "Permission denied: " + MODIFY_ONDEVICEPERSONALIZATION_STATE); 80 } 81 Objects.requireNonNull(callback); 82 83 sBackgroundExecutor.execute( 84 () -> { 85 try { 86 UserPrivacyStatus userPrivacyStatus = UserPrivacyStatus.getInstance(); 87 88 boolean oldStatus = userPrivacyStatus.isPersonalizationStatusEnabled(); 89 userPrivacyStatus.setPersonalizationStatusEnabled(enabled); 90 boolean newStatus = userPrivacyStatus.isPersonalizationStatusEnabled(); 91 92 if (oldStatus == newStatus) { 93 sendSuccess(callback); 94 return; 95 } 96 97 // Rollback all user data if personalization status changes 98 RawUserData userData = RawUserData.getInstance(); 99 UserDataCollector userDataCollector = 100 UserDataCollector.getInstance(mContext); 101 userDataCollector.clearUserData(userData); 102 userDataCollector.clearMetadata(); 103 104 // TODO(b/302018665): replicate system server storage to T devices. 105 if (!SdkLevel.isAtLeastU()) { 106 userPrivacyStatus.setPersonalizationStatusEnabled(enabled); 107 sendSuccess(callback); 108 return; 109 } 110 // Persist in the system server for U+ devices 111 OnDevicePersonalizationSystemServiceManager systemServiceManager = 112 mContext.getSystemService( 113 OnDevicePersonalizationSystemServiceManager.class); 114 // Cannot find system server on U+. 115 if (systemServiceManager == null) { 116 sendError(callback, SERVICE_NOT_IMPLEMENTED); 117 return; 118 } 119 IOnDevicePersonalizationSystemService systemService = 120 systemServiceManager.getService(); 121 // The system service is not ready. 122 if (systemService == null) { 123 sendError(callback, SERVICE_NOT_IMPLEMENTED); 124 return; 125 } 126 try { 127 systemService.setPersonalizationStatus( 128 enabled, 129 new IOnDevicePersonalizationSystemServiceCallback.Stub() { 130 @Override 131 public void onResult(Bundle bundle) throws RemoteException { 132 userPrivacyStatus.setPersonalizationStatusEnabled( 133 enabled); 134 callback.onSuccess(); 135 } 136 137 @Override 138 public void onError(int errorCode) throws RemoteException { 139 callback.onFailure(errorCode); 140 } 141 }); 142 } catch (RemoteException re) { 143 sLogger.e(TAG + ": Unable to send result to the callback.", re); 144 ClientErrorLogger.getInstance() 145 .logErrorWithExceptionInfo( 146 re, 147 AD_SERVICES_ERROR_REPORTED__ERROR_CODE__API_REMOTE_EXCEPTION, 148 AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__ODP); 149 } 150 } catch (Exception e) { 151 sLogger.e(TAG + ": Failed to set personalization status.", e); 152 ClientErrorLogger.getInstance() 153 .logErrorWithExceptionInfo( 154 e, 155 AD_SERVICES_ERROR_REPORTED__ERROR_CODE__ON_DEVICE_PERSONALIZATION_ERROR, 156 AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__ODP); 157 sendError(callback, Constants.STATUS_INTERNAL_ERROR); 158 } 159 }); 160 } 161 sendSuccess( @onNull IOnDevicePersonalizationConfigServiceCallback callback)162 private void sendSuccess( 163 @NonNull IOnDevicePersonalizationConfigServiceCallback callback) { 164 try { 165 callback.onSuccess(); 166 } catch (RemoteException e) { 167 sLogger.e(TAG + ": Callback error", e); 168 ClientErrorLogger.getInstance() 169 .logErrorWithExceptionInfo( 170 e, 171 AD_SERVICES_ERROR_REPORTED__ERROR_CODE__API_CALLBACK_ERROR, 172 AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__ODP); 173 } 174 } 175 sendError( @onNull IOnDevicePersonalizationConfigServiceCallback callback, int errorCode)176 private void sendError( 177 @NonNull IOnDevicePersonalizationConfigServiceCallback callback, int errorCode) { 178 try { 179 callback.onFailure(errorCode); 180 } catch (RemoteException e) { 181 sLogger.e(TAG + ": Callback error", e); 182 ClientErrorLogger.getInstance() 183 .logErrorWithExceptionInfo( 184 e, 185 AD_SERVICES_ERROR_REPORTED__ERROR_CODE__API_CALLBACK_ERROR, 186 AD_SERVICES_ERROR_REPORTED__PPAPI_NAME__ODP); 187 } 188 } 189 getGlobalKillSwitch()190 private boolean getGlobalKillSwitch() { 191 long origId = Binder.clearCallingIdentity(); 192 boolean globalKillSwitch = FlagsFactory.getFlags().getGlobalKillSwitch(); 193 Binder.restoreCallingIdentity(origId); 194 return globalKillSwitch; 195 } 196 } 197