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