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