blob: d2de382d9f463e17ee3480cb3f53f398ad84c3cb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
17package android.app;
18
svetoslavganov75986cf2009-05-14 22:28:01 -070019import com.android.internal.policy.PolicyManager;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080020import com.android.internal.util.XmlUtils;
svetoslavganov75986cf2009-05-14 22:28:01 -070021
22import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
25import android.content.ComponentName;
26import android.content.ContentResolver;
27import android.content.Context;
28import android.content.ContextWrapper;
29import android.content.IContentProvider;
30import android.content.Intent;
31import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070032import android.content.IIntentReceiver;
33import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.ReceiverCallNotAllowedException;
35import android.content.ServiceConnection;
36import android.content.SharedPreferences;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.pm.ApplicationInfo;
38import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070039import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.content.pm.IPackageDataObserver;
41import android.content.pm.IPackageDeleteObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.pm.IPackageInstallObserver;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080043import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.content.pm.IPackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070045import android.content.pm.IPackageStatsObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.content.pm.PackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.content.res.AssetManager;
48import android.content.res.Resources;
Vasu Nori74f170f2010-06-01 18:06:18 -070049import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.database.sqlite.SQLiteDatabase;
51import android.database.sqlite.SQLiteDatabase.CursorFactory;
52import android.graphics.Bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import android.graphics.drawable.Drawable;
54import android.hardware.SensorManager;
Bai Taoa58a8752010-07-13 15:32:16 +080055import android.location.CountryDetector;
56import android.location.ICountryDetector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import android.location.ILocationManager;
58import android.location.LocationManager;
59import android.media.AudioManager;
60import android.net.ConnectivityManager;
61import android.net.IConnectivityManager;
Irfan Sheriffc9b68512010-04-08 14:12:33 -070062import android.net.ThrottleManager;
63import android.net.IThrottleManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import android.net.Uri;
65import android.net.wifi.IWifiManager;
66import android.net.wifi.WifiManager;
67import android.os.Binder;
Adam Powellc63806d2010-09-23 16:21:30 -070068import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069import android.os.Bundle;
Dan Egnorf18a01c2009-11-12 11:32:50 -080070import android.os.DropBoxManager;
Oscar Montemayor539d3c42010-01-29 15:27:00 -080071import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.os.FileUtils;
73import android.os.Handler;
74import android.os.IBinder;
75import android.os.IPowerManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070076import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.os.PowerManager;
78import android.os.Process;
svetoslavganov75986cf2009-05-14 22:28:01 -070079import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.ServiceManager;
81import android.os.Vibrator;
82import android.os.FileUtils.FileStatus;
San Mehatb1043402010-02-05 08:26:50 -080083import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.telephony.TelephonyManager;
Dianne Hackborn9f531192010-08-04 17:48:03 -070085import android.content.ClipboardManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.util.AndroidRuntimeException;
87import android.util.Log;
88import android.view.ContextThemeWrapper;
89import android.view.LayoutInflater;
90import android.view.WindowManagerImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070091import android.view.accessibility.AccessibilityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.view.inputmethod.InputMethodManager;
Fred Quintana60307342009-03-24 22:48:12 -070093import android.accounts.AccountManager;
94import android.accounts.IAccountManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080095import android.app.admin.DevicePolicyManager;
Dan Egnorf18a01c2009-11-12 11:32:50 -080096import com.android.internal.os.IDropBoxManagerService;
Dan Egnor95240272009-10-27 18:23:39 -070097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import java.io.File;
99import java.io.FileInputStream;
100import java.io.FileNotFoundException;
101import java.io.FileOutputStream;
102import java.io.IOException;
103import java.io.InputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import java.util.ArrayList;
105import java.util.HashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.List;
107import java.util.Map;
The Android Open Source Project10592532009-03-18 17:39:46 -0700108import java.util.Set;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110class ReceiverRestrictedContext extends ContextWrapper {
111 ReceiverRestrictedContext(Context base) {
112 super(base);
113 }
114
115 @Override
116 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
117 return registerReceiver(receiver, filter, null, null);
118 }
119
120 @Override
121 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
122 String broadcastPermission, Handler scheduler) {
123 throw new ReceiverCallNotAllowedException(
124 "IntentReceiver components are not allowed to register to receive intents");
125 //ex.fillInStackTrace();
126 //Log.e("IntentReceiver", ex.getMessage(), ex);
127 //return mContext.registerReceiver(receiver, filter, broadcastPermission,
128 // scheduler);
129 }
130
131 @Override
132 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
133 throw new ReceiverCallNotAllowedException(
134 "IntentReceiver components are not allowed to bind to services");
135 //ex.fillInStackTrace();
136 //Log.e("IntentReceiver", ex.getMessage(), ex);
137 //return mContext.bindService(service, interfaceName, conn, flags);
138 }
139}
140
141/**
Dianne Hackborn21556372010-02-04 16:34:40 -0800142 * Common implementation of Context API, which provides the base
143 * context object for Activity and other application components.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144 */
Dianne Hackborn21556372010-02-04 16:34:40 -0800145class ContextImpl extends Context {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 private final static String TAG = "ApplicationContext";
Mitsuru Oshima569076c2009-07-02 20:06:08 -0700147 private final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700149 private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
150 new HashMap<String, SharedPreferencesImpl>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700152 /*package*/ LoadedApk mPackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 private Resources mResources;
154 /*package*/ ActivityThread mMainThread;
155 private Context mOuterContext;
156 private IBinder mActivityToken = null;
157 private ApplicationContentResolver mContentResolver;
158 private int mThemeResource = 0;
159 private Resources.Theme mTheme = null;
160 private PackageManager mPackageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 private Context mReceiverRestrictedContext = null;
Romain Guy870e09f2009-07-06 16:35:25 -0700162 private boolean mRestricted;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163
164 private final Object mSync = new Object();
165
166 private File mDatabasesDir;
167 private File mPreferencesDir;
168 private File mFilesDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 private File mCacheDir;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800170 private File mExternalFilesDir;
171 private File mExternalCacheDir;
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 private static final String[] EMPTY_FILE_LIST = {};
174
Brad Fitzpatrick224ba0c2010-11-12 12:22:15 -0800175 /**
176 * Override this class when the system service constructor needs a
177 * ContextImpl. Else, use StaticServiceFetcher below.
178 */
179 /*package*/ static class ServiceFetcher {
180 int mContextCacheIndex = -1;
181
182 /**
183 * Main entrypoint; only override if you don't need caching.
184 */
185 public Object getService(ContextImpl ctx) {
186 ArrayList<Object> cache = ctx.mServiceCache;
187 Object service;
188 synchronized (cache) {
189 if (cache.size() == 0) {
190 // Initialize the cache vector on first access.
191 // At this point sNextPerContextServiceCacheIndex
192 // is the number of potential services that are
193 // cached per-Context.
194 for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
195 cache.add(null);
196 }
197 } else {
198 service = cache.get(mContextCacheIndex);
199 if (service != null) {
200 return service;
201 }
202 }
203 service = createService(ctx);
204 cache.set(mContextCacheIndex, service);
205 return service;
206 }
207 }
208
209 /**
210 * Override this to create a new per-Context instance of the
211 * service. getService() will handle locking and caching.
212 */
213 public Object createService(ContextImpl ctx) {
214 throw new RuntimeException("Not implemented");
215 }
216 }
217
218 /**
219 * Override this class for services to be cached process-wide.
220 */
221 abstract static class StaticServiceFetcher extends ServiceFetcher {
222 private Object mCachedInstance;
223
224 @Override
225 public final Object getService(ContextImpl unused) {
226 synchronized (StaticServiceFetcher.this) {
227 Object service = mCachedInstance;
228 if (service != null) {
229 return service;
230 }
231 return mCachedInstance = createStaticService();
232 }
233 }
234
235 public abstract Object createStaticService();
236 }
237
238 private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =
239 new HashMap<String, ServiceFetcher>();
240
241 private static int sNextPerContextServiceCacheIndex = 0;
242 private static void registerService(String serviceName, ServiceFetcher fetcher) {
243 if (!(fetcher instanceof StaticServiceFetcher)) {
244 fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
245 }
246 SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
247 }
248
249 // This one's defined separately and given a variable name so it
250 // can be re-used by getWallpaperManager(), avoiding a HashMap
251 // lookup.
252 private static ServiceFetcher WALLPAPER_FETCHER = new ServiceFetcher() {
253 public Object createService(ContextImpl ctx) {
254 return new WallpaperManager(ctx.getOuterContext(),
255 ctx.mMainThread.getHandler());
256 }};
257
258 static {
259 registerService(ACCESSIBILITY_SERVICE, new ServiceFetcher() {
260 public Object getService(ContextImpl ctx) {
261 return AccessibilityManager.getInstance(ctx);
262 }});
263
264 registerService(ACCOUNT_SERVICE, new ServiceFetcher() {
265 public Object createService(ContextImpl ctx) {
266 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
267 IAccountManager service = IAccountManager.Stub.asInterface(b);
268 return new AccountManager(ctx, service);
269 }});
270
271 registerService(ACTIVITY_SERVICE, new ServiceFetcher() {
272 public Object createService(ContextImpl ctx) {
273 return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
274 }});
275
276 registerService(ALARM_SERVICE, new StaticServiceFetcher() {
277 public Object createStaticService() {
278 IBinder b = ServiceManager.getService(ALARM_SERVICE);
279 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
280 return new AlarmManager(service);
281 }});
282
283 registerService(AUDIO_SERVICE, new ServiceFetcher() {
284 public Object createService(ContextImpl ctx) {
285 return new AudioManager(ctx);
286 }});
287
288 registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
289 public Object createService(ContextImpl ctx) {
290 return new ClipboardManager(ctx.getOuterContext(),
291 ctx.mMainThread.getHandler());
292 }});
293
294 registerService(CONNECTIVITY_SERVICE, new StaticServiceFetcher() {
295 public Object createStaticService() {
296 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
297 return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));
298 }});
299
300 registerService(COUNTRY_DETECTOR, new StaticServiceFetcher() {
301 public Object createStaticService() {
302 IBinder b = ServiceManager.getService(COUNTRY_DETECTOR);
303 return new CountryDetector(ICountryDetector.Stub.asInterface(b));
304 }});
305
306 registerService(DEVICE_POLICY_SERVICE, new ServiceFetcher() {
307 public Object createService(ContextImpl ctx) {
308 return DevicePolicyManager.create(ctx, ctx.mMainThread.getHandler());
309 }});
310
311 registerService(DOWNLOAD_SERVICE, new ServiceFetcher() {
312 public Object createService(ContextImpl ctx) {
313 return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName());
314 }});
315
316 registerService(DROPBOX_SERVICE, new StaticServiceFetcher() {
317 public Object createStaticService() {
318 return createDropBoxManager();
319 }});
320
321 registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
322 public Object createService(ContextImpl ctx) {
323 return InputMethodManager.getInstance(ctx);
324 }});
325
326 registerService(KEYGUARD_SERVICE, new ServiceFetcher() {
327 public Object getService(ContextImpl ctx) {
328 // TODO: why isn't this caching it? It wasn't
329 // before, so I'm preserving the old behavior and
330 // using getService(), instead of createService()
331 // which would do the caching.
332 return new KeyguardManager();
333 }});
334
335 registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
336 public Object createService(ContextImpl ctx) {
337 return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
338 }});
339
340 registerService(LOCATION_SERVICE, new StaticServiceFetcher() {
341 public Object createStaticService() {
342 IBinder b = ServiceManager.getService(LOCATION_SERVICE);
343 return new LocationManager(ILocationManager.Stub.asInterface(b));
344 }});
345
346 registerService(NOTIFICATION_SERVICE, new ServiceFetcher() {
347 public Object createService(ContextImpl ctx) {
348 final Context outerContext = ctx.getOuterContext();
349 return new NotificationManager(
350 new ContextThemeWrapper(outerContext,
351 outerContext.getApplicationInfo().targetSdkVersion >=
352 Build.VERSION_CODES.HONEYCOMB
353 ? com.android.internal.R.style.Theme_Holo_Dialog
354 : com.android.internal.R.style.Theme_Dialog),
355 ctx.mMainThread.getHandler());
356 }});
357
358 // Note: this was previously cached in a static variable, but
359 // constructed using mMainThread.getHandler(), so converting
360 // it to be a regular Context-cached service...
361 registerService(POWER_SERVICE, new ServiceFetcher() {
362 public Object createService(ContextImpl ctx) {
363 IBinder b = ServiceManager.getService(POWER_SERVICE);
364 IPowerManager service = IPowerManager.Stub.asInterface(b);
365 return new PowerManager(service, ctx.mMainThread.getHandler());
366 }});
367
368 registerService(SEARCH_SERVICE, new ServiceFetcher() {
369 public Object createService(ContextImpl ctx) {
370 return new SearchManager(ctx.getOuterContext(),
371 ctx.mMainThread.getHandler());
372 }});
373
374 registerService(SENSOR_SERVICE, new ServiceFetcher() {
375 public Object createService(ContextImpl ctx) {
376 return new SensorManager(ctx.mMainThread.getHandler().getLooper());
377 }});
378
379 registerService(STATUS_BAR_SERVICE, new ServiceFetcher() {
380 public Object createService(ContextImpl ctx) {
381 return new StatusBarManager(ctx.getOuterContext());
382 }});
383
384 registerService(STORAGE_SERVICE, new ServiceFetcher() {
385 public Object createService(ContextImpl ctx) {
386 try {
387 return new StorageManager(ctx.mMainThread.getHandler().getLooper());
388 } catch (RemoteException rex) {
389 Log.e(TAG, "Failed to create StorageManager", rex);
390 return null;
391 }
392 }});
393
394 registerService(TELEPHONY_SERVICE, new ServiceFetcher() {
395 public Object createService(ContextImpl ctx) {
396 return new TelephonyManager(ctx.getOuterContext());
397 }});
398
399 registerService(THROTTLE_SERVICE, new StaticServiceFetcher() {
400 public Object createStaticService() {
401 IBinder b = ServiceManager.getService(THROTTLE_SERVICE);
402 return new ThrottleManager(IThrottleManager.Stub.asInterface(b));
403 }});
404
405 registerService(UI_MODE_SERVICE, new ServiceFetcher() {
406 public Object createService(ContextImpl ctx) {
407 return new UiModeManager();
408 }});
409
410 registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
411 public Object createService(ContextImpl ctx) {
412 return new Vibrator();
413 }});
414
415 registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
416
417 registerService(WIFI_SERVICE, new ServiceFetcher() {
418 public Object createService(ContextImpl ctx) {
419 IBinder b = ServiceManager.getService(WIFI_SERVICE);
420 IWifiManager service = IWifiManager.Stub.asInterface(b);
421 return new WifiManager(service, ctx.mMainThread.getHandler());
422 }});
423
424 registerService(WINDOW_SERVICE, new ServiceFetcher() {
425 public Object getService(ContextImpl ctx) {
426 return WindowManagerImpl.getDefault();
427 }});
428 }
429
430 // The system service cache for the system services that are
431 // cached per-ContextImpl. Package-scoped to avoid accessor
432 // methods.
433 final ArrayList<Object> mServiceCache = new ArrayList<Object>();
434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 @Override
436 public AssetManager getAssets() {
437 return mResources.getAssets();
438 }
439
440 @Override
441 public Resources getResources() {
442 return mResources;
443 }
444
445 @Override
446 public PackageManager getPackageManager() {
447 if (mPackageManager != null) {
448 return mPackageManager;
449 }
450
451 IPackageManager pm = ActivityThread.getPackageManager();
452 if (pm != null) {
453 // Doesn't matter if we make more than one instance.
454 return (mPackageManager = new ApplicationPackageManager(this, pm));
455 }
456
457 return null;
458 }
459
460 @Override
461 public ContentResolver getContentResolver() {
462 return mContentResolver;
463 }
464
465 @Override
466 public Looper getMainLooper() {
467 return mMainThread.getLooper();
468 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 @Override
471 public Context getApplicationContext() {
Christopher Tateeb9e9ec2010-03-23 17:14:36 -0700472 return (mPackageInfo != null) ?
473 mPackageInfo.getApplication() : mMainThread.getApplication();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 @Override
477 public void setTheme(int resid) {
478 mThemeResource = resid;
479 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 @Override
482 public Resources.Theme getTheme() {
483 if (mTheme == null) {
484 if (mThemeResource == 0) {
Joe Onorato170e5482010-10-29 13:26:11 -0700485 final Context outerContext = getOuterContext();
486 mThemeResource = (outerContext.getApplicationInfo().targetSdkVersion
487 >= Build.VERSION_CODES.HONEYCOMB)
488 ? com.android.internal.R.style.Theme_Holo
489 : com.android.internal.R.style.Theme;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 }
491 mTheme = mResources.newTheme();
492 mTheme.applyStyle(mThemeResource, true);
493 }
494 return mTheme;
495 }
496
497 @Override
498 public ClassLoader getClassLoader() {
499 return mPackageInfo != null ?
500 mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
501 }
502
503 @Override
504 public String getPackageName() {
505 if (mPackageInfo != null) {
506 return mPackageInfo.getPackageName();
507 }
508 throw new RuntimeException("Not supported in system context");
509 }
510
511 @Override
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700512 public ApplicationInfo getApplicationInfo() {
513 if (mPackageInfo != null) {
514 return mPackageInfo.getApplicationInfo();
515 }
516 throw new RuntimeException("Not supported in system context");
517 }
518
519 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 public String getPackageResourcePath() {
521 if (mPackageInfo != null) {
522 return mPackageInfo.getResDir();
523 }
524 throw new RuntimeException("Not supported in system context");
525 }
526
527 @Override
528 public String getPackageCodePath() {
529 if (mPackageInfo != null) {
530 return mPackageInfo.getAppDir();
531 }
532 throw new RuntimeException("Not supported in system context");
533 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200534
Brad Fitzpatrickd3da4402010-11-10 08:27:11 -0800535 static File makeBackupFile(File prefsFile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 return new File(prefsFile.getPath() + ".bak");
537 }
538
Joe Onorato23ecae32009-06-10 17:07:15 -0700539 public File getSharedPrefsFile(String name) {
540 return makeFilename(getPreferencesDir(), name + ".xml");
541 }
542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 @Override
544 public SharedPreferences getSharedPreferences(String name, int mode) {
545 SharedPreferencesImpl sp;
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700546 File prefsFile;
547 boolean needInitialLoad = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 synchronized (sSharedPrefs) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700549 sp = sSharedPrefs.get(name);
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700550 if (sp != null && !sp.hasFileChangedUnexpectedly()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 return sp;
552 }
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700553 prefsFile = getSharedPrefsFile(name);
554 if (sp == null) {
555 sp = new SharedPreferencesImpl(prefsFile, mode, null);
556 sSharedPrefs.put(name, sp);
557 needInitialLoad = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 }
559 }
560
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700561 synchronized (sp) {
562 if (needInitialLoad && sp.isLoaded()) {
563 // lost the race to load; another thread handled it
564 return sp;
565 }
566 File backup = makeBackupFile(prefsFile);
567 if (backup.exists()) {
568 prefsFile.delete();
569 backup.renameTo(prefsFile);
570 }
571
572 // Debugging
573 if (prefsFile.exists() && !prefsFile.canRead()) {
574 Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
575 }
576
577 Map map = null;
Brad Fitzpatrick5913630e2010-11-19 15:08:12 -0800578 FileStatus stat = new FileStatus();
579 if (FileUtils.getFileStatus(prefsFile.getPath(), stat) && prefsFile.canRead()) {
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700580 try {
581 FileInputStream str = new FileInputStream(prefsFile);
582 map = XmlUtils.readMapXml(str);
583 str.close();
Brad Fitzpatrickd3da4402010-11-10 08:27:11 -0800584 } catch (XmlPullParserException e) {
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700585 Log.w(TAG, "getSharedPreferences", e);
586 } catch (FileNotFoundException e) {
587 Log.w(TAG, "getSharedPreferences", e);
588 } catch (IOException e) {
589 Log.w(TAG, "getSharedPreferences", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591 }
Brad Fitzpatrick5913630e2010-11-19 15:08:12 -0800592 sp.replace(map, stat);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 }
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700594 return sp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 }
596
597 private File getPreferencesDir() {
598 synchronized (mSync) {
599 if (mPreferencesDir == null) {
600 mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
601 }
602 return mPreferencesDir;
603 }
604 }
605
606 @Override
607 public FileInputStream openFileInput(String name)
608 throws FileNotFoundException {
609 File f = makeFilename(getFilesDir(), name);
610 return new FileInputStream(f);
611 }
612
613 @Override
614 public FileOutputStream openFileOutput(String name, int mode)
615 throws FileNotFoundException {
616 final boolean append = (mode&MODE_APPEND) != 0;
617 File f = makeFilename(getFilesDir(), name);
618 try {
619 FileOutputStream fos = new FileOutputStream(f, append);
620 setFilePermissionsFromMode(f.getPath(), mode, 0);
621 return fos;
622 } catch (FileNotFoundException e) {
623 }
624
625 File parent = f.getParentFile();
626 parent.mkdir();
627 FileUtils.setPermissions(
628 parent.getPath(),
629 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
630 -1, -1);
631 FileOutputStream fos = new FileOutputStream(f, append);
632 setFilePermissionsFromMode(f.getPath(), mode, 0);
633 return fos;
634 }
635
636 @Override
637 public boolean deleteFile(String name) {
638 File f = makeFilename(getFilesDir(), name);
639 return f.delete();
640 }
641
642 @Override
643 public File getFilesDir() {
644 synchronized (mSync) {
645 if (mFilesDir == null) {
646 mFilesDir = new File(getDataDirFile(), "files");
647 }
648 if (!mFilesDir.exists()) {
649 if(!mFilesDir.mkdirs()) {
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200650 Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 return null;
652 }
653 FileUtils.setPermissions(
654 mFilesDir.getPath(),
655 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
656 -1, -1);
657 }
658 return mFilesDir;
659 }
660 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 @Override
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800663 public File getExternalFilesDir(String type) {
664 synchronized (mSync) {
665 if (mExternalFilesDir == null) {
666 mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
667 getPackageName());
668 }
669 if (!mExternalFilesDir.exists()) {
670 try {
671 (new File(Environment.getExternalStorageAndroidDataDir(),
672 ".nomedia")).createNewFile();
673 } catch (IOException e) {
674 }
675 if (!mExternalFilesDir.mkdirs()) {
676 Log.w(TAG, "Unable to create external files directory");
677 return null;
678 }
679 }
680 if (type == null) {
681 return mExternalFilesDir;
682 }
683 File dir = new File(mExternalFilesDir, type);
684 if (!dir.exists()) {
685 if (!dir.mkdirs()) {
686 Log.w(TAG, "Unable to create external media directory " + dir);
687 return null;
688 }
689 }
690 return dir;
691 }
692 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200693
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800694 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 public File getCacheDir() {
696 synchronized (mSync) {
697 if (mCacheDir == null) {
698 mCacheDir = new File(getDataDirFile(), "cache");
699 }
700 if (!mCacheDir.exists()) {
701 if(!mCacheDir.mkdirs()) {
702 Log.w(TAG, "Unable to create cache directory");
703 return null;
704 }
705 FileUtils.setPermissions(
706 mCacheDir.getPath(),
707 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
708 -1, -1);
709 }
710 }
711 return mCacheDir;
712 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200713
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800714 @Override
715 public File getExternalCacheDir() {
716 synchronized (mSync) {
717 if (mExternalCacheDir == null) {
718 mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
719 getPackageName());
720 }
721 if (!mExternalCacheDir.exists()) {
722 try {
723 (new File(Environment.getExternalStorageAndroidDataDir(),
724 ".nomedia")).createNewFile();
725 } catch (IOException e) {
726 }
727 if (!mExternalCacheDir.mkdirs()) {
728 Log.w(TAG, "Unable to create external cache directory");
729 return null;
730 }
731 }
732 return mExternalCacheDir;
733 }
734 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 @Override
737 public File getFileStreamPath(String name) {
738 return makeFilename(getFilesDir(), name);
739 }
740
741 @Override
742 public String[] fileList() {
743 final String[] list = getFilesDir().list();
744 return (list != null) ? list : EMPTY_FILE_LIST;
745 }
746
747 @Override
748 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800749 File f = validateFilePath(name, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
751 setFilePermissionsFromMode(f.getPath(), mode, 0);
752 return db;
753 }
754
755 @Override
Vasu Nori74f170f2010-06-01 18:06:18 -0700756 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
757 DatabaseErrorHandler errorHandler) {
758 File f = validateFilePath(name, true);
759 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
760 setFilePermissionsFromMode(f.getPath(), mode, 0);
761 return db;
762 }
763
764 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 public boolean deleteDatabase(String name) {
766 try {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800767 File f = validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 return f.delete();
769 } catch (Exception e) {
770 }
771 return false;
772 }
773
774 @Override
775 public File getDatabasePath(String name) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800776 return validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 }
778
779 @Override
780 public String[] databaseList() {
781 final String[] list = getDatabasesDir().list();
782 return (list != null) ? list : EMPTY_FILE_LIST;
783 }
784
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 private File getDatabasesDir() {
787 synchronized (mSync) {
788 if (mDatabasesDir == null) {
789 mDatabasesDir = new File(getDataDirFile(), "databases");
790 }
791 if (mDatabasesDir.getPath().equals("databases")) {
792 mDatabasesDir = new File("/data/system");
793 }
794 return mDatabasesDir;
795 }
796 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 @Override
799 public Drawable getWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700800 return getWallpaperManager().getDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801 }
802
803 @Override
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700804 public Drawable peekWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700805 return getWallpaperManager().peekDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
807
808 @Override
809 public int getWallpaperDesiredMinimumWidth() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700810 return getWallpaperManager().getDesiredMinimumWidth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 }
812
813 @Override
814 public int getWallpaperDesiredMinimumHeight() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700815 return getWallpaperManager().getDesiredMinimumHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 }
817
818 @Override
819 public void setWallpaper(Bitmap bitmap) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700820 getWallpaperManager().setBitmap(bitmap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 }
822
823 @Override
824 public void setWallpaper(InputStream data) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700825 getWallpaperManager().setStream(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 }
827
828 @Override
829 public void clearWallpaper() throws IOException {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700830 getWallpaperManager().clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 }
832
833 @Override
834 public void startActivity(Intent intent) {
835 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
836 throw new AndroidRuntimeException(
837 "Calling startActivity() from outside of an Activity "
838 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
839 + " Is this really what you want?");
840 }
841 mMainThread.getInstrumentation().execStartActivity(
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700842 getOuterContext(), mMainThread.getApplicationThread(), null,
843 (Activity)null, intent, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 }
845
846 @Override
Dianne Hackborn621e17d2010-11-22 15:59:56 -0800847 public void startActivities(Intent[] intents) {
848 if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
849 throw new AndroidRuntimeException(
850 "Calling startActivities() from outside of an Activity "
851 + " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
852 + " Is this really what you want?");
853 }
854 mMainThread.getInstrumentation().execStartActivities(
855 getOuterContext(), mMainThread.getApplicationThread(), null,
856 (Activity)null, intents);
857 }
858
859 @Override
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700860 public void startIntentSender(IntentSender intent,
861 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
862 throws IntentSender.SendIntentException {
863 try {
864 String resolvedType = null;
865 if (fillInIntent != null) {
866 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
867 }
868 int result = ActivityManagerNative.getDefault()
869 .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
870 fillInIntent, resolvedType, null, null,
871 0, flagsMask, flagsValues);
872 if (result == IActivityManager.START_CANCELED) {
873 throw new IntentSender.SendIntentException();
874 }
875 Instrumentation.checkStartActivityResult(result, null);
876 } catch (RemoteException e) {
877 }
878 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200879
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700880 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 public void sendBroadcast(Intent intent) {
882 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
883 try {
884 ActivityManagerNative.getDefault().broadcastIntent(
885 mMainThread.getApplicationThread(), intent, resolvedType, null,
886 Activity.RESULT_OK, null, null, null, false, false);
887 } catch (RemoteException e) {
888 }
889 }
890
891 @Override
892 public void sendBroadcast(Intent intent, String receiverPermission) {
893 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
894 try {
895 ActivityManagerNative.getDefault().broadcastIntent(
896 mMainThread.getApplicationThread(), intent, resolvedType, null,
897 Activity.RESULT_OK, null, null, receiverPermission, false, false);
898 } catch (RemoteException e) {
899 }
900 }
901
902 @Override
903 public void sendOrderedBroadcast(Intent intent,
904 String receiverPermission) {
905 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
906 try {
907 ActivityManagerNative.getDefault().broadcastIntent(
908 mMainThread.getApplicationThread(), intent, resolvedType, null,
909 Activity.RESULT_OK, null, null, receiverPermission, true, false);
910 } catch (RemoteException e) {
911 }
912 }
913
914 @Override
915 public void sendOrderedBroadcast(Intent intent,
916 String receiverPermission, BroadcastReceiver resultReceiver,
917 Handler scheduler, int initialCode, String initialData,
918 Bundle initialExtras) {
919 IIntentReceiver rd = null;
920 if (resultReceiver != null) {
921 if (mPackageInfo != null) {
922 if (scheduler == null) {
923 scheduler = mMainThread.getHandler();
924 }
925 rd = mPackageInfo.getReceiverDispatcher(
926 resultReceiver, getOuterContext(), scheduler,
927 mMainThread.getInstrumentation(), false);
928 } else {
929 if (scheduler == null) {
930 scheduler = mMainThread.getHandler();
931 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700932 rd = new LoadedApk.ReceiverDispatcher(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
934 }
935 }
936 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
937 try {
938 ActivityManagerNative.getDefault().broadcastIntent(
939 mMainThread.getApplicationThread(), intent, resolvedType, rd,
940 initialCode, initialData, initialExtras, receiverPermission,
941 true, false);
942 } catch (RemoteException e) {
943 }
944 }
945
946 @Override
947 public void sendStickyBroadcast(Intent intent) {
948 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
949 try {
950 ActivityManagerNative.getDefault().broadcastIntent(
951 mMainThread.getApplicationThread(), intent, resolvedType, null,
952 Activity.RESULT_OK, null, null, null, false, true);
953 } catch (RemoteException e) {
954 }
955 }
956
957 @Override
Dianne Hackbornefa199f2009-09-19 12:03:15 -0700958 public void sendStickyOrderedBroadcast(Intent intent,
959 BroadcastReceiver resultReceiver,
960 Handler scheduler, int initialCode, String initialData,
961 Bundle initialExtras) {
962 IIntentReceiver rd = null;
963 if (resultReceiver != null) {
964 if (mPackageInfo != null) {
965 if (scheduler == null) {
966 scheduler = mMainThread.getHandler();
967 }
968 rd = mPackageInfo.getReceiverDispatcher(
969 resultReceiver, getOuterContext(), scheduler,
970 mMainThread.getInstrumentation(), false);
971 } else {
972 if (scheduler == null) {
973 scheduler = mMainThread.getHandler();
974 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700975 rd = new LoadedApk.ReceiverDispatcher(
Dianne Hackbornefa199f2009-09-19 12:03:15 -0700976 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
977 }
978 }
979 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
980 try {
981 ActivityManagerNative.getDefault().broadcastIntent(
982 mMainThread.getApplicationThread(), intent, resolvedType, rd,
983 initialCode, initialData, initialExtras, null,
984 true, true);
985 } catch (RemoteException e) {
986 }
987 }
988
989 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 public void removeStickyBroadcast(Intent intent) {
991 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
992 if (resolvedType != null) {
993 intent = new Intent(intent);
994 intent.setDataAndType(intent.getData(), resolvedType);
995 }
996 try {
997 ActivityManagerNative.getDefault().unbroadcastIntent(
998 mMainThread.getApplicationThread(), intent);
999 } catch (RemoteException e) {
1000 }
1001 }
1002
1003 @Override
1004 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
1005 return registerReceiver(receiver, filter, null, null);
1006 }
1007
1008 @Override
1009 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
1010 String broadcastPermission, Handler scheduler) {
1011 return registerReceiverInternal(receiver, filter, broadcastPermission,
1012 scheduler, getOuterContext());
1013 }
1014
1015 private Intent registerReceiverInternal(BroadcastReceiver receiver,
1016 IntentFilter filter, String broadcastPermission,
1017 Handler scheduler, Context context) {
1018 IIntentReceiver rd = null;
1019 if (receiver != null) {
1020 if (mPackageInfo != null && context != null) {
1021 if (scheduler == null) {
1022 scheduler = mMainThread.getHandler();
1023 }
1024 rd = mPackageInfo.getReceiverDispatcher(
1025 receiver, context, scheduler,
1026 mMainThread.getInstrumentation(), true);
1027 } else {
1028 if (scheduler == null) {
1029 scheduler = mMainThread.getHandler();
1030 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001031 rd = new LoadedApk.ReceiverDispatcher(
Dianne Hackborn399cccb2010-04-13 22:57:49 -07001032 receiver, context, scheduler, null, true).getIIntentReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 }
1034 }
1035 try {
1036 return ActivityManagerNative.getDefault().registerReceiver(
1037 mMainThread.getApplicationThread(),
1038 rd, filter, broadcastPermission);
1039 } catch (RemoteException e) {
1040 return null;
1041 }
1042 }
1043
1044 @Override
1045 public void unregisterReceiver(BroadcastReceiver receiver) {
1046 if (mPackageInfo != null) {
1047 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
1048 getOuterContext(), receiver);
1049 try {
1050 ActivityManagerNative.getDefault().unregisterReceiver(rd);
1051 } catch (RemoteException e) {
1052 }
1053 } else {
1054 throw new RuntimeException("Not supported in system context");
1055 }
1056 }
1057
1058 @Override
1059 public ComponentName startService(Intent service) {
1060 try {
1061 ComponentName cn = ActivityManagerNative.getDefault().startService(
1062 mMainThread.getApplicationThread(), service,
1063 service.resolveTypeIfNeeded(getContentResolver()));
1064 if (cn != null && cn.getPackageName().equals("!")) {
1065 throw new SecurityException(
1066 "Not allowed to start service " + service
1067 + " without permission " + cn.getClassName());
1068 }
1069 return cn;
1070 } catch (RemoteException e) {
1071 return null;
1072 }
1073 }
1074
1075 @Override
1076 public boolean stopService(Intent service) {
1077 try {
1078 int res = ActivityManagerNative.getDefault().stopService(
1079 mMainThread.getApplicationThread(), service,
1080 service.resolveTypeIfNeeded(getContentResolver()));
1081 if (res < 0) {
1082 throw new SecurityException(
1083 "Not allowed to stop service " + service);
1084 }
1085 return res != 0;
1086 } catch (RemoteException e) {
1087 return false;
1088 }
1089 }
1090
1091 @Override
1092 public boolean bindService(Intent service, ServiceConnection conn,
1093 int flags) {
1094 IServiceConnection sd;
1095 if (mPackageInfo != null) {
1096 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
1097 mMainThread.getHandler(), flags);
1098 } else {
1099 throw new RuntimeException("Not supported in system context");
1100 }
1101 try {
1102 int res = ActivityManagerNative.getDefault().bindService(
1103 mMainThread.getApplicationThread(), getActivityToken(),
1104 service, service.resolveTypeIfNeeded(getContentResolver()),
1105 sd, flags);
1106 if (res < 0) {
1107 throw new SecurityException(
1108 "Not allowed to bind to service " + service);
1109 }
1110 return res != 0;
1111 } catch (RemoteException e) {
1112 return false;
1113 }
1114 }
1115
1116 @Override
1117 public void unbindService(ServiceConnection conn) {
1118 if (mPackageInfo != null) {
1119 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
1120 getOuterContext(), conn);
1121 try {
1122 ActivityManagerNative.getDefault().unbindService(sd);
1123 } catch (RemoteException e) {
1124 }
1125 } else {
1126 throw new RuntimeException("Not supported in system context");
1127 }
1128 }
1129
1130 @Override
1131 public boolean startInstrumentation(ComponentName className,
1132 String profileFile, Bundle arguments) {
1133 try {
1134 return ActivityManagerNative.getDefault().startInstrumentation(
1135 className, profileFile, 0, arguments, null);
1136 } catch (RemoteException e) {
1137 // System has crashed, nothing we can do.
1138 }
1139 return false;
1140 }
1141
1142 @Override
1143 public Object getSystemService(String name) {
Brad Fitzpatrick224ba0c2010-11-12 12:22:15 -08001144 ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
1145 return fetcher == null ? null : fetcher.getService(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 }
1147
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001148 private WallpaperManager getWallpaperManager() {
Brad Fitzpatrick224ba0c2010-11-12 12:22:15 -08001149 return (WallpaperManager) WALLPAPER_FETCHER.getService(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 }
1151
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001152 /* package */ static DropBoxManager createDropBoxManager() {
1153 IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1154 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001155 if (service == null) {
1156 // Don't return a DropBoxManager that will NPE upon use.
1157 // This also avoids caching a broken DropBoxManager in
1158 // getDropBoxManager during early boot, before the
1159 // DROPBOX_SERVICE is registered.
1160 return null;
1161 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001162 return new DropBoxManager(service);
1163 }
1164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 @Override
1166 public int checkPermission(String permission, int pid, int uid) {
1167 if (permission == null) {
1168 throw new IllegalArgumentException("permission is null");
1169 }
1170
1171 if (!Process.supportsProcesses()) {
1172 return PackageManager.PERMISSION_GRANTED;
1173 }
1174 try {
1175 return ActivityManagerNative.getDefault().checkPermission(
1176 permission, pid, uid);
1177 } catch (RemoteException e) {
1178 return PackageManager.PERMISSION_DENIED;
1179 }
1180 }
1181
1182 @Override
1183 public int checkCallingPermission(String permission) {
1184 if (permission == null) {
1185 throw new IllegalArgumentException("permission is null");
1186 }
1187
1188 if (!Process.supportsProcesses()) {
1189 return PackageManager.PERMISSION_GRANTED;
1190 }
1191 int pid = Binder.getCallingPid();
1192 if (pid != Process.myPid()) {
1193 return checkPermission(permission, pid,
1194 Binder.getCallingUid());
1195 }
1196 return PackageManager.PERMISSION_DENIED;
1197 }
1198
1199 @Override
1200 public int checkCallingOrSelfPermission(String permission) {
1201 if (permission == null) {
1202 throw new IllegalArgumentException("permission is null");
1203 }
1204
1205 return checkPermission(permission, Binder.getCallingPid(),
1206 Binder.getCallingUid());
1207 }
1208
1209 private void enforce(
1210 String permission, int resultOfCheck,
1211 boolean selfToo, int uid, String message) {
1212 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1213 throw new SecurityException(
1214 (message != null ? (message + ": ") : "") +
1215 (selfToo
1216 ? "Neither user " + uid + " nor current process has "
1217 : "User " + uid + " does not have ") +
1218 permission +
1219 ".");
1220 }
1221 }
1222
1223 public void enforcePermission(
1224 String permission, int pid, int uid, String message) {
1225 enforce(permission,
1226 checkPermission(permission, pid, uid),
1227 false,
1228 uid,
1229 message);
1230 }
1231
1232 public void enforceCallingPermission(String permission, String message) {
1233 enforce(permission,
1234 checkCallingPermission(permission),
1235 false,
1236 Binder.getCallingUid(),
1237 message);
1238 }
1239
1240 public void enforceCallingOrSelfPermission(
1241 String permission, String message) {
1242 enforce(permission,
1243 checkCallingOrSelfPermission(permission),
1244 true,
1245 Binder.getCallingUid(),
1246 message);
1247 }
1248
1249 @Override
1250 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1251 try {
1252 ActivityManagerNative.getDefault().grantUriPermission(
1253 mMainThread.getApplicationThread(), toPackage, uri,
1254 modeFlags);
1255 } catch (RemoteException e) {
1256 }
1257 }
1258
1259 @Override
1260 public void revokeUriPermission(Uri uri, int modeFlags) {
1261 try {
1262 ActivityManagerNative.getDefault().revokeUriPermission(
1263 mMainThread.getApplicationThread(), uri,
1264 modeFlags);
1265 } catch (RemoteException e) {
1266 }
1267 }
1268
1269 @Override
1270 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1271 if (!Process.supportsProcesses()) {
1272 return PackageManager.PERMISSION_GRANTED;
1273 }
1274 try {
1275 return ActivityManagerNative.getDefault().checkUriPermission(
1276 uri, pid, uid, modeFlags);
1277 } catch (RemoteException e) {
1278 return PackageManager.PERMISSION_DENIED;
1279 }
1280 }
1281
1282 @Override
1283 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1284 if (!Process.supportsProcesses()) {
1285 return PackageManager.PERMISSION_GRANTED;
1286 }
1287 int pid = Binder.getCallingPid();
1288 if (pid != Process.myPid()) {
1289 return checkUriPermission(uri, pid,
1290 Binder.getCallingUid(), modeFlags);
1291 }
1292 return PackageManager.PERMISSION_DENIED;
1293 }
1294
1295 @Override
1296 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1297 return checkUriPermission(uri, Binder.getCallingPid(),
1298 Binder.getCallingUid(), modeFlags);
1299 }
1300
1301 @Override
1302 public int checkUriPermission(Uri uri, String readPermission,
1303 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001304 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001305 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1306 + readPermission + " writePermission=" + writePermission
1307 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1308 }
1309 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1310 if (readPermission == null
1311 || checkPermission(readPermission, pid, uid)
1312 == PackageManager.PERMISSION_GRANTED) {
1313 return PackageManager.PERMISSION_GRANTED;
1314 }
1315 }
1316 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1317 if (writePermission == null
1318 || checkPermission(writePermission, pid, uid)
1319 == PackageManager.PERMISSION_GRANTED) {
1320 return PackageManager.PERMISSION_GRANTED;
1321 }
1322 }
1323 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1324 : PackageManager.PERMISSION_DENIED;
1325 }
1326
1327 private String uriModeFlagToString(int uriModeFlags) {
1328 switch (uriModeFlags) {
1329 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1330 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1331 return "read and write";
1332 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1333 return "read";
1334 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1335 return "write";
1336 }
1337 throw new IllegalArgumentException(
1338 "Unknown permission mode flags: " + uriModeFlags);
1339 }
1340
1341 private void enforceForUri(
1342 int modeFlags, int resultOfCheck, boolean selfToo,
1343 int uid, Uri uri, String message) {
1344 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1345 throw new SecurityException(
1346 (message != null ? (message + ": ") : "") +
1347 (selfToo
1348 ? "Neither user " + uid + " nor current process has "
1349 : "User " + uid + " does not have ") +
1350 uriModeFlagToString(modeFlags) +
1351 " permission on " +
1352 uri +
1353 ".");
1354 }
1355 }
1356
1357 public void enforceUriPermission(
1358 Uri uri, int pid, int uid, int modeFlags, String message) {
1359 enforceForUri(
1360 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1361 false, uid, uri, message);
1362 }
1363
1364 public void enforceCallingUriPermission(
1365 Uri uri, int modeFlags, String message) {
1366 enforceForUri(
1367 modeFlags, checkCallingUriPermission(uri, modeFlags),
1368 false, Binder.getCallingUid(), uri, message);
1369 }
1370
1371 public void enforceCallingOrSelfUriPermission(
1372 Uri uri, int modeFlags, String message) {
1373 enforceForUri(
1374 modeFlags,
1375 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1376 Binder.getCallingUid(), uri, message);
1377 }
1378
1379 public void enforceUriPermission(
1380 Uri uri, String readPermission, String writePermission,
1381 int pid, int uid, int modeFlags, String message) {
1382 enforceForUri(modeFlags,
1383 checkUriPermission(
1384 uri, readPermission, writePermission, pid, uid,
1385 modeFlags),
1386 false,
1387 uid,
1388 uri,
1389 message);
1390 }
1391
1392 @Override
1393 public Context createPackageContext(String packageName, int flags)
1394 throws PackageManager.NameNotFoundException {
1395 if (packageName.equals("system") || packageName.equals("android")) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001396 return new ContextImpl(mMainThread.getSystemContext());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
1398
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001399 LoadedApk pi =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 mMainThread.getPackageInfo(packageName, flags);
1401 if (pi != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001402 ContextImpl c = new ContextImpl();
Romain Guy870e09f2009-07-06 16:35:25 -07001403 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001404 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 if (c.mResources != null) {
1406 return c;
1407 }
1408 }
1409
1410 // Should be a better exception.
1411 throw new PackageManager.NameNotFoundException(
1412 "Application package " + packageName + " not found");
1413 }
1414
Romain Guy870e09f2009-07-06 16:35:25 -07001415 @Override
1416 public boolean isRestricted() {
1417 return mRestricted;
1418 }
1419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 private File getDataDirFile() {
1421 if (mPackageInfo != null) {
1422 return mPackageInfo.getDataDirFile();
1423 }
1424 throw new RuntimeException("Not supported in system context");
1425 }
1426
1427 @Override
1428 public File getDir(String name, int mode) {
1429 name = "app_" + name;
1430 File file = makeFilename(getDataDirFile(), name);
1431 if (!file.exists()) {
1432 file.mkdir();
1433 setFilePermissionsFromMode(file.getPath(), mode,
1434 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1435 }
1436 return file;
1437 }
1438
Dianne Hackborn21556372010-02-04 16:34:40 -08001439 static ContextImpl createSystemContext(ActivityThread mainThread) {
1440 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 context.init(Resources.getSystem(), mainThread);
1442 return context;
1443 }
1444
Dianne Hackborn21556372010-02-04 16:34:40 -08001445 ContextImpl() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 mOuterContext = this;
1447 }
1448
1449 /**
1450 * Create a new ApplicationContext from an existing one. The new one
1451 * works and operates the same as the one it is copying.
1452 *
1453 * @param context Existing application context.
1454 */
Dianne Hackborn21556372010-02-04 16:34:40 -08001455 public ContextImpl(ContextImpl context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 mPackageInfo = context.mPackageInfo;
1457 mResources = context.mResources;
1458 mMainThread = context.mMainThread;
1459 mContentResolver = context.mContentResolver;
1460 mOuterContext = this;
1461 }
1462
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001463 final void init(LoadedApk packageInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001465 init(packageInfo, activityToken, mainThread, null);
1466 }
1467
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001468 final void init(LoadedApk packageInfo,
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001469 IBinder activityToken, ActivityThread mainThread,
1470 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 mPackageInfo = packageInfo;
1472 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001473
Dianne Hackborn559a7872010-04-07 18:19:41 -07001474 if (mResources != null && container != null
1475 && container.getCompatibilityInfo().applicationScale !=
1476 mResources.getCompatibilityInfo().applicationScale) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001477 if (DEBUG) {
1478 Log.d(TAG, "loaded context has different scaling. Using container's" +
1479 " compatiblity info:" + container.getDisplayMetrics());
1480 }
1481 mResources = mainThread.getTopLevelResources(
1482 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 mMainThread = mainThread;
1485 mContentResolver = new ApplicationContentResolver(this, mainThread);
1486
1487 setActivityToken(activityToken);
1488 }
1489
1490 final void init(Resources resources, ActivityThread mainThread) {
1491 mPackageInfo = null;
1492 mResources = resources;
1493 mMainThread = mainThread;
1494 mContentResolver = new ApplicationContentResolver(this, mainThread);
1495 }
1496
1497 final void scheduleFinalCleanup(String who, String what) {
1498 mMainThread.scheduleContextCleanup(this, who, what);
1499 }
1500
1501 final void performFinalCleanup(String who, String what) {
1502 //Log.i(TAG, "Cleanup up context: " + this);
1503 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1504 }
1505
1506 final Context getReceiverRestrictedContext() {
1507 if (mReceiverRestrictedContext != null) {
1508 return mReceiverRestrictedContext;
1509 }
1510 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1511 }
1512
1513 final void setActivityToken(IBinder token) {
1514 mActivityToken = token;
1515 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 final void setOuterContext(Context context) {
1518 mOuterContext = context;
1519 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 final Context getOuterContext() {
1522 return mOuterContext;
1523 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 final IBinder getActivityToken() {
1526 return mActivityToken;
1527 }
1528
Brad Fitzpatrickd3da4402010-11-10 08:27:11 -08001529 static void setFilePermissionsFromMode(String name, int mode,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 int extraPermissions) {
1531 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1532 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1533 |extraPermissions;
1534 if ((mode&MODE_WORLD_READABLE) != 0) {
1535 perms |= FileUtils.S_IROTH;
1536 }
1537 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1538 perms |= FileUtils.S_IWOTH;
1539 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001540 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1542 + ", perms=0x" + Integer.toHexString(perms));
1543 }
1544 FileUtils.setPermissions(name, perms, -1, -1);
1545 }
1546
Oscar Montemayora8529f62009-11-18 10:14:20 -08001547 private File validateFilePath(String name, boolean createDirectory) {
1548 File dir;
1549 File f;
1550
1551 if (name.charAt(0) == File.separatorChar) {
1552 String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1553 dir = new File(dirPath);
1554 name = name.substring(name.lastIndexOf(File.separatorChar));
1555 f = new File(dir, name);
1556 } else {
1557 dir = getDatabasesDir();
1558 f = makeFilename(dir, name);
1559 }
1560
1561 if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1562 FileUtils.setPermissions(dir.getPath(),
1563 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1564 -1, -1);
1565 }
1566
1567 return f;
1568 }
1569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 private File makeFilename(File base, String name) {
1571 if (name.indexOf(File.separatorChar) < 0) {
1572 return new File(base, name);
1573 }
1574 throw new IllegalArgumentException(
Oscar Montemayora8529f62009-11-18 10:14:20 -08001575 "File " + name + " contains a path separator");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 }
1577
1578 // ----------------------------------------------------------------------
1579 // ----------------------------------------------------------------------
1580 // ----------------------------------------------------------------------
1581
1582 private static final class ApplicationContentResolver extends ContentResolver {
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07001583 public ApplicationContentResolver(Context context, ActivityThread mainThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 super(context);
1585 mMainThread = mainThread;
1586 }
1587
1588 @Override
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07001589 protected IContentProvider acquireProvider(Context context, String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 return mMainThread.acquireProvider(context, name);
1591 }
1592
1593 @Override
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07001594 protected IContentProvider acquireExistingProvider(Context context, String name) {
1595 return mMainThread.acquireExistingProvider(context, name);
1596 }
1597
1598 @Override
1599 public boolean releaseProvider(IContentProvider provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 return mMainThread.releaseProvider(provider);
1601 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 private final ActivityThread mMainThread;
1604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605}