blob: 487cfdaf9b4c606d03f030b0ec518624c63d5ad9 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.util.XmlUtils;
svetoslavganov75986cf2009-05-14 22:28:01 -070021import com.google.android.collect.Maps;
22
23import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
Nick Pellybd022f42009-08-14 18:33:38 -070025import android.bluetooth.BluetoothAdapter;
26import android.bluetooth.IBluetooth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.content.BroadcastReceiver;
28import android.content.ComponentName;
29import android.content.ContentResolver;
30import android.content.Context;
31import android.content.ContextWrapper;
32import android.content.IContentProvider;
33import android.content.Intent;
34import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070035import android.content.IIntentReceiver;
36import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.ReceiverCallNotAllowedException;
38import android.content.ServiceConnection;
39import android.content.SharedPreferences;
40import android.content.pm.ActivityInfo;
41import android.content.pm.ApplicationInfo;
42import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070043import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.content.pm.IPackageDataObserver;
45import android.content.pm.IPackageDeleteObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.content.pm.IPackageInstallObserver;
47import android.content.pm.IPackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070048import android.content.pm.IPackageStatsObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.pm.InstrumentationInfo;
50import android.content.pm.PackageInfo;
51import android.content.pm.PackageManager;
52import android.content.pm.PermissionGroupInfo;
53import android.content.pm.PermissionInfo;
54import android.content.pm.ProviderInfo;
55import android.content.pm.ResolveInfo;
56import android.content.pm.ServiceInfo;
57import android.content.res.AssetManager;
58import android.content.res.Resources;
59import android.content.res.XmlResourceParser;
60import android.database.sqlite.SQLiteDatabase;
61import android.database.sqlite.SQLiteDatabase.CursorFactory;
62import android.graphics.Bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.graphics.drawable.Drawable;
64import android.hardware.SensorManager;
65import android.location.ILocationManager;
66import android.location.LocationManager;
67import android.media.AudioManager;
68import android.net.ConnectivityManager;
69import android.net.IConnectivityManager;
70import android.net.Uri;
71import android.net.wifi.IWifiManager;
72import android.net.wifi.WifiManager;
73import android.os.Binder;
74import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.os.FileUtils;
76import android.os.Handler;
77import android.os.IBinder;
78import android.os.IPowerManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070079import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.os.PowerManager;
81import android.os.Process;
svetoslavganov75986cf2009-05-14 22:28:01 -070082import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.os.ServiceManager;
84import android.os.Vibrator;
85import android.os.FileUtils.FileStatus;
86import android.telephony.TelephonyManager;
87import android.text.ClipboardManager;
88import android.util.AndroidRuntimeException;
89import android.util.Log;
90import android.view.ContextThemeWrapper;
91import android.view.LayoutInflater;
92import android.view.WindowManagerImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070093import android.view.accessibility.AccessibilityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.view.inputmethod.InputMethodManager;
Fred Quintana60307342009-03-24 22:48:12 -070095import android.accounts.AccountManager;
96import android.accounts.IAccountManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
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;
104import java.lang.ref.WeakReference;
105import java.util.ArrayList;
106import java.util.HashMap;
svetoslavganov75986cf2009-05-14 22:28:01 -0700107import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.util.Iterator;
109import java.util.List;
110import java.util.Map;
The Android Open Source Project10592532009-03-18 17:39:46 -0700111import java.util.Set;
svetoslavganov75986cf2009-05-14 22:28:01 -0700112import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import java.util.Map.Entry;
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115class ReceiverRestrictedContext extends ContextWrapper {
116 ReceiverRestrictedContext(Context base) {
117 super(base);
118 }
119
120 @Override
121 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
122 return registerReceiver(receiver, filter, null, null);
123 }
124
125 @Override
126 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
127 String broadcastPermission, Handler scheduler) {
128 throw new ReceiverCallNotAllowedException(
129 "IntentReceiver components are not allowed to register to receive intents");
130 //ex.fillInStackTrace();
131 //Log.e("IntentReceiver", ex.getMessage(), ex);
132 //return mContext.registerReceiver(receiver, filter, broadcastPermission,
133 // scheduler);
134 }
135
136 @Override
137 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
138 throw new ReceiverCallNotAllowedException(
139 "IntentReceiver components are not allowed to bind to services");
140 //ex.fillInStackTrace();
141 //Log.e("IntentReceiver", ex.getMessage(), ex);
142 //return mContext.bindService(service, interfaceName, conn, flags);
143 }
144}
145
146/**
147 * Common implementation of Context API, which Activity and other application
148 * classes inherit.
149 */
150class ApplicationContext extends Context {
151 private final static String TAG = "ApplicationContext";
Mitsuru Oshima569076c2009-07-02 20:06:08 -0700152 private final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 private final static boolean DEBUG_ICONS = false;
154
155 private static final Object sSync = new Object();
Fred Quintana60307342009-03-24 22:48:12 -0700156 private static AccountManager sAccountManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 private static AlarmManager sAlarmManager;
158 private static PowerManager sPowerManager;
159 private static ConnectivityManager sConnectivityManager;
160 private static WifiManager sWifiManager;
161 private static LocationManager sLocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
163 new HashMap<File, SharedPreferencesImpl>();
164
165 private AudioManager mAudioManager;
166 /*package*/ ActivityThread.PackageInfo mPackageInfo;
167 private Resources mResources;
168 /*package*/ ActivityThread mMainThread;
169 private Context mOuterContext;
170 private IBinder mActivityToken = null;
171 private ApplicationContentResolver mContentResolver;
172 private int mThemeResource = 0;
173 private Resources.Theme mTheme = null;
174 private PackageManager mPackageManager;
175 private NotificationManager mNotificationManager = null;
176 private ActivityManager mActivityManager = null;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700177 private WallpaperManager mWallpaperManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 private Context mReceiverRestrictedContext = null;
179 private SearchManager mSearchManager = null;
180 private SensorManager mSensorManager = null;
181 private Vibrator mVibrator = null;
182 private LayoutInflater mLayoutInflater = null;
183 private StatusBarManager mStatusBarManager = null;
184 private TelephonyManager mTelephonyManager = null;
185 private ClipboardManager mClipboardManager = null;
Nick Pellybd022f42009-08-14 18:33:38 -0700186 private boolean mIsBluetoothAdapterCached = false;
187 private BluetoothAdapter mBluetoothAdapter;
Romain Guy870e09f2009-07-06 16:35:25 -0700188 private boolean mRestricted;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
190 private final Object mSync = new Object();
191
192 private File mDatabasesDir;
193 private File mPreferencesDir;
194 private File mFilesDir;
195
196
197 private File mCacheDir;
198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 private static long sInstanceCount = 0;
200
201 private static final String[] EMPTY_FILE_LIST = {};
202
203 @Override
204 protected void finalize() throws Throwable {
205 super.finalize();
206 --sInstanceCount;
207 }
208
209 public static long getInstanceCount() {
210 return sInstanceCount;
211 }
212
213 @Override
214 public AssetManager getAssets() {
215 return mResources.getAssets();
216 }
217
218 @Override
219 public Resources getResources() {
220 return mResources;
221 }
222
223 @Override
224 public PackageManager getPackageManager() {
225 if (mPackageManager != null) {
226 return mPackageManager;
227 }
228
229 IPackageManager pm = ActivityThread.getPackageManager();
230 if (pm != null) {
231 // Doesn't matter if we make more than one instance.
232 return (mPackageManager = new ApplicationPackageManager(this, pm));
233 }
234
235 return null;
236 }
237
238 @Override
239 public ContentResolver getContentResolver() {
240 return mContentResolver;
241 }
242
243 @Override
244 public Looper getMainLooper() {
245 return mMainThread.getLooper();
246 }
247
248 @Override
249 public Context getApplicationContext() {
250 return mMainThread.getApplication();
251 }
252
253 @Override
254 public void setTheme(int resid) {
255 mThemeResource = resid;
256 }
257
258 @Override
259 public Resources.Theme getTheme() {
260 if (mTheme == null) {
261 if (mThemeResource == 0) {
262 mThemeResource = com.android.internal.R.style.Theme;
263 }
264 mTheme = mResources.newTheme();
265 mTheme.applyStyle(mThemeResource, true);
266 }
267 return mTheme;
268 }
269
270 @Override
271 public ClassLoader getClassLoader() {
272 return mPackageInfo != null ?
273 mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
274 }
275
276 @Override
277 public String getPackageName() {
278 if (mPackageInfo != null) {
279 return mPackageInfo.getPackageName();
280 }
281 throw new RuntimeException("Not supported in system context");
282 }
283
284 @Override
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700285 public ApplicationInfo getApplicationInfo() {
286 if (mPackageInfo != null) {
287 return mPackageInfo.getApplicationInfo();
288 }
289 throw new RuntimeException("Not supported in system context");
290 }
291
292 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 public String getPackageResourcePath() {
294 if (mPackageInfo != null) {
295 return mPackageInfo.getResDir();
296 }
297 throw new RuntimeException("Not supported in system context");
298 }
299
300 @Override
301 public String getPackageCodePath() {
302 if (mPackageInfo != null) {
303 return mPackageInfo.getAppDir();
304 }
305 throw new RuntimeException("Not supported in system context");
306 }
307
308 private static File makeBackupFile(File prefsFile) {
309 return new File(prefsFile.getPath() + ".bak");
310 }
311
Joe Onorato23ecae32009-06-10 17:07:15 -0700312 public File getSharedPrefsFile(String name) {
313 return makeFilename(getPreferencesDir(), name + ".xml");
314 }
315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 @Override
317 public SharedPreferences getSharedPreferences(String name, int mode) {
318 SharedPreferencesImpl sp;
Joe Onorato23ecae32009-06-10 17:07:15 -0700319 File f = getSharedPrefsFile(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 synchronized (sSharedPrefs) {
321 sp = sSharedPrefs.get(f);
322 if (sp != null && !sp.hasFileChanged()) {
323 //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
324 return sp;
325 }
326 }
327
328 FileInputStream str = null;
329 File backup = makeBackupFile(f);
330 if (backup.exists()) {
331 f.delete();
332 backup.renameTo(f);
333 }
334
335 // Debugging
336 if (f.exists() && !f.canRead()) {
337 Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
338 }
339
340 Map map = null;
341 if (f.exists() && f.canRead()) {
342 try {
343 str = new FileInputStream(f);
344 map = XmlUtils.readMapXml(str);
345 str.close();
346 } catch (org.xmlpull.v1.XmlPullParserException e) {
347 Log.w(TAG, "getSharedPreferences", e);
348 } catch (FileNotFoundException e) {
349 Log.w(TAG, "getSharedPreferences", e);
350 } catch (IOException e) {
351 Log.w(TAG, "getSharedPreferences", e);
352 }
353 }
354
355 synchronized (sSharedPrefs) {
356 if (sp != null) {
357 //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
358 sp.replace(map);
359 } else {
360 sp = sSharedPrefs.get(f);
361 if (sp == null) {
362 sp = new SharedPreferencesImpl(f, mode, map);
363 sSharedPrefs.put(f, sp);
364 }
365 }
366 return sp;
367 }
368 }
369
370 private File getPreferencesDir() {
371 synchronized (mSync) {
372 if (mPreferencesDir == null) {
373 mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
374 }
375 return mPreferencesDir;
376 }
377 }
378
379 @Override
380 public FileInputStream openFileInput(String name)
381 throws FileNotFoundException {
382 File f = makeFilename(getFilesDir(), name);
383 return new FileInputStream(f);
384 }
385
386 @Override
387 public FileOutputStream openFileOutput(String name, int mode)
388 throws FileNotFoundException {
389 final boolean append = (mode&MODE_APPEND) != 0;
390 File f = makeFilename(getFilesDir(), name);
391 try {
392 FileOutputStream fos = new FileOutputStream(f, append);
393 setFilePermissionsFromMode(f.getPath(), mode, 0);
394 return fos;
395 } catch (FileNotFoundException e) {
396 }
397
398 File parent = f.getParentFile();
399 parent.mkdir();
400 FileUtils.setPermissions(
401 parent.getPath(),
402 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
403 -1, -1);
404 FileOutputStream fos = new FileOutputStream(f, append);
405 setFilePermissionsFromMode(f.getPath(), mode, 0);
406 return fos;
407 }
408
409 @Override
410 public boolean deleteFile(String name) {
411 File f = makeFilename(getFilesDir(), name);
412 return f.delete();
413 }
414
415 @Override
416 public File getFilesDir() {
417 synchronized (mSync) {
418 if (mFilesDir == null) {
419 mFilesDir = new File(getDataDirFile(), "files");
420 }
421 if (!mFilesDir.exists()) {
422 if(!mFilesDir.mkdirs()) {
423 Log.w(TAG, "Unable to create files directory");
424 return null;
425 }
426 FileUtils.setPermissions(
427 mFilesDir.getPath(),
428 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
429 -1, -1);
430 }
431 return mFilesDir;
432 }
433 }
434
435 @Override
436 public File getCacheDir() {
437 synchronized (mSync) {
438 if (mCacheDir == null) {
439 mCacheDir = new File(getDataDirFile(), "cache");
440 }
441 if (!mCacheDir.exists()) {
442 if(!mCacheDir.mkdirs()) {
443 Log.w(TAG, "Unable to create cache directory");
444 return null;
445 }
446 FileUtils.setPermissions(
447 mCacheDir.getPath(),
448 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
449 -1, -1);
450 }
451 }
452 return mCacheDir;
453 }
454
455
456 @Override
457 public File getFileStreamPath(String name) {
458 return makeFilename(getFilesDir(), name);
459 }
460
461 @Override
462 public String[] fileList() {
463 final String[] list = getFilesDir().list();
464 return (list != null) ? list : EMPTY_FILE_LIST;
465 }
466
467 @Override
468 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
469 File dir = getDatabasesDir();
470 if (!dir.isDirectory() && dir.mkdir()) {
471 FileUtils.setPermissions(dir.getPath(),
472 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
473 -1, -1);
474 }
475
476 File f = makeFilename(dir, name);
477 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
478 setFilePermissionsFromMode(f.getPath(), mode, 0);
479 return db;
480 }
481
482 @Override
483 public boolean deleteDatabase(String name) {
484 try {
485 File f = makeFilename(getDatabasesDir(), name);
486 return f.delete();
487 } catch (Exception e) {
488 }
489 return false;
490 }
491
492 @Override
493 public File getDatabasePath(String name) {
494 return makeFilename(getDatabasesDir(), name);
495 }
496
497 @Override
498 public String[] databaseList() {
499 final String[] list = getDatabasesDir().list();
500 return (list != null) ? list : EMPTY_FILE_LIST;
501 }
502
503
504 private File getDatabasesDir() {
505 synchronized (mSync) {
506 if (mDatabasesDir == null) {
507 mDatabasesDir = new File(getDataDirFile(), "databases");
508 }
509 if (mDatabasesDir.getPath().equals("databases")) {
510 mDatabasesDir = new File("/data/system");
511 }
512 return mDatabasesDir;
513 }
514 }
515
516 @Override
517 public Drawable getWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700518 return getWallpaperManager().getDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 }
520
521 @Override
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700522 public Drawable peekWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700523 return getWallpaperManager().peekDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 }
525
526 @Override
527 public int getWallpaperDesiredMinimumWidth() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700528 return getWallpaperManager().getDesiredMinimumWidth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 }
530
531 @Override
532 public int getWallpaperDesiredMinimumHeight() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700533 return getWallpaperManager().getDesiredMinimumHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 }
535
536 @Override
537 public void setWallpaper(Bitmap bitmap) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700538 getWallpaperManager().setBitmap(bitmap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 }
540
541 @Override
542 public void setWallpaper(InputStream data) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700543 getWallpaperManager().setStream(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800544 }
545
546 @Override
547 public void clearWallpaper() throws IOException {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700548 getWallpaperManager().clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 }
550
551 @Override
552 public void startActivity(Intent intent) {
553 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
554 throw new AndroidRuntimeException(
555 "Calling startActivity() from outside of an Activity "
556 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
557 + " Is this really what you want?");
558 }
559 mMainThread.getInstrumentation().execStartActivity(
560 getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
561 }
562
563 @Override
564 public void sendBroadcast(Intent intent) {
565 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
566 try {
567 ActivityManagerNative.getDefault().broadcastIntent(
568 mMainThread.getApplicationThread(), intent, resolvedType, null,
569 Activity.RESULT_OK, null, null, null, false, false);
570 } catch (RemoteException e) {
571 }
572 }
573
574 @Override
575 public void sendBroadcast(Intent intent, String receiverPermission) {
576 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
577 try {
578 ActivityManagerNative.getDefault().broadcastIntent(
579 mMainThread.getApplicationThread(), intent, resolvedType, null,
580 Activity.RESULT_OK, null, null, receiverPermission, false, false);
581 } catch (RemoteException e) {
582 }
583 }
584
585 @Override
586 public void sendOrderedBroadcast(Intent intent,
587 String receiverPermission) {
588 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
589 try {
590 ActivityManagerNative.getDefault().broadcastIntent(
591 mMainThread.getApplicationThread(), intent, resolvedType, null,
592 Activity.RESULT_OK, null, null, receiverPermission, true, false);
593 } catch (RemoteException e) {
594 }
595 }
596
597 @Override
598 public void sendOrderedBroadcast(Intent intent,
599 String receiverPermission, BroadcastReceiver resultReceiver,
600 Handler scheduler, int initialCode, String initialData,
601 Bundle initialExtras) {
602 IIntentReceiver rd = null;
603 if (resultReceiver != null) {
604 if (mPackageInfo != null) {
605 if (scheduler == null) {
606 scheduler = mMainThread.getHandler();
607 }
608 rd = mPackageInfo.getReceiverDispatcher(
609 resultReceiver, getOuterContext(), scheduler,
610 mMainThread.getInstrumentation(), false);
611 } else {
612 if (scheduler == null) {
613 scheduler = mMainThread.getHandler();
614 }
615 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
616 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
617 }
618 }
619 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
620 try {
621 ActivityManagerNative.getDefault().broadcastIntent(
622 mMainThread.getApplicationThread(), intent, resolvedType, rd,
623 initialCode, initialData, initialExtras, receiverPermission,
624 true, false);
625 } catch (RemoteException e) {
626 }
627 }
628
629 @Override
630 public void sendStickyBroadcast(Intent intent) {
631 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
632 try {
633 ActivityManagerNative.getDefault().broadcastIntent(
634 mMainThread.getApplicationThread(), intent, resolvedType, null,
635 Activity.RESULT_OK, null, null, null, false, true);
636 } catch (RemoteException e) {
637 }
638 }
639
640 @Override
641 public void removeStickyBroadcast(Intent intent) {
642 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
643 if (resolvedType != null) {
644 intent = new Intent(intent);
645 intent.setDataAndType(intent.getData(), resolvedType);
646 }
647 try {
648 ActivityManagerNative.getDefault().unbroadcastIntent(
649 mMainThread.getApplicationThread(), intent);
650 } catch (RemoteException e) {
651 }
652 }
653
654 @Override
655 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
656 return registerReceiver(receiver, filter, null, null);
657 }
658
659 @Override
660 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
661 String broadcastPermission, Handler scheduler) {
662 return registerReceiverInternal(receiver, filter, broadcastPermission,
663 scheduler, getOuterContext());
664 }
665
666 private Intent registerReceiverInternal(BroadcastReceiver receiver,
667 IntentFilter filter, String broadcastPermission,
668 Handler scheduler, Context context) {
669 IIntentReceiver rd = null;
670 if (receiver != null) {
671 if (mPackageInfo != null && context != null) {
672 if (scheduler == null) {
673 scheduler = mMainThread.getHandler();
674 }
675 rd = mPackageInfo.getReceiverDispatcher(
676 receiver, context, scheduler,
677 mMainThread.getInstrumentation(), true);
678 } else {
679 if (scheduler == null) {
680 scheduler = mMainThread.getHandler();
681 }
682 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
683 receiver, context, scheduler, null, false).getIIntentReceiver();
684 }
685 }
686 try {
687 return ActivityManagerNative.getDefault().registerReceiver(
688 mMainThread.getApplicationThread(),
689 rd, filter, broadcastPermission);
690 } catch (RemoteException e) {
691 return null;
692 }
693 }
694
695 @Override
696 public void unregisterReceiver(BroadcastReceiver receiver) {
697 if (mPackageInfo != null) {
698 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
699 getOuterContext(), receiver);
700 try {
701 ActivityManagerNative.getDefault().unregisterReceiver(rd);
702 } catch (RemoteException e) {
703 }
704 } else {
705 throw new RuntimeException("Not supported in system context");
706 }
707 }
708
709 @Override
710 public ComponentName startService(Intent service) {
711 try {
712 ComponentName cn = ActivityManagerNative.getDefault().startService(
713 mMainThread.getApplicationThread(), service,
714 service.resolveTypeIfNeeded(getContentResolver()));
715 if (cn != null && cn.getPackageName().equals("!")) {
716 throw new SecurityException(
717 "Not allowed to start service " + service
718 + " without permission " + cn.getClassName());
719 }
720 return cn;
721 } catch (RemoteException e) {
722 return null;
723 }
724 }
725
726 @Override
727 public boolean stopService(Intent service) {
728 try {
729 int res = ActivityManagerNative.getDefault().stopService(
730 mMainThread.getApplicationThread(), service,
731 service.resolveTypeIfNeeded(getContentResolver()));
732 if (res < 0) {
733 throw new SecurityException(
734 "Not allowed to stop service " + service);
735 }
736 return res != 0;
737 } catch (RemoteException e) {
738 return false;
739 }
740 }
741
742 @Override
743 public boolean bindService(Intent service, ServiceConnection conn,
744 int flags) {
745 IServiceConnection sd;
746 if (mPackageInfo != null) {
747 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
748 mMainThread.getHandler(), flags);
749 } else {
750 throw new RuntimeException("Not supported in system context");
751 }
752 try {
753 int res = ActivityManagerNative.getDefault().bindService(
754 mMainThread.getApplicationThread(), getActivityToken(),
755 service, service.resolveTypeIfNeeded(getContentResolver()),
756 sd, flags);
757 if (res < 0) {
758 throw new SecurityException(
759 "Not allowed to bind to service " + service);
760 }
761 return res != 0;
762 } catch (RemoteException e) {
763 return false;
764 }
765 }
766
767 @Override
768 public void unbindService(ServiceConnection conn) {
769 if (mPackageInfo != null) {
770 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
771 getOuterContext(), conn);
772 try {
773 ActivityManagerNative.getDefault().unbindService(sd);
774 } catch (RemoteException e) {
775 }
776 } else {
777 throw new RuntimeException("Not supported in system context");
778 }
779 }
780
781 @Override
782 public boolean startInstrumentation(ComponentName className,
783 String profileFile, Bundle arguments) {
784 try {
785 return ActivityManagerNative.getDefault().startInstrumentation(
786 className, profileFile, 0, arguments, null);
787 } catch (RemoteException e) {
788 // System has crashed, nothing we can do.
789 }
790 return false;
791 }
792
793 @Override
794 public Object getSystemService(String name) {
795 if (WINDOW_SERVICE.equals(name)) {
796 return WindowManagerImpl.getDefault();
797 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
798 synchronized (mSync) {
799 LayoutInflater inflater = mLayoutInflater;
800 if (inflater != null) {
801 return inflater;
802 }
803 mLayoutInflater = inflater =
804 PolicyManager.makeNewLayoutInflater(getOuterContext());
805 return inflater;
806 }
807 } else if (ACTIVITY_SERVICE.equals(name)) {
808 return getActivityManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700809 } else if (INPUT_METHOD_SERVICE.equals(name)) {
810 return InputMethodManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 } else if (ALARM_SERVICE.equals(name)) {
812 return getAlarmManager();
Fred Quintana60307342009-03-24 22:48:12 -0700813 } else if (ACCOUNT_SERVICE.equals(name)) {
814 return getAccountManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 } else if (POWER_SERVICE.equals(name)) {
816 return getPowerManager();
817 } else if (CONNECTIVITY_SERVICE.equals(name)) {
818 return getConnectivityManager();
819 } else if (WIFI_SERVICE.equals(name)) {
820 return getWifiManager();
821 } else if (NOTIFICATION_SERVICE.equals(name)) {
822 return getNotificationManager();
823 } else if (KEYGUARD_SERVICE.equals(name)) {
824 return new KeyguardManager();
svetoslavganov75986cf2009-05-14 22:28:01 -0700825 } else if (ACCESSIBILITY_SERVICE.equals(name)) {
826 return AccessibilityManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 } else if (LOCATION_SERVICE.equals(name)) {
828 return getLocationManager();
829 } else if (SEARCH_SERVICE.equals(name)) {
830 return getSearchManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700831 } else if (SENSOR_SERVICE.equals(name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 return getSensorManager();
833 } else if (BLUETOOTH_SERVICE.equals(name)) {
Nick Pellybd022f42009-08-14 18:33:38 -0700834 return getBluetoothAdapter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 } else if (VIBRATOR_SERVICE.equals(name)) {
836 return getVibrator();
837 } else if (STATUS_BAR_SERVICE.equals(name)) {
838 synchronized (mSync) {
839 if (mStatusBarManager == null) {
840 mStatusBarManager = new StatusBarManager(getOuterContext());
841 }
842 return mStatusBarManager;
843 }
844 } else if (AUDIO_SERVICE.equals(name)) {
845 return getAudioManager();
846 } else if (TELEPHONY_SERVICE.equals(name)) {
847 return getTelephonyManager();
848 } else if (CLIPBOARD_SERVICE.equals(name)) {
849 return getClipboardManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700850 } else if (WALLPAPER_SERVICE.equals(name)) {
851 return getWallpaperManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 }
853
854 return null;
855 }
856
Fred Quintana60307342009-03-24 22:48:12 -0700857 private AccountManager getAccountManager() {
858 synchronized (sSync) {
859 if (sAccountManager == null) {
860 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
861 IAccountManager service = IAccountManager.Stub.asInterface(b);
862 sAccountManager = new AccountManager(this, service);
863 }
864 }
865 return sAccountManager;
866 }
867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 private ActivityManager getActivityManager() {
869 synchronized (mSync) {
870 if (mActivityManager == null) {
871 mActivityManager = new ActivityManager(getOuterContext(),
872 mMainThread.getHandler());
873 }
874 }
875 return mActivityManager;
876 }
877
878 private AlarmManager getAlarmManager() {
879 synchronized (sSync) {
880 if (sAlarmManager == null) {
881 IBinder b = ServiceManager.getService(ALARM_SERVICE);
882 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
883 sAlarmManager = new AlarmManager(service);
884 }
885 }
886 return sAlarmManager;
887 }
888
889 private PowerManager getPowerManager() {
890 synchronized (sSync) {
891 if (sPowerManager == null) {
892 IBinder b = ServiceManager.getService(POWER_SERVICE);
893 IPowerManager service = IPowerManager.Stub.asInterface(b);
894 sPowerManager = new PowerManager(service, mMainThread.getHandler());
895 }
896 }
897 return sPowerManager;
898 }
899
900 private ConnectivityManager getConnectivityManager()
901 {
902 synchronized (sSync) {
903 if (sConnectivityManager == null) {
904 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
905 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
906 sConnectivityManager = new ConnectivityManager(service);
907 }
908 }
909 return sConnectivityManager;
910 }
911
912 private WifiManager getWifiManager()
913 {
914 synchronized (sSync) {
915 if (sWifiManager == null) {
916 IBinder b = ServiceManager.getService(WIFI_SERVICE);
917 IWifiManager service = IWifiManager.Stub.asInterface(b);
918 sWifiManager = new WifiManager(service, mMainThread.getHandler());
919 }
920 }
921 return sWifiManager;
922 }
923
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700924 private NotificationManager getNotificationManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 synchronized (mSync) {
926 if (mNotificationManager == null) {
927 mNotificationManager = new NotificationManager(
928 new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
929 mMainThread.getHandler());
930 }
931 }
932 return mNotificationManager;
933 }
934
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700935 private WallpaperManager getWallpaperManager() {
936 synchronized (mSync) {
937 if (mWallpaperManager == null) {
938 mWallpaperManager = new WallpaperManager(getOuterContext(),
939 mMainThread.getHandler());
940 }
941 }
942 return mWallpaperManager;
943 }
944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 private TelephonyManager getTelephonyManager() {
946 synchronized (mSync) {
947 if (mTelephonyManager == null) {
948 mTelephonyManager = new TelephonyManager(getOuterContext());
949 }
950 }
951 return mTelephonyManager;
952 }
953
954 private ClipboardManager getClipboardManager() {
955 synchronized (mSync) {
956 if (mClipboardManager == null) {
957 mClipboardManager = new ClipboardManager(getOuterContext(),
958 mMainThread.getHandler());
959 }
960 }
961 return mClipboardManager;
962 }
963
964 private LocationManager getLocationManager() {
965 synchronized (sSync) {
966 if (sLocationManager == null) {
967 IBinder b = ServiceManager.getService(LOCATION_SERVICE);
968 ILocationManager service = ILocationManager.Stub.asInterface(b);
969 sLocationManager = new LocationManager(service);
970 }
971 }
972 return sLocationManager;
973 }
974
975 private SearchManager getSearchManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 synchronized (mSync) {
977 if (mSearchManager == null) {
978 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
979 }
980 }
981 return mSearchManager;
982 }
983
Nick Pellybd022f42009-08-14 18:33:38 -0700984 private synchronized BluetoothAdapter getBluetoothAdapter() {
985 if (!mIsBluetoothAdapterCached) {
986 mIsBluetoothAdapterCached = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 IBinder b = ServiceManager.getService(BLUETOOTH_SERVICE);
Nick Pellybd022f42009-08-14 18:33:38 -0700988 if (b != null) {
989 IBluetooth service = IBluetooth.Stub.asInterface(b);
990 mBluetoothAdapter = new BluetoothAdapter(service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 }
Nick Pellybd022f42009-08-14 18:33:38 -0700993 return mBluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 }
995
996 private SensorManager getSensorManager() {
997 synchronized (mSync) {
998 if (mSensorManager == null) {
999 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1000 }
1001 }
1002 return mSensorManager;
1003 }
1004
1005 private Vibrator getVibrator() {
1006 synchronized (mSync) {
1007 if (mVibrator == null) {
1008 mVibrator = new Vibrator();
1009 }
1010 }
1011 return mVibrator;
1012 }
1013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 private AudioManager getAudioManager()
1015 {
1016 if (mAudioManager == null) {
1017 mAudioManager = new AudioManager(this);
1018 }
1019 return mAudioManager;
1020 }
1021
1022 @Override
1023 public int checkPermission(String permission, int pid, int uid) {
1024 if (permission == null) {
1025 throw new IllegalArgumentException("permission is null");
1026 }
1027
1028 if (!Process.supportsProcesses()) {
1029 return PackageManager.PERMISSION_GRANTED;
1030 }
1031 try {
1032 return ActivityManagerNative.getDefault().checkPermission(
1033 permission, pid, uid);
1034 } catch (RemoteException e) {
1035 return PackageManager.PERMISSION_DENIED;
1036 }
1037 }
1038
1039 @Override
1040 public int checkCallingPermission(String permission) {
1041 if (permission == null) {
1042 throw new IllegalArgumentException("permission is null");
1043 }
1044
1045 if (!Process.supportsProcesses()) {
1046 return PackageManager.PERMISSION_GRANTED;
1047 }
1048 int pid = Binder.getCallingPid();
1049 if (pid != Process.myPid()) {
1050 return checkPermission(permission, pid,
1051 Binder.getCallingUid());
1052 }
1053 return PackageManager.PERMISSION_DENIED;
1054 }
1055
1056 @Override
1057 public int checkCallingOrSelfPermission(String permission) {
1058 if (permission == null) {
1059 throw new IllegalArgumentException("permission is null");
1060 }
1061
1062 return checkPermission(permission, Binder.getCallingPid(),
1063 Binder.getCallingUid());
1064 }
1065
1066 private void enforce(
1067 String permission, int resultOfCheck,
1068 boolean selfToo, int uid, String message) {
1069 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1070 throw new SecurityException(
1071 (message != null ? (message + ": ") : "") +
1072 (selfToo
1073 ? "Neither user " + uid + " nor current process has "
1074 : "User " + uid + " does not have ") +
1075 permission +
1076 ".");
1077 }
1078 }
1079
1080 public void enforcePermission(
1081 String permission, int pid, int uid, String message) {
1082 enforce(permission,
1083 checkPermission(permission, pid, uid),
1084 false,
1085 uid,
1086 message);
1087 }
1088
1089 public void enforceCallingPermission(String permission, String message) {
1090 enforce(permission,
1091 checkCallingPermission(permission),
1092 false,
1093 Binder.getCallingUid(),
1094 message);
1095 }
1096
1097 public void enforceCallingOrSelfPermission(
1098 String permission, String message) {
1099 enforce(permission,
1100 checkCallingOrSelfPermission(permission),
1101 true,
1102 Binder.getCallingUid(),
1103 message);
1104 }
1105
1106 @Override
1107 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1108 try {
1109 ActivityManagerNative.getDefault().grantUriPermission(
1110 mMainThread.getApplicationThread(), toPackage, uri,
1111 modeFlags);
1112 } catch (RemoteException e) {
1113 }
1114 }
1115
1116 @Override
1117 public void revokeUriPermission(Uri uri, int modeFlags) {
1118 try {
1119 ActivityManagerNative.getDefault().revokeUriPermission(
1120 mMainThread.getApplicationThread(), uri,
1121 modeFlags);
1122 } catch (RemoteException e) {
1123 }
1124 }
1125
1126 @Override
1127 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1128 if (!Process.supportsProcesses()) {
1129 return PackageManager.PERMISSION_GRANTED;
1130 }
1131 try {
1132 return ActivityManagerNative.getDefault().checkUriPermission(
1133 uri, pid, uid, modeFlags);
1134 } catch (RemoteException e) {
1135 return PackageManager.PERMISSION_DENIED;
1136 }
1137 }
1138
1139 @Override
1140 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1141 if (!Process.supportsProcesses()) {
1142 return PackageManager.PERMISSION_GRANTED;
1143 }
1144 int pid = Binder.getCallingPid();
1145 if (pid != Process.myPid()) {
1146 return checkUriPermission(uri, pid,
1147 Binder.getCallingUid(), modeFlags);
1148 }
1149 return PackageManager.PERMISSION_DENIED;
1150 }
1151
1152 @Override
1153 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1154 return checkUriPermission(uri, Binder.getCallingPid(),
1155 Binder.getCallingUid(), modeFlags);
1156 }
1157
1158 @Override
1159 public int checkUriPermission(Uri uri, String readPermission,
1160 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001161 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1163 + readPermission + " writePermission=" + writePermission
1164 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1165 }
1166 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1167 if (readPermission == null
1168 || checkPermission(readPermission, pid, uid)
1169 == PackageManager.PERMISSION_GRANTED) {
1170 return PackageManager.PERMISSION_GRANTED;
1171 }
1172 }
1173 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1174 if (writePermission == null
1175 || checkPermission(writePermission, pid, uid)
1176 == PackageManager.PERMISSION_GRANTED) {
1177 return PackageManager.PERMISSION_GRANTED;
1178 }
1179 }
1180 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1181 : PackageManager.PERMISSION_DENIED;
1182 }
1183
1184 private String uriModeFlagToString(int uriModeFlags) {
1185 switch (uriModeFlags) {
1186 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1187 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1188 return "read and write";
1189 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1190 return "read";
1191 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1192 return "write";
1193 }
1194 throw new IllegalArgumentException(
1195 "Unknown permission mode flags: " + uriModeFlags);
1196 }
1197
1198 private void enforceForUri(
1199 int modeFlags, int resultOfCheck, boolean selfToo,
1200 int uid, Uri uri, String message) {
1201 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1202 throw new SecurityException(
1203 (message != null ? (message + ": ") : "") +
1204 (selfToo
1205 ? "Neither user " + uid + " nor current process has "
1206 : "User " + uid + " does not have ") +
1207 uriModeFlagToString(modeFlags) +
1208 " permission on " +
1209 uri +
1210 ".");
1211 }
1212 }
1213
1214 public void enforceUriPermission(
1215 Uri uri, int pid, int uid, int modeFlags, String message) {
1216 enforceForUri(
1217 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1218 false, uid, uri, message);
1219 }
1220
1221 public void enforceCallingUriPermission(
1222 Uri uri, int modeFlags, String message) {
1223 enforceForUri(
1224 modeFlags, checkCallingUriPermission(uri, modeFlags),
1225 false, Binder.getCallingUid(), uri, message);
1226 }
1227
1228 public void enforceCallingOrSelfUriPermission(
1229 Uri uri, int modeFlags, String message) {
1230 enforceForUri(
1231 modeFlags,
1232 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1233 Binder.getCallingUid(), uri, message);
1234 }
1235
1236 public void enforceUriPermission(
1237 Uri uri, String readPermission, String writePermission,
1238 int pid, int uid, int modeFlags, String message) {
1239 enforceForUri(modeFlags,
1240 checkUriPermission(
1241 uri, readPermission, writePermission, pid, uid,
1242 modeFlags),
1243 false,
1244 uid,
1245 uri,
1246 message);
1247 }
1248
1249 @Override
1250 public Context createPackageContext(String packageName, int flags)
1251 throws PackageManager.NameNotFoundException {
1252 if (packageName.equals("system") || packageName.equals("android")) {
1253 return new ApplicationContext(mMainThread.getSystemContext());
1254 }
1255
1256 ActivityThread.PackageInfo pi =
1257 mMainThread.getPackageInfo(packageName, flags);
1258 if (pi != null) {
1259 ApplicationContext c = new ApplicationContext();
Romain Guy870e09f2009-07-06 16:35:25 -07001260 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001261 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001262 if (c.mResources != null) {
1263 return c;
1264 }
1265 }
1266
1267 // Should be a better exception.
1268 throw new PackageManager.NameNotFoundException(
1269 "Application package " + packageName + " not found");
1270 }
1271
Romain Guy870e09f2009-07-06 16:35:25 -07001272 @Override
1273 public boolean isRestricted() {
1274 return mRestricted;
1275 }
1276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 private File getDataDirFile() {
1278 if (mPackageInfo != null) {
1279 return mPackageInfo.getDataDirFile();
1280 }
1281 throw new RuntimeException("Not supported in system context");
1282 }
1283
1284 @Override
1285 public File getDir(String name, int mode) {
1286 name = "app_" + name;
1287 File file = makeFilename(getDataDirFile(), name);
1288 if (!file.exists()) {
1289 file.mkdir();
1290 setFilePermissionsFromMode(file.getPath(), mode,
1291 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1292 }
1293 return file;
1294 }
1295
1296 static ApplicationContext createSystemContext(ActivityThread mainThread) {
1297 ApplicationContext context = new ApplicationContext();
1298 context.init(Resources.getSystem(), mainThread);
1299 return context;
1300 }
1301
1302 ApplicationContext() {
1303 ++sInstanceCount;
1304 mOuterContext = this;
1305 }
1306
1307 /**
1308 * Create a new ApplicationContext from an existing one. The new one
1309 * works and operates the same as the one it is copying.
1310 *
1311 * @param context Existing application context.
1312 */
1313 public ApplicationContext(ApplicationContext context) {
1314 ++sInstanceCount;
1315 mPackageInfo = context.mPackageInfo;
1316 mResources = context.mResources;
1317 mMainThread = context.mMainThread;
1318 mContentResolver = context.mContentResolver;
1319 mOuterContext = this;
1320 }
1321
1322 final void init(ActivityThread.PackageInfo packageInfo,
1323 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001324 init(packageInfo, activityToken, mainThread, null);
1325 }
1326
1327 final void init(ActivityThread.PackageInfo packageInfo,
1328 IBinder activityToken, ActivityThread mainThread,
1329 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 mPackageInfo = packageInfo;
1331 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001332
1333 if (container != null && container.getCompatibilityInfo().applicationScale !=
1334 mResources.getCompatibilityInfo().applicationScale) {
1335 if (DEBUG) {
1336 Log.d(TAG, "loaded context has different scaling. Using container's" +
1337 " compatiblity info:" + container.getDisplayMetrics());
1338 }
1339 mResources = mainThread.getTopLevelResources(
1340 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 mMainThread = mainThread;
1343 mContentResolver = new ApplicationContentResolver(this, mainThread);
1344
1345 setActivityToken(activityToken);
1346 }
1347
1348 final void init(Resources resources, ActivityThread mainThread) {
1349 mPackageInfo = null;
1350 mResources = resources;
1351 mMainThread = mainThread;
1352 mContentResolver = new ApplicationContentResolver(this, mainThread);
1353 }
1354
1355 final void scheduleFinalCleanup(String who, String what) {
1356 mMainThread.scheduleContextCleanup(this, who, what);
1357 }
1358
1359 final void performFinalCleanup(String who, String what) {
1360 //Log.i(TAG, "Cleanup up context: " + this);
1361 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1362 }
1363
1364 final Context getReceiverRestrictedContext() {
1365 if (mReceiverRestrictedContext != null) {
1366 return mReceiverRestrictedContext;
1367 }
1368 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1369 }
1370
1371 final void setActivityToken(IBinder token) {
1372 mActivityToken = token;
1373 }
1374
1375 final void setOuterContext(Context context) {
1376 mOuterContext = context;
1377 }
1378
1379 final Context getOuterContext() {
1380 return mOuterContext;
1381 }
1382
1383 final IBinder getActivityToken() {
1384 return mActivityToken;
1385 }
1386
1387 private static void setFilePermissionsFromMode(String name, int mode,
1388 int extraPermissions) {
1389 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1390 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1391 |extraPermissions;
1392 if ((mode&MODE_WORLD_READABLE) != 0) {
1393 perms |= FileUtils.S_IROTH;
1394 }
1395 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1396 perms |= FileUtils.S_IWOTH;
1397 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001398 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1400 + ", perms=0x" + Integer.toHexString(perms));
1401 }
1402 FileUtils.setPermissions(name, perms, -1, -1);
1403 }
1404
1405 private File makeFilename(File base, String name) {
1406 if (name.indexOf(File.separatorChar) < 0) {
1407 return new File(base, name);
1408 }
1409 throw new IllegalArgumentException(
1410 "File " + name + " contains a path separator");
1411 }
1412
1413 // ----------------------------------------------------------------------
1414 // ----------------------------------------------------------------------
1415 // ----------------------------------------------------------------------
1416
1417 private static final class ApplicationContentResolver extends ContentResolver {
1418 public ApplicationContentResolver(Context context,
1419 ActivityThread mainThread)
1420 {
1421 super(context);
1422 mMainThread = mainThread;
1423 }
1424
1425 @Override
1426 protected IContentProvider acquireProvider(Context context, String name)
1427 {
1428 return mMainThread.acquireProvider(context, name);
1429 }
1430
1431 @Override
1432 public boolean releaseProvider(IContentProvider provider)
1433 {
1434 return mMainThread.releaseProvider(provider);
1435 }
1436
1437 private final ActivityThread mMainThread;
1438 }
1439
1440 // ----------------------------------------------------------------------
1441 // ----------------------------------------------------------------------
1442 // ----------------------------------------------------------------------
1443
1444 /*package*/
1445 static final class ApplicationPackageManager extends PackageManager {
1446 @Override
1447 public PackageInfo getPackageInfo(String packageName, int flags)
1448 throws NameNotFoundException {
1449 try {
1450 PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1451 if (pi != null) {
1452 return pi;
1453 }
1454 } catch (RemoteException e) {
1455 throw new RuntimeException("Package manager has died", e);
1456 }
1457
1458 throw new NameNotFoundException(packageName);
1459 }
1460
Mihai Predaeae850c2009-05-13 10:13:48 +02001461 @Override
1462 public Intent getLaunchIntentForPackage(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 // First see if the package has an INFO activity; the existence of
1464 // such an activity is implied to be the desired front-door for the
1465 // overall package (such as if it has multiple launcher entries).
Mihai Predaeae850c2009-05-13 10:13:48 +02001466 Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1467 intentToResolve.addCategory(Intent.CATEGORY_INFO);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001468 intentToResolve.setPackage(packageName);
1469 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
Mihai Predaeae850c2009-05-13 10:13:48 +02001470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 // Otherwise, try to find a main launcher activity.
Mihai Predaeae850c2009-05-13 10:13:48 +02001472 if (resolveInfo == null) {
1473 // reuse the intent instance
1474 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1475 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001476 intentToResolve.setPackage(packageName);
1477 resolveInfo = resolveActivity(intentToResolve, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001479 if (resolveInfo == null) {
1480 return null;
1481 }
1482 Intent intent = new Intent(Intent.ACTION_MAIN);
1483 intent.setClassName(packageName, resolveInfo.activityInfo.name);
1484 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1485 return intent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 @Override
1489 public int[] getPackageGids(String packageName)
1490 throws NameNotFoundException {
1491 try {
1492 int[] gids = mPM.getPackageGids(packageName);
1493 if (gids == null || gids.length > 0) {
1494 return gids;
1495 }
1496 } catch (RemoteException e) {
1497 throw new RuntimeException("Package manager has died", e);
1498 }
1499
1500 throw new NameNotFoundException(packageName);
1501 }
1502
1503 @Override
1504 public PermissionInfo getPermissionInfo(String name, int flags)
1505 throws NameNotFoundException {
1506 try {
1507 PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1508 if (pi != null) {
1509 return pi;
1510 }
1511 } catch (RemoteException e) {
1512 throw new RuntimeException("Package manager has died", e);
1513 }
1514
1515 throw new NameNotFoundException(name);
1516 }
1517
1518 @Override
1519 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1520 throws NameNotFoundException {
1521 try {
1522 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1523 if (pi != null) {
1524 return pi;
1525 }
1526 } catch (RemoteException e) {
1527 throw new RuntimeException("Package manager has died", e);
1528 }
1529
1530 throw new NameNotFoundException(group);
1531 }
1532
1533 @Override
1534 public PermissionGroupInfo getPermissionGroupInfo(String name,
1535 int flags) throws NameNotFoundException {
1536 try {
1537 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1538 if (pgi != null) {
1539 return pgi;
1540 }
1541 } catch (RemoteException e) {
1542 throw new RuntimeException("Package manager has died", e);
1543 }
1544
1545 throw new NameNotFoundException(name);
1546 }
1547
1548 @Override
1549 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1550 try {
1551 return mPM.getAllPermissionGroups(flags);
1552 } catch (RemoteException e) {
1553 throw new RuntimeException("Package manager has died", e);
1554 }
1555 }
1556
1557 @Override
1558 public ApplicationInfo getApplicationInfo(String packageName, int flags)
1559 throws NameNotFoundException {
1560 try {
1561 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
1562 if (ai != null) {
1563 return ai;
1564 }
1565 } catch (RemoteException e) {
1566 throw new RuntimeException("Package manager has died", e);
1567 }
1568
1569 throw new NameNotFoundException(packageName);
1570 }
1571
1572 @Override
1573 public ActivityInfo getActivityInfo(ComponentName className, int flags)
1574 throws NameNotFoundException {
1575 try {
1576 ActivityInfo ai = mPM.getActivityInfo(className, flags);
1577 if (ai != null) {
1578 return ai;
1579 }
1580 } catch (RemoteException e) {
1581 throw new RuntimeException("Package manager has died", e);
1582 }
1583
1584 throw new NameNotFoundException(className.toString());
1585 }
1586
1587 @Override
1588 public ActivityInfo getReceiverInfo(ComponentName className, int flags)
1589 throws NameNotFoundException {
1590 try {
1591 ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1592 if (ai != null) {
1593 return ai;
1594 }
1595 } catch (RemoteException e) {
1596 throw new RuntimeException("Package manager has died", e);
1597 }
1598
1599 throw new NameNotFoundException(className.toString());
1600 }
1601
1602 @Override
1603 public ServiceInfo getServiceInfo(ComponentName className, int flags)
1604 throws NameNotFoundException {
1605 try {
1606 ServiceInfo si = mPM.getServiceInfo(className, flags);
1607 if (si != null) {
1608 return si;
1609 }
1610 } catch (RemoteException e) {
1611 throw new RuntimeException("Package manager has died", e);
1612 }
1613
1614 throw new NameNotFoundException(className.toString());
1615 }
1616
1617 @Override
1618 public String[] getSystemSharedLibraryNames() {
1619 try {
1620 return mPM.getSystemSharedLibraryNames();
1621 } catch (RemoteException e) {
1622 throw new RuntimeException("Package manager has died", e);
1623 }
1624 }
1625
1626 @Override
Dianne Hackborn49237342009-08-27 20:08:01 -07001627 public FeatureInfo[] getSystemAvailableFeatures() {
1628 try {
1629 return mPM.getSystemAvailableFeatures();
1630 } catch (RemoteException e) {
1631 throw new RuntimeException("Package manager has died", e);
1632 }
1633 }
1634
1635 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 public int checkPermission(String permName, String pkgName) {
1637 try {
1638 return mPM.checkPermission(permName, pkgName);
1639 } catch (RemoteException e) {
1640 throw new RuntimeException("Package manager has died", e);
1641 }
1642 }
1643
1644 @Override
1645 public boolean addPermission(PermissionInfo info) {
1646 try {
1647 return mPM.addPermission(info);
1648 } catch (RemoteException e) {
1649 throw new RuntimeException("Package manager has died", e);
1650 }
1651 }
1652
1653 @Override
1654 public void removePermission(String name) {
1655 try {
1656 mPM.removePermission(name);
1657 } catch (RemoteException e) {
1658 throw new RuntimeException("Package manager has died", e);
1659 }
1660 }
1661
1662 @Override
1663 public int checkSignatures(String pkg1, String pkg2) {
1664 try {
1665 return mPM.checkSignatures(pkg1, pkg2);
1666 } catch (RemoteException e) {
1667 throw new RuntimeException("Package manager has died", e);
1668 }
1669 }
1670
1671 @Override
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001672 public int checkSignatures(int uid1, int uid2) {
1673 try {
1674 return mPM.checkUidSignatures(uid1, uid2);
1675 } catch (RemoteException e) {
1676 throw new RuntimeException("Package manager has died", e);
1677 }
1678 }
1679
1680 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 public String[] getPackagesForUid(int uid) {
1682 try {
1683 return mPM.getPackagesForUid(uid);
1684 } catch (RemoteException e) {
1685 throw new RuntimeException("Package manager has died", e);
1686 }
1687 }
1688
1689 @Override
1690 public String getNameForUid(int uid) {
1691 try {
1692 return mPM.getNameForUid(uid);
1693 } catch (RemoteException e) {
1694 throw new RuntimeException("Package manager has died", e);
1695 }
1696 }
1697
1698 @Override
1699 public int getUidForSharedUser(String sharedUserName)
1700 throws NameNotFoundException {
1701 try {
1702 int uid = mPM.getUidForSharedUser(sharedUserName);
1703 if(uid != -1) {
1704 return uid;
1705 }
1706 } catch (RemoteException e) {
1707 throw new RuntimeException("Package manager has died", e);
1708 }
1709 throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1710 }
1711
1712 @Override
1713 public List<PackageInfo> getInstalledPackages(int flags) {
1714 try {
1715 return mPM.getInstalledPackages(flags);
1716 } catch (RemoteException e) {
1717 throw new RuntimeException("Package manager has died", e);
1718 }
1719 }
1720
1721 @Override
1722 public List<ApplicationInfo> getInstalledApplications(int flags) {
1723 try {
1724 return mPM.getInstalledApplications(flags);
1725 } catch (RemoteException e) {
1726 throw new RuntimeException("Package manager has died", e);
1727 }
1728 }
1729
1730 @Override
1731 public ResolveInfo resolveActivity(Intent intent, int flags) {
1732 try {
1733 return mPM.resolveIntent(
1734 intent,
1735 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1736 flags);
1737 } catch (RemoteException e) {
1738 throw new RuntimeException("Package manager has died", e);
1739 }
1740 }
1741
1742 @Override
1743 public List<ResolveInfo> queryIntentActivities(Intent intent,
1744 int flags) {
1745 try {
1746 return mPM.queryIntentActivities(
1747 intent,
1748 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1749 flags);
1750 } catch (RemoteException e) {
1751 throw new RuntimeException("Package manager has died", e);
1752 }
1753 }
1754
1755 @Override
1756 public List<ResolveInfo> queryIntentActivityOptions(
1757 ComponentName caller, Intent[] specifics, Intent intent,
1758 int flags) {
1759 final ContentResolver resolver = mContext.getContentResolver();
1760
1761 String[] specificTypes = null;
1762 if (specifics != null) {
1763 final int N = specifics.length;
1764 for (int i=0; i<N; i++) {
1765 Intent sp = specifics[i];
1766 if (sp != null) {
1767 String t = sp.resolveTypeIfNeeded(resolver);
1768 if (t != null) {
1769 if (specificTypes == null) {
1770 specificTypes = new String[N];
1771 }
1772 specificTypes[i] = t;
1773 }
1774 }
1775 }
1776 }
1777
1778 try {
1779 return mPM.queryIntentActivityOptions(caller, specifics,
1780 specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
1781 flags);
1782 } catch (RemoteException e) {
1783 throw new RuntimeException("Package manager has died", e);
1784 }
1785 }
1786
1787 @Override
1788 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
1789 try {
1790 return mPM.queryIntentReceivers(
1791 intent,
1792 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1793 flags);
1794 } catch (RemoteException e) {
1795 throw new RuntimeException("Package manager has died", e);
1796 }
1797 }
1798
1799 @Override
1800 public ResolveInfo resolveService(Intent intent, int flags) {
1801 try {
1802 return mPM.resolveService(
1803 intent,
1804 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1805 flags);
1806 } catch (RemoteException e) {
1807 throw new RuntimeException("Package manager has died", e);
1808 }
1809 }
1810
1811 @Override
1812 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
1813 try {
1814 return mPM.queryIntentServices(
1815 intent,
1816 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1817 flags);
1818 } catch (RemoteException e) {
1819 throw new RuntimeException("Package manager has died", e);
1820 }
1821 }
1822
1823 @Override
1824 public ProviderInfo resolveContentProvider(String name,
1825 int flags) {
1826 try {
1827 return mPM.resolveContentProvider(name, flags);
1828 } catch (RemoteException e) {
1829 throw new RuntimeException("Package manager has died", e);
1830 }
1831 }
1832
1833 @Override
1834 public List<ProviderInfo> queryContentProviders(String processName,
1835 int uid, int flags) {
1836 try {
1837 return mPM.queryContentProviders(processName, uid, flags);
1838 } catch (RemoteException e) {
1839 throw new RuntimeException("Package manager has died", e);
1840 }
1841 }
1842
1843 @Override
1844 public InstrumentationInfo getInstrumentationInfo(
1845 ComponentName className, int flags)
1846 throws NameNotFoundException {
1847 try {
1848 InstrumentationInfo ii = mPM.getInstrumentationInfo(
1849 className, flags);
1850 if (ii != null) {
1851 return ii;
1852 }
1853 } catch (RemoteException e) {
1854 throw new RuntimeException("Package manager has died", e);
1855 }
1856
1857 throw new NameNotFoundException(className.toString());
1858 }
1859
1860 @Override
1861 public List<InstrumentationInfo> queryInstrumentation(
1862 String targetPackage, int flags) {
1863 try {
1864 return mPM.queryInstrumentation(targetPackage, flags);
1865 } catch (RemoteException e) {
1866 throw new RuntimeException("Package manager has died", e);
1867 }
1868 }
1869
1870 @Override public Drawable getDrawable(String packageName, int resid,
1871 ApplicationInfo appInfo) {
1872 ResourceName name = new ResourceName(packageName, resid);
1873 Drawable dr = getCachedIcon(name);
1874 if (dr != null) {
1875 return dr;
1876 }
1877 if (appInfo == null) {
1878 try {
1879 appInfo = getApplicationInfo(packageName, 0);
1880 } catch (NameNotFoundException e) {
1881 return null;
1882 }
1883 }
1884 try {
1885 Resources r = getResourcesForApplication(appInfo);
1886 dr = r.getDrawable(resid);
Dianne Hackborn11ea3342009-07-22 21:48:55 -07001887 if (false) {
1888 RuntimeException e = new RuntimeException("here");
1889 e.fillInStackTrace();
1890 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
1891 + " from package " + packageName
1892 + ": app scale=" + r.getCompatibilityInfo().applicationScale
1893 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
1894 e);
1895 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
1897 + Integer.toHexString(resid) + " from " + r
1898 + ": " + dr);
1899 putCachedIcon(name, dr);
1900 return dr;
1901 } catch (NameNotFoundException e) {
1902 Log.w("PackageManager", "Failure retrieving resources for"
1903 + appInfo.packageName);
1904 } catch (RuntimeException e) {
1905 // If an exception was thrown, fall through to return
1906 // default icon.
1907 Log.w("PackageManager", "Failure retrieving icon 0x"
1908 + Integer.toHexString(resid) + " in package "
1909 + packageName, e);
1910 }
1911 return null;
1912 }
1913
1914 @Override public Drawable getActivityIcon(ComponentName activityName)
1915 throws NameNotFoundException {
1916 return getActivityInfo(activityName, 0).loadIcon(this);
1917 }
1918
1919 @Override public Drawable getActivityIcon(Intent intent)
1920 throws NameNotFoundException {
1921 if (intent.getComponent() != null) {
1922 return getActivityIcon(intent.getComponent());
1923 }
1924
1925 ResolveInfo info = resolveActivity(
1926 intent, PackageManager.MATCH_DEFAULT_ONLY);
1927 if (info != null) {
1928 return info.activityInfo.loadIcon(this);
1929 }
1930
1931 throw new NameNotFoundException(intent.toURI());
1932 }
1933
1934 @Override public Drawable getDefaultActivityIcon() {
1935 return Resources.getSystem().getDrawable(
1936 com.android.internal.R.drawable.sym_def_app_icon);
1937 }
1938
1939 @Override public Drawable getApplicationIcon(ApplicationInfo info) {
1940 final int icon = info.icon;
1941 if (icon != 0) {
1942 ResourceName name = new ResourceName(info, icon);
1943 Drawable dr = getCachedIcon(name);
1944 if (dr != null) {
1945 return dr;
1946 }
1947 try {
1948 Resources r = getResourcesForApplication(info);
1949 dr = r.getDrawable(icon);
1950 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
1951 + Integer.toHexString(icon) + " from " + r
1952 + ": " + dr);
1953 putCachedIcon(name, dr);
1954 return dr;
1955 } catch (NameNotFoundException e) {
1956 Log.w("PackageManager", "Failure retrieving resources for"
1957 + info.packageName);
1958 } catch (RuntimeException e) {
1959 // If an exception was thrown, fall through to return
1960 // default icon.
1961 Log.w("PackageManager", "Failure retrieving app icon", e);
1962 }
1963 }
1964 return getDefaultActivityIcon();
1965 }
1966
1967 @Override public Drawable getApplicationIcon(String packageName)
1968 throws NameNotFoundException {
1969 return getApplicationIcon(getApplicationInfo(packageName, 0));
1970 }
1971
1972 @Override public Resources getResourcesForActivity(
1973 ComponentName activityName) throws NameNotFoundException {
1974 return getResourcesForApplication(
1975 getActivityInfo(activityName, 0).applicationInfo);
1976 }
1977
1978 @Override public Resources getResourcesForApplication(
1979 ApplicationInfo app) throws NameNotFoundException {
1980 if (app.packageName.equals("system")) {
1981 return mContext.mMainThread.getSystemContext().getResources();
1982 }
1983 Resources r = mContext.mMainThread.getTopLevelResources(
1984 app.uid == Process.myUid() ? app.sourceDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -07001985 : app.publicSourceDir, mContext.mPackageInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 if (r != null) {
1987 return r;
1988 }
1989 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
1990 }
1991
1992 @Override public Resources getResourcesForApplication(
1993 String appPackageName) throws NameNotFoundException {
1994 return getResourcesForApplication(
1995 getApplicationInfo(appPackageName, 0));
1996 }
1997
1998 int mCachedSafeMode = -1;
1999 @Override public boolean isSafeMode() {
2000 try {
2001 if (mCachedSafeMode < 0) {
2002 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2003 }
2004 return mCachedSafeMode != 0;
2005 } catch (RemoteException e) {
2006 throw new RuntimeException("Package manager has died", e);
2007 }
2008 }
2009
2010 static void configurationChanged() {
2011 synchronized (sSync) {
2012 sIconCache.clear();
2013 sStringCache.clear();
2014 }
2015 }
2016
2017 ApplicationPackageManager(ApplicationContext context,
2018 IPackageManager pm) {
2019 mContext = context;
2020 mPM = pm;
2021 }
2022
2023 private Drawable getCachedIcon(ResourceName name) {
2024 synchronized (sSync) {
2025 WeakReference<Drawable> wr = sIconCache.get(name);
2026 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2027 + name + ": " + wr);
2028 if (wr != null) { // we have the activity
2029 Drawable dr = wr.get();
2030 if (dr != null) {
2031 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2032 + name + ": " + dr);
2033 return dr;
2034 }
2035 // our entry has been purged
2036 sIconCache.remove(name);
2037 }
2038 }
2039 return null;
2040 }
2041
2042 private void establishPackageRemovedReceiver() {
2043 // mContext.registerReceiverInternal() winds up acquiring the
2044 // main ActivityManagerService.this lock. If we hold our usual
2045 // sSync global lock at the same time, we impose a required ordering
2046 // on those two locks, which is not good for deadlock prevention.
2047 // Use a dedicated lock around initialization of
2048 // sPackageRemovedReceiver to avoid this.
2049 synchronized (sPackageRemovedSync) {
2050 if (sPackageRemovedReceiver == null) {
2051 sPackageRemovedReceiver = new PackageRemovedReceiver();
2052 IntentFilter filter = new IntentFilter(
2053 Intent.ACTION_PACKAGE_REMOVED);
2054 filter.addDataScheme("package");
2055 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2056 filter, null, null, null);
2057 }
2058 }
2059 }
2060
2061 private void putCachedIcon(ResourceName name, Drawable dr) {
2062 establishPackageRemovedReceiver();
2063
2064 synchronized (sSync) {
2065 sIconCache.put(name, new WeakReference<Drawable>(dr));
2066 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2067 + name + ": " + dr);
2068 }
2069 }
2070
2071 private static final class PackageRemovedReceiver extends BroadcastReceiver {
2072 @Override
2073 public void onReceive(Context context, Intent intent) {
2074 Uri data = intent.getData();
2075 String ssp;
2076 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
2077 boolean needCleanup = false;
2078 synchronized (sSync) {
2079 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2080 while (it.hasNext()) {
2081 ResourceName nm = it.next();
2082 if (nm.packageName.equals(ssp)) {
2083 //Log.i(TAG, "Removing cached drawable for " + nm);
2084 it.remove();
2085 needCleanup = true;
2086 }
2087 }
2088 it = sStringCache.keySet().iterator();
2089 while (it.hasNext()) {
2090 ResourceName nm = it.next();
2091 if (nm.packageName.equals(ssp)) {
2092 //Log.i(TAG, "Removing cached string for " + nm);
2093 it.remove();
2094 needCleanup = true;
2095 }
2096 }
2097 }
2098 if (needCleanup || ActivityThread.currentActivityThread().hasPackageInfo(ssp)) {
2099 ActivityThread.currentActivityThread().scheduleGcIdler();
2100 }
2101 }
2102 }
2103 }
2104
2105 private static final class ResourceName {
2106 final String packageName;
2107 final int iconId;
2108
2109 ResourceName(String _packageName, int _iconId) {
2110 packageName = _packageName;
2111 iconId = _iconId;
2112 }
2113
2114 ResourceName(ApplicationInfo aInfo, int _iconId) {
2115 this(aInfo.packageName, _iconId);
2116 }
2117
2118 ResourceName(ComponentInfo cInfo, int _iconId) {
2119 this(cInfo.applicationInfo.packageName, _iconId);
2120 }
2121
2122 ResourceName(ResolveInfo rInfo, int _iconId) {
2123 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2124 }
2125
2126 @Override
2127 public boolean equals(Object o) {
2128 if (this == o) return true;
2129 if (o == null || getClass() != o.getClass()) return false;
2130
2131 ResourceName that = (ResourceName) o;
2132
2133 if (iconId != that.iconId) return false;
2134 return !(packageName != null ?
2135 !packageName.equals(that.packageName) : that.packageName != null);
2136
2137 }
2138
2139 @Override
2140 public int hashCode() {
2141 int result;
2142 result = packageName.hashCode();
2143 result = 31 * result + iconId;
2144 return result;
2145 }
2146
2147 @Override
2148 public String toString() {
2149 return "{ResourceName " + packageName + " / " + iconId + "}";
2150 }
2151 }
2152
2153 private CharSequence getCachedString(ResourceName name) {
2154 synchronized (sSync) {
2155 WeakReference<CharSequence> wr = sStringCache.get(name);
2156 if (wr != null) { // we have the activity
2157 CharSequence cs = wr.get();
2158 if (cs != null) {
2159 return cs;
2160 }
2161 // our entry has been purged
2162 sStringCache.remove(name);
2163 }
2164 }
2165 return null;
2166 }
2167
2168 private void putCachedString(ResourceName name, CharSequence cs) {
2169 establishPackageRemovedReceiver();
2170
2171 synchronized (sSync) {
2172 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2173 }
2174 }
2175
2176 private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
2177 CharSequence cs = getCachedString(name);
2178 if (cs != null) {
2179 return cs;
2180 }
2181 try {
2182 Resources r = getResourcesForApplication(app);
2183 cs = r.getText(id);
2184 putCachedString(name, cs);
2185 } catch (NameNotFoundException e) {
2186 Log.w("PackageManager", "Failure retrieving resources for"
2187 + app.packageName);
2188 } catch (RuntimeException e) {
2189 // If an exception was thrown, fall through to return null
2190 Log.w("ApplicationInfo", "Failure retrieving activity name", e);
2191 }
2192 return cs;
2193 }
2194
2195 @Override
2196 public CharSequence getText(String packageName, int resid,
2197 ApplicationInfo appInfo) {
2198 ResourceName name = new ResourceName(packageName, resid);
2199 CharSequence text = getCachedString(name);
2200 if (text != null) {
2201 return text;
2202 }
2203 if (appInfo == null) {
2204 try {
2205 appInfo = getApplicationInfo(packageName, 0);
2206 } catch (NameNotFoundException e) {
2207 return null;
2208 }
2209 }
2210 try {
2211 Resources r = getResourcesForApplication(appInfo);
2212 text = r.getText(resid);
2213 putCachedString(name, text);
2214 return text;
2215 } catch (NameNotFoundException e) {
2216 Log.w("PackageManager", "Failure retrieving resources for"
2217 + appInfo.packageName);
2218 } catch (RuntimeException e) {
2219 // If an exception was thrown, fall through to return
2220 // default icon.
2221 Log.w("PackageManager", "Failure retrieving text 0x"
2222 + Integer.toHexString(resid) + " in package "
2223 + packageName, e);
2224 }
2225 return null;
2226 }
2227
2228 @Override
2229 public XmlResourceParser getXml(String packageName, int resid,
2230 ApplicationInfo appInfo) {
2231 if (appInfo == null) {
2232 try {
2233 appInfo = getApplicationInfo(packageName, 0);
2234 } catch (NameNotFoundException e) {
2235 return null;
2236 }
2237 }
2238 try {
2239 Resources r = getResourcesForApplication(appInfo);
2240 return r.getXml(resid);
2241 } catch (RuntimeException e) {
2242 // If an exception was thrown, fall through to return
2243 // default icon.
2244 Log.w("PackageManager", "Failure retrieving xml 0x"
2245 + Integer.toHexString(resid) + " in package "
2246 + packageName, e);
2247 } catch (NameNotFoundException e) {
2248 Log.w("PackageManager", "Failure retrieving resources for"
2249 + appInfo.packageName);
2250 }
2251 return null;
2252 }
2253
2254 @Override
2255 public CharSequence getApplicationLabel(ApplicationInfo info) {
2256 if (info.nonLocalizedLabel != null) {
2257 return info.nonLocalizedLabel;
2258 }
2259 final int id = info.labelRes;
2260 if (id != 0) {
2261 CharSequence cs = getLabel(new ResourceName(info, id), info, id);
2262 if (cs != null) {
2263 return cs;
2264 }
2265 }
2266 return info.packageName;
2267 }
2268
2269 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002270 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2271 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 try {
Jacek Surazski65e13172009-04-28 15:26:38 +02002273 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002274 } catch (RemoteException e) {
2275 // Should never happen!
2276 }
2277 }
2278
2279 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002280 public String getInstallerPackageName(String packageName) {
2281 try {
2282 return mPM.getInstallerPackageName(packageName);
2283 } catch (RemoteException e) {
2284 // Should never happen!
2285 }
2286 return null;
2287 }
2288
2289 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2291 try {
2292 mPM.deletePackage(packageName, observer, flags);
2293 } catch (RemoteException e) {
2294 // Should never happen!
2295 }
2296 }
2297 @Override
2298 public void clearApplicationUserData(String packageName,
2299 IPackageDataObserver observer) {
2300 try {
2301 mPM.clearApplicationUserData(packageName, observer);
2302 } catch (RemoteException e) {
2303 // Should never happen!
2304 }
2305 }
2306 @Override
2307 public void deleteApplicationCacheFiles(String packageName,
2308 IPackageDataObserver observer) {
2309 try {
2310 mPM.deleteApplicationCacheFiles(packageName, observer);
2311 } catch (RemoteException e) {
2312 // Should never happen!
2313 }
2314 }
2315 @Override
2316 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2317 try {
2318 mPM.freeStorageAndNotify(idealStorageSize, observer);
2319 } catch (RemoteException e) {
2320 // Should never happen!
2321 }
2322 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002324 @Override
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002325 public void freeStorage(long freeStorageSize, IntentSender pi) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002326 try {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002327 mPM.freeStorage(freeStorageSize, pi);
2328 } catch (RemoteException e) {
2329 // Should never happen!
2330 }
2331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002332
2333 @Override
2334 public void getPackageSizeInfo(String packageName,
2335 IPackageStatsObserver observer) {
2336 try {
2337 mPM.getPackageSizeInfo(packageName, observer);
2338 } catch (RemoteException e) {
2339 // Should never happen!
2340 }
2341 }
2342 @Override
2343 public void addPackageToPreferred(String packageName) {
2344 try {
2345 mPM.addPackageToPreferred(packageName);
2346 } catch (RemoteException e) {
2347 // Should never happen!
2348 }
2349 }
2350
2351 @Override
2352 public void removePackageFromPreferred(String packageName) {
2353 try {
2354 mPM.removePackageFromPreferred(packageName);
2355 } catch (RemoteException e) {
2356 // Should never happen!
2357 }
2358 }
2359
2360 @Override
2361 public List<PackageInfo> getPreferredPackages(int flags) {
2362 try {
2363 return mPM.getPreferredPackages(flags);
2364 } catch (RemoteException e) {
2365 // Should never happen!
2366 }
2367 return new ArrayList<PackageInfo>();
2368 }
2369
2370 @Override
2371 public void addPreferredActivity(IntentFilter filter,
2372 int match, ComponentName[] set, ComponentName activity) {
2373 try {
2374 mPM.addPreferredActivity(filter, match, set, activity);
2375 } catch (RemoteException e) {
2376 // Should never happen!
2377 }
2378 }
2379
2380 @Override
Satish Sampath8dbe6122009-06-02 23:35:54 +01002381 public void replacePreferredActivity(IntentFilter filter,
2382 int match, ComponentName[] set, ComponentName activity) {
2383 try {
2384 mPM.replacePreferredActivity(filter, match, set, activity);
2385 } catch (RemoteException e) {
2386 // Should never happen!
2387 }
2388 }
2389
2390 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002391 public void clearPackagePreferredActivities(String packageName) {
2392 try {
2393 mPM.clearPackagePreferredActivities(packageName);
2394 } catch (RemoteException e) {
2395 // Should never happen!
2396 }
2397 }
2398
2399 @Override
2400 public int getPreferredActivities(List<IntentFilter> outFilters,
2401 List<ComponentName> outActivities, String packageName) {
2402 try {
2403 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2404 } catch (RemoteException e) {
2405 // Should never happen!
2406 }
2407 return 0;
2408 }
2409
2410 @Override
2411 public void setComponentEnabledSetting(ComponentName componentName,
2412 int newState, int flags) {
2413 try {
2414 mPM.setComponentEnabledSetting(componentName, newState, flags);
2415 } catch (RemoteException e) {
2416 // Should never happen!
2417 }
2418 }
2419
2420 @Override
2421 public int getComponentEnabledSetting(ComponentName componentName) {
2422 try {
2423 return mPM.getComponentEnabledSetting(componentName);
2424 } catch (RemoteException e) {
2425 // Should never happen!
2426 }
2427 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2428 }
2429
2430 @Override
2431 public void setApplicationEnabledSetting(String packageName,
2432 int newState, int flags) {
2433 try {
2434 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2435 } catch (RemoteException e) {
2436 // Should never happen!
2437 }
2438 }
2439
2440 @Override
2441 public int getApplicationEnabledSetting(String packageName) {
2442 try {
2443 return mPM.getApplicationEnabledSetting(packageName);
2444 } catch (RemoteException e) {
2445 // Should never happen!
2446 }
2447 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2448 }
2449
2450 private final ApplicationContext mContext;
2451 private final IPackageManager mPM;
2452
2453 private static final Object sSync = new Object();
2454 private static final Object sPackageRemovedSync = new Object();
2455 private static BroadcastReceiver sPackageRemovedReceiver;
2456 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2457 = new HashMap<ResourceName, WeakReference<Drawable> >();
2458 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2459 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2460 }
2461
2462 // ----------------------------------------------------------------------
2463 // ----------------------------------------------------------------------
2464 // ----------------------------------------------------------------------
2465
2466 private static final class SharedPreferencesImpl implements SharedPreferences {
2467
2468 private final File mFile;
2469 private final File mBackupFile;
2470 private final int mMode;
2471 private Map mMap;
2472 private final FileStatus mFileStatus = new FileStatus();
2473 private long mTimestamp;
2474
The Android Open Source Project10592532009-03-18 17:39:46 -07002475 private static final Object mContent = new Object();
2476 private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477
2478 SharedPreferencesImpl(
2479 File file, int mode, Map initialContents) {
2480 mFile = file;
2481 mBackupFile = makeBackupFile(file);
2482 mMode = mode;
2483 mMap = initialContents != null ? initialContents : new HashMap();
2484 if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
2485 mTimestamp = mFileStatus.mtime;
2486 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002487 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002488 }
2489
2490 public boolean hasFileChanged() {
2491 synchronized (this) {
2492 if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2493 return true;
2494 }
2495 return mTimestamp != mFileStatus.mtime;
2496 }
2497 }
2498
2499 public void replace(Map newContents) {
2500 if (newContents != null) {
2501 synchronized (this) {
2502 mMap = newContents;
2503 }
2504 }
2505 }
2506
2507 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2508 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002509 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 }
2511 }
2512
2513 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2514 synchronized(this) {
2515 mListeners.remove(listener);
2516 }
2517 }
2518
2519 public Map<String, ?> getAll() {
2520 synchronized(this) {
2521 //noinspection unchecked
2522 return new HashMap(mMap);
2523 }
2524 }
2525
2526 public String getString(String key, String defValue) {
2527 synchronized (this) {
2528 String v = (String)mMap.get(key);
2529 return v != null ? v : defValue;
2530 }
2531 }
2532
2533 public int getInt(String key, int defValue) {
2534 synchronized (this) {
2535 Integer v = (Integer)mMap.get(key);
2536 return v != null ? v : defValue;
2537 }
2538 }
2539 public long getLong(String key, long defValue) {
2540 synchronized (this) {
2541 Long v = (Long) mMap.get(key);
2542 return v != null ? v : defValue;
2543 }
2544 }
2545 public float getFloat(String key, float defValue) {
2546 synchronized (this) {
2547 Float v = (Float)mMap.get(key);
2548 return v != null ? v : defValue;
2549 }
2550 }
2551 public boolean getBoolean(String key, boolean defValue) {
2552 synchronized (this) {
2553 Boolean v = (Boolean)mMap.get(key);
2554 return v != null ? v : defValue;
2555 }
2556 }
2557
2558 public boolean contains(String key) {
2559 synchronized (this) {
2560 return mMap.containsKey(key);
2561 }
2562 }
2563
2564 public final class EditorImpl implements Editor {
2565 private final Map<String, Object> mModified = Maps.newHashMap();
2566 private boolean mClear = false;
2567
2568 public Editor putString(String key, String value) {
2569 synchronized (this) {
2570 mModified.put(key, value);
2571 return this;
2572 }
2573 }
2574 public Editor putInt(String key, int value) {
2575 synchronized (this) {
2576 mModified.put(key, value);
2577 return this;
2578 }
2579 }
2580 public Editor putLong(String key, long value) {
2581 synchronized (this) {
2582 mModified.put(key, value);
2583 return this;
2584 }
2585 }
2586 public Editor putFloat(String key, float value) {
2587 synchronized (this) {
2588 mModified.put(key, value);
2589 return this;
2590 }
2591 }
2592 public Editor putBoolean(String key, boolean value) {
2593 synchronized (this) {
2594 mModified.put(key, value);
2595 return this;
2596 }
2597 }
2598
2599 public Editor remove(String key) {
2600 synchronized (this) {
2601 mModified.put(key, this);
2602 return this;
2603 }
2604 }
2605
2606 public Editor clear() {
2607 synchronized (this) {
2608 mClear = true;
2609 return this;
2610 }
2611 }
2612
2613 public boolean commit() {
2614 boolean returnValue;
2615
2616 boolean hasListeners;
2617 List<String> keysModified = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07002618 Set<OnSharedPreferenceChangeListener> listeners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619
2620 synchronized (SharedPreferencesImpl.this) {
2621 hasListeners = mListeners.size() > 0;
2622 if (hasListeners) {
2623 keysModified = new ArrayList<String>();
The Android Open Source Project10592532009-03-18 17:39:46 -07002624 listeners =
2625 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 }
2627
2628 synchronized (this) {
2629 if (mClear) {
2630 mMap.clear();
2631 mClear = false;
2632 }
2633
The Android Open Source Project10592532009-03-18 17:39:46 -07002634 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 String k = e.getKey();
2636 Object v = e.getValue();
2637 if (v == this) {
2638 mMap.remove(k);
2639 } else {
2640 mMap.put(k, v);
2641 }
2642
2643 if (hasListeners) {
2644 keysModified.add(k);
2645 }
2646 }
2647
2648 mModified.clear();
2649 }
2650
2651 returnValue = writeFileLocked();
2652 }
2653
2654 if (hasListeners) {
2655 for (int i = keysModified.size() - 1; i >= 0; i--) {
2656 final String key = keysModified.get(i);
The Android Open Source Project10592532009-03-18 17:39:46 -07002657 for (OnSharedPreferenceChangeListener listener : listeners) {
2658 if (listener != null) {
2659 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
2660 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 }
2662 }
2663 }
2664
2665 return returnValue;
2666 }
2667 }
2668
2669 public Editor edit() {
2670 return new EditorImpl();
2671 }
2672
2673 private FileOutputStream createFileOutputStream(File file) {
2674 FileOutputStream str = null;
2675 try {
2676 str = new FileOutputStream(file);
2677 } catch (FileNotFoundException e) {
2678 File parent = file.getParentFile();
2679 if (!parent.mkdir()) {
2680 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
2681 return null;
2682 }
2683 FileUtils.setPermissions(
2684 parent.getPath(),
2685 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2686 -1, -1);
2687 try {
2688 str = new FileOutputStream(file);
2689 } catch (FileNotFoundException e2) {
2690 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
2691 }
2692 }
2693 return str;
2694 }
2695
2696 private boolean writeFileLocked() {
2697 // Rename the current file so it may be used as a backup during the next read
2698 if (mFile.exists()) {
2699 if (!mFile.renameTo(mBackupFile)) {
2700 Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
2701 }
2702 }
2703
2704 // Attempt to write the file, delete the backup and return true as atomically as
2705 // possible. If any exception occurs, delete the new file; next time we will restore
2706 // from the backup.
2707 try {
2708 FileOutputStream str = createFileOutputStream(mFile);
2709 if (str == null) {
2710 return false;
2711 }
2712 XmlUtils.writeMapXml(mMap, str);
2713 str.close();
2714 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
2715 if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2716 mTimestamp = mFileStatus.mtime;
2717 }
2718
Dianne Hackborn51bf0772009-03-24 19:11:41 -07002719 // Writing was successful, delete the backup file if there is one.
2720 mBackupFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002721 return true;
2722 } catch (XmlPullParserException e) {
2723 Log.w(TAG, "writeFileLocked: Got exception:", e);
2724 } catch (IOException e) {
2725 Log.w(TAG, "writeFileLocked: Got exception:", e);
2726 }
2727 // Clean up an unsuccessfully written file
2728 if (mFile.exists()) {
2729 if (!mFile.delete()) {
2730 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
2731 }
2732 }
2733 return false;
2734 }
2735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736}