/* * 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 android.app.sdksandbox; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.SharedLibraryInfo; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** * Represents an SDK loaded in the sandbox process. * *
Returned in response to {@link SdkSandboxManager#loadSdk}, on success. An application can * obtain it by calling {@link SdkSandboxManager#loadSdk}. It should use this object to obtain an * interface to the SDK through {@link #getInterface()}. * *
The SDK should create it when {@link SandboxedSdkProvider#onLoadSdk} is called, and drop all
* references to it when {@link SandboxedSdkProvider#beforeUnloadSdk()} is called. Additionally, the
* SDK should fail calls made to the {@code IBinder} returned from {@link #getInterface()} after
* {@link SandboxedSdkProvider#beforeUnloadSdk()} has been called.
*/
public final class SandboxedSdk implements Parcelable {
public static final @NonNull Creator This interface can later be retrieved using {@link #getInterface()}.
*/
public SandboxedSdk(@NonNull IBinder sdkInterface) {
mInterface = sdkInterface;
}
private SandboxedSdk(@NonNull Parcel in) {
mInterface = in.readStrongBinder();
if (in.readInt() != 0) {
mSharedLibraryInfo = SharedLibraryInfo.CREATOR.createFromParcel(in);
}
}
/**
* Attaches information about the SDK like name, version and others which may be useful to
* identify the SDK.
*
* This is used by the system service to attach the library info to the {@link SandboxedSdk}
* object return by the SDK after it has been loaded
*
* @param sharedLibraryInfo The SDK's library info. This contains the name, version and other
* details about the sdk.
* @throws IllegalStateException if a base sharedLibraryInfo has already been set.
* @hide
*/
public void attachSharedLibraryInfo(@NonNull SharedLibraryInfo sharedLibraryInfo) {
if (mSharedLibraryInfo != null) {
throw new IllegalStateException("SharedLibraryInfo already set");
}
Objects.requireNonNull(sharedLibraryInfo, "SharedLibraryInfo cannot be null");
mSharedLibraryInfo = sharedLibraryInfo;
}
/**
* Returns the interface to the SDK that was loaded in response to {@link
* SdkSandboxManager#loadSdk}. A {@code null} interface is returned if the Binder has since
* become unavailable, in response to the SDK being unloaded.
*/
public @Nullable IBinder getInterface() {
// This will be null if the remote SDK has been unloaded and the IBinder originally provided
// is now a dead object.
return mInterface;
}
/**
* Returns the {@link SharedLibraryInfo} for the SDK.
*
* @throws IllegalStateException if the system service has not yet attached {@link
* SharedLibraryInfo} to the {@link SandboxedSdk} object sent by the SDK.
*/
public @NonNull SharedLibraryInfo getSharedLibraryInfo() {
if (mSharedLibraryInfo == null) {
throw new IllegalStateException(
"SharedLibraryInfo has not been set. This is populated by our system service "
+ "once the SandboxedSdk is sent back from as a response to "
+ "android.app.sdksandbox.SandboxedSdkProvider$onLoadSdk. Please use "
+ "android.app.sdksandbox.SdkSandboxManager#getSandboxedSdks or "
+ "android.app.sdksandbox.SdkSandboxController#getSandboxedSdks to "
+ "get the correctly populated SandboxedSdks.");
}
return mSharedLibraryInfo;
}
/** {@inheritDoc} */
@Override
public int describeContents() {
return 0;
}
/** {@inheritDoc} */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStrongBinder(mInterface);
if (mSharedLibraryInfo != null) {
dest.writeInt(1);
mSharedLibraryInfo.writeToParcel(dest, 0);
} else {
dest.writeInt(0);
}
}
}