/* * 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.android.ondevicepersonalization.services; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.ondevicepersonalization.aidl.IExecuteCallback; import android.ondevicepersonalization.aidl.IOnDevicePersonalizationManagingService; import android.ondevicepersonalization.aidl.IRequestSurfacePackageCallback; import android.os.Binder; import android.os.IBinder; import android.os.PersistableBundle; import com.android.internal.annotations.VisibleForTesting; import com.android.ondevicepersonalization.services.request.AppRequestFlow; import com.android.ondevicepersonalization.services.request.RenderFlow; import java.util.Objects; /** Implementation of OnDevicePersonalizationManagingService */ public class OnDevicePersonalizationManagingServiceDelegate extends IOnDevicePersonalizationManagingService.Stub { @NonNull private final Context mContext; @VisibleForTesting static class Injector { AppRequestFlow getAppRequestFlow( String callingPackageName, String servicePackageName, PersistableBundle params, IExecuteCallback callback, Context context) { return new AppRequestFlow( callingPackageName, servicePackageName, params, callback, context); } RenderFlow getRenderFlow( String slotResultToken, IBinder hostToken, int displayId, int width, int height, IRequestSurfacePackageCallback callback, Context context) { return new RenderFlow( slotResultToken, hostToken, displayId, width, height, callback, context); } } @NonNull private final Injector mInjector; public OnDevicePersonalizationManagingServiceDelegate(@NonNull Context context) { this(context, new Injector()); } @VisibleForTesting public OnDevicePersonalizationManagingServiceDelegate( @NonNull Context context, @NonNull Injector injector) { mContext = Objects.requireNonNull(context); mInjector = Objects.requireNonNull(injector); } @Override public String getVersion() { return "1.0"; } @Override public void execute( @NonNull String callingPackageName, @NonNull String servicePackageName, @NonNull PersistableBundle params, @NonNull IExecuteCallback callback) { Objects.requireNonNull(callingPackageName); Objects.requireNonNull(servicePackageName); Objects.requireNonNull(params); Objects.requireNonNull(callback); final int uid = Binder.getCallingUid(); enforceCallingPackageBelongsToUid(callingPackageName, uid); AppRequestFlow flow = mInjector.getAppRequestFlow( callingPackageName, servicePackageName, params, callback, mContext); flow.run(); } @Override public void requestSurfacePackage( @NonNull String slotResultToken, @NonNull IBinder hostToken, int displayId, int width, int height, @NonNull IRequestSurfacePackageCallback callback) { Objects.requireNonNull(slotResultToken); Objects.requireNonNull(hostToken); Objects.requireNonNull(callback); if (width <= 0) { throw new IllegalArgumentException("width must be > 0"); } if (height <= 0) { throw new IllegalArgumentException("height must be > 0"); } if (displayId < 0) { throw new IllegalArgumentException("displayId must be >= 0"); } RenderFlow flow = mInjector.getRenderFlow( slotResultToken, hostToken, displayId, width, height, callback, mContext); flow.run(); } private void enforceCallingPackageBelongsToUid(@NonNull String packageName, int uid) { int packageUid; PackageManager pm = mContext.getPackageManager(); try { packageUid = pm.getPackageUid(packageName, 0); } catch (PackageManager.NameNotFoundException e) { throw new SecurityException(packageName + " not found"); } if (packageUid != uid) { throw new SecurityException(packageName + " does not belong to uid " + uid); } //TODO(b/242792629): Handle requests from the SDK sandbox. } }