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.libraries.plugin.internal;
18 
19 import android.os.Parcel;
20 import android.os.ParcelFileDescriptor;
21 import android.os.Parcelable;
22 
23 import com.google.auto.value.AutoValue;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.Lists;
26 
27 import java.io.Closeable;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.util.ArrayList;
31 import java.util.List;
32 
33 /** Native and non-native file descriptor and corresponding checksum. */
34 @AutoValue
35 public abstract class PluginCode implements Parcelable, Closeable {
36     /**
37      * Native file descriptor. This may point to the same file as nonNativeFd(), but we need
38      * separate descriptors for each, since file descriptors cannot be created in the sandbox, and
39      * the passed in file descriptor cannot be rewinded.
40      */
nativeFd()41     public abstract ParcelFileDescriptor nativeFd();
42 
43     /**
44      * Non-native file descriptor. This may point to the same file as nativeFd(), but we need
45      * separate descriptors for each, since file descriptors cannot be created in the sandbox, and
46      * the passed in file descriptor cannot be rewinded.
47      */
nonNativeFd()48     public abstract ParcelFileDescriptor nonNativeFd();
49 
50     /** Checksum for version checking and caching */
checksum()51     public abstract String checksum();
52 
53     @Override
describeContents()54     public final int describeContents() {
55         return Parcelable.CONTENTS_FILE_DESCRIPTOR;
56     }
57 
58     @Override
writeToParcel(Parcel dest, int flags)59     public final void writeToParcel(Parcel dest, int flags) {
60         nativeFd().writeToParcel(dest, flags);
61         nonNativeFd().writeToParcel(dest, flags);
62         dest.writeString(checksum());
63     }
64 
65     @Override
close()66     public void close() throws IOException {
67         nativeFd().close();
68         nonNativeFd().close();
69     }
70 
71     public static final Creator<PluginCode> CREATOR =
72             new Creator<PluginCode>() {
73                 @Override
74                 public PluginCode createFromParcel(Parcel source) {
75                     Builder builder = builder();
76                     builder.setNativeFd(ParcelFileDescriptor.CREATOR.createFromParcel(source));
77                     builder.setNonNativeFd(ParcelFileDescriptor.CREATOR.createFromParcel(source));
78                     builder.setChecksum(source.readString());
79                     return builder.build();
80                 }
81 
82                 @Override
83                 public PluginCode[] newArray(int size) {
84                     return new PluginCode[size];
85                 }
86             };
87 
88     /** Instantiate a default builder of {@link PluginCode}. */
builder()89     public static Builder builder() {
90         return new AutoValue_PluginCode.Builder();
91     }
92 
93     /** Creates a builder from this {@link PluginCode}. */
toBuilder()94     public abstract Builder toBuilder();
95 
96     /** Builder to {@link PluginCode}. */
97     @AutoValue.Builder
98     public abstract static class Builder {
99         /** Sets nativeFd. */
setNativeFd(ParcelFileDescriptor nativeFd)100         public abstract Builder setNativeFd(ParcelFileDescriptor nativeFd);
101 
102         /** Sets nonNativeFd. */
setNonNativeFd(ParcelFileDescriptor nonNativeFd)103         public abstract Builder setNonNativeFd(ParcelFileDescriptor nonNativeFd);
104 
105         /** Sets checkSum. */
setChecksum(String checksum)106         public abstract Builder setChecksum(String checksum);
107 
108         /** Builds {@link PluginCode}. */
build()109         public abstract PluginCode build();
110     }
111 
112     /** Duplicates a list of {@link PluginCode}. */
dup(Iterable<PluginCode> source)113     public static CloseableList<PluginCode> dup(Iterable<PluginCode> source) throws IOException {
114         List<PluginCode> duplicatedList = new ArrayList<>();
115         for (PluginCode pluginCode : source) {
116             duplicatedList.add(
117                     PluginCode.builder()
118                             .setNativeFd(pluginCode.nativeFd().dup())
119                             .setNonNativeFd(pluginCode.nonNativeFd().dup())
120                             .setChecksum(pluginCode.checksum())
121                             .build());
122         }
123         return new CloseableList<>(duplicatedList);
124     }
125 
126     /** Creates a list of {@link FileInputStream} from native fds. */
createFileInputStreamListFromNativeFds( ImmutableList<PluginCode> fds)127     public static CloseableList<FileInputStream> createFileInputStreamListFromNativeFds(
128             ImmutableList<PluginCode> fds) {
129         List<FileInputStream> fileInputStreamList =
130                 Lists.transform(fds, fd -> new FileInputStream(fd.nativeFd().getFileDescriptor()));
131         return new CloseableList<>(fileInputStreamList);
132     }
133 
134     /** Creates a list of {@link FileInputStream} from non-native fds. */
createFileInputStreamListFromNonNativeFds( ImmutableList<PluginCode> fds)135     public static CloseableList<FileInputStream> createFileInputStreamListFromNonNativeFds(
136             ImmutableList<PluginCode> fds) {
137         List<FileInputStream> fileInputStreamList =
138                 Lists.transform(
139                         fds, fd -> new FileInputStream(fd.nonNativeFd().getFileDescriptor()));
140         return new CloseableList<>(fileInputStreamList);
141     }
142 }
143