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