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 android.app.sdksandbox; 18 19 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.pm.SharedLibraryInfo; 23 import android.os.IBinder; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import java.util.Objects; 28 29 /** 30 * Represents an SDK loaded in the sandbox process. 31 * 32 * <p>Returned in response to {@link SdkSandboxManager#loadSdk}, on success. An application can 33 * obtain it by calling {@link SdkSandboxManager#loadSdk}. It should use this object to obtain an 34 * interface to the SDK through {@link #getInterface()}. 35 * 36 * <p>The SDK should create it when {@link SandboxedSdkProvider#onLoadSdk} is called, and drop all 37 * references to it when {@link SandboxedSdkProvider#beforeUnloadSdk()} is called. Additionally, the 38 * SDK should fail calls made to the {@code IBinder} returned from {@link #getInterface()} after 39 * {@link SandboxedSdkProvider#beforeUnloadSdk()} has been called. 40 */ 41 public final class SandboxedSdk implements Parcelable { 42 public static final @NonNull Creator<SandboxedSdk> CREATOR = 43 new Creator<SandboxedSdk>() { 44 @Override 45 public SandboxedSdk createFromParcel(Parcel in) { 46 return new SandboxedSdk(in); 47 } 48 49 @Override 50 public SandboxedSdk[] newArray(int size) { 51 return new SandboxedSdk[size]; 52 } 53 }; 54 private IBinder mInterface; 55 private @Nullable SharedLibraryInfo mSharedLibraryInfo; 56 57 /** 58 * Creates a {@link SandboxedSdk} object. 59 * 60 * @param sdkInterface The SDK's interface. This will be the entrypoint into the sandboxed SDK 61 * for the application. The SDK should keep this valid until it's loaded in the sandbox, and 62 * start failing calls to this interface once it has been unloaded. 63 * <p>This interface can later be retrieved using {@link #getInterface()}. 64 */ SandboxedSdk(@onNull IBinder sdkInterface)65 public SandboxedSdk(@NonNull IBinder sdkInterface) { 66 mInterface = sdkInterface; 67 } 68 SandboxedSdk(@onNull Parcel in)69 private SandboxedSdk(@NonNull Parcel in) { 70 mInterface = in.readStrongBinder(); 71 if (in.readInt() != 0) { 72 mSharedLibraryInfo = SharedLibraryInfo.CREATOR.createFromParcel(in); 73 } 74 } 75 76 /** 77 * Attaches information about the SDK like name, version and others which may be useful to 78 * identify the SDK. 79 * 80 * <p>This is used by the system service to attach the library info to the {@link SandboxedSdk} 81 * object return by the SDK after it has been loaded 82 * 83 * @param sharedLibraryInfo The SDK's library info. This contains the name, version and other 84 * details about the sdk. 85 * @throws IllegalStateException if a base sharedLibraryInfo has already been set. 86 * @hide 87 */ attachSharedLibraryInfo(@onNull SharedLibraryInfo sharedLibraryInfo)88 public void attachSharedLibraryInfo(@NonNull SharedLibraryInfo sharedLibraryInfo) { 89 if (mSharedLibraryInfo != null) { 90 throw new IllegalStateException("SharedLibraryInfo already set"); 91 } 92 Objects.requireNonNull(sharedLibraryInfo, "SharedLibraryInfo cannot be null"); 93 mSharedLibraryInfo = sharedLibraryInfo; 94 } 95 96 /** 97 * Returns the interface to the SDK that was loaded in response to {@link 98 * SdkSandboxManager#loadSdk}. A {@code null} interface is returned if the Binder has since 99 * become unavailable, in response to the SDK being unloaded. 100 */ getInterface()101 public @Nullable IBinder getInterface() { 102 // This will be null if the remote SDK has been unloaded and the IBinder originally provided 103 // is now a dead object. 104 return mInterface; 105 } 106 107 /** 108 * Returns the {@link SharedLibraryInfo} for the SDK. 109 * 110 * @throws IllegalStateException if the system service has not yet attached {@link 111 * SharedLibraryInfo} to the {@link SandboxedSdk} object sent by the SDK. 112 */ getSharedLibraryInfo()113 public @NonNull SharedLibraryInfo getSharedLibraryInfo() { 114 if (mSharedLibraryInfo == null) { 115 throw new IllegalStateException( 116 "SharedLibraryInfo has not been set. This is populated by our system service " 117 + "once the SandboxedSdk is sent back from as a response to " 118 + "android.app.sdksandbox.SandboxedSdkProvider$onLoadSdk. Please use " 119 + "android.app.sdksandbox.SdkSandboxManager#getSandboxedSdks or " 120 + "android.app.sdksandbox.SdkSandboxController#getSandboxedSdks to " 121 + "get the correctly populated SandboxedSdks."); 122 } 123 return mSharedLibraryInfo; 124 } 125 126 /** {@inheritDoc} */ 127 @Override describeContents()128 public int describeContents() { 129 return 0; 130 } 131 132 /** {@inheritDoc} */ 133 @Override writeToParcel(@onNull Parcel dest, int flags)134 public void writeToParcel(@NonNull Parcel dest, int flags) { 135 dest.writeStrongBinder(mInterface); 136 if (mSharedLibraryInfo != null) { 137 dest.writeInt(1); 138 mSharedLibraryInfo.writeToParcel(dest, 0); 139 } else { 140 dest.writeInt(0); 141 } 142 } 143 } 144