blob: 1e04abf32f980003236c25da8c716a1bbaf6c751 [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.BroadcastReceiver;
26import android.content.ComponentName;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.ContextWrapper;
30import android.content.IContentProvider;
31import android.content.Intent;
32import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070033import android.content.IIntentReceiver;
34import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.ReceiverCallNotAllowedException;
36import android.content.ServiceConnection;
37import android.content.SharedPreferences;
38import android.content.pm.ActivityInfo;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070041import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.pm.IPackageDataObserver;
43import android.content.pm.IPackageDeleteObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.content.pm.IPackageInstallObserver;
45import android.content.pm.IPackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070046import android.content.pm.IPackageStatsObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.content.pm.InstrumentationInfo;
48import android.content.pm.PackageInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.PermissionGroupInfo;
51import android.content.pm.PermissionInfo;
52import android.content.pm.ProviderInfo;
53import android.content.pm.ResolveInfo;
54import android.content.pm.ServiceInfo;
55import android.content.res.AssetManager;
56import android.content.res.Resources;
57import android.content.res.XmlResourceParser;
58import android.database.sqlite.SQLiteDatabase;
59import android.database.sqlite.SQLiteDatabase.CursorFactory;
60import android.graphics.Bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.graphics.drawable.Drawable;
62import android.hardware.SensorManager;
63import android.location.ILocationManager;
64import android.location.LocationManager;
65import android.media.AudioManager;
66import android.net.ConnectivityManager;
67import android.net.IConnectivityManager;
68import android.net.Uri;
69import android.net.wifi.IWifiManager;
70import android.net.wifi.WifiManager;
71import android.os.Binder;
72import android.os.Bundle;
Dan Egnorf18a01c2009-11-12 11:32:50 -080073import android.os.DropBoxManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.os.FileUtils;
75import android.os.Handler;
76import android.os.IBinder;
77import android.os.IPowerManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070078import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.PowerManager;
80import android.os.Process;
svetoslavganov75986cf2009-05-14 22:28:01 -070081import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.ServiceManager;
83import android.os.Vibrator;
84import android.os.FileUtils.FileStatus;
85import android.telephony.TelephonyManager;
86import android.text.ClipboardManager;
87import android.util.AndroidRuntimeException;
88import android.util.Log;
89import android.view.ContextThemeWrapper;
90import android.view.LayoutInflater;
91import android.view.WindowManagerImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070092import android.view.accessibility.AccessibilityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093import android.view.inputmethod.InputMethodManager;
Fred Quintana60307342009-03-24 22:48:12 -070094import android.accounts.AccountManager;
95import android.accounts.IAccountManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
Dan Egnorf18a01c2009-11-12 11:32:50 -080097import com.android.internal.os.IDropBoxManagerService;
Dan Egnor95240272009-10-27 18:23:39 -070098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import java.io.File;
100import java.io.FileInputStream;
101import java.io.FileNotFoundException;
102import java.io.FileOutputStream;
103import java.io.IOException;
104import java.io.InputStream;
105import java.lang.ref.WeakReference;
106import java.util.ArrayList;
107import java.util.HashMap;
svetoslavganov75986cf2009-05-14 22:28:01 -0700108import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import java.util.Iterator;
110import java.util.List;
111import java.util.Map;
The Android Open Source Project10592532009-03-18 17:39:46 -0700112import java.util.Set;
svetoslavganov75986cf2009-05-14 22:28:01 -0700113import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import java.util.Map.Entry;
115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116class ReceiverRestrictedContext extends ContextWrapper {
117 ReceiverRestrictedContext(Context base) {
118 super(base);
119 }
120
121 @Override
122 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
123 return registerReceiver(receiver, filter, null, null);
124 }
125
126 @Override
127 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
128 String broadcastPermission, Handler scheduler) {
129 throw new ReceiverCallNotAllowedException(
130 "IntentReceiver components are not allowed to register to receive intents");
131 //ex.fillInStackTrace();
132 //Log.e("IntentReceiver", ex.getMessage(), ex);
133 //return mContext.registerReceiver(receiver, filter, broadcastPermission,
134 // scheduler);
135 }
136
137 @Override
138 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
139 throw new ReceiverCallNotAllowedException(
140 "IntentReceiver components are not allowed to bind to services");
141 //ex.fillInStackTrace();
142 //Log.e("IntentReceiver", ex.getMessage(), ex);
143 //return mContext.bindService(service, interfaceName, conn, flags);
144 }
145}
146
147/**
148 * Common implementation of Context API, which Activity and other application
149 * classes inherit.
150 */
151class ApplicationContext extends Context {
152 private final static String TAG = "ApplicationContext";
Mitsuru Oshima569076c2009-07-02 20:06:08 -0700153 private final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 private final static boolean DEBUG_ICONS = false;
155
156 private static final Object sSync = new Object();
157 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;
Romain Guy870e09f2009-07-06 16:35:25 -0700186 private boolean mRestricted;
Fred Quintanae00a3112009-09-22 15:13:30 -0700187 private AccountManager mAccountManager; // protected by mSync
Dan Egnorf18a01c2009-11-12 11:32:50 -0800188 private DropBoxManager mDropBoxManager = null;
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();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 } else if (VIBRATOR_SERVICE.equals(name)) {
887 return getVibrator();
888 } else if (STATUS_BAR_SERVICE.equals(name)) {
889 synchronized (mSync) {
890 if (mStatusBarManager == null) {
891 mStatusBarManager = new StatusBarManager(getOuterContext());
892 }
893 return mStatusBarManager;
894 }
895 } else if (AUDIO_SERVICE.equals(name)) {
896 return getAudioManager();
897 } else if (TELEPHONY_SERVICE.equals(name)) {
898 return getTelephonyManager();
899 } else if (CLIPBOARD_SERVICE.equals(name)) {
900 return getClipboardManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700901 } else if (WALLPAPER_SERVICE.equals(name)) {
902 return getWallpaperManager();
Dan Egnor95240272009-10-27 18:23:39 -0700903 } else if (DROPBOX_SERVICE.equals(name)) {
Dan Egnorf18a01c2009-11-12 11:32:50 -0800904 return getDropBoxManager();
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() {
Fred Quintanae00a3112009-09-22 15:13:30 -0700911 synchronized (mSync) {
912 if (mAccountManager == null) {
Fred Quintana60307342009-03-24 22:48:12 -0700913 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
914 IAccountManager service = IAccountManager.Stub.asInterface(b);
Fred Quintanae00a3112009-09-22 15:13:30 -0700915 mAccountManager = new AccountManager(this, service);
Fred Quintana60307342009-03-24 22:48:12 -0700916 }
Fred Quintanae00a3112009-09-22 15:13:30 -0700917 return mAccountManager;
Fred Quintana60307342009-03-24 22:48:12 -0700918 }
Fred Quintana60307342009-03-24 22:48:12 -0700919 }
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 private SensorManager getSensorManager() {
1038 synchronized (mSync) {
1039 if (mSensorManager == null) {
1040 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1041 }
1042 }
1043 return mSensorManager;
1044 }
1045
1046 private Vibrator getVibrator() {
1047 synchronized (mSync) {
1048 if (mVibrator == null) {
1049 mVibrator = new Vibrator();
1050 }
1051 }
1052 return mVibrator;
1053 }
Dan Egnor95240272009-10-27 18:23:39 -07001054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 private AudioManager getAudioManager()
1056 {
1057 if (mAudioManager == null) {
1058 mAudioManager = new AudioManager(this);
1059 }
1060 return mAudioManager;
1061 }
1062
Dan Egnorf18a01c2009-11-12 11:32:50 -08001063 private DropBoxManager getDropBoxManager() {
Dan Egnor95240272009-10-27 18:23:39 -07001064 synchronized (mSync) {
Dan Egnorf18a01c2009-11-12 11:32:50 -08001065 if (mDropBoxManager == null) {
Dan Egnor95240272009-10-27 18:23:39 -07001066 IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
Dan Egnorf18a01c2009-11-12 11:32:50 -08001067 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1068 mDropBoxManager = new DropBoxManager(service);
Dan Egnor95240272009-10-27 18:23:39 -07001069 }
1070 }
Dan Egnorf18a01c2009-11-12 11:32:50 -08001071 return mDropBoxManager;
Dan Egnor95240272009-10-27 18:23:39 -07001072 }
1073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 @Override
1075 public int checkPermission(String permission, int pid, int uid) {
1076 if (permission == null) {
1077 throw new IllegalArgumentException("permission is null");
1078 }
1079
1080 if (!Process.supportsProcesses()) {
1081 return PackageManager.PERMISSION_GRANTED;
1082 }
1083 try {
1084 return ActivityManagerNative.getDefault().checkPermission(
1085 permission, pid, uid);
1086 } catch (RemoteException e) {
1087 return PackageManager.PERMISSION_DENIED;
1088 }
1089 }
1090
1091 @Override
1092 public int checkCallingPermission(String permission) {
1093 if (permission == null) {
1094 throw new IllegalArgumentException("permission is null");
1095 }
1096
1097 if (!Process.supportsProcesses()) {
1098 return PackageManager.PERMISSION_GRANTED;
1099 }
1100 int pid = Binder.getCallingPid();
1101 if (pid != Process.myPid()) {
1102 return checkPermission(permission, pid,
1103 Binder.getCallingUid());
1104 }
1105 return PackageManager.PERMISSION_DENIED;
1106 }
1107
1108 @Override
1109 public int checkCallingOrSelfPermission(String permission) {
1110 if (permission == null) {
1111 throw new IllegalArgumentException("permission is null");
1112 }
1113
1114 return checkPermission(permission, Binder.getCallingPid(),
1115 Binder.getCallingUid());
1116 }
1117
1118 private void enforce(
1119 String permission, int resultOfCheck,
1120 boolean selfToo, int uid, String message) {
1121 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1122 throw new SecurityException(
1123 (message != null ? (message + ": ") : "") +
1124 (selfToo
1125 ? "Neither user " + uid + " nor current process has "
1126 : "User " + uid + " does not have ") +
1127 permission +
1128 ".");
1129 }
1130 }
1131
1132 public void enforcePermission(
1133 String permission, int pid, int uid, String message) {
1134 enforce(permission,
1135 checkPermission(permission, pid, uid),
1136 false,
1137 uid,
1138 message);
1139 }
1140
1141 public void enforceCallingPermission(String permission, String message) {
1142 enforce(permission,
1143 checkCallingPermission(permission),
1144 false,
1145 Binder.getCallingUid(),
1146 message);
1147 }
1148
1149 public void enforceCallingOrSelfPermission(
1150 String permission, String message) {
1151 enforce(permission,
1152 checkCallingOrSelfPermission(permission),
1153 true,
1154 Binder.getCallingUid(),
1155 message);
1156 }
1157
1158 @Override
1159 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1160 try {
1161 ActivityManagerNative.getDefault().grantUriPermission(
1162 mMainThread.getApplicationThread(), toPackage, uri,
1163 modeFlags);
1164 } catch (RemoteException e) {
1165 }
1166 }
1167
1168 @Override
1169 public void revokeUriPermission(Uri uri, int modeFlags) {
1170 try {
1171 ActivityManagerNative.getDefault().revokeUriPermission(
1172 mMainThread.getApplicationThread(), uri,
1173 modeFlags);
1174 } catch (RemoteException e) {
1175 }
1176 }
1177
1178 @Override
1179 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1180 if (!Process.supportsProcesses()) {
1181 return PackageManager.PERMISSION_GRANTED;
1182 }
1183 try {
1184 return ActivityManagerNative.getDefault().checkUriPermission(
1185 uri, pid, uid, modeFlags);
1186 } catch (RemoteException e) {
1187 return PackageManager.PERMISSION_DENIED;
1188 }
1189 }
1190
1191 @Override
1192 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1193 if (!Process.supportsProcesses()) {
1194 return PackageManager.PERMISSION_GRANTED;
1195 }
1196 int pid = Binder.getCallingPid();
1197 if (pid != Process.myPid()) {
1198 return checkUriPermission(uri, pid,
1199 Binder.getCallingUid(), modeFlags);
1200 }
1201 return PackageManager.PERMISSION_DENIED;
1202 }
1203
1204 @Override
1205 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1206 return checkUriPermission(uri, Binder.getCallingPid(),
1207 Binder.getCallingUid(), modeFlags);
1208 }
1209
1210 @Override
1211 public int checkUriPermission(Uri uri, String readPermission,
1212 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001213 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1215 + readPermission + " writePermission=" + writePermission
1216 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1217 }
1218 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1219 if (readPermission == null
1220 || checkPermission(readPermission, pid, uid)
1221 == PackageManager.PERMISSION_GRANTED) {
1222 return PackageManager.PERMISSION_GRANTED;
1223 }
1224 }
1225 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1226 if (writePermission == null
1227 || checkPermission(writePermission, pid, uid)
1228 == PackageManager.PERMISSION_GRANTED) {
1229 return PackageManager.PERMISSION_GRANTED;
1230 }
1231 }
1232 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1233 : PackageManager.PERMISSION_DENIED;
1234 }
1235
1236 private String uriModeFlagToString(int uriModeFlags) {
1237 switch (uriModeFlags) {
1238 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1239 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1240 return "read and write";
1241 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1242 return "read";
1243 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1244 return "write";
1245 }
1246 throw new IllegalArgumentException(
1247 "Unknown permission mode flags: " + uriModeFlags);
1248 }
1249
1250 private void enforceForUri(
1251 int modeFlags, int resultOfCheck, boolean selfToo,
1252 int uid, Uri uri, String message) {
1253 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1254 throw new SecurityException(
1255 (message != null ? (message + ": ") : "") +
1256 (selfToo
1257 ? "Neither user " + uid + " nor current process has "
1258 : "User " + uid + " does not have ") +
1259 uriModeFlagToString(modeFlags) +
1260 " permission on " +
1261 uri +
1262 ".");
1263 }
1264 }
1265
1266 public void enforceUriPermission(
1267 Uri uri, int pid, int uid, int modeFlags, String message) {
1268 enforceForUri(
1269 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1270 false, uid, uri, message);
1271 }
1272
1273 public void enforceCallingUriPermission(
1274 Uri uri, int modeFlags, String message) {
1275 enforceForUri(
1276 modeFlags, checkCallingUriPermission(uri, modeFlags),
1277 false, Binder.getCallingUid(), uri, message);
1278 }
1279
1280 public void enforceCallingOrSelfUriPermission(
1281 Uri uri, int modeFlags, String message) {
1282 enforceForUri(
1283 modeFlags,
1284 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1285 Binder.getCallingUid(), uri, message);
1286 }
1287
1288 public void enforceUriPermission(
1289 Uri uri, String readPermission, String writePermission,
1290 int pid, int uid, int modeFlags, String message) {
1291 enforceForUri(modeFlags,
1292 checkUriPermission(
1293 uri, readPermission, writePermission, pid, uid,
1294 modeFlags),
1295 false,
1296 uid,
1297 uri,
1298 message);
1299 }
1300
1301 @Override
1302 public Context createPackageContext(String packageName, int flags)
1303 throws PackageManager.NameNotFoundException {
1304 if (packageName.equals("system") || packageName.equals("android")) {
1305 return new ApplicationContext(mMainThread.getSystemContext());
1306 }
1307
1308 ActivityThread.PackageInfo pi =
1309 mMainThread.getPackageInfo(packageName, flags);
1310 if (pi != null) {
1311 ApplicationContext c = new ApplicationContext();
Romain Guy870e09f2009-07-06 16:35:25 -07001312 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001313 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 if (c.mResources != null) {
1315 return c;
1316 }
1317 }
1318
1319 // Should be a better exception.
1320 throw new PackageManager.NameNotFoundException(
1321 "Application package " + packageName + " not found");
1322 }
1323
Romain Guy870e09f2009-07-06 16:35:25 -07001324 @Override
1325 public boolean isRestricted() {
1326 return mRestricted;
1327 }
1328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 private File getDataDirFile() {
1330 if (mPackageInfo != null) {
1331 return mPackageInfo.getDataDirFile();
1332 }
1333 throw new RuntimeException("Not supported in system context");
1334 }
1335
1336 @Override
1337 public File getDir(String name, int mode) {
1338 name = "app_" + name;
1339 File file = makeFilename(getDataDirFile(), name);
1340 if (!file.exists()) {
1341 file.mkdir();
1342 setFilePermissionsFromMode(file.getPath(), mode,
1343 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1344 }
1345 return file;
1346 }
1347
1348 static ApplicationContext createSystemContext(ActivityThread mainThread) {
1349 ApplicationContext context = new ApplicationContext();
1350 context.init(Resources.getSystem(), mainThread);
1351 return context;
1352 }
1353
1354 ApplicationContext() {
1355 ++sInstanceCount;
1356 mOuterContext = this;
1357 }
1358
1359 /**
1360 * Create a new ApplicationContext from an existing one. The new one
1361 * works and operates the same as the one it is copying.
1362 *
1363 * @param context Existing application context.
1364 */
1365 public ApplicationContext(ApplicationContext context) {
1366 ++sInstanceCount;
1367 mPackageInfo = context.mPackageInfo;
1368 mResources = context.mResources;
1369 mMainThread = context.mMainThread;
1370 mContentResolver = context.mContentResolver;
1371 mOuterContext = this;
1372 }
1373
1374 final void init(ActivityThread.PackageInfo packageInfo,
1375 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001376 init(packageInfo, activityToken, mainThread, null);
1377 }
1378
1379 final void init(ActivityThread.PackageInfo packageInfo,
1380 IBinder activityToken, ActivityThread mainThread,
1381 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 mPackageInfo = packageInfo;
1383 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001384
1385 if (container != null && container.getCompatibilityInfo().applicationScale !=
1386 mResources.getCompatibilityInfo().applicationScale) {
1387 if (DEBUG) {
1388 Log.d(TAG, "loaded context has different scaling. Using container's" +
1389 " compatiblity info:" + container.getDisplayMetrics());
1390 }
1391 mResources = mainThread.getTopLevelResources(
1392 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 mMainThread = mainThread;
1395 mContentResolver = new ApplicationContentResolver(this, mainThread);
1396
1397 setActivityToken(activityToken);
1398 }
1399
1400 final void init(Resources resources, ActivityThread mainThread) {
1401 mPackageInfo = null;
1402 mResources = resources;
1403 mMainThread = mainThread;
1404 mContentResolver = new ApplicationContentResolver(this, mainThread);
1405 }
1406
1407 final void scheduleFinalCleanup(String who, String what) {
1408 mMainThread.scheduleContextCleanup(this, who, what);
1409 }
1410
1411 final void performFinalCleanup(String who, String what) {
1412 //Log.i(TAG, "Cleanup up context: " + this);
1413 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1414 }
1415
1416 final Context getReceiverRestrictedContext() {
1417 if (mReceiverRestrictedContext != null) {
1418 return mReceiverRestrictedContext;
1419 }
1420 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1421 }
1422
1423 final void setActivityToken(IBinder token) {
1424 mActivityToken = token;
1425 }
1426
1427 final void setOuterContext(Context context) {
1428 mOuterContext = context;
1429 }
1430
1431 final Context getOuterContext() {
1432 return mOuterContext;
1433 }
1434
1435 final IBinder getActivityToken() {
1436 return mActivityToken;
1437 }
1438
1439 private static void setFilePermissionsFromMode(String name, int mode,
1440 int extraPermissions) {
1441 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1442 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1443 |extraPermissions;
1444 if ((mode&MODE_WORLD_READABLE) != 0) {
1445 perms |= FileUtils.S_IROTH;
1446 }
1447 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1448 perms |= FileUtils.S_IWOTH;
1449 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001450 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1452 + ", perms=0x" + Integer.toHexString(perms));
1453 }
1454 FileUtils.setPermissions(name, perms, -1, -1);
1455 }
1456
1457 private File makeFilename(File base, String name) {
1458 if (name.indexOf(File.separatorChar) < 0) {
1459 return new File(base, name);
1460 }
1461 throw new IllegalArgumentException(
1462 "File " + name + " contains a path separator");
1463 }
1464
1465 // ----------------------------------------------------------------------
1466 // ----------------------------------------------------------------------
1467 // ----------------------------------------------------------------------
1468
1469 private static final class ApplicationContentResolver extends ContentResolver {
1470 public ApplicationContentResolver(Context context,
1471 ActivityThread mainThread)
1472 {
1473 super(context);
1474 mMainThread = mainThread;
1475 }
1476
1477 @Override
1478 protected IContentProvider acquireProvider(Context context, String name)
1479 {
1480 return mMainThread.acquireProvider(context, name);
1481 }
1482
1483 @Override
1484 public boolean releaseProvider(IContentProvider provider)
1485 {
1486 return mMainThread.releaseProvider(provider);
1487 }
1488
1489 private final ActivityThread mMainThread;
1490 }
1491
1492 // ----------------------------------------------------------------------
1493 // ----------------------------------------------------------------------
1494 // ----------------------------------------------------------------------
1495
1496 /*package*/
1497 static final class ApplicationPackageManager extends PackageManager {
1498 @Override
1499 public PackageInfo getPackageInfo(String packageName, int flags)
1500 throws NameNotFoundException {
1501 try {
1502 PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1503 if (pi != null) {
1504 return pi;
1505 }
1506 } catch (RemoteException e) {
1507 throw new RuntimeException("Package manager has died", e);
1508 }
1509
1510 throw new NameNotFoundException(packageName);
1511 }
1512
Mihai Predaeae850c2009-05-13 10:13:48 +02001513 @Override
1514 public Intent getLaunchIntentForPackage(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 // First see if the package has an INFO activity; the existence of
1516 // such an activity is implied to be the desired front-door for the
1517 // overall package (such as if it has multiple launcher entries).
Mihai Predaeae850c2009-05-13 10:13:48 +02001518 Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1519 intentToResolve.addCategory(Intent.CATEGORY_INFO);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001520 intentToResolve.setPackage(packageName);
1521 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
Mihai Predaeae850c2009-05-13 10:13:48 +02001522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 // Otherwise, try to find a main launcher activity.
Mihai Predaeae850c2009-05-13 10:13:48 +02001524 if (resolveInfo == null) {
1525 // reuse the intent instance
1526 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1527 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001528 intentToResolve.setPackage(packageName);
1529 resolveInfo = resolveActivity(intentToResolve, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001531 if (resolveInfo == null) {
1532 return null;
1533 }
1534 Intent intent = new Intent(Intent.ACTION_MAIN);
1535 intent.setClassName(packageName, resolveInfo.activityInfo.name);
1536 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1537 return intent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 @Override
1541 public int[] getPackageGids(String packageName)
1542 throws NameNotFoundException {
1543 try {
1544 int[] gids = mPM.getPackageGids(packageName);
1545 if (gids == null || gids.length > 0) {
1546 return gids;
1547 }
1548 } catch (RemoteException e) {
1549 throw new RuntimeException("Package manager has died", e);
1550 }
1551
1552 throw new NameNotFoundException(packageName);
1553 }
1554
1555 @Override
1556 public PermissionInfo getPermissionInfo(String name, int flags)
1557 throws NameNotFoundException {
1558 try {
1559 PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1560 if (pi != null) {
1561 return pi;
1562 }
1563 } catch (RemoteException e) {
1564 throw new RuntimeException("Package manager has died", e);
1565 }
1566
1567 throw new NameNotFoundException(name);
1568 }
1569
1570 @Override
1571 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1572 throws NameNotFoundException {
1573 try {
1574 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1575 if (pi != null) {
1576 return pi;
1577 }
1578 } catch (RemoteException e) {
1579 throw new RuntimeException("Package manager has died", e);
1580 }
1581
1582 throw new NameNotFoundException(group);
1583 }
1584
1585 @Override
1586 public PermissionGroupInfo getPermissionGroupInfo(String name,
1587 int flags) throws NameNotFoundException {
1588 try {
1589 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1590 if (pgi != null) {
1591 return pgi;
1592 }
1593 } catch (RemoteException e) {
1594 throw new RuntimeException("Package manager has died", e);
1595 }
1596
1597 throw new NameNotFoundException(name);
1598 }
1599
1600 @Override
1601 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1602 try {
1603 return mPM.getAllPermissionGroups(flags);
1604 } catch (RemoteException e) {
1605 throw new RuntimeException("Package manager has died", e);
1606 }
1607 }
1608
1609 @Override
1610 public ApplicationInfo getApplicationInfo(String packageName, int flags)
1611 throws NameNotFoundException {
1612 try {
1613 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
1614 if (ai != null) {
1615 return ai;
1616 }
1617 } catch (RemoteException e) {
1618 throw new RuntimeException("Package manager has died", e);
1619 }
1620
1621 throw new NameNotFoundException(packageName);
1622 }
1623
1624 @Override
1625 public ActivityInfo getActivityInfo(ComponentName className, int flags)
1626 throws NameNotFoundException {
1627 try {
1628 ActivityInfo ai = mPM.getActivityInfo(className, flags);
1629 if (ai != null) {
1630 return ai;
1631 }
1632 } catch (RemoteException e) {
1633 throw new RuntimeException("Package manager has died", e);
1634 }
1635
1636 throw new NameNotFoundException(className.toString());
1637 }
1638
1639 @Override
1640 public ActivityInfo getReceiverInfo(ComponentName className, int flags)
1641 throws NameNotFoundException {
1642 try {
1643 ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1644 if (ai != null) {
1645 return ai;
1646 }
1647 } catch (RemoteException e) {
1648 throw new RuntimeException("Package manager has died", e);
1649 }
1650
1651 throw new NameNotFoundException(className.toString());
1652 }
1653
1654 @Override
1655 public ServiceInfo getServiceInfo(ComponentName className, int flags)
1656 throws NameNotFoundException {
1657 try {
1658 ServiceInfo si = mPM.getServiceInfo(className, flags);
1659 if (si != null) {
1660 return si;
1661 }
1662 } catch (RemoteException e) {
1663 throw new RuntimeException("Package manager has died", e);
1664 }
1665
1666 throw new NameNotFoundException(className.toString());
1667 }
1668
1669 @Override
1670 public String[] getSystemSharedLibraryNames() {
1671 try {
1672 return mPM.getSystemSharedLibraryNames();
1673 } catch (RemoteException e) {
1674 throw new RuntimeException("Package manager has died", e);
1675 }
1676 }
1677
1678 @Override
Dianne Hackborn49237342009-08-27 20:08:01 -07001679 public FeatureInfo[] getSystemAvailableFeatures() {
1680 try {
1681 return mPM.getSystemAvailableFeatures();
1682 } catch (RemoteException e) {
1683 throw new RuntimeException("Package manager has died", e);
1684 }
1685 }
1686
1687 @Override
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001688 public boolean hasSystemFeature(String name) {
1689 try {
1690 return mPM.hasSystemFeature(name);
1691 } catch (RemoteException e) {
1692 throw new RuntimeException("Package manager has died", e);
1693 }
1694 }
1695
1696 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 public int checkPermission(String permName, String pkgName) {
1698 try {
1699 return mPM.checkPermission(permName, pkgName);
1700 } catch (RemoteException e) {
1701 throw new RuntimeException("Package manager has died", e);
1702 }
1703 }
1704
1705 @Override
1706 public boolean addPermission(PermissionInfo info) {
1707 try {
1708 return mPM.addPermission(info);
1709 } catch (RemoteException e) {
1710 throw new RuntimeException("Package manager has died", e);
1711 }
1712 }
1713
1714 @Override
1715 public void removePermission(String name) {
1716 try {
1717 mPM.removePermission(name);
1718 } catch (RemoteException e) {
1719 throw new RuntimeException("Package manager has died", e);
1720 }
1721 }
1722
1723 @Override
1724 public int checkSignatures(String pkg1, String pkg2) {
1725 try {
1726 return mPM.checkSignatures(pkg1, pkg2);
1727 } catch (RemoteException e) {
1728 throw new RuntimeException("Package manager has died", e);
1729 }
1730 }
1731
1732 @Override
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001733 public int checkSignatures(int uid1, int uid2) {
1734 try {
1735 return mPM.checkUidSignatures(uid1, uid2);
1736 } catch (RemoteException e) {
1737 throw new RuntimeException("Package manager has died", e);
1738 }
1739 }
1740
1741 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 public String[] getPackagesForUid(int uid) {
1743 try {
1744 return mPM.getPackagesForUid(uid);
1745 } catch (RemoteException e) {
1746 throw new RuntimeException("Package manager has died", e);
1747 }
1748 }
1749
1750 @Override
1751 public String getNameForUid(int uid) {
1752 try {
1753 return mPM.getNameForUid(uid);
1754 } catch (RemoteException e) {
1755 throw new RuntimeException("Package manager has died", e);
1756 }
1757 }
1758
1759 @Override
1760 public int getUidForSharedUser(String sharedUserName)
1761 throws NameNotFoundException {
1762 try {
1763 int uid = mPM.getUidForSharedUser(sharedUserName);
1764 if(uid != -1) {
1765 return uid;
1766 }
1767 } catch (RemoteException e) {
1768 throw new RuntimeException("Package manager has died", e);
1769 }
1770 throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1771 }
1772
1773 @Override
1774 public List<PackageInfo> getInstalledPackages(int flags) {
1775 try {
1776 return mPM.getInstalledPackages(flags);
1777 } catch (RemoteException e) {
1778 throw new RuntimeException("Package manager has died", e);
1779 }
1780 }
1781
1782 @Override
1783 public List<ApplicationInfo> getInstalledApplications(int flags) {
1784 try {
1785 return mPM.getInstalledApplications(flags);
1786 } catch (RemoteException e) {
1787 throw new RuntimeException("Package manager has died", e);
1788 }
1789 }
1790
1791 @Override
1792 public ResolveInfo resolveActivity(Intent intent, int flags) {
1793 try {
1794 return mPM.resolveIntent(
1795 intent,
1796 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1797 flags);
1798 } catch (RemoteException e) {
1799 throw new RuntimeException("Package manager has died", e);
1800 }
1801 }
1802
1803 @Override
1804 public List<ResolveInfo> queryIntentActivities(Intent intent,
1805 int flags) {
1806 try {
1807 return mPM.queryIntentActivities(
1808 intent,
1809 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1810 flags);
1811 } catch (RemoteException e) {
1812 throw new RuntimeException("Package manager has died", e);
1813 }
1814 }
1815
1816 @Override
1817 public List<ResolveInfo> queryIntentActivityOptions(
1818 ComponentName caller, Intent[] specifics, Intent intent,
1819 int flags) {
1820 final ContentResolver resolver = mContext.getContentResolver();
1821
1822 String[] specificTypes = null;
1823 if (specifics != null) {
1824 final int N = specifics.length;
1825 for (int i=0; i<N; i++) {
1826 Intent sp = specifics[i];
1827 if (sp != null) {
1828 String t = sp.resolveTypeIfNeeded(resolver);
1829 if (t != null) {
1830 if (specificTypes == null) {
1831 specificTypes = new String[N];
1832 }
1833 specificTypes[i] = t;
1834 }
1835 }
1836 }
1837 }
1838
1839 try {
1840 return mPM.queryIntentActivityOptions(caller, specifics,
1841 specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
1842 flags);
1843 } catch (RemoteException e) {
1844 throw new RuntimeException("Package manager has died", e);
1845 }
1846 }
1847
1848 @Override
1849 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
1850 try {
1851 return mPM.queryIntentReceivers(
1852 intent,
1853 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1854 flags);
1855 } catch (RemoteException e) {
1856 throw new RuntimeException("Package manager has died", e);
1857 }
1858 }
1859
1860 @Override
1861 public ResolveInfo resolveService(Intent intent, int flags) {
1862 try {
1863 return mPM.resolveService(
1864 intent,
1865 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1866 flags);
1867 } catch (RemoteException e) {
1868 throw new RuntimeException("Package manager has died", e);
1869 }
1870 }
1871
1872 @Override
1873 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
1874 try {
1875 return mPM.queryIntentServices(
1876 intent,
1877 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1878 flags);
1879 } catch (RemoteException e) {
1880 throw new RuntimeException("Package manager has died", e);
1881 }
1882 }
1883
1884 @Override
1885 public ProviderInfo resolveContentProvider(String name,
1886 int flags) {
1887 try {
1888 return mPM.resolveContentProvider(name, flags);
1889 } catch (RemoteException e) {
1890 throw new RuntimeException("Package manager has died", e);
1891 }
1892 }
1893
1894 @Override
1895 public List<ProviderInfo> queryContentProviders(String processName,
1896 int uid, int flags) {
1897 try {
1898 return mPM.queryContentProviders(processName, uid, flags);
1899 } catch (RemoteException e) {
1900 throw new RuntimeException("Package manager has died", e);
1901 }
1902 }
1903
1904 @Override
1905 public InstrumentationInfo getInstrumentationInfo(
1906 ComponentName className, int flags)
1907 throws NameNotFoundException {
1908 try {
1909 InstrumentationInfo ii = mPM.getInstrumentationInfo(
1910 className, flags);
1911 if (ii != null) {
1912 return ii;
1913 }
1914 } catch (RemoteException e) {
1915 throw new RuntimeException("Package manager has died", e);
1916 }
1917
1918 throw new NameNotFoundException(className.toString());
1919 }
1920
1921 @Override
1922 public List<InstrumentationInfo> queryInstrumentation(
1923 String targetPackage, int flags) {
1924 try {
1925 return mPM.queryInstrumentation(targetPackage, flags);
1926 } catch (RemoteException e) {
1927 throw new RuntimeException("Package manager has died", e);
1928 }
1929 }
1930
1931 @Override public Drawable getDrawable(String packageName, int resid,
1932 ApplicationInfo appInfo) {
1933 ResourceName name = new ResourceName(packageName, resid);
1934 Drawable dr = getCachedIcon(name);
1935 if (dr != null) {
1936 return dr;
1937 }
1938 if (appInfo == null) {
1939 try {
1940 appInfo = getApplicationInfo(packageName, 0);
1941 } catch (NameNotFoundException e) {
1942 return null;
1943 }
1944 }
1945 try {
1946 Resources r = getResourcesForApplication(appInfo);
1947 dr = r.getDrawable(resid);
Dianne Hackborn11ea3342009-07-22 21:48:55 -07001948 if (false) {
1949 RuntimeException e = new RuntimeException("here");
1950 e.fillInStackTrace();
1951 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
1952 + " from package " + packageName
1953 + ": app scale=" + r.getCompatibilityInfo().applicationScale
1954 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
1955 e);
1956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
1958 + Integer.toHexString(resid) + " from " + r
1959 + ": " + dr);
1960 putCachedIcon(name, dr);
1961 return dr;
1962 } catch (NameNotFoundException e) {
1963 Log.w("PackageManager", "Failure retrieving resources for"
1964 + appInfo.packageName);
1965 } catch (RuntimeException e) {
1966 // If an exception was thrown, fall through to return
1967 // default icon.
1968 Log.w("PackageManager", "Failure retrieving icon 0x"
1969 + Integer.toHexString(resid) + " in package "
1970 + packageName, e);
1971 }
1972 return null;
1973 }
1974
1975 @Override public Drawable getActivityIcon(ComponentName activityName)
1976 throws NameNotFoundException {
1977 return getActivityInfo(activityName, 0).loadIcon(this);
1978 }
1979
1980 @Override public Drawable getActivityIcon(Intent intent)
1981 throws NameNotFoundException {
1982 if (intent.getComponent() != null) {
1983 return getActivityIcon(intent.getComponent());
1984 }
1985
1986 ResolveInfo info = resolveActivity(
1987 intent, PackageManager.MATCH_DEFAULT_ONLY);
1988 if (info != null) {
1989 return info.activityInfo.loadIcon(this);
1990 }
1991
1992 throw new NameNotFoundException(intent.toURI());
1993 }
1994
1995 @Override public Drawable getDefaultActivityIcon() {
1996 return Resources.getSystem().getDrawable(
1997 com.android.internal.R.drawable.sym_def_app_icon);
1998 }
1999
2000 @Override public Drawable getApplicationIcon(ApplicationInfo info) {
2001 final int icon = info.icon;
2002 if (icon != 0) {
2003 ResourceName name = new ResourceName(info, icon);
2004 Drawable dr = getCachedIcon(name);
2005 if (dr != null) {
2006 return dr;
2007 }
2008 try {
2009 Resources r = getResourcesForApplication(info);
2010 dr = r.getDrawable(icon);
2011 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2012 + Integer.toHexString(icon) + " from " + r
2013 + ": " + dr);
2014 putCachedIcon(name, dr);
2015 return dr;
2016 } catch (NameNotFoundException e) {
2017 Log.w("PackageManager", "Failure retrieving resources for"
2018 + info.packageName);
2019 } catch (RuntimeException e) {
2020 // If an exception was thrown, fall through to return
2021 // default icon.
2022 Log.w("PackageManager", "Failure retrieving app icon", e);
2023 }
2024 }
2025 return getDefaultActivityIcon();
2026 }
2027
2028 @Override public Drawable getApplicationIcon(String packageName)
2029 throws NameNotFoundException {
2030 return getApplicationIcon(getApplicationInfo(packageName, 0));
2031 }
2032
2033 @Override public Resources getResourcesForActivity(
2034 ComponentName activityName) throws NameNotFoundException {
2035 return getResourcesForApplication(
2036 getActivityInfo(activityName, 0).applicationInfo);
2037 }
2038
2039 @Override public Resources getResourcesForApplication(
2040 ApplicationInfo app) throws NameNotFoundException {
2041 if (app.packageName.equals("system")) {
2042 return mContext.mMainThread.getSystemContext().getResources();
2043 }
2044 Resources r = mContext.mMainThread.getTopLevelResources(
2045 app.uid == Process.myUid() ? app.sourceDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002046 : app.publicSourceDir, mContext.mPackageInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 if (r != null) {
2048 return r;
2049 }
2050 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2051 }
2052
2053 @Override public Resources getResourcesForApplication(
2054 String appPackageName) throws NameNotFoundException {
2055 return getResourcesForApplication(
2056 getApplicationInfo(appPackageName, 0));
2057 }
2058
2059 int mCachedSafeMode = -1;
2060 @Override public boolean isSafeMode() {
2061 try {
2062 if (mCachedSafeMode < 0) {
2063 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2064 }
2065 return mCachedSafeMode != 0;
2066 } catch (RemoteException e) {
2067 throw new RuntimeException("Package manager has died", e);
2068 }
2069 }
2070
2071 static void configurationChanged() {
2072 synchronized (sSync) {
2073 sIconCache.clear();
2074 sStringCache.clear();
2075 }
2076 }
2077
2078 ApplicationPackageManager(ApplicationContext context,
2079 IPackageManager pm) {
2080 mContext = context;
2081 mPM = pm;
2082 }
2083
2084 private Drawable getCachedIcon(ResourceName name) {
2085 synchronized (sSync) {
2086 WeakReference<Drawable> wr = sIconCache.get(name);
2087 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2088 + name + ": " + wr);
2089 if (wr != null) { // we have the activity
2090 Drawable dr = wr.get();
2091 if (dr != null) {
2092 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2093 + name + ": " + dr);
2094 return dr;
2095 }
2096 // our entry has been purged
2097 sIconCache.remove(name);
2098 }
2099 }
2100 return null;
2101 }
2102
2103 private void establishPackageRemovedReceiver() {
2104 // mContext.registerReceiverInternal() winds up acquiring the
2105 // main ActivityManagerService.this lock. If we hold our usual
2106 // sSync global lock at the same time, we impose a required ordering
2107 // on those two locks, which is not good for deadlock prevention.
2108 // Use a dedicated lock around initialization of
2109 // sPackageRemovedReceiver to avoid this.
2110 synchronized (sPackageRemovedSync) {
2111 if (sPackageRemovedReceiver == null) {
2112 sPackageRemovedReceiver = new PackageRemovedReceiver();
2113 IntentFilter filter = new IntentFilter(
2114 Intent.ACTION_PACKAGE_REMOVED);
2115 filter.addDataScheme("package");
2116 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2117 filter, null, null, null);
2118 }
2119 }
2120 }
2121
2122 private void putCachedIcon(ResourceName name, Drawable dr) {
2123 establishPackageRemovedReceiver();
2124
2125 synchronized (sSync) {
2126 sIconCache.put(name, new WeakReference<Drawable>(dr));
2127 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2128 + name + ": " + dr);
2129 }
2130 }
2131
2132 private static final class PackageRemovedReceiver extends BroadcastReceiver {
2133 @Override
2134 public void onReceive(Context context, Intent intent) {
2135 Uri data = intent.getData();
2136 String ssp;
2137 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
2138 boolean needCleanup = false;
2139 synchronized (sSync) {
2140 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2141 while (it.hasNext()) {
2142 ResourceName nm = it.next();
2143 if (nm.packageName.equals(ssp)) {
2144 //Log.i(TAG, "Removing cached drawable for " + nm);
2145 it.remove();
2146 needCleanup = true;
2147 }
2148 }
2149 it = sStringCache.keySet().iterator();
2150 while (it.hasNext()) {
2151 ResourceName nm = it.next();
2152 if (nm.packageName.equals(ssp)) {
2153 //Log.i(TAG, "Removing cached string for " + nm);
2154 it.remove();
2155 needCleanup = true;
2156 }
2157 }
2158 }
2159 if (needCleanup || ActivityThread.currentActivityThread().hasPackageInfo(ssp)) {
2160 ActivityThread.currentActivityThread().scheduleGcIdler();
2161 }
2162 }
2163 }
2164 }
2165
2166 private static final class ResourceName {
2167 final String packageName;
2168 final int iconId;
2169
2170 ResourceName(String _packageName, int _iconId) {
2171 packageName = _packageName;
2172 iconId = _iconId;
2173 }
2174
2175 ResourceName(ApplicationInfo aInfo, int _iconId) {
2176 this(aInfo.packageName, _iconId);
2177 }
2178
2179 ResourceName(ComponentInfo cInfo, int _iconId) {
2180 this(cInfo.applicationInfo.packageName, _iconId);
2181 }
2182
2183 ResourceName(ResolveInfo rInfo, int _iconId) {
2184 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2185 }
2186
2187 @Override
2188 public boolean equals(Object o) {
2189 if (this == o) return true;
2190 if (o == null || getClass() != o.getClass()) return false;
2191
2192 ResourceName that = (ResourceName) o;
2193
2194 if (iconId != that.iconId) return false;
2195 return !(packageName != null ?
2196 !packageName.equals(that.packageName) : that.packageName != null);
2197
2198 }
2199
2200 @Override
2201 public int hashCode() {
2202 int result;
2203 result = packageName.hashCode();
2204 result = 31 * result + iconId;
2205 return result;
2206 }
2207
2208 @Override
2209 public String toString() {
2210 return "{ResourceName " + packageName + " / " + iconId + "}";
2211 }
2212 }
2213
2214 private CharSequence getCachedString(ResourceName name) {
2215 synchronized (sSync) {
2216 WeakReference<CharSequence> wr = sStringCache.get(name);
2217 if (wr != null) { // we have the activity
2218 CharSequence cs = wr.get();
2219 if (cs != null) {
2220 return cs;
2221 }
2222 // our entry has been purged
2223 sStringCache.remove(name);
2224 }
2225 }
2226 return null;
2227 }
2228
2229 private void putCachedString(ResourceName name, CharSequence cs) {
2230 establishPackageRemovedReceiver();
2231
2232 synchronized (sSync) {
2233 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2234 }
2235 }
2236
2237 private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
2238 CharSequence cs = getCachedString(name);
2239 if (cs != null) {
2240 return cs;
2241 }
2242 try {
2243 Resources r = getResourcesForApplication(app);
2244 cs = r.getText(id);
2245 putCachedString(name, cs);
2246 } catch (NameNotFoundException e) {
2247 Log.w("PackageManager", "Failure retrieving resources for"
2248 + app.packageName);
2249 } catch (RuntimeException e) {
2250 // If an exception was thrown, fall through to return null
2251 Log.w("ApplicationInfo", "Failure retrieving activity name", e);
2252 }
2253 return cs;
2254 }
2255
2256 @Override
2257 public CharSequence getText(String packageName, int resid,
2258 ApplicationInfo appInfo) {
2259 ResourceName name = new ResourceName(packageName, resid);
2260 CharSequence text = getCachedString(name);
2261 if (text != null) {
2262 return text;
2263 }
2264 if (appInfo == null) {
2265 try {
2266 appInfo = getApplicationInfo(packageName, 0);
2267 } catch (NameNotFoundException e) {
2268 return null;
2269 }
2270 }
2271 try {
2272 Resources r = getResourcesForApplication(appInfo);
2273 text = r.getText(resid);
2274 putCachedString(name, text);
2275 return text;
2276 } catch (NameNotFoundException e) {
2277 Log.w("PackageManager", "Failure retrieving resources for"
2278 + appInfo.packageName);
2279 } catch (RuntimeException e) {
2280 // If an exception was thrown, fall through to return
2281 // default icon.
2282 Log.w("PackageManager", "Failure retrieving text 0x"
2283 + Integer.toHexString(resid) + " in package "
2284 + packageName, e);
2285 }
2286 return null;
2287 }
2288
2289 @Override
2290 public XmlResourceParser getXml(String packageName, int resid,
2291 ApplicationInfo appInfo) {
2292 if (appInfo == null) {
2293 try {
2294 appInfo = getApplicationInfo(packageName, 0);
2295 } catch (NameNotFoundException e) {
2296 return null;
2297 }
2298 }
2299 try {
2300 Resources r = getResourcesForApplication(appInfo);
2301 return r.getXml(resid);
2302 } catch (RuntimeException e) {
2303 // If an exception was thrown, fall through to return
2304 // default icon.
2305 Log.w("PackageManager", "Failure retrieving xml 0x"
2306 + Integer.toHexString(resid) + " in package "
2307 + packageName, e);
2308 } catch (NameNotFoundException e) {
2309 Log.w("PackageManager", "Failure retrieving resources for"
2310 + appInfo.packageName);
2311 }
2312 return null;
2313 }
2314
2315 @Override
2316 public CharSequence getApplicationLabel(ApplicationInfo info) {
2317 if (info.nonLocalizedLabel != null) {
2318 return info.nonLocalizedLabel;
2319 }
2320 final int id = info.labelRes;
2321 if (id != 0) {
2322 CharSequence cs = getLabel(new ResourceName(info, id), info, id);
2323 if (cs != null) {
2324 return cs;
2325 }
2326 }
2327 return info.packageName;
2328 }
2329
2330 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002331 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2332 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 try {
Jacek Surazski65e13172009-04-28 15:26:38 +02002334 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 } catch (RemoteException e) {
2336 // Should never happen!
2337 }
2338 }
2339
2340 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002341 public String getInstallerPackageName(String packageName) {
2342 try {
2343 return mPM.getInstallerPackageName(packageName);
2344 } catch (RemoteException e) {
2345 // Should never happen!
2346 }
2347 return null;
2348 }
2349
2350 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2352 try {
2353 mPM.deletePackage(packageName, observer, flags);
2354 } catch (RemoteException e) {
2355 // Should never happen!
2356 }
2357 }
2358 @Override
2359 public void clearApplicationUserData(String packageName,
2360 IPackageDataObserver observer) {
2361 try {
2362 mPM.clearApplicationUserData(packageName, observer);
2363 } catch (RemoteException e) {
2364 // Should never happen!
2365 }
2366 }
2367 @Override
2368 public void deleteApplicationCacheFiles(String packageName,
2369 IPackageDataObserver observer) {
2370 try {
2371 mPM.deleteApplicationCacheFiles(packageName, observer);
2372 } catch (RemoteException e) {
2373 // Should never happen!
2374 }
2375 }
2376 @Override
2377 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2378 try {
2379 mPM.freeStorageAndNotify(idealStorageSize, observer);
2380 } catch (RemoteException e) {
2381 // Should never happen!
2382 }
2383 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 @Override
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002386 public void freeStorage(long freeStorageSize, IntentSender pi) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002387 try {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002388 mPM.freeStorage(freeStorageSize, pi);
2389 } catch (RemoteException e) {
2390 // Should never happen!
2391 }
2392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002393
2394 @Override
2395 public void getPackageSizeInfo(String packageName,
2396 IPackageStatsObserver observer) {
2397 try {
2398 mPM.getPackageSizeInfo(packageName, observer);
2399 } catch (RemoteException e) {
2400 // Should never happen!
2401 }
2402 }
2403 @Override
2404 public void addPackageToPreferred(String packageName) {
2405 try {
2406 mPM.addPackageToPreferred(packageName);
2407 } catch (RemoteException e) {
2408 // Should never happen!
2409 }
2410 }
2411
2412 @Override
2413 public void removePackageFromPreferred(String packageName) {
2414 try {
2415 mPM.removePackageFromPreferred(packageName);
2416 } catch (RemoteException e) {
2417 // Should never happen!
2418 }
2419 }
2420
2421 @Override
2422 public List<PackageInfo> getPreferredPackages(int flags) {
2423 try {
2424 return mPM.getPreferredPackages(flags);
2425 } catch (RemoteException e) {
2426 // Should never happen!
2427 }
2428 return new ArrayList<PackageInfo>();
2429 }
2430
2431 @Override
2432 public void addPreferredActivity(IntentFilter filter,
2433 int match, ComponentName[] set, ComponentName activity) {
2434 try {
2435 mPM.addPreferredActivity(filter, match, set, activity);
2436 } catch (RemoteException e) {
2437 // Should never happen!
2438 }
2439 }
2440
2441 @Override
Satish Sampath8dbe6122009-06-02 23:35:54 +01002442 public void replacePreferredActivity(IntentFilter filter,
2443 int match, ComponentName[] set, ComponentName activity) {
2444 try {
2445 mPM.replacePreferredActivity(filter, match, set, activity);
2446 } catch (RemoteException e) {
2447 // Should never happen!
2448 }
2449 }
2450
2451 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002452 public void clearPackagePreferredActivities(String packageName) {
2453 try {
2454 mPM.clearPackagePreferredActivities(packageName);
2455 } catch (RemoteException e) {
2456 // Should never happen!
2457 }
2458 }
2459
2460 @Override
2461 public int getPreferredActivities(List<IntentFilter> outFilters,
2462 List<ComponentName> outActivities, String packageName) {
2463 try {
2464 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2465 } catch (RemoteException e) {
2466 // Should never happen!
2467 }
2468 return 0;
2469 }
2470
2471 @Override
2472 public void setComponentEnabledSetting(ComponentName componentName,
2473 int newState, int flags) {
2474 try {
2475 mPM.setComponentEnabledSetting(componentName, newState, flags);
2476 } catch (RemoteException e) {
2477 // Should never happen!
2478 }
2479 }
2480
2481 @Override
2482 public int getComponentEnabledSetting(ComponentName componentName) {
2483 try {
2484 return mPM.getComponentEnabledSetting(componentName);
2485 } catch (RemoteException e) {
2486 // Should never happen!
2487 }
2488 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2489 }
2490
2491 @Override
2492 public void setApplicationEnabledSetting(String packageName,
2493 int newState, int flags) {
2494 try {
2495 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2496 } catch (RemoteException e) {
2497 // Should never happen!
2498 }
2499 }
2500
2501 @Override
2502 public int getApplicationEnabledSetting(String packageName) {
2503 try {
2504 return mPM.getApplicationEnabledSetting(packageName);
2505 } catch (RemoteException e) {
2506 // Should never happen!
2507 }
2508 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2509 }
2510
2511 private final ApplicationContext mContext;
2512 private final IPackageManager mPM;
2513
2514 private static final Object sSync = new Object();
2515 private static final Object sPackageRemovedSync = new Object();
2516 private static BroadcastReceiver sPackageRemovedReceiver;
2517 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2518 = new HashMap<ResourceName, WeakReference<Drawable> >();
2519 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2520 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2521 }
2522
2523 // ----------------------------------------------------------------------
2524 // ----------------------------------------------------------------------
2525 // ----------------------------------------------------------------------
2526
2527 private static final class SharedPreferencesImpl implements SharedPreferences {
2528
2529 private final File mFile;
2530 private final File mBackupFile;
2531 private final int mMode;
2532 private Map mMap;
2533 private final FileStatus mFileStatus = new FileStatus();
2534 private long mTimestamp;
2535
The Android Open Source Project10592532009-03-18 17:39:46 -07002536 private static final Object mContent = new Object();
2537 private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002538
2539 SharedPreferencesImpl(
2540 File file, int mode, Map initialContents) {
2541 mFile = file;
2542 mBackupFile = makeBackupFile(file);
2543 mMode = mode;
2544 mMap = initialContents != null ? initialContents : new HashMap();
2545 if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
2546 mTimestamp = mFileStatus.mtime;
2547 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002548 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002549 }
2550
2551 public boolean hasFileChanged() {
2552 synchronized (this) {
2553 if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2554 return true;
2555 }
2556 return mTimestamp != mFileStatus.mtime;
2557 }
2558 }
2559
2560 public void replace(Map newContents) {
2561 if (newContents != null) {
2562 synchronized (this) {
2563 mMap = newContents;
2564 }
2565 }
2566 }
2567
2568 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2569 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002570 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 }
2572 }
2573
2574 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2575 synchronized(this) {
2576 mListeners.remove(listener);
2577 }
2578 }
2579
2580 public Map<String, ?> getAll() {
2581 synchronized(this) {
2582 //noinspection unchecked
2583 return new HashMap(mMap);
2584 }
2585 }
2586
2587 public String getString(String key, String defValue) {
2588 synchronized (this) {
2589 String v = (String)mMap.get(key);
2590 return v != null ? v : defValue;
2591 }
2592 }
2593
2594 public int getInt(String key, int defValue) {
2595 synchronized (this) {
2596 Integer v = (Integer)mMap.get(key);
2597 return v != null ? v : defValue;
2598 }
2599 }
2600 public long getLong(String key, long defValue) {
2601 synchronized (this) {
2602 Long v = (Long) mMap.get(key);
2603 return v != null ? v : defValue;
2604 }
2605 }
2606 public float getFloat(String key, float defValue) {
2607 synchronized (this) {
2608 Float v = (Float)mMap.get(key);
2609 return v != null ? v : defValue;
2610 }
2611 }
2612 public boolean getBoolean(String key, boolean defValue) {
2613 synchronized (this) {
2614 Boolean v = (Boolean)mMap.get(key);
2615 return v != null ? v : defValue;
2616 }
2617 }
2618
2619 public boolean contains(String key) {
2620 synchronized (this) {
2621 return mMap.containsKey(key);
2622 }
2623 }
2624
2625 public final class EditorImpl implements Editor {
2626 private final Map<String, Object> mModified = Maps.newHashMap();
2627 private boolean mClear = false;
2628
2629 public Editor putString(String key, String value) {
2630 synchronized (this) {
2631 mModified.put(key, value);
2632 return this;
2633 }
2634 }
2635 public Editor putInt(String key, int value) {
2636 synchronized (this) {
2637 mModified.put(key, value);
2638 return this;
2639 }
2640 }
2641 public Editor putLong(String key, long value) {
2642 synchronized (this) {
2643 mModified.put(key, value);
2644 return this;
2645 }
2646 }
2647 public Editor putFloat(String key, float value) {
2648 synchronized (this) {
2649 mModified.put(key, value);
2650 return this;
2651 }
2652 }
2653 public Editor putBoolean(String key, boolean value) {
2654 synchronized (this) {
2655 mModified.put(key, value);
2656 return this;
2657 }
2658 }
2659
2660 public Editor remove(String key) {
2661 synchronized (this) {
2662 mModified.put(key, this);
2663 return this;
2664 }
2665 }
2666
2667 public Editor clear() {
2668 synchronized (this) {
2669 mClear = true;
2670 return this;
2671 }
2672 }
2673
2674 public boolean commit() {
2675 boolean returnValue;
2676
2677 boolean hasListeners;
2678 List<String> keysModified = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07002679 Set<OnSharedPreferenceChangeListener> listeners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680
2681 synchronized (SharedPreferencesImpl.this) {
2682 hasListeners = mListeners.size() > 0;
2683 if (hasListeners) {
2684 keysModified = new ArrayList<String>();
The Android Open Source Project10592532009-03-18 17:39:46 -07002685 listeners =
2686 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002687 }
2688
2689 synchronized (this) {
2690 if (mClear) {
2691 mMap.clear();
2692 mClear = false;
2693 }
2694
The Android Open Source Project10592532009-03-18 17:39:46 -07002695 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 String k = e.getKey();
2697 Object v = e.getValue();
2698 if (v == this) {
2699 mMap.remove(k);
2700 } else {
2701 mMap.put(k, v);
2702 }
2703
2704 if (hasListeners) {
2705 keysModified.add(k);
2706 }
2707 }
2708
2709 mModified.clear();
2710 }
2711
2712 returnValue = writeFileLocked();
2713 }
2714
2715 if (hasListeners) {
2716 for (int i = keysModified.size() - 1; i >= 0; i--) {
2717 final String key = keysModified.get(i);
The Android Open Source Project10592532009-03-18 17:39:46 -07002718 for (OnSharedPreferenceChangeListener listener : listeners) {
2719 if (listener != null) {
2720 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
2721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 }
2723 }
2724 }
2725
2726 return returnValue;
2727 }
2728 }
2729
2730 public Editor edit() {
2731 return new EditorImpl();
2732 }
2733
2734 private FileOutputStream createFileOutputStream(File file) {
2735 FileOutputStream str = null;
2736 try {
2737 str = new FileOutputStream(file);
2738 } catch (FileNotFoundException e) {
2739 File parent = file.getParentFile();
2740 if (!parent.mkdir()) {
2741 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
2742 return null;
2743 }
2744 FileUtils.setPermissions(
2745 parent.getPath(),
2746 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2747 -1, -1);
2748 try {
2749 str = new FileOutputStream(file);
2750 } catch (FileNotFoundException e2) {
2751 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
2752 }
2753 }
2754 return str;
2755 }
2756
2757 private boolean writeFileLocked() {
2758 // Rename the current file so it may be used as a backup during the next read
2759 if (mFile.exists()) {
2760 if (!mFile.renameTo(mBackupFile)) {
2761 Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002762 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 }
2764 }
2765
2766 // Attempt to write the file, delete the backup and return true as atomically as
2767 // possible. If any exception occurs, delete the new file; next time we will restore
2768 // from the backup.
2769 try {
2770 FileOutputStream str = createFileOutputStream(mFile);
2771 if (str == null) {
2772 return false;
2773 }
2774 XmlUtils.writeMapXml(mMap, str);
2775 str.close();
2776 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
2777 if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2778 mTimestamp = mFileStatus.mtime;
2779 }
2780
Dianne Hackborn51bf0772009-03-24 19:11:41 -07002781 // Writing was successful, delete the backup file if there is one.
2782 mBackupFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002783 return true;
2784 } catch (XmlPullParserException e) {
2785 Log.w(TAG, "writeFileLocked: Got exception:", e);
2786 } catch (IOException e) {
2787 Log.w(TAG, "writeFileLocked: Got exception:", e);
2788 }
2789 // Clean up an unsuccessfully written file
2790 if (mFile.exists()) {
2791 if (!mFile.delete()) {
2792 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
2793 }
2794 }
2795 return false;
2796 }
2797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002798}