blob: dc8d873ebce10993a07636173b9c92933e17136a [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
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700564 public void startIntentSender(IntentSender intent,
565 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
566 throws IntentSender.SendIntentException {
567 try {
568 String resolvedType = null;
569 if (fillInIntent != null) {
570 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
571 }
572 int result = ActivityManagerNative.getDefault()
573 .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
574 fillInIntent, resolvedType, null, null,
575 0, flagsMask, flagsValues);
576 if (result == IActivityManager.START_CANCELED) {
577 throw new IntentSender.SendIntentException();
578 }
579 Instrumentation.checkStartActivityResult(result, null);
580 } catch (RemoteException e) {
581 }
582 }
583
584 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 public void sendBroadcast(Intent intent) {
586 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
587 try {
588 ActivityManagerNative.getDefault().broadcastIntent(
589 mMainThread.getApplicationThread(), intent, resolvedType, null,
590 Activity.RESULT_OK, null, null, null, false, false);
591 } catch (RemoteException e) {
592 }
593 }
594
595 @Override
596 public void sendBroadcast(Intent intent, String receiverPermission) {
597 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
598 try {
599 ActivityManagerNative.getDefault().broadcastIntent(
600 mMainThread.getApplicationThread(), intent, resolvedType, null,
601 Activity.RESULT_OK, null, null, receiverPermission, false, false);
602 } catch (RemoteException e) {
603 }
604 }
605
606 @Override
607 public void sendOrderedBroadcast(Intent intent,
608 String receiverPermission) {
609 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
610 try {
611 ActivityManagerNative.getDefault().broadcastIntent(
612 mMainThread.getApplicationThread(), intent, resolvedType, null,
613 Activity.RESULT_OK, null, null, receiverPermission, true, false);
614 } catch (RemoteException e) {
615 }
616 }
617
618 @Override
619 public void sendOrderedBroadcast(Intent intent,
620 String receiverPermission, BroadcastReceiver resultReceiver,
621 Handler scheduler, int initialCode, String initialData,
622 Bundle initialExtras) {
623 IIntentReceiver rd = null;
624 if (resultReceiver != null) {
625 if (mPackageInfo != null) {
626 if (scheduler == null) {
627 scheduler = mMainThread.getHandler();
628 }
629 rd = mPackageInfo.getReceiverDispatcher(
630 resultReceiver, getOuterContext(), scheduler,
631 mMainThread.getInstrumentation(), false);
632 } else {
633 if (scheduler == null) {
634 scheduler = mMainThread.getHandler();
635 }
636 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
637 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
638 }
639 }
640 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
641 try {
642 ActivityManagerNative.getDefault().broadcastIntent(
643 mMainThread.getApplicationThread(), intent, resolvedType, rd,
644 initialCode, initialData, initialExtras, receiverPermission,
645 true, false);
646 } catch (RemoteException e) {
647 }
648 }
649
650 @Override
651 public void sendStickyBroadcast(Intent intent) {
652 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
653 try {
654 ActivityManagerNative.getDefault().broadcastIntent(
655 mMainThread.getApplicationThread(), intent, resolvedType, null,
656 Activity.RESULT_OK, null, null, null, false, true);
657 } catch (RemoteException e) {
658 }
659 }
660
661 @Override
662 public void removeStickyBroadcast(Intent intent) {
663 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
664 if (resolvedType != null) {
665 intent = new Intent(intent);
666 intent.setDataAndType(intent.getData(), resolvedType);
667 }
668 try {
669 ActivityManagerNative.getDefault().unbroadcastIntent(
670 mMainThread.getApplicationThread(), intent);
671 } catch (RemoteException e) {
672 }
673 }
674
675 @Override
676 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
677 return registerReceiver(receiver, filter, null, null);
678 }
679
680 @Override
681 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
682 String broadcastPermission, Handler scheduler) {
683 return registerReceiverInternal(receiver, filter, broadcastPermission,
684 scheduler, getOuterContext());
685 }
686
687 private Intent registerReceiverInternal(BroadcastReceiver receiver,
688 IntentFilter filter, String broadcastPermission,
689 Handler scheduler, Context context) {
690 IIntentReceiver rd = null;
691 if (receiver != null) {
692 if (mPackageInfo != null && context != null) {
693 if (scheduler == null) {
694 scheduler = mMainThread.getHandler();
695 }
696 rd = mPackageInfo.getReceiverDispatcher(
697 receiver, context, scheduler,
698 mMainThread.getInstrumentation(), true);
699 } else {
700 if (scheduler == null) {
701 scheduler = mMainThread.getHandler();
702 }
703 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
704 receiver, context, scheduler, null, false).getIIntentReceiver();
705 }
706 }
707 try {
708 return ActivityManagerNative.getDefault().registerReceiver(
709 mMainThread.getApplicationThread(),
710 rd, filter, broadcastPermission);
711 } catch (RemoteException e) {
712 return null;
713 }
714 }
715
716 @Override
717 public void unregisterReceiver(BroadcastReceiver receiver) {
718 if (mPackageInfo != null) {
719 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
720 getOuterContext(), receiver);
721 try {
722 ActivityManagerNative.getDefault().unregisterReceiver(rd);
723 } catch (RemoteException e) {
724 }
725 } else {
726 throw new RuntimeException("Not supported in system context");
727 }
728 }
729
730 @Override
731 public ComponentName startService(Intent service) {
732 try {
733 ComponentName cn = ActivityManagerNative.getDefault().startService(
734 mMainThread.getApplicationThread(), service,
735 service.resolveTypeIfNeeded(getContentResolver()));
736 if (cn != null && cn.getPackageName().equals("!")) {
737 throw new SecurityException(
738 "Not allowed to start service " + service
739 + " without permission " + cn.getClassName());
740 }
741 return cn;
742 } catch (RemoteException e) {
743 return null;
744 }
745 }
746
747 @Override
748 public boolean stopService(Intent service) {
749 try {
750 int res = ActivityManagerNative.getDefault().stopService(
751 mMainThread.getApplicationThread(), service,
752 service.resolveTypeIfNeeded(getContentResolver()));
753 if (res < 0) {
754 throw new SecurityException(
755 "Not allowed to stop service " + service);
756 }
757 return res != 0;
758 } catch (RemoteException e) {
759 return false;
760 }
761 }
762
763 @Override
764 public boolean bindService(Intent service, ServiceConnection conn,
765 int flags) {
766 IServiceConnection sd;
767 if (mPackageInfo != null) {
768 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
769 mMainThread.getHandler(), flags);
770 } else {
771 throw new RuntimeException("Not supported in system context");
772 }
773 try {
774 int res = ActivityManagerNative.getDefault().bindService(
775 mMainThread.getApplicationThread(), getActivityToken(),
776 service, service.resolveTypeIfNeeded(getContentResolver()),
777 sd, flags);
778 if (res < 0) {
779 throw new SecurityException(
780 "Not allowed to bind to service " + service);
781 }
782 return res != 0;
783 } catch (RemoteException e) {
784 return false;
785 }
786 }
787
788 @Override
789 public void unbindService(ServiceConnection conn) {
790 if (mPackageInfo != null) {
791 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
792 getOuterContext(), conn);
793 try {
794 ActivityManagerNative.getDefault().unbindService(sd);
795 } catch (RemoteException e) {
796 }
797 } else {
798 throw new RuntimeException("Not supported in system context");
799 }
800 }
801
802 @Override
803 public boolean startInstrumentation(ComponentName className,
804 String profileFile, Bundle arguments) {
805 try {
806 return ActivityManagerNative.getDefault().startInstrumentation(
807 className, profileFile, 0, arguments, null);
808 } catch (RemoteException e) {
809 // System has crashed, nothing we can do.
810 }
811 return false;
812 }
813
814 @Override
815 public Object getSystemService(String name) {
816 if (WINDOW_SERVICE.equals(name)) {
817 return WindowManagerImpl.getDefault();
818 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
819 synchronized (mSync) {
820 LayoutInflater inflater = mLayoutInflater;
821 if (inflater != null) {
822 return inflater;
823 }
824 mLayoutInflater = inflater =
825 PolicyManager.makeNewLayoutInflater(getOuterContext());
826 return inflater;
827 }
828 } else if (ACTIVITY_SERVICE.equals(name)) {
829 return getActivityManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700830 } else if (INPUT_METHOD_SERVICE.equals(name)) {
831 return InputMethodManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 } else if (ALARM_SERVICE.equals(name)) {
833 return getAlarmManager();
Fred Quintana60307342009-03-24 22:48:12 -0700834 } else if (ACCOUNT_SERVICE.equals(name)) {
835 return getAccountManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 } else if (POWER_SERVICE.equals(name)) {
837 return getPowerManager();
838 } else if (CONNECTIVITY_SERVICE.equals(name)) {
839 return getConnectivityManager();
840 } else if (WIFI_SERVICE.equals(name)) {
841 return getWifiManager();
842 } else if (NOTIFICATION_SERVICE.equals(name)) {
843 return getNotificationManager();
844 } else if (KEYGUARD_SERVICE.equals(name)) {
845 return new KeyguardManager();
svetoslavganov75986cf2009-05-14 22:28:01 -0700846 } else if (ACCESSIBILITY_SERVICE.equals(name)) {
847 return AccessibilityManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 } else if (LOCATION_SERVICE.equals(name)) {
849 return getLocationManager();
850 } else if (SEARCH_SERVICE.equals(name)) {
851 return getSearchManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700852 } else if (SENSOR_SERVICE.equals(name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 return getSensorManager();
854 } else if (BLUETOOTH_SERVICE.equals(name)) {
Nick Pellybd022f42009-08-14 18:33:38 -0700855 return getBluetoothAdapter();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 } else if (VIBRATOR_SERVICE.equals(name)) {
857 return getVibrator();
858 } else if (STATUS_BAR_SERVICE.equals(name)) {
859 synchronized (mSync) {
860 if (mStatusBarManager == null) {
861 mStatusBarManager = new StatusBarManager(getOuterContext());
862 }
863 return mStatusBarManager;
864 }
865 } else if (AUDIO_SERVICE.equals(name)) {
866 return getAudioManager();
867 } else if (TELEPHONY_SERVICE.equals(name)) {
868 return getTelephonyManager();
869 } else if (CLIPBOARD_SERVICE.equals(name)) {
870 return getClipboardManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700871 } else if (WALLPAPER_SERVICE.equals(name)) {
872 return getWallpaperManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
874
875 return null;
876 }
877
Fred Quintana60307342009-03-24 22:48:12 -0700878 private AccountManager getAccountManager() {
879 synchronized (sSync) {
880 if (sAccountManager == null) {
881 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
882 IAccountManager service = IAccountManager.Stub.asInterface(b);
883 sAccountManager = new AccountManager(this, service);
884 }
885 }
886 return sAccountManager;
887 }
888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800889 private ActivityManager getActivityManager() {
890 synchronized (mSync) {
891 if (mActivityManager == null) {
892 mActivityManager = new ActivityManager(getOuterContext(),
893 mMainThread.getHandler());
894 }
895 }
896 return mActivityManager;
897 }
898
899 private AlarmManager getAlarmManager() {
900 synchronized (sSync) {
901 if (sAlarmManager == null) {
902 IBinder b = ServiceManager.getService(ALARM_SERVICE);
903 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
904 sAlarmManager = new AlarmManager(service);
905 }
906 }
907 return sAlarmManager;
908 }
909
910 private PowerManager getPowerManager() {
911 synchronized (sSync) {
912 if (sPowerManager == null) {
913 IBinder b = ServiceManager.getService(POWER_SERVICE);
914 IPowerManager service = IPowerManager.Stub.asInterface(b);
915 sPowerManager = new PowerManager(service, mMainThread.getHandler());
916 }
917 }
918 return sPowerManager;
919 }
920
921 private ConnectivityManager getConnectivityManager()
922 {
923 synchronized (sSync) {
924 if (sConnectivityManager == null) {
925 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
926 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
927 sConnectivityManager = new ConnectivityManager(service);
928 }
929 }
930 return sConnectivityManager;
931 }
932
933 private WifiManager getWifiManager()
934 {
935 synchronized (sSync) {
936 if (sWifiManager == null) {
937 IBinder b = ServiceManager.getService(WIFI_SERVICE);
938 IWifiManager service = IWifiManager.Stub.asInterface(b);
939 sWifiManager = new WifiManager(service, mMainThread.getHandler());
940 }
941 }
942 return sWifiManager;
943 }
944
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700945 private NotificationManager getNotificationManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 synchronized (mSync) {
947 if (mNotificationManager == null) {
948 mNotificationManager = new NotificationManager(
949 new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
950 mMainThread.getHandler());
951 }
952 }
953 return mNotificationManager;
954 }
955
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700956 private WallpaperManager getWallpaperManager() {
957 synchronized (mSync) {
958 if (mWallpaperManager == null) {
959 mWallpaperManager = new WallpaperManager(getOuterContext(),
960 mMainThread.getHandler());
961 }
962 }
963 return mWallpaperManager;
964 }
965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 private TelephonyManager getTelephonyManager() {
967 synchronized (mSync) {
968 if (mTelephonyManager == null) {
969 mTelephonyManager = new TelephonyManager(getOuterContext());
970 }
971 }
972 return mTelephonyManager;
973 }
974
975 private ClipboardManager getClipboardManager() {
976 synchronized (mSync) {
977 if (mClipboardManager == null) {
978 mClipboardManager = new ClipboardManager(getOuterContext(),
979 mMainThread.getHandler());
980 }
981 }
982 return mClipboardManager;
983 }
984
985 private LocationManager getLocationManager() {
986 synchronized (sSync) {
987 if (sLocationManager == null) {
988 IBinder b = ServiceManager.getService(LOCATION_SERVICE);
989 ILocationManager service = ILocationManager.Stub.asInterface(b);
990 sLocationManager = new LocationManager(service);
991 }
992 }
993 return sLocationManager;
994 }
995
996 private SearchManager getSearchManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 synchronized (mSync) {
998 if (mSearchManager == null) {
999 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
1000 }
1001 }
1002 return mSearchManager;
1003 }
1004
Nick Pellybd022f42009-08-14 18:33:38 -07001005 private synchronized BluetoothAdapter getBluetoothAdapter() {
1006 if (!mIsBluetoothAdapterCached) {
1007 mIsBluetoothAdapterCached = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 IBinder b = ServiceManager.getService(BLUETOOTH_SERVICE);
Nick Pellybd022f42009-08-14 18:33:38 -07001009 if (b != null) {
1010 IBluetooth service = IBluetooth.Stub.asInterface(b);
1011 mBluetoothAdapter = new BluetoothAdapter(service);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 }
Nick Pellybd022f42009-08-14 18:33:38 -07001014 return mBluetoothAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 }
1016
1017 private SensorManager getSensorManager() {
1018 synchronized (mSync) {
1019 if (mSensorManager == null) {
1020 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1021 }
1022 }
1023 return mSensorManager;
1024 }
1025
1026 private Vibrator getVibrator() {
1027 synchronized (mSync) {
1028 if (mVibrator == null) {
1029 mVibrator = new Vibrator();
1030 }
1031 }
1032 return mVibrator;
1033 }
1034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 private AudioManager getAudioManager()
1036 {
1037 if (mAudioManager == null) {
1038 mAudioManager = new AudioManager(this);
1039 }
1040 return mAudioManager;
1041 }
1042
1043 @Override
1044 public int checkPermission(String permission, int pid, int uid) {
1045 if (permission == null) {
1046 throw new IllegalArgumentException("permission is null");
1047 }
1048
1049 if (!Process.supportsProcesses()) {
1050 return PackageManager.PERMISSION_GRANTED;
1051 }
1052 try {
1053 return ActivityManagerNative.getDefault().checkPermission(
1054 permission, pid, uid);
1055 } catch (RemoteException e) {
1056 return PackageManager.PERMISSION_DENIED;
1057 }
1058 }
1059
1060 @Override
1061 public int checkCallingPermission(String permission) {
1062 if (permission == null) {
1063 throw new IllegalArgumentException("permission is null");
1064 }
1065
1066 if (!Process.supportsProcesses()) {
1067 return PackageManager.PERMISSION_GRANTED;
1068 }
1069 int pid = Binder.getCallingPid();
1070 if (pid != Process.myPid()) {
1071 return checkPermission(permission, pid,
1072 Binder.getCallingUid());
1073 }
1074 return PackageManager.PERMISSION_DENIED;
1075 }
1076
1077 @Override
1078 public int checkCallingOrSelfPermission(String permission) {
1079 if (permission == null) {
1080 throw new IllegalArgumentException("permission is null");
1081 }
1082
1083 return checkPermission(permission, Binder.getCallingPid(),
1084 Binder.getCallingUid());
1085 }
1086
1087 private void enforce(
1088 String permission, int resultOfCheck,
1089 boolean selfToo, int uid, String message) {
1090 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1091 throw new SecurityException(
1092 (message != null ? (message + ": ") : "") +
1093 (selfToo
1094 ? "Neither user " + uid + " nor current process has "
1095 : "User " + uid + " does not have ") +
1096 permission +
1097 ".");
1098 }
1099 }
1100
1101 public void enforcePermission(
1102 String permission, int pid, int uid, String message) {
1103 enforce(permission,
1104 checkPermission(permission, pid, uid),
1105 false,
1106 uid,
1107 message);
1108 }
1109
1110 public void enforceCallingPermission(String permission, String message) {
1111 enforce(permission,
1112 checkCallingPermission(permission),
1113 false,
1114 Binder.getCallingUid(),
1115 message);
1116 }
1117
1118 public void enforceCallingOrSelfPermission(
1119 String permission, String message) {
1120 enforce(permission,
1121 checkCallingOrSelfPermission(permission),
1122 true,
1123 Binder.getCallingUid(),
1124 message);
1125 }
1126
1127 @Override
1128 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1129 try {
1130 ActivityManagerNative.getDefault().grantUriPermission(
1131 mMainThread.getApplicationThread(), toPackage, uri,
1132 modeFlags);
1133 } catch (RemoteException e) {
1134 }
1135 }
1136
1137 @Override
1138 public void revokeUriPermission(Uri uri, int modeFlags) {
1139 try {
1140 ActivityManagerNative.getDefault().revokeUriPermission(
1141 mMainThread.getApplicationThread(), uri,
1142 modeFlags);
1143 } catch (RemoteException e) {
1144 }
1145 }
1146
1147 @Override
1148 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1149 if (!Process.supportsProcesses()) {
1150 return PackageManager.PERMISSION_GRANTED;
1151 }
1152 try {
1153 return ActivityManagerNative.getDefault().checkUriPermission(
1154 uri, pid, uid, modeFlags);
1155 } catch (RemoteException e) {
1156 return PackageManager.PERMISSION_DENIED;
1157 }
1158 }
1159
1160 @Override
1161 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1162 if (!Process.supportsProcesses()) {
1163 return PackageManager.PERMISSION_GRANTED;
1164 }
1165 int pid = Binder.getCallingPid();
1166 if (pid != Process.myPid()) {
1167 return checkUriPermission(uri, pid,
1168 Binder.getCallingUid(), modeFlags);
1169 }
1170 return PackageManager.PERMISSION_DENIED;
1171 }
1172
1173 @Override
1174 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1175 return checkUriPermission(uri, Binder.getCallingPid(),
1176 Binder.getCallingUid(), modeFlags);
1177 }
1178
1179 @Override
1180 public int checkUriPermission(Uri uri, String readPermission,
1181 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001182 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1184 + readPermission + " writePermission=" + writePermission
1185 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1186 }
1187 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1188 if (readPermission == null
1189 || checkPermission(readPermission, pid, uid)
1190 == PackageManager.PERMISSION_GRANTED) {
1191 return PackageManager.PERMISSION_GRANTED;
1192 }
1193 }
1194 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1195 if (writePermission == null
1196 || checkPermission(writePermission, pid, uid)
1197 == PackageManager.PERMISSION_GRANTED) {
1198 return PackageManager.PERMISSION_GRANTED;
1199 }
1200 }
1201 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1202 : PackageManager.PERMISSION_DENIED;
1203 }
1204
1205 private String uriModeFlagToString(int uriModeFlags) {
1206 switch (uriModeFlags) {
1207 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1208 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1209 return "read and write";
1210 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1211 return "read";
1212 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1213 return "write";
1214 }
1215 throw new IllegalArgumentException(
1216 "Unknown permission mode flags: " + uriModeFlags);
1217 }
1218
1219 private void enforceForUri(
1220 int modeFlags, int resultOfCheck, boolean selfToo,
1221 int uid, Uri uri, String message) {
1222 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1223 throw new SecurityException(
1224 (message != null ? (message + ": ") : "") +
1225 (selfToo
1226 ? "Neither user " + uid + " nor current process has "
1227 : "User " + uid + " does not have ") +
1228 uriModeFlagToString(modeFlags) +
1229 " permission on " +
1230 uri +
1231 ".");
1232 }
1233 }
1234
1235 public void enforceUriPermission(
1236 Uri uri, int pid, int uid, int modeFlags, String message) {
1237 enforceForUri(
1238 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1239 false, uid, uri, message);
1240 }
1241
1242 public void enforceCallingUriPermission(
1243 Uri uri, int modeFlags, String message) {
1244 enforceForUri(
1245 modeFlags, checkCallingUriPermission(uri, modeFlags),
1246 false, Binder.getCallingUid(), uri, message);
1247 }
1248
1249 public void enforceCallingOrSelfUriPermission(
1250 Uri uri, int modeFlags, String message) {
1251 enforceForUri(
1252 modeFlags,
1253 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1254 Binder.getCallingUid(), uri, message);
1255 }
1256
1257 public void enforceUriPermission(
1258 Uri uri, String readPermission, String writePermission,
1259 int pid, int uid, int modeFlags, String message) {
1260 enforceForUri(modeFlags,
1261 checkUriPermission(
1262 uri, readPermission, writePermission, pid, uid,
1263 modeFlags),
1264 false,
1265 uid,
1266 uri,
1267 message);
1268 }
1269
1270 @Override
1271 public Context createPackageContext(String packageName, int flags)
1272 throws PackageManager.NameNotFoundException {
1273 if (packageName.equals("system") || packageName.equals("android")) {
1274 return new ApplicationContext(mMainThread.getSystemContext());
1275 }
1276
1277 ActivityThread.PackageInfo pi =
1278 mMainThread.getPackageInfo(packageName, flags);
1279 if (pi != null) {
1280 ApplicationContext c = new ApplicationContext();
Romain Guy870e09f2009-07-06 16:35:25 -07001281 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001282 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 if (c.mResources != null) {
1284 return c;
1285 }
1286 }
1287
1288 // Should be a better exception.
1289 throw new PackageManager.NameNotFoundException(
1290 "Application package " + packageName + " not found");
1291 }
1292
Romain Guy870e09f2009-07-06 16:35:25 -07001293 @Override
1294 public boolean isRestricted() {
1295 return mRestricted;
1296 }
1297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 private File getDataDirFile() {
1299 if (mPackageInfo != null) {
1300 return mPackageInfo.getDataDirFile();
1301 }
1302 throw new RuntimeException("Not supported in system context");
1303 }
1304
1305 @Override
1306 public File getDir(String name, int mode) {
1307 name = "app_" + name;
1308 File file = makeFilename(getDataDirFile(), name);
1309 if (!file.exists()) {
1310 file.mkdir();
1311 setFilePermissionsFromMode(file.getPath(), mode,
1312 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1313 }
1314 return file;
1315 }
1316
1317 static ApplicationContext createSystemContext(ActivityThread mainThread) {
1318 ApplicationContext context = new ApplicationContext();
1319 context.init(Resources.getSystem(), mainThread);
1320 return context;
1321 }
1322
1323 ApplicationContext() {
1324 ++sInstanceCount;
1325 mOuterContext = this;
1326 }
1327
1328 /**
1329 * Create a new ApplicationContext from an existing one. The new one
1330 * works and operates the same as the one it is copying.
1331 *
1332 * @param context Existing application context.
1333 */
1334 public ApplicationContext(ApplicationContext context) {
1335 ++sInstanceCount;
1336 mPackageInfo = context.mPackageInfo;
1337 mResources = context.mResources;
1338 mMainThread = context.mMainThread;
1339 mContentResolver = context.mContentResolver;
1340 mOuterContext = this;
1341 }
1342
1343 final void init(ActivityThread.PackageInfo packageInfo,
1344 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001345 init(packageInfo, activityToken, mainThread, null);
1346 }
1347
1348 final void init(ActivityThread.PackageInfo packageInfo,
1349 IBinder activityToken, ActivityThread mainThread,
1350 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 mPackageInfo = packageInfo;
1352 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001353
1354 if (container != null && container.getCompatibilityInfo().applicationScale !=
1355 mResources.getCompatibilityInfo().applicationScale) {
1356 if (DEBUG) {
1357 Log.d(TAG, "loaded context has different scaling. Using container's" +
1358 " compatiblity info:" + container.getDisplayMetrics());
1359 }
1360 mResources = mainThread.getTopLevelResources(
1361 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 mMainThread = mainThread;
1364 mContentResolver = new ApplicationContentResolver(this, mainThread);
1365
1366 setActivityToken(activityToken);
1367 }
1368
1369 final void init(Resources resources, ActivityThread mainThread) {
1370 mPackageInfo = null;
1371 mResources = resources;
1372 mMainThread = mainThread;
1373 mContentResolver = new ApplicationContentResolver(this, mainThread);
1374 }
1375
1376 final void scheduleFinalCleanup(String who, String what) {
1377 mMainThread.scheduleContextCleanup(this, who, what);
1378 }
1379
1380 final void performFinalCleanup(String who, String what) {
1381 //Log.i(TAG, "Cleanup up context: " + this);
1382 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1383 }
1384
1385 final Context getReceiverRestrictedContext() {
1386 if (mReceiverRestrictedContext != null) {
1387 return mReceiverRestrictedContext;
1388 }
1389 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1390 }
1391
1392 final void setActivityToken(IBinder token) {
1393 mActivityToken = token;
1394 }
1395
1396 final void setOuterContext(Context context) {
1397 mOuterContext = context;
1398 }
1399
1400 final Context getOuterContext() {
1401 return mOuterContext;
1402 }
1403
1404 final IBinder getActivityToken() {
1405 return mActivityToken;
1406 }
1407
1408 private static void setFilePermissionsFromMode(String name, int mode,
1409 int extraPermissions) {
1410 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1411 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1412 |extraPermissions;
1413 if ((mode&MODE_WORLD_READABLE) != 0) {
1414 perms |= FileUtils.S_IROTH;
1415 }
1416 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1417 perms |= FileUtils.S_IWOTH;
1418 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001419 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1421 + ", perms=0x" + Integer.toHexString(perms));
1422 }
1423 FileUtils.setPermissions(name, perms, -1, -1);
1424 }
1425
1426 private File makeFilename(File base, String name) {
1427 if (name.indexOf(File.separatorChar) < 0) {
1428 return new File(base, name);
1429 }
1430 throw new IllegalArgumentException(
1431 "File " + name + " contains a path separator");
1432 }
1433
1434 // ----------------------------------------------------------------------
1435 // ----------------------------------------------------------------------
1436 // ----------------------------------------------------------------------
1437
1438 private static final class ApplicationContentResolver extends ContentResolver {
1439 public ApplicationContentResolver(Context context,
1440 ActivityThread mainThread)
1441 {
1442 super(context);
1443 mMainThread = mainThread;
1444 }
1445
1446 @Override
1447 protected IContentProvider acquireProvider(Context context, String name)
1448 {
1449 return mMainThread.acquireProvider(context, name);
1450 }
1451
1452 @Override
1453 public boolean releaseProvider(IContentProvider provider)
1454 {
1455 return mMainThread.releaseProvider(provider);
1456 }
1457
1458 private final ActivityThread mMainThread;
1459 }
1460
1461 // ----------------------------------------------------------------------
1462 // ----------------------------------------------------------------------
1463 // ----------------------------------------------------------------------
1464
1465 /*package*/
1466 static final class ApplicationPackageManager extends PackageManager {
1467 @Override
1468 public PackageInfo getPackageInfo(String packageName, int flags)
1469 throws NameNotFoundException {
1470 try {
1471 PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1472 if (pi != null) {
1473 return pi;
1474 }
1475 } catch (RemoteException e) {
1476 throw new RuntimeException("Package manager has died", e);
1477 }
1478
1479 throw new NameNotFoundException(packageName);
1480 }
1481
Mihai Predaeae850c2009-05-13 10:13:48 +02001482 @Override
1483 public Intent getLaunchIntentForPackage(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 // First see if the package has an INFO activity; the existence of
1485 // such an activity is implied to be the desired front-door for the
1486 // overall package (such as if it has multiple launcher entries).
Mihai Predaeae850c2009-05-13 10:13:48 +02001487 Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1488 intentToResolve.addCategory(Intent.CATEGORY_INFO);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001489 intentToResolve.setPackage(packageName);
1490 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
Mihai Predaeae850c2009-05-13 10:13:48 +02001491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 // Otherwise, try to find a main launcher activity.
Mihai Predaeae850c2009-05-13 10:13:48 +02001493 if (resolveInfo == null) {
1494 // reuse the intent instance
1495 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1496 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001497 intentToResolve.setPackage(packageName);
1498 resolveInfo = resolveActivity(intentToResolve, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001500 if (resolveInfo == null) {
1501 return null;
1502 }
1503 Intent intent = new Intent(Intent.ACTION_MAIN);
1504 intent.setClassName(packageName, resolveInfo.activityInfo.name);
1505 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1506 return intent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 @Override
1510 public int[] getPackageGids(String packageName)
1511 throws NameNotFoundException {
1512 try {
1513 int[] gids = mPM.getPackageGids(packageName);
1514 if (gids == null || gids.length > 0) {
1515 return gids;
1516 }
1517 } catch (RemoteException e) {
1518 throw new RuntimeException("Package manager has died", e);
1519 }
1520
1521 throw new NameNotFoundException(packageName);
1522 }
1523
1524 @Override
1525 public PermissionInfo getPermissionInfo(String name, int flags)
1526 throws NameNotFoundException {
1527 try {
1528 PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1529 if (pi != null) {
1530 return pi;
1531 }
1532 } catch (RemoteException e) {
1533 throw new RuntimeException("Package manager has died", e);
1534 }
1535
1536 throw new NameNotFoundException(name);
1537 }
1538
1539 @Override
1540 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1541 throws NameNotFoundException {
1542 try {
1543 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1544 if (pi != null) {
1545 return pi;
1546 }
1547 } catch (RemoteException e) {
1548 throw new RuntimeException("Package manager has died", e);
1549 }
1550
1551 throw new NameNotFoundException(group);
1552 }
1553
1554 @Override
1555 public PermissionGroupInfo getPermissionGroupInfo(String name,
1556 int flags) throws NameNotFoundException {
1557 try {
1558 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1559 if (pgi != null) {
1560 return pgi;
1561 }
1562 } catch (RemoteException e) {
1563 throw new RuntimeException("Package manager has died", e);
1564 }
1565
1566 throw new NameNotFoundException(name);
1567 }
1568
1569 @Override
1570 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1571 try {
1572 return mPM.getAllPermissionGroups(flags);
1573 } catch (RemoteException e) {
1574 throw new RuntimeException("Package manager has died", e);
1575 }
1576 }
1577
1578 @Override
1579 public ApplicationInfo getApplicationInfo(String packageName, int flags)
1580 throws NameNotFoundException {
1581 try {
1582 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
1583 if (ai != null) {
1584 return ai;
1585 }
1586 } catch (RemoteException e) {
1587 throw new RuntimeException("Package manager has died", e);
1588 }
1589
1590 throw new NameNotFoundException(packageName);
1591 }
1592
1593 @Override
1594 public ActivityInfo getActivityInfo(ComponentName className, int flags)
1595 throws NameNotFoundException {
1596 try {
1597 ActivityInfo ai = mPM.getActivityInfo(className, flags);
1598 if (ai != null) {
1599 return ai;
1600 }
1601 } catch (RemoteException e) {
1602 throw new RuntimeException("Package manager has died", e);
1603 }
1604
1605 throw new NameNotFoundException(className.toString());
1606 }
1607
1608 @Override
1609 public ActivityInfo getReceiverInfo(ComponentName className, int flags)
1610 throws NameNotFoundException {
1611 try {
1612 ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1613 if (ai != null) {
1614 return ai;
1615 }
1616 } catch (RemoteException e) {
1617 throw new RuntimeException("Package manager has died", e);
1618 }
1619
1620 throw new NameNotFoundException(className.toString());
1621 }
1622
1623 @Override
1624 public ServiceInfo getServiceInfo(ComponentName className, int flags)
1625 throws NameNotFoundException {
1626 try {
1627 ServiceInfo si = mPM.getServiceInfo(className, flags);
1628 if (si != null) {
1629 return si;
1630 }
1631 } catch (RemoteException e) {
1632 throw new RuntimeException("Package manager has died", e);
1633 }
1634
1635 throw new NameNotFoundException(className.toString());
1636 }
1637
1638 @Override
1639 public String[] getSystemSharedLibraryNames() {
1640 try {
1641 return mPM.getSystemSharedLibraryNames();
1642 } catch (RemoteException e) {
1643 throw new RuntimeException("Package manager has died", e);
1644 }
1645 }
1646
1647 @Override
Dianne Hackborn49237342009-08-27 20:08:01 -07001648 public FeatureInfo[] getSystemAvailableFeatures() {
1649 try {
1650 return mPM.getSystemAvailableFeatures();
1651 } catch (RemoteException e) {
1652 throw new RuntimeException("Package manager has died", e);
1653 }
1654 }
1655
1656 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 public int checkPermission(String permName, String pkgName) {
1658 try {
1659 return mPM.checkPermission(permName, pkgName);
1660 } catch (RemoteException e) {
1661 throw new RuntimeException("Package manager has died", e);
1662 }
1663 }
1664
1665 @Override
1666 public boolean addPermission(PermissionInfo info) {
1667 try {
1668 return mPM.addPermission(info);
1669 } catch (RemoteException e) {
1670 throw new RuntimeException("Package manager has died", e);
1671 }
1672 }
1673
1674 @Override
1675 public void removePermission(String name) {
1676 try {
1677 mPM.removePermission(name);
1678 } catch (RemoteException e) {
1679 throw new RuntimeException("Package manager has died", e);
1680 }
1681 }
1682
1683 @Override
1684 public int checkSignatures(String pkg1, String pkg2) {
1685 try {
1686 return mPM.checkSignatures(pkg1, pkg2);
1687 } catch (RemoteException e) {
1688 throw new RuntimeException("Package manager has died", e);
1689 }
1690 }
1691
1692 @Override
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001693 public int checkSignatures(int uid1, int uid2) {
1694 try {
1695 return mPM.checkUidSignatures(uid1, uid2);
1696 } catch (RemoteException e) {
1697 throw new RuntimeException("Package manager has died", e);
1698 }
1699 }
1700
1701 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 public String[] getPackagesForUid(int uid) {
1703 try {
1704 return mPM.getPackagesForUid(uid);
1705 } catch (RemoteException e) {
1706 throw new RuntimeException("Package manager has died", e);
1707 }
1708 }
1709
1710 @Override
1711 public String getNameForUid(int uid) {
1712 try {
1713 return mPM.getNameForUid(uid);
1714 } catch (RemoteException e) {
1715 throw new RuntimeException("Package manager has died", e);
1716 }
1717 }
1718
1719 @Override
1720 public int getUidForSharedUser(String sharedUserName)
1721 throws NameNotFoundException {
1722 try {
1723 int uid = mPM.getUidForSharedUser(sharedUserName);
1724 if(uid != -1) {
1725 return uid;
1726 }
1727 } catch (RemoteException e) {
1728 throw new RuntimeException("Package manager has died", e);
1729 }
1730 throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1731 }
1732
1733 @Override
1734 public List<PackageInfo> getInstalledPackages(int flags) {
1735 try {
1736 return mPM.getInstalledPackages(flags);
1737 } catch (RemoteException e) {
1738 throw new RuntimeException("Package manager has died", e);
1739 }
1740 }
1741
1742 @Override
1743 public List<ApplicationInfo> getInstalledApplications(int flags) {
1744 try {
1745 return mPM.getInstalledApplications(flags);
1746 } catch (RemoteException e) {
1747 throw new RuntimeException("Package manager has died", e);
1748 }
1749 }
1750
1751 @Override
1752 public ResolveInfo resolveActivity(Intent intent, int flags) {
1753 try {
1754 return mPM.resolveIntent(
1755 intent,
1756 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1757 flags);
1758 } catch (RemoteException e) {
1759 throw new RuntimeException("Package manager has died", e);
1760 }
1761 }
1762
1763 @Override
1764 public List<ResolveInfo> queryIntentActivities(Intent intent,
1765 int flags) {
1766 try {
1767 return mPM.queryIntentActivities(
1768 intent,
1769 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1770 flags);
1771 } catch (RemoteException e) {
1772 throw new RuntimeException("Package manager has died", e);
1773 }
1774 }
1775
1776 @Override
1777 public List<ResolveInfo> queryIntentActivityOptions(
1778 ComponentName caller, Intent[] specifics, Intent intent,
1779 int flags) {
1780 final ContentResolver resolver = mContext.getContentResolver();
1781
1782 String[] specificTypes = null;
1783 if (specifics != null) {
1784 final int N = specifics.length;
1785 for (int i=0; i<N; i++) {
1786 Intent sp = specifics[i];
1787 if (sp != null) {
1788 String t = sp.resolveTypeIfNeeded(resolver);
1789 if (t != null) {
1790 if (specificTypes == null) {
1791 specificTypes = new String[N];
1792 }
1793 specificTypes[i] = t;
1794 }
1795 }
1796 }
1797 }
1798
1799 try {
1800 return mPM.queryIntentActivityOptions(caller, specifics,
1801 specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
1802 flags);
1803 } catch (RemoteException e) {
1804 throw new RuntimeException("Package manager has died", e);
1805 }
1806 }
1807
1808 @Override
1809 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
1810 try {
1811 return mPM.queryIntentReceivers(
1812 intent,
1813 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1814 flags);
1815 } catch (RemoteException e) {
1816 throw new RuntimeException("Package manager has died", e);
1817 }
1818 }
1819
1820 @Override
1821 public ResolveInfo resolveService(Intent intent, int flags) {
1822 try {
1823 return mPM.resolveService(
1824 intent,
1825 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1826 flags);
1827 } catch (RemoteException e) {
1828 throw new RuntimeException("Package manager has died", e);
1829 }
1830 }
1831
1832 @Override
1833 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
1834 try {
1835 return mPM.queryIntentServices(
1836 intent,
1837 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1838 flags);
1839 } catch (RemoteException e) {
1840 throw new RuntimeException("Package manager has died", e);
1841 }
1842 }
1843
1844 @Override
1845 public ProviderInfo resolveContentProvider(String name,
1846 int flags) {
1847 try {
1848 return mPM.resolveContentProvider(name, flags);
1849 } catch (RemoteException e) {
1850 throw new RuntimeException("Package manager has died", e);
1851 }
1852 }
1853
1854 @Override
1855 public List<ProviderInfo> queryContentProviders(String processName,
1856 int uid, int flags) {
1857 try {
1858 return mPM.queryContentProviders(processName, uid, flags);
1859 } catch (RemoteException e) {
1860 throw new RuntimeException("Package manager has died", e);
1861 }
1862 }
1863
1864 @Override
1865 public InstrumentationInfo getInstrumentationInfo(
1866 ComponentName className, int flags)
1867 throws NameNotFoundException {
1868 try {
1869 InstrumentationInfo ii = mPM.getInstrumentationInfo(
1870 className, flags);
1871 if (ii != null) {
1872 return ii;
1873 }
1874 } catch (RemoteException e) {
1875 throw new RuntimeException("Package manager has died", e);
1876 }
1877
1878 throw new NameNotFoundException(className.toString());
1879 }
1880
1881 @Override
1882 public List<InstrumentationInfo> queryInstrumentation(
1883 String targetPackage, int flags) {
1884 try {
1885 return mPM.queryInstrumentation(targetPackage, flags);
1886 } catch (RemoteException e) {
1887 throw new RuntimeException("Package manager has died", e);
1888 }
1889 }
1890
1891 @Override public Drawable getDrawable(String packageName, int resid,
1892 ApplicationInfo appInfo) {
1893 ResourceName name = new ResourceName(packageName, resid);
1894 Drawable dr = getCachedIcon(name);
1895 if (dr != null) {
1896 return dr;
1897 }
1898 if (appInfo == null) {
1899 try {
1900 appInfo = getApplicationInfo(packageName, 0);
1901 } catch (NameNotFoundException e) {
1902 return null;
1903 }
1904 }
1905 try {
1906 Resources r = getResourcesForApplication(appInfo);
1907 dr = r.getDrawable(resid);
Dianne Hackborn11ea3342009-07-22 21:48:55 -07001908 if (false) {
1909 RuntimeException e = new RuntimeException("here");
1910 e.fillInStackTrace();
1911 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
1912 + " from package " + packageName
1913 + ": app scale=" + r.getCompatibilityInfo().applicationScale
1914 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
1915 e);
1916 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
1918 + Integer.toHexString(resid) + " from " + r
1919 + ": " + dr);
1920 putCachedIcon(name, dr);
1921 return dr;
1922 } catch (NameNotFoundException e) {
1923 Log.w("PackageManager", "Failure retrieving resources for"
1924 + appInfo.packageName);
1925 } catch (RuntimeException e) {
1926 // If an exception was thrown, fall through to return
1927 // default icon.
1928 Log.w("PackageManager", "Failure retrieving icon 0x"
1929 + Integer.toHexString(resid) + " in package "
1930 + packageName, e);
1931 }
1932 return null;
1933 }
1934
1935 @Override public Drawable getActivityIcon(ComponentName activityName)
1936 throws NameNotFoundException {
1937 return getActivityInfo(activityName, 0).loadIcon(this);
1938 }
1939
1940 @Override public Drawable getActivityIcon(Intent intent)
1941 throws NameNotFoundException {
1942 if (intent.getComponent() != null) {
1943 return getActivityIcon(intent.getComponent());
1944 }
1945
1946 ResolveInfo info = resolveActivity(
1947 intent, PackageManager.MATCH_DEFAULT_ONLY);
1948 if (info != null) {
1949 return info.activityInfo.loadIcon(this);
1950 }
1951
1952 throw new NameNotFoundException(intent.toURI());
1953 }
1954
1955 @Override public Drawable getDefaultActivityIcon() {
1956 return Resources.getSystem().getDrawable(
1957 com.android.internal.R.drawable.sym_def_app_icon);
1958 }
1959
1960 @Override public Drawable getApplicationIcon(ApplicationInfo info) {
1961 final int icon = info.icon;
1962 if (icon != 0) {
1963 ResourceName name = new ResourceName(info, icon);
1964 Drawable dr = getCachedIcon(name);
1965 if (dr != null) {
1966 return dr;
1967 }
1968 try {
1969 Resources r = getResourcesForApplication(info);
1970 dr = r.getDrawable(icon);
1971 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
1972 + Integer.toHexString(icon) + " from " + r
1973 + ": " + dr);
1974 putCachedIcon(name, dr);
1975 return dr;
1976 } catch (NameNotFoundException e) {
1977 Log.w("PackageManager", "Failure retrieving resources for"
1978 + info.packageName);
1979 } catch (RuntimeException e) {
1980 // If an exception was thrown, fall through to return
1981 // default icon.
1982 Log.w("PackageManager", "Failure retrieving app icon", e);
1983 }
1984 }
1985 return getDefaultActivityIcon();
1986 }
1987
1988 @Override public Drawable getApplicationIcon(String packageName)
1989 throws NameNotFoundException {
1990 return getApplicationIcon(getApplicationInfo(packageName, 0));
1991 }
1992
1993 @Override public Resources getResourcesForActivity(
1994 ComponentName activityName) throws NameNotFoundException {
1995 return getResourcesForApplication(
1996 getActivityInfo(activityName, 0).applicationInfo);
1997 }
1998
1999 @Override public Resources getResourcesForApplication(
2000 ApplicationInfo app) throws NameNotFoundException {
2001 if (app.packageName.equals("system")) {
2002 return mContext.mMainThread.getSystemContext().getResources();
2003 }
2004 Resources r = mContext.mMainThread.getTopLevelResources(
2005 app.uid == Process.myUid() ? app.sourceDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002006 : app.publicSourceDir, mContext.mPackageInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 if (r != null) {
2008 return r;
2009 }
2010 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2011 }
2012
2013 @Override public Resources getResourcesForApplication(
2014 String appPackageName) throws NameNotFoundException {
2015 return getResourcesForApplication(
2016 getApplicationInfo(appPackageName, 0));
2017 }
2018
2019 int mCachedSafeMode = -1;
2020 @Override public boolean isSafeMode() {
2021 try {
2022 if (mCachedSafeMode < 0) {
2023 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2024 }
2025 return mCachedSafeMode != 0;
2026 } catch (RemoteException e) {
2027 throw new RuntimeException("Package manager has died", e);
2028 }
2029 }
2030
2031 static void configurationChanged() {
2032 synchronized (sSync) {
2033 sIconCache.clear();
2034 sStringCache.clear();
2035 }
2036 }
2037
2038 ApplicationPackageManager(ApplicationContext context,
2039 IPackageManager pm) {
2040 mContext = context;
2041 mPM = pm;
2042 }
2043
2044 private Drawable getCachedIcon(ResourceName name) {
2045 synchronized (sSync) {
2046 WeakReference<Drawable> wr = sIconCache.get(name);
2047 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2048 + name + ": " + wr);
2049 if (wr != null) { // we have the activity
2050 Drawable dr = wr.get();
2051 if (dr != null) {
2052 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2053 + name + ": " + dr);
2054 return dr;
2055 }
2056 // our entry has been purged
2057 sIconCache.remove(name);
2058 }
2059 }
2060 return null;
2061 }
2062
2063 private void establishPackageRemovedReceiver() {
2064 // mContext.registerReceiverInternal() winds up acquiring the
2065 // main ActivityManagerService.this lock. If we hold our usual
2066 // sSync global lock at the same time, we impose a required ordering
2067 // on those two locks, which is not good for deadlock prevention.
2068 // Use a dedicated lock around initialization of
2069 // sPackageRemovedReceiver to avoid this.
2070 synchronized (sPackageRemovedSync) {
2071 if (sPackageRemovedReceiver == null) {
2072 sPackageRemovedReceiver = new PackageRemovedReceiver();
2073 IntentFilter filter = new IntentFilter(
2074 Intent.ACTION_PACKAGE_REMOVED);
2075 filter.addDataScheme("package");
2076 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2077 filter, null, null, null);
2078 }
2079 }
2080 }
2081
2082 private void putCachedIcon(ResourceName name, Drawable dr) {
2083 establishPackageRemovedReceiver();
2084
2085 synchronized (sSync) {
2086 sIconCache.put(name, new WeakReference<Drawable>(dr));
2087 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2088 + name + ": " + dr);
2089 }
2090 }
2091
2092 private static final class PackageRemovedReceiver extends BroadcastReceiver {
2093 @Override
2094 public void onReceive(Context context, Intent intent) {
2095 Uri data = intent.getData();
2096 String ssp;
2097 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
2098 boolean needCleanup = false;
2099 synchronized (sSync) {
2100 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2101 while (it.hasNext()) {
2102 ResourceName nm = it.next();
2103 if (nm.packageName.equals(ssp)) {
2104 //Log.i(TAG, "Removing cached drawable for " + nm);
2105 it.remove();
2106 needCleanup = true;
2107 }
2108 }
2109 it = sStringCache.keySet().iterator();
2110 while (it.hasNext()) {
2111 ResourceName nm = it.next();
2112 if (nm.packageName.equals(ssp)) {
2113 //Log.i(TAG, "Removing cached string for " + nm);
2114 it.remove();
2115 needCleanup = true;
2116 }
2117 }
2118 }
2119 if (needCleanup || ActivityThread.currentActivityThread().hasPackageInfo(ssp)) {
2120 ActivityThread.currentActivityThread().scheduleGcIdler();
2121 }
2122 }
2123 }
2124 }
2125
2126 private static final class ResourceName {
2127 final String packageName;
2128 final int iconId;
2129
2130 ResourceName(String _packageName, int _iconId) {
2131 packageName = _packageName;
2132 iconId = _iconId;
2133 }
2134
2135 ResourceName(ApplicationInfo aInfo, int _iconId) {
2136 this(aInfo.packageName, _iconId);
2137 }
2138
2139 ResourceName(ComponentInfo cInfo, int _iconId) {
2140 this(cInfo.applicationInfo.packageName, _iconId);
2141 }
2142
2143 ResourceName(ResolveInfo rInfo, int _iconId) {
2144 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2145 }
2146
2147 @Override
2148 public boolean equals(Object o) {
2149 if (this == o) return true;
2150 if (o == null || getClass() != o.getClass()) return false;
2151
2152 ResourceName that = (ResourceName) o;
2153
2154 if (iconId != that.iconId) return false;
2155 return !(packageName != null ?
2156 !packageName.equals(that.packageName) : that.packageName != null);
2157
2158 }
2159
2160 @Override
2161 public int hashCode() {
2162 int result;
2163 result = packageName.hashCode();
2164 result = 31 * result + iconId;
2165 return result;
2166 }
2167
2168 @Override
2169 public String toString() {
2170 return "{ResourceName " + packageName + " / " + iconId + "}";
2171 }
2172 }
2173
2174 private CharSequence getCachedString(ResourceName name) {
2175 synchronized (sSync) {
2176 WeakReference<CharSequence> wr = sStringCache.get(name);
2177 if (wr != null) { // we have the activity
2178 CharSequence cs = wr.get();
2179 if (cs != null) {
2180 return cs;
2181 }
2182 // our entry has been purged
2183 sStringCache.remove(name);
2184 }
2185 }
2186 return null;
2187 }
2188
2189 private void putCachedString(ResourceName name, CharSequence cs) {
2190 establishPackageRemovedReceiver();
2191
2192 synchronized (sSync) {
2193 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2194 }
2195 }
2196
2197 private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
2198 CharSequence cs = getCachedString(name);
2199 if (cs != null) {
2200 return cs;
2201 }
2202 try {
2203 Resources r = getResourcesForApplication(app);
2204 cs = r.getText(id);
2205 putCachedString(name, cs);
2206 } catch (NameNotFoundException e) {
2207 Log.w("PackageManager", "Failure retrieving resources for"
2208 + app.packageName);
2209 } catch (RuntimeException e) {
2210 // If an exception was thrown, fall through to return null
2211 Log.w("ApplicationInfo", "Failure retrieving activity name", e);
2212 }
2213 return cs;
2214 }
2215
2216 @Override
2217 public CharSequence getText(String packageName, int resid,
2218 ApplicationInfo appInfo) {
2219 ResourceName name = new ResourceName(packageName, resid);
2220 CharSequence text = getCachedString(name);
2221 if (text != null) {
2222 return text;
2223 }
2224 if (appInfo == null) {
2225 try {
2226 appInfo = getApplicationInfo(packageName, 0);
2227 } catch (NameNotFoundException e) {
2228 return null;
2229 }
2230 }
2231 try {
2232 Resources r = getResourcesForApplication(appInfo);
2233 text = r.getText(resid);
2234 putCachedString(name, text);
2235 return text;
2236 } catch (NameNotFoundException e) {
2237 Log.w("PackageManager", "Failure retrieving resources for"
2238 + appInfo.packageName);
2239 } catch (RuntimeException e) {
2240 // If an exception was thrown, fall through to return
2241 // default icon.
2242 Log.w("PackageManager", "Failure retrieving text 0x"
2243 + Integer.toHexString(resid) + " in package "
2244 + packageName, e);
2245 }
2246 return null;
2247 }
2248
2249 @Override
2250 public XmlResourceParser getXml(String packageName, int resid,
2251 ApplicationInfo appInfo) {
2252 if (appInfo == null) {
2253 try {
2254 appInfo = getApplicationInfo(packageName, 0);
2255 } catch (NameNotFoundException e) {
2256 return null;
2257 }
2258 }
2259 try {
2260 Resources r = getResourcesForApplication(appInfo);
2261 return r.getXml(resid);
2262 } catch (RuntimeException e) {
2263 // If an exception was thrown, fall through to return
2264 // default icon.
2265 Log.w("PackageManager", "Failure retrieving xml 0x"
2266 + Integer.toHexString(resid) + " in package "
2267 + packageName, e);
2268 } catch (NameNotFoundException e) {
2269 Log.w("PackageManager", "Failure retrieving resources for"
2270 + appInfo.packageName);
2271 }
2272 return null;
2273 }
2274
2275 @Override
2276 public CharSequence getApplicationLabel(ApplicationInfo info) {
2277 if (info.nonLocalizedLabel != null) {
2278 return info.nonLocalizedLabel;
2279 }
2280 final int id = info.labelRes;
2281 if (id != 0) {
2282 CharSequence cs = getLabel(new ResourceName(info, id), info, id);
2283 if (cs != null) {
2284 return cs;
2285 }
2286 }
2287 return info.packageName;
2288 }
2289
2290 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002291 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2292 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 try {
Jacek Surazski65e13172009-04-28 15:26:38 +02002294 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002295 } catch (RemoteException e) {
2296 // Should never happen!
2297 }
2298 }
2299
2300 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002301 public String getInstallerPackageName(String packageName) {
2302 try {
2303 return mPM.getInstallerPackageName(packageName);
2304 } catch (RemoteException e) {
2305 // Should never happen!
2306 }
2307 return null;
2308 }
2309
2310 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2312 try {
2313 mPM.deletePackage(packageName, observer, flags);
2314 } catch (RemoteException e) {
2315 // Should never happen!
2316 }
2317 }
2318 @Override
2319 public void clearApplicationUserData(String packageName,
2320 IPackageDataObserver observer) {
2321 try {
2322 mPM.clearApplicationUserData(packageName, observer);
2323 } catch (RemoteException e) {
2324 // Should never happen!
2325 }
2326 }
2327 @Override
2328 public void deleteApplicationCacheFiles(String packageName,
2329 IPackageDataObserver observer) {
2330 try {
2331 mPM.deleteApplicationCacheFiles(packageName, observer);
2332 } catch (RemoteException e) {
2333 // Should never happen!
2334 }
2335 }
2336 @Override
2337 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2338 try {
2339 mPM.freeStorageAndNotify(idealStorageSize, observer);
2340 } catch (RemoteException e) {
2341 // Should never happen!
2342 }
2343 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 @Override
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002346 public void freeStorage(long freeStorageSize, IntentSender pi) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002347 try {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002348 mPM.freeStorage(freeStorageSize, pi);
2349 } catch (RemoteException e) {
2350 // Should never happen!
2351 }
2352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353
2354 @Override
2355 public void getPackageSizeInfo(String packageName,
2356 IPackageStatsObserver observer) {
2357 try {
2358 mPM.getPackageSizeInfo(packageName, observer);
2359 } catch (RemoteException e) {
2360 // Should never happen!
2361 }
2362 }
2363 @Override
2364 public void addPackageToPreferred(String packageName) {
2365 try {
2366 mPM.addPackageToPreferred(packageName);
2367 } catch (RemoteException e) {
2368 // Should never happen!
2369 }
2370 }
2371
2372 @Override
2373 public void removePackageFromPreferred(String packageName) {
2374 try {
2375 mPM.removePackageFromPreferred(packageName);
2376 } catch (RemoteException e) {
2377 // Should never happen!
2378 }
2379 }
2380
2381 @Override
2382 public List<PackageInfo> getPreferredPackages(int flags) {
2383 try {
2384 return mPM.getPreferredPackages(flags);
2385 } catch (RemoteException e) {
2386 // Should never happen!
2387 }
2388 return new ArrayList<PackageInfo>();
2389 }
2390
2391 @Override
2392 public void addPreferredActivity(IntentFilter filter,
2393 int match, ComponentName[] set, ComponentName activity) {
2394 try {
2395 mPM.addPreferredActivity(filter, match, set, activity);
2396 } catch (RemoteException e) {
2397 // Should never happen!
2398 }
2399 }
2400
2401 @Override
Satish Sampath8dbe6122009-06-02 23:35:54 +01002402 public void replacePreferredActivity(IntentFilter filter,
2403 int match, ComponentName[] set, ComponentName activity) {
2404 try {
2405 mPM.replacePreferredActivity(filter, match, set, activity);
2406 } catch (RemoteException e) {
2407 // Should never happen!
2408 }
2409 }
2410
2411 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 public void clearPackagePreferredActivities(String packageName) {
2413 try {
2414 mPM.clearPackagePreferredActivities(packageName);
2415 } catch (RemoteException e) {
2416 // Should never happen!
2417 }
2418 }
2419
2420 @Override
2421 public int getPreferredActivities(List<IntentFilter> outFilters,
2422 List<ComponentName> outActivities, String packageName) {
2423 try {
2424 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2425 } catch (RemoteException e) {
2426 // Should never happen!
2427 }
2428 return 0;
2429 }
2430
2431 @Override
2432 public void setComponentEnabledSetting(ComponentName componentName,
2433 int newState, int flags) {
2434 try {
2435 mPM.setComponentEnabledSetting(componentName, newState, flags);
2436 } catch (RemoteException e) {
2437 // Should never happen!
2438 }
2439 }
2440
2441 @Override
2442 public int getComponentEnabledSetting(ComponentName componentName) {
2443 try {
2444 return mPM.getComponentEnabledSetting(componentName);
2445 } catch (RemoteException e) {
2446 // Should never happen!
2447 }
2448 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2449 }
2450
2451 @Override
2452 public void setApplicationEnabledSetting(String packageName,
2453 int newState, int flags) {
2454 try {
2455 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2456 } catch (RemoteException e) {
2457 // Should never happen!
2458 }
2459 }
2460
2461 @Override
2462 public int getApplicationEnabledSetting(String packageName) {
2463 try {
2464 return mPM.getApplicationEnabledSetting(packageName);
2465 } catch (RemoteException e) {
2466 // Should never happen!
2467 }
2468 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2469 }
2470
2471 private final ApplicationContext mContext;
2472 private final IPackageManager mPM;
2473
2474 private static final Object sSync = new Object();
2475 private static final Object sPackageRemovedSync = new Object();
2476 private static BroadcastReceiver sPackageRemovedReceiver;
2477 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2478 = new HashMap<ResourceName, WeakReference<Drawable> >();
2479 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2480 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2481 }
2482
2483 // ----------------------------------------------------------------------
2484 // ----------------------------------------------------------------------
2485 // ----------------------------------------------------------------------
2486
2487 private static final class SharedPreferencesImpl implements SharedPreferences {
2488
2489 private final File mFile;
2490 private final File mBackupFile;
2491 private final int mMode;
2492 private Map mMap;
2493 private final FileStatus mFileStatus = new FileStatus();
2494 private long mTimestamp;
2495
The Android Open Source Project10592532009-03-18 17:39:46 -07002496 private static final Object mContent = new Object();
2497 private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498
2499 SharedPreferencesImpl(
2500 File file, int mode, Map initialContents) {
2501 mFile = file;
2502 mBackupFile = makeBackupFile(file);
2503 mMode = mode;
2504 mMap = initialContents != null ? initialContents : new HashMap();
2505 if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
2506 mTimestamp = mFileStatus.mtime;
2507 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002508 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 }
2510
2511 public boolean hasFileChanged() {
2512 synchronized (this) {
2513 if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2514 return true;
2515 }
2516 return mTimestamp != mFileStatus.mtime;
2517 }
2518 }
2519
2520 public void replace(Map newContents) {
2521 if (newContents != null) {
2522 synchronized (this) {
2523 mMap = newContents;
2524 }
2525 }
2526 }
2527
2528 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2529 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002530 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 }
2532 }
2533
2534 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2535 synchronized(this) {
2536 mListeners.remove(listener);
2537 }
2538 }
2539
2540 public Map<String, ?> getAll() {
2541 synchronized(this) {
2542 //noinspection unchecked
2543 return new HashMap(mMap);
2544 }
2545 }
2546
2547 public String getString(String key, String defValue) {
2548 synchronized (this) {
2549 String v = (String)mMap.get(key);
2550 return v != null ? v : defValue;
2551 }
2552 }
2553
2554 public int getInt(String key, int defValue) {
2555 synchronized (this) {
2556 Integer v = (Integer)mMap.get(key);
2557 return v != null ? v : defValue;
2558 }
2559 }
2560 public long getLong(String key, long defValue) {
2561 synchronized (this) {
2562 Long v = (Long) mMap.get(key);
2563 return v != null ? v : defValue;
2564 }
2565 }
2566 public float getFloat(String key, float defValue) {
2567 synchronized (this) {
2568 Float v = (Float)mMap.get(key);
2569 return v != null ? v : defValue;
2570 }
2571 }
2572 public boolean getBoolean(String key, boolean defValue) {
2573 synchronized (this) {
2574 Boolean v = (Boolean)mMap.get(key);
2575 return v != null ? v : defValue;
2576 }
2577 }
2578
2579 public boolean contains(String key) {
2580 synchronized (this) {
2581 return mMap.containsKey(key);
2582 }
2583 }
2584
2585 public final class EditorImpl implements Editor {
2586 private final Map<String, Object> mModified = Maps.newHashMap();
2587 private boolean mClear = false;
2588
2589 public Editor putString(String key, String value) {
2590 synchronized (this) {
2591 mModified.put(key, value);
2592 return this;
2593 }
2594 }
2595 public Editor putInt(String key, int value) {
2596 synchronized (this) {
2597 mModified.put(key, value);
2598 return this;
2599 }
2600 }
2601 public Editor putLong(String key, long value) {
2602 synchronized (this) {
2603 mModified.put(key, value);
2604 return this;
2605 }
2606 }
2607 public Editor putFloat(String key, float value) {
2608 synchronized (this) {
2609 mModified.put(key, value);
2610 return this;
2611 }
2612 }
2613 public Editor putBoolean(String key, boolean value) {
2614 synchronized (this) {
2615 mModified.put(key, value);
2616 return this;
2617 }
2618 }
2619
2620 public Editor remove(String key) {
2621 synchronized (this) {
2622 mModified.put(key, this);
2623 return this;
2624 }
2625 }
2626
2627 public Editor clear() {
2628 synchronized (this) {
2629 mClear = true;
2630 return this;
2631 }
2632 }
2633
2634 public boolean commit() {
2635 boolean returnValue;
2636
2637 boolean hasListeners;
2638 List<String> keysModified = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07002639 Set<OnSharedPreferenceChangeListener> listeners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640
2641 synchronized (SharedPreferencesImpl.this) {
2642 hasListeners = mListeners.size() > 0;
2643 if (hasListeners) {
2644 keysModified = new ArrayList<String>();
The Android Open Source Project10592532009-03-18 17:39:46 -07002645 listeners =
2646 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002647 }
2648
2649 synchronized (this) {
2650 if (mClear) {
2651 mMap.clear();
2652 mClear = false;
2653 }
2654
The Android Open Source Project10592532009-03-18 17:39:46 -07002655 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 String k = e.getKey();
2657 Object v = e.getValue();
2658 if (v == this) {
2659 mMap.remove(k);
2660 } else {
2661 mMap.put(k, v);
2662 }
2663
2664 if (hasListeners) {
2665 keysModified.add(k);
2666 }
2667 }
2668
2669 mModified.clear();
2670 }
2671
2672 returnValue = writeFileLocked();
2673 }
2674
2675 if (hasListeners) {
2676 for (int i = keysModified.size() - 1; i >= 0; i--) {
2677 final String key = keysModified.get(i);
The Android Open Source Project10592532009-03-18 17:39:46 -07002678 for (OnSharedPreferenceChangeListener listener : listeners) {
2679 if (listener != null) {
2680 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
2681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002682 }
2683 }
2684 }
2685
2686 return returnValue;
2687 }
2688 }
2689
2690 public Editor edit() {
2691 return new EditorImpl();
2692 }
2693
2694 private FileOutputStream createFileOutputStream(File file) {
2695 FileOutputStream str = null;
2696 try {
2697 str = new FileOutputStream(file);
2698 } catch (FileNotFoundException e) {
2699 File parent = file.getParentFile();
2700 if (!parent.mkdir()) {
2701 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
2702 return null;
2703 }
2704 FileUtils.setPermissions(
2705 parent.getPath(),
2706 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2707 -1, -1);
2708 try {
2709 str = new FileOutputStream(file);
2710 } catch (FileNotFoundException e2) {
2711 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
2712 }
2713 }
2714 return str;
2715 }
2716
2717 private boolean writeFileLocked() {
2718 // Rename the current file so it may be used as a backup during the next read
2719 if (mFile.exists()) {
2720 if (!mFile.renameTo(mBackupFile)) {
2721 Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
2722 }
2723 }
2724
2725 // Attempt to write the file, delete the backup and return true as atomically as
2726 // possible. If any exception occurs, delete the new file; next time we will restore
2727 // from the backup.
2728 try {
2729 FileOutputStream str = createFileOutputStream(mFile);
2730 if (str == null) {
2731 return false;
2732 }
2733 XmlUtils.writeMapXml(mMap, str);
2734 str.close();
2735 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
2736 if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2737 mTimestamp = mFileStatus.mtime;
2738 }
2739
Dianne Hackborn51bf0772009-03-24 19:11:41 -07002740 // Writing was successful, delete the backup file if there is one.
2741 mBackupFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 return true;
2743 } catch (XmlPullParserException e) {
2744 Log.w(TAG, "writeFileLocked: Got exception:", e);
2745 } catch (IOException e) {
2746 Log.w(TAG, "writeFileLocked: Got exception:", e);
2747 }
2748 // Clean up an unsuccessfully written file
2749 if (mFile.exists()) {
2750 if (!mFile.delete()) {
2751 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
2752 }
2753 }
2754 return false;
2755 }
2756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757}