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