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