• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import static android.app.sdksandbox.SdkSandboxSystemServiceRegistry.ServiceMutator;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.content.Context;
24 import android.content.ContextWrapper;
25 import android.content.pm.ApplicationInfo;
26 import android.content.res.AssetManager;
27 import android.content.res.Resources;
28 
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.io.File;
32 
33 /**
34  * Refers to the context of the SDK loaded in the SDK sandbox process.
35  *
36  * <p>It is a wrapper of the client application (which loading SDK to the sandbox) context, to
37  * represent the context of the SDK loaded by that application.
38  *
39  * <p>An instance of the {@link SandboxedSdkContext} will be created by the SDK sandbox, and then
40  * attached to the {@link SandboxedSdkProvider} after the SDK is loaded.
41  *
42  * <p>Each sdk will get their own private storage directories and the file storage API on this
43  * object will utilize those areas.
44  *
45  * @hide
46  */
47 public final class SandboxedSdkContext extends ContextWrapper {
48 
49     private final Resources mResources;
50     private final AssetManager mAssets;
51     private final String mClientPackageName;
52     private final String mSdkName;
53     private final ApplicationInfo mSdkProviderInfo;
54     @Nullable private final File mCeDataDir;
55     @Nullable private final File mDeDataDir;
56     private final SdkSandboxSystemServiceRegistry mSdkSandboxSystemServiceRegistry;
57     private final ClassLoader mClassLoader;
58     private final boolean mCustomizedSdkContextEnabled;
59 
SandboxedSdkContext( @onNull Context baseContext, @NonNull ClassLoader classLoader, @NonNull String clientPackageName, @NonNull ApplicationInfo info, @NonNull String sdkName, @Nullable String sdkCeDataDir, @Nullable String sdkDeDataDir, boolean isCustomizedSdkContextEnabled)60     public SandboxedSdkContext(
61             @NonNull Context baseContext,
62             @NonNull ClassLoader classLoader,
63             @NonNull String clientPackageName,
64             @NonNull ApplicationInfo info,
65             @NonNull String sdkName,
66             @Nullable String sdkCeDataDir,
67             @Nullable String sdkDeDataDir,
68             boolean isCustomizedSdkContextEnabled) {
69         this(
70                 baseContext,
71                 classLoader,
72                 clientPackageName,
73                 info,
74                 sdkName,
75                 sdkCeDataDir,
76                 sdkDeDataDir,
77                 isCustomizedSdkContextEnabled,
78                 SdkSandboxSystemServiceRegistry.getInstance());
79     }
80 
81     @VisibleForTesting
SandboxedSdkContext( @onNull Context baseContext, @NonNull ClassLoader classLoader, @NonNull String clientPackageName, @NonNull ApplicationInfo info, @NonNull String sdkName, @Nullable String sdkCeDataDir, @Nullable String sdkDeDataDir, boolean isCustomizedSdkContextEnabled, SdkSandboxSystemServiceRegistry sdkSandboxSystemServiceRegistry)82     public SandboxedSdkContext(
83             @NonNull Context baseContext,
84             @NonNull ClassLoader classLoader,
85             @NonNull String clientPackageName,
86             @NonNull ApplicationInfo info,
87             @NonNull String sdkName,
88             @Nullable String sdkCeDataDir,
89             @Nullable String sdkDeDataDir,
90             boolean isCustomizedSdkContextEnabled,
91             SdkSandboxSystemServiceRegistry sdkSandboxSystemServiceRegistry) {
92         super(baseContext);
93         mClientPackageName = clientPackageName;
94         mSdkName = sdkName;
95         mSdkProviderInfo = info;
96         Resources resources = null;
97         try {
98             resources = baseContext.getPackageManager().getResourcesForApplication(info);
99         } catch (Exception ignored) {
100         }
101 
102         if (resources != null) {
103             mResources = resources;
104             mAssets = resources.getAssets();
105         } else {
106             mResources = null;
107             mAssets = null;
108         }
109 
110         mCeDataDir = (sdkCeDataDir != null) ? new File(sdkCeDataDir) : null;
111         mDeDataDir = (sdkDeDataDir != null) ? new File(sdkDeDataDir) : null;
112 
113         mSdkSandboxSystemServiceRegistry = sdkSandboxSystemServiceRegistry;
114         mClassLoader = classLoader;
115         mCustomizedSdkContextEnabled = isCustomizedSdkContextEnabled;
116     }
117 
118     /**
119      * Return a new Context object for the current SandboxedSdkContext but whose storage APIs are
120      * backed by sdk specific credential-protected storage.
121      *
122      * @see Context#isCredentialProtectedStorage()
123      */
124     @Override
125     @NonNull
createCredentialProtectedStorageContext()126     public Context createCredentialProtectedStorageContext() {
127         Context newBaseContext = getBaseContext().createCredentialProtectedStorageContext();
128         return new SandboxedSdkContext(
129                 newBaseContext,
130                 mClassLoader,
131                 mClientPackageName,
132                 mSdkProviderInfo,
133                 mSdkName,
134                 (mCeDataDir != null) ? mCeDataDir.toString() : null,
135                 (mDeDataDir != null) ? mDeDataDir.toString() : null,
136                 mCustomizedSdkContextEnabled);
137     }
138 
139     /**
140      * Return a new Context object for the current SandboxedSdkContext but whose storage
141      * APIs are backed by sdk specific device-protected storage.
142      *
143      * @see Context#isDeviceProtectedStorage()
144      */
145     @Override
146     @NonNull
createDeviceProtectedStorageContext()147     public Context createDeviceProtectedStorageContext() {
148         Context newBaseContext = getBaseContext().createDeviceProtectedStorageContext();
149         return new SandboxedSdkContext(
150                 newBaseContext,
151                 mClassLoader,
152                 mClientPackageName,
153                 mSdkProviderInfo,
154                 mSdkName,
155                 (mCeDataDir != null) ? mCeDataDir.toString() : null,
156                 (mDeDataDir != null) ? mDeDataDir.toString() : null,
157                 mCustomizedSdkContextEnabled);
158     }
159 
160     /**
161      * Returns the SDK name defined in the SDK's manifest.
162      */
163     @NonNull
getSdkName()164     public String getSdkName() {
165         return mSdkName;
166     }
167 
168     /**
169      * Returns the SDK package name defined in the SDK's manifest.
170      *
171      * @hide
172      */
173     @NonNull
getSdkPackageName()174     public String getSdkPackageName() {
175         return mSdkProviderInfo.packageName;
176     }
177 
178     /**
179      * Returns the package name of the client application corresponding to the sandbox.
180      *
181      */
182     @NonNull
getClientPackageName()183     public String getClientPackageName() {
184         return mClientPackageName;
185     }
186 
187     /** Returns the resources defined in the SDK's .apk file. */
188     @Override
189     @Nullable
getResources()190     public Resources getResources() {
191         if (mCustomizedSdkContextEnabled) {
192             return getBaseContext().getResources();
193         }
194         return mResources;
195     }
196 
197     /** Returns the assets defined in the SDK's .apk file. */
198     @Override
199     @Nullable
getAssets()200     public AssetManager getAssets() {
201         if (mCustomizedSdkContextEnabled) {
202             return getBaseContext().getAssets();
203         }
204         return mAssets;
205     }
206 
207     /** Returns sdk-specific internal storage directory. */
208     @Override
209     @Nullable
getDataDir()210     public File getDataDir() {
211         if (mCustomizedSdkContextEnabled) {
212             return getBaseContext().getDataDir();
213         }
214 
215         File res = null;
216         if (isCredentialProtectedStorage()) {
217             res = mCeDataDir;
218         } else if (isDeviceProtectedStorage()) {
219             res = mDeDataDir;
220         }
221         if (res == null) {
222             throw new RuntimeException("No data directory found for sdk: " + getSdkName());
223         }
224         return res;
225     }
226 
227     @Override
228     @Nullable
getSystemService(String name)229     public Object getSystemService(String name) {
230         if (name == null) {
231             return null;
232         }
233         Object service = getBaseContext().getSystemService(name);
234         ServiceMutator serviceMutator = mSdkSandboxSystemServiceRegistry.getServiceMutator(name);
235         if (serviceMutator != null) {
236             service = serviceMutator.setContext(service, this);
237         }
238         return service;
239     }
240 
241     @Override
getClassLoader()242     public ClassLoader getClassLoader() {
243         if (mCustomizedSdkContextEnabled) {
244             return getBaseContext().getClassLoader();
245         }
246         return mClassLoader;
247     }
248 }
249