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.server.art;
18 
19 import static com.android.server.art.OutputArtifacts.PermissionSettings;
20 import static com.android.server.art.OutputArtifacts.PermissionSettings.SeContext;
21 import static com.android.server.art.ProfilePath.PrebuiltProfilePath;
22 import static com.android.server.art.ProfilePath.PrimaryCurProfilePath;
23 import static com.android.server.art.ProfilePath.PrimaryRefProfilePath;
24 import static com.android.server.art.ProfilePath.SecondaryCurProfilePath;
25 import static com.android.server.art.ProfilePath.SecondaryRefProfilePath;
26 import static com.android.server.art.ProfilePath.TmpProfilePath;
27 import static com.android.server.art.ProfilePath.WritableProfilePath;
28 
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 
32 /** @hide */
33 public final class AidlUtils {
AidlUtils()34     private AidlUtils() {}
35 
36     @NonNull
buildArtifactsPath(@onNull String dexPath, @NonNull String isa, boolean isInDalvikCache, boolean isPreReboot)37     private static ArtifactsPath buildArtifactsPath(@NonNull String dexPath, @NonNull String isa,
38             boolean isInDalvikCache, boolean isPreReboot) {
39         var artifactsPath = new ArtifactsPath();
40         artifactsPath.dexPath = dexPath;
41         artifactsPath.isa = isa;
42         artifactsPath.isInDalvikCache = isInDalvikCache;
43         artifactsPath.isPreReboot = isPreReboot;
44         return artifactsPath;
45     }
46 
47     @NonNull
buildArtifactsPathAsInput( @onNull String dexPath, @NonNull String isa, boolean isInDalvikCache)48     public static ArtifactsPath buildArtifactsPathAsInput(
49             @NonNull String dexPath, @NonNull String isa, boolean isInDalvikCache) {
50         // The callers expect artifacts to be used as inputs, so we should always pick the
51         // non-Pre-reboot ones.
52         return buildArtifactsPath(dexPath, isa, isInDalvikCache, false /* isPreReboot */);
53     }
54 
55     @NonNull
buildArtifactsPathAsInputPreReboot( @onNull String dexPath, @NonNull String isa, boolean isInDalvikCache)56     public static ArtifactsPath buildArtifactsPathAsInputPreReboot(
57             @NonNull String dexPath, @NonNull String isa, boolean isInDalvikCache) {
58         // Normally this should not be called, unless the caller really means to use Pre-reboot
59         // artifacts as inputs.
60         return buildArtifactsPath(dexPath, isa, isInDalvikCache, true /* isPreReboot */);
61     }
62 
63     @NonNull
buildFsPermission( int uid, int gid, boolean isOtherReadable, boolean isOtherExecutable)64     public static FsPermission buildFsPermission(
65             int uid, int gid, boolean isOtherReadable, boolean isOtherExecutable) {
66         var fsPermission = new FsPermission();
67         fsPermission.uid = uid;
68         fsPermission.gid = gid;
69         fsPermission.isOtherReadable = isOtherReadable;
70         fsPermission.isOtherExecutable = isOtherExecutable;
71         return fsPermission;
72     }
73 
74     @NonNull
buildFsPermission(int uid, int gid, boolean isOtherReadable)75     public static FsPermission buildFsPermission(int uid, int gid, boolean isOtherReadable) {
76         return buildFsPermission(uid, gid, isOtherReadable, false /* isOtherExecutable */);
77     }
78 
79     @NonNull
buildDexMetadataPath(@onNull String dexPath)80     public static DexMetadataPath buildDexMetadataPath(@NonNull String dexPath) {
81         var dexMetadataPath = new DexMetadataPath();
82         dexMetadataPath.dexPath = dexPath;
83         return dexMetadataPath;
84     }
85 
86     @NonNull
buildPermissionSettings(@onNull FsPermission dirFsPermission, @NonNull FsPermission fileFsPermission, @Nullable SeContext seContext)87     public static PermissionSettings buildPermissionSettings(@NonNull FsPermission dirFsPermission,
88             @NonNull FsPermission fileFsPermission, @Nullable SeContext seContext) {
89         var permissionSettings = new PermissionSettings();
90         permissionSettings.dirFsPermission = dirFsPermission;
91         permissionSettings.fileFsPermission = fileFsPermission;
92         permissionSettings.seContext = seContext;
93         return permissionSettings;
94     }
95 
96     @NonNull
buildOutputArtifacts(@onNull String dexPath, @NonNull String isa, boolean isInDalvikCache, @NonNull PermissionSettings permissionSettings, boolean isPreReboot)97     public static OutputArtifacts buildOutputArtifacts(@NonNull String dexPath, @NonNull String isa,
98             boolean isInDalvikCache, @NonNull PermissionSettings permissionSettings,
99             boolean isPreReboot) {
100         var outputArtifacts = new OutputArtifacts();
101         outputArtifacts.artifactsPath =
102                 buildArtifactsPath(dexPath, isa, isInDalvikCache, isPreReboot);
103         outputArtifacts.permissionSettings = permissionSettings;
104         return outputArtifacts;
105     }
106 
107     @NonNull
buildPrimaryRefProfilePath( @onNull String packageName, @NonNull String profileName, boolean isPreReboot)108     private static PrimaryRefProfilePath buildPrimaryRefProfilePath(
109             @NonNull String packageName, @NonNull String profileName, boolean isPreReboot) {
110         var primaryRefProfilePath = new PrimaryRefProfilePath();
111         primaryRefProfilePath.packageName = packageName;
112         primaryRefProfilePath.profileName = profileName;
113         primaryRefProfilePath.isPreReboot = isPreReboot;
114         return primaryRefProfilePath;
115     }
116 
117     @NonNull
buildSecondaryRefProfilePath( @onNull String dexPath, boolean isPreReboot)118     private static SecondaryRefProfilePath buildSecondaryRefProfilePath(
119             @NonNull String dexPath, boolean isPreReboot) {
120         var secondaryRefProfilePath = new SecondaryRefProfilePath();
121         secondaryRefProfilePath.dexPath = dexPath;
122         secondaryRefProfilePath.isPreReboot = isPreReboot;
123         return secondaryRefProfilePath;
124     }
125 
126     @NonNull
buildProfilePathForPrimaryRefAsInput( @onNull String packageName, @NonNull String profileName)127     public static ProfilePath buildProfilePathForPrimaryRefAsInput(
128             @NonNull String packageName, @NonNull String profileName) {
129         // The callers expect a profile to be used as an input, so we should always pick the
130         // non-Pre-reboot one.
131         return ProfilePath.primaryRefProfilePath(
132                 buildPrimaryRefProfilePath(packageName, profileName, false /* isPreReboot */));
133     }
134 
135     @NonNull
buildProfilePathForPrebuilt(@onNull String dexPath)136     public static ProfilePath buildProfilePathForPrebuilt(@NonNull String dexPath) {
137         var prebuiltProfilePath = new PrebuiltProfilePath();
138         prebuiltProfilePath.dexPath = dexPath;
139         return ProfilePath.prebuiltProfilePath(prebuiltProfilePath);
140     }
141 
142     @NonNull
buildProfilePathForDm(@onNull String dexPath)143     public static ProfilePath buildProfilePathForDm(@NonNull String dexPath) {
144         return ProfilePath.dexMetadataPath(buildDexMetadataPath(dexPath));
145     }
146 
147     @NonNull
buildProfilePathForPrimaryCur( int userId, @NonNull String packageName, @NonNull String profileName)148     public static ProfilePath buildProfilePathForPrimaryCur(
149             int userId, @NonNull String packageName, @NonNull String profileName) {
150         var primaryCurProfilePath = new PrimaryCurProfilePath();
151         primaryCurProfilePath.userId = userId;
152         primaryCurProfilePath.packageName = packageName;
153         primaryCurProfilePath.profileName = profileName;
154         return ProfilePath.primaryCurProfilePath(primaryCurProfilePath);
155     }
156 
157     @NonNull
buildProfilePathForSecondaryRefAsInput(@onNull String dexPath)158     public static ProfilePath buildProfilePathForSecondaryRefAsInput(@NonNull String dexPath) {
159         // The callers expect a profile to be used as an input, so we should always pick the
160         // non-Pre-reboot one.
161         return ProfilePath.secondaryRefProfilePath(
162                 buildSecondaryRefProfilePath(dexPath, false /* isPreReboot */));
163     }
164 
165     @NonNull
buildProfilePathForSecondaryCur(@onNull String dexPath)166     public static ProfilePath buildProfilePathForSecondaryCur(@NonNull String dexPath) {
167         var secondaryCurProfilePath = new SecondaryCurProfilePath();
168         secondaryCurProfilePath.dexPath = dexPath;
169         return ProfilePath.secondaryCurProfilePath(secondaryCurProfilePath);
170     }
171 
172     @NonNull
buildOutputProfile( @onNull WritableProfilePath finalPath, int uid, int gid, boolean isPublic)173     private static OutputProfile buildOutputProfile(
174             @NonNull WritableProfilePath finalPath, int uid, int gid, boolean isPublic) {
175         var outputProfile = new OutputProfile();
176         outputProfile.profilePath = new TmpProfilePath();
177         outputProfile.profilePath.finalPath = finalPath;
178         outputProfile.profilePath.id = ""; // Will be filled by artd.
179         outputProfile.profilePath.tmpPath = ""; // Will be filled by artd.
180         outputProfile.fsPermission = buildFsPermission(uid, gid, isPublic);
181         return outputProfile;
182     }
183 
184     @NonNull
buildOutputProfileForPrimary(@onNull String packageName, @NonNull String profileName, int uid, int gid, boolean isPublic, boolean isPreReboot)185     public static OutputProfile buildOutputProfileForPrimary(@NonNull String packageName,
186             @NonNull String profileName, int uid, int gid, boolean isPublic, boolean isPreReboot) {
187         return buildOutputProfile(WritableProfilePath.forPrimary(buildPrimaryRefProfilePath(
188                                           packageName, profileName, isPreReboot)),
189                 uid, gid, isPublic);
190     }
191 
192     @NonNull
buildOutputProfileForSecondary( @onNull String dexPath, int uid, int gid, boolean isPublic, boolean isPreReboot)193     public static OutputProfile buildOutputProfileForSecondary(
194             @NonNull String dexPath, int uid, int gid, boolean isPublic, boolean isPreReboot) {
195         return buildOutputProfile(WritableProfilePath.forSecondary(
196                                           buildSecondaryRefProfilePath(dexPath, isPreReboot)),
197                 uid, gid, isPublic);
198     }
199 
200     @NonNull
buildSeContext(@onNull String seInfo, int uid)201     public static SeContext buildSeContext(@NonNull String seInfo, int uid) {
202         var seContext = new SeContext();
203         seContext.seInfo = seInfo;
204         seContext.uid = uid;
205         return seContext;
206     }
207 
208     @NonNull
buildRuntimeArtifactsPath( @onNull String packageName, @NonNull String dexPath, @NonNull String isa)209     public static RuntimeArtifactsPath buildRuntimeArtifactsPath(
210             @NonNull String packageName, @NonNull String dexPath, @NonNull String isa) {
211         var runtimeArtifactsPath = new RuntimeArtifactsPath();
212         runtimeArtifactsPath.packageName = packageName;
213         runtimeArtifactsPath.dexPath = dexPath;
214         runtimeArtifactsPath.isa = isa;
215         return runtimeArtifactsPath;
216     }
217 
218     @NonNull
toWritableProfilePath(@onNull ProfilePath profile)219     public static WritableProfilePath toWritableProfilePath(@NonNull ProfilePath profile) {
220         switch (profile.getTag()) {
221             case ProfilePath.primaryRefProfilePath:
222                 return WritableProfilePath.forPrimary(profile.getPrimaryRefProfilePath());
223             case ProfilePath.secondaryRefProfilePath:
224                 return WritableProfilePath.forSecondary(profile.getSecondaryRefProfilePath());
225             default:
226                 throw new IllegalStateException("ProfilePath tag " + profile.getTag()
227                         + " does not represent a writable type");
228         }
229     }
230 
231     @NonNull
toString(@onNull PrimaryRefProfilePath profile)232     public static String toString(@NonNull PrimaryRefProfilePath profile) {
233         return String.format(
234                 "PrimaryRefProfilePath[packageName = %s, profileName = %s, isPreReboot = %b]",
235                 profile.packageName, profile.profileName, profile.isPreReboot);
236     }
237 
238     @NonNull
toString(@onNull SecondaryRefProfilePath profile)239     public static String toString(@NonNull SecondaryRefProfilePath profile) {
240         return String.format("SecondaryRefProfilePath[dexPath = %s, isPreReboot = %b]",
241                 profile.dexPath, profile.isPreReboot);
242     }
243 
244     @NonNull
toString(@onNull PrebuiltProfilePath profile)245     public static String toString(@NonNull PrebuiltProfilePath profile) {
246         return String.format("PrebuiltProfilePath[dexPath = %s]", profile.dexPath);
247     }
248 
249     @NonNull
toString(@onNull DexMetadataPath profile)250     public static String toString(@NonNull DexMetadataPath profile) {
251         return String.format("DexMetadataPath[dexPath = %s]", profile.dexPath);
252     }
253 
254     @NonNull
toString(@onNull WritableProfilePath profile)255     public static String toString(@NonNull WritableProfilePath profile) {
256         switch (profile.getTag()) {
257             case WritableProfilePath.forPrimary:
258                 return toString(profile.getForPrimary());
259             case WritableProfilePath.forSecondary:
260                 return toString(profile.getForSecondary());
261             default:
262                 throw new IllegalStateException(
263                         "Unknown WritableProfilePath tag " + profile.getTag());
264         }
265     }
266 
267     @NonNull
toString(@onNull ProfilePath profile)268     public static String toString(@NonNull ProfilePath profile) {
269         switch (profile.getTag()) {
270             case ProfilePath.primaryRefProfilePath:
271                 return toString(profile.getPrimaryRefProfilePath());
272             case ProfilePath.secondaryRefProfilePath:
273                 return toString(profile.getSecondaryRefProfilePath());
274             case ProfilePath.prebuiltProfilePath:
275                 return toString(profile.getPrebuiltProfilePath());
276             case ProfilePath.dexMetadataPath:
277                 return toString(profile.getDexMetadataPath());
278             default:
279                 throw new UnsupportedOperationException(
280                         "Only a subset of profile paths are supported to be converted to string, "
281                         + "got " + profile.getTag());
282         }
283     }
284 }
285