blob: 81e894fbeee71d7b9263b5ac7256486fd3cb1a43 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
svetoslavganov75986cf2009-05-14 22:28:01 -070019import com.android.internal.policy.PolicyManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import com.android.internal.util.XmlUtils;
svetoslavganov75986cf2009-05-14 22:28:01 -070021import com.google.android.collect.Maps;
22
23import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
25import android.bluetooth.BluetoothDevice;
26import android.bluetooth.IBluetoothDevice;
27import android.content.BroadcastReceiver;
28import android.content.ComponentName;
29import android.content.ContentResolver;
30import android.content.Context;
31import android.content.ContextWrapper;
32import android.content.IContentProvider;
33import android.content.Intent;
34import android.content.IntentFilter;
35import android.content.ReceiverCallNotAllowedException;
36import android.content.ServiceConnection;
37import android.content.SharedPreferences;
38import android.content.pm.ActivityInfo;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.ComponentInfo;
41import android.content.pm.IPackageDataObserver;
42import android.content.pm.IPackageDeleteObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.content.pm.IPackageInstallObserver;
44import android.content.pm.IPackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070045import android.content.pm.IPackageStatsObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.content.pm.InstrumentationInfo;
47import android.content.pm.PackageInfo;
48import android.content.pm.PackageManager;
49import android.content.pm.PermissionGroupInfo;
50import android.content.pm.PermissionInfo;
51import android.content.pm.ProviderInfo;
52import android.content.pm.ResolveInfo;
53import android.content.pm.ServiceInfo;
54import android.content.res.AssetManager;
55import android.content.res.Resources;
56import android.content.res.XmlResourceParser;
57import android.database.sqlite.SQLiteDatabase;
58import android.database.sqlite.SQLiteDatabase.CursorFactory;
59import android.graphics.Bitmap;
60import android.graphics.BitmapFactory;
61import android.graphics.drawable.BitmapDrawable;
62import android.graphics.drawable.Drawable;
63import android.hardware.SensorManager;
64import android.location.ILocationManager;
65import android.location.LocationManager;
66import android.media.AudioManager;
67import android.net.ConnectivityManager;
68import android.net.IConnectivityManager;
69import android.net.Uri;
70import android.net.wifi.IWifiManager;
71import android.net.wifi.WifiManager;
72import android.os.Binder;
73import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.os.FileUtils;
75import android.os.Handler;
76import android.os.IBinder;
77import android.os.IPowerManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070078import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.ParcelFileDescriptor;
80import android.os.PowerManager;
81import android.os.Process;
svetoslavganov75986cf2009-05-14 22:28:01 -070082import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083import android.os.ServiceManager;
84import android.os.Vibrator;
85import android.os.FileUtils.FileStatus;
86import android.telephony.TelephonyManager;
87import android.text.ClipboardManager;
88import android.util.AndroidRuntimeException;
89import android.util.Log;
90import android.view.ContextThemeWrapper;
91import android.view.LayoutInflater;
92import android.view.WindowManagerImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070093import android.view.accessibility.AccessibilityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.view.inputmethod.InputMethodManager;
95
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import 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;
svetoslavganov75986cf2009-05-14 22:28:01 -0700105import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import java.util.Iterator;
107import java.util.List;
108import java.util.Map;
The Android Open Source Project10592532009-03-18 17:39:46 -0700109import java.util.Set;
svetoslavganov75986cf2009-05-14 22:28:01 -0700110import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import java.util.Map.Entry;
112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113class ReceiverRestrictedContext extends ContextWrapper {
114 ReceiverRestrictedContext(Context base) {
115 super(base);
116 }
117
118 @Override
119 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
120 return registerReceiver(receiver, filter, null, null);
121 }
122
123 @Override
124 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
125 String broadcastPermission, Handler scheduler) {
126 throw new ReceiverCallNotAllowedException(
127 "IntentReceiver components are not allowed to register to receive intents");
128 //ex.fillInStackTrace();
129 //Log.e("IntentReceiver", ex.getMessage(), ex);
130 //return mContext.registerReceiver(receiver, filter, broadcastPermission,
131 // scheduler);
132 }
133
134 @Override
135 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
136 throw new ReceiverCallNotAllowedException(
137 "IntentReceiver components are not allowed to bind to services");
138 //ex.fillInStackTrace();
139 //Log.e("IntentReceiver", ex.getMessage(), ex);
140 //return mContext.bindService(service, interfaceName, conn, flags);
141 }
142}
143
144/**
145 * Common implementation of Context API, which Activity and other application
146 * classes inherit.
147 */
148class ApplicationContext extends Context {
149 private final static String TAG = "ApplicationContext";
150 private final static boolean DEBUG_ICONS = false;
151
152 private static final Object sSync = new Object();
153 private static AlarmManager sAlarmManager;
154 private static PowerManager sPowerManager;
155 private static ConnectivityManager sConnectivityManager;
156 private static WifiManager sWifiManager;
157 private static LocationManager sLocationManager;
158 private static boolean sIsBluetoothDeviceCached = false;
159 private static BluetoothDevice sBluetoothDevice;
160 private static IWallpaperService sWallpaperService;
161 private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
162 new HashMap<File, SharedPreferencesImpl>();
163
164 private AudioManager mAudioManager;
165 /*package*/ ActivityThread.PackageInfo mPackageInfo;
166 private Resources mResources;
167 /*package*/ ActivityThread mMainThread;
168 private Context mOuterContext;
169 private IBinder mActivityToken = null;
170 private ApplicationContentResolver mContentResolver;
171 private int mThemeResource = 0;
172 private Resources.Theme mTheme = null;
173 private PackageManager mPackageManager;
174 private NotificationManager mNotificationManager = null;
svetoslavganov75986cf2009-05-14 22:28:01 -0700175 private AccessibilityManager mAccessibilityManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 private ActivityManager mActivityManager = null;
177 private Context mReceiverRestrictedContext = null;
178 private SearchManager mSearchManager = null;
179 private SensorManager mSensorManager = null;
180 private Vibrator mVibrator = null;
181 private LayoutInflater mLayoutInflater = null;
182 private StatusBarManager mStatusBarManager = null;
183 private TelephonyManager mTelephonyManager = null;
184 private ClipboardManager mClipboardManager = null;
185
186 private final Object mSync = new Object();
187
188 private File mDatabasesDir;
189 private File mPreferencesDir;
190 private File mFilesDir;
191
192
193 private File mCacheDir;
194
195 private Drawable mWallpaper;
196 private IWallpaperServiceCallback mWallpaperCallback = null;
197
198 private static long sInstanceCount = 0;
199
200 private static final String[] EMPTY_FILE_LIST = {};
201
202 @Override
203 protected void finalize() throws Throwable {
204 super.finalize();
205 --sInstanceCount;
206 }
207
208 public static long getInstanceCount() {
209 return sInstanceCount;
210 }
211
212 @Override
213 public AssetManager getAssets() {
214 return mResources.getAssets();
215 }
216
217 @Override
218 public Resources getResources() {
219 return mResources;
220 }
221
222 @Override
223 public PackageManager getPackageManager() {
224 if (mPackageManager != null) {
225 return mPackageManager;
226 }
227
228 IPackageManager pm = ActivityThread.getPackageManager();
229 if (pm != null) {
230 // Doesn't matter if we make more than one instance.
231 return (mPackageManager = new ApplicationPackageManager(this, pm));
232 }
233
234 return null;
235 }
236
237 @Override
238 public ContentResolver getContentResolver() {
239 return mContentResolver;
240 }
241
242 @Override
243 public Looper getMainLooper() {
244 return mMainThread.getLooper();
245 }
246
247 @Override
248 public Context getApplicationContext() {
249 return mMainThread.getApplication();
250 }
251
252 @Override
253 public void setTheme(int resid) {
254 mThemeResource = resid;
255 }
256
257 @Override
258 public Resources.Theme getTheme() {
259 if (mTheme == null) {
260 if (mThemeResource == 0) {
261 mThemeResource = com.android.internal.R.style.Theme;
262 }
263 mTheme = mResources.newTheme();
264 mTheme.applyStyle(mThemeResource, true);
265 }
266 return mTheme;
267 }
268
269 @Override
270 public ClassLoader getClassLoader() {
271 return mPackageInfo != null ?
272 mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
273 }
274
275 @Override
276 public String getPackageName() {
277 if (mPackageInfo != null) {
278 return mPackageInfo.getPackageName();
279 }
280 throw new RuntimeException("Not supported in system context");
281 }
282
283 @Override
284 public String getPackageResourcePath() {
285 if (mPackageInfo != null) {
286 return mPackageInfo.getResDir();
287 }
288 throw new RuntimeException("Not supported in system context");
289 }
290
291 @Override
292 public String getPackageCodePath() {
293 if (mPackageInfo != null) {
294 return mPackageInfo.getAppDir();
295 }
296 throw new RuntimeException("Not supported in system context");
297 }
298
299 private static File makeBackupFile(File prefsFile) {
300 return new File(prefsFile.getPath() + ".bak");
301 }
302
303 @Override
304 public SharedPreferences getSharedPreferences(String name, int mode) {
305 SharedPreferencesImpl sp;
306 File f = makeFilename(getPreferencesDir(), name + ".xml");
307 synchronized (sSharedPrefs) {
308 sp = sSharedPrefs.get(f);
309 if (sp != null && !sp.hasFileChanged()) {
310 //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
311 return sp;
312 }
313 }
314
315 FileInputStream str = null;
316 File backup = makeBackupFile(f);
317 if (backup.exists()) {
318 f.delete();
319 backup.renameTo(f);
320 }
321
322 // Debugging
323 if (f.exists() && !f.canRead()) {
324 Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
325 }
326
327 Map map = null;
328 if (f.exists() && f.canRead()) {
329 try {
330 str = new FileInputStream(f);
331 map = XmlUtils.readMapXml(str);
332 str.close();
333 } catch (org.xmlpull.v1.XmlPullParserException e) {
334 Log.w(TAG, "getSharedPreferences", e);
335 } catch (FileNotFoundException e) {
336 Log.w(TAG, "getSharedPreferences", e);
337 } catch (IOException e) {
338 Log.w(TAG, "getSharedPreferences", e);
339 }
340 }
341
342 synchronized (sSharedPrefs) {
343 if (sp != null) {
344 //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
345 sp.replace(map);
346 } else {
347 sp = sSharedPrefs.get(f);
348 if (sp == null) {
349 sp = new SharedPreferencesImpl(f, mode, map);
350 sSharedPrefs.put(f, sp);
351 }
352 }
353 return sp;
354 }
355 }
356
357 private File getPreferencesDir() {
358 synchronized (mSync) {
359 if (mPreferencesDir == null) {
360 mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
361 }
362 return mPreferencesDir;
363 }
364 }
365
366 @Override
367 public FileInputStream openFileInput(String name)
368 throws FileNotFoundException {
369 File f = makeFilename(getFilesDir(), name);
370 return new FileInputStream(f);
371 }
372
373 @Override
374 public FileOutputStream openFileOutput(String name, int mode)
375 throws FileNotFoundException {
376 final boolean append = (mode&MODE_APPEND) != 0;
377 File f = makeFilename(getFilesDir(), name);
378 try {
379 FileOutputStream fos = new FileOutputStream(f, append);
380 setFilePermissionsFromMode(f.getPath(), mode, 0);
381 return fos;
382 } catch (FileNotFoundException e) {
383 }
384
385 File parent = f.getParentFile();
386 parent.mkdir();
387 FileUtils.setPermissions(
388 parent.getPath(),
389 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
390 -1, -1);
391 FileOutputStream fos = new FileOutputStream(f, append);
392 setFilePermissionsFromMode(f.getPath(), mode, 0);
393 return fos;
394 }
395
396 @Override
397 public boolean deleteFile(String name) {
398 File f = makeFilename(getFilesDir(), name);
399 return f.delete();
400 }
401
402 @Override
403 public File getFilesDir() {
404 synchronized (mSync) {
405 if (mFilesDir == null) {
406 mFilesDir = new File(getDataDirFile(), "files");
407 }
408 if (!mFilesDir.exists()) {
409 if(!mFilesDir.mkdirs()) {
410 Log.w(TAG, "Unable to create files directory");
411 return null;
412 }
413 FileUtils.setPermissions(
414 mFilesDir.getPath(),
415 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
416 -1, -1);
417 }
418 return mFilesDir;
419 }
420 }
421
422 @Override
423 public File getCacheDir() {
424 synchronized (mSync) {
425 if (mCacheDir == null) {
426 mCacheDir = new File(getDataDirFile(), "cache");
427 }
428 if (!mCacheDir.exists()) {
429 if(!mCacheDir.mkdirs()) {
430 Log.w(TAG, "Unable to create cache directory");
431 return null;
432 }
433 FileUtils.setPermissions(
434 mCacheDir.getPath(),
435 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
436 -1, -1);
437 }
438 }
439 return mCacheDir;
440 }
441
442
443 @Override
444 public File getFileStreamPath(String name) {
445 return makeFilename(getFilesDir(), name);
446 }
447
448 @Override
449 public String[] fileList() {
450 final String[] list = getFilesDir().list();
451 return (list != null) ? list : EMPTY_FILE_LIST;
452 }
453
454 @Override
455 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
456 File dir = getDatabasesDir();
457 if (!dir.isDirectory() && dir.mkdir()) {
458 FileUtils.setPermissions(dir.getPath(),
459 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
460 -1, -1);
461 }
462
463 File f = makeFilename(dir, name);
464 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
465 setFilePermissionsFromMode(f.getPath(), mode, 0);
466 return db;
467 }
468
469 @Override
470 public boolean deleteDatabase(String name) {
471 try {
472 File f = makeFilename(getDatabasesDir(), name);
473 return f.delete();
474 } catch (Exception e) {
475 }
476 return false;
477 }
478
479 @Override
480 public File getDatabasePath(String name) {
481 return makeFilename(getDatabasesDir(), name);
482 }
483
484 @Override
485 public String[] databaseList() {
486 final String[] list = getDatabasesDir().list();
487 return (list != null) ? list : EMPTY_FILE_LIST;
488 }
489
490
491 private File getDatabasesDir() {
492 synchronized (mSync) {
493 if (mDatabasesDir == null) {
494 mDatabasesDir = new File(getDataDirFile(), "databases");
495 }
496 if (mDatabasesDir.getPath().equals("databases")) {
497 mDatabasesDir = new File("/data/system");
498 }
499 return mDatabasesDir;
500 }
501 }
502
503 @Override
504 public Drawable getWallpaper() {
505 Drawable dr = peekWallpaper();
506 return dr != null ? dr : getResources().getDrawable(
507 com.android.internal.R.drawable.default_wallpaper);
508 }
509
510 @Override
511 public synchronized Drawable peekWallpaper() {
512 if (mWallpaper != null) {
513 return mWallpaper;
514 }
515 mWallpaperCallback = new WallpaperCallback(this);
516 mWallpaper = getCurrentWallpaperLocked();
517 return mWallpaper;
518 }
519
520 private Drawable getCurrentWallpaperLocked() {
521 try {
522 ParcelFileDescriptor fd = getWallpaperService().getWallpaper(mWallpaperCallback);
523 if (fd != null) {
524 Bitmap bm = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
525 if (bm != null) {
526 return new BitmapDrawable(bm);
527 }
528 }
529 } catch (RemoteException e) {
530 }
531 return null;
532 }
533
534 @Override
535 public int getWallpaperDesiredMinimumWidth() {
536 try {
537 return getWallpaperService().getWidthHint();
538 } catch (RemoteException e) {
539 // Shouldn't happen!
540 return 0;
541 }
542 }
543
544 @Override
545 public int getWallpaperDesiredMinimumHeight() {
546 try {
547 return getWallpaperService().getHeightHint();
548 } catch (RemoteException e) {
549 // Shouldn't happen!
550 return 0;
551 }
552 }
553
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700554 /**
555 * @hide
556 */
557 @Override
558 public float getApplicationScale() {
559 if (mPackageInfo != null) {
560 return mPackageInfo.getApplicationScale();
561 } else {
562 // same as system density
563 return 1.0f;
564 }
565 }
566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 @Override
568 public void setWallpaper(Bitmap bitmap) throws IOException {
569 try {
570 ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
571 if (fd == null) {
572 return;
573 }
574 FileOutputStream fos = null;
575 try {
576 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
577 bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
578 } finally {
579 if (fos != null) {
580 fos.close();
581 }
582 }
583 } catch (RemoteException e) {
584 }
585 }
586
587 @Override
588 public void setWallpaper(InputStream data) throws IOException {
589 try {
590 ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
591 if (fd == null) {
592 return;
593 }
594 FileOutputStream fos = null;
595 try {
596 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
597 setWallpaper(data, fos);
598 } finally {
599 if (fos != null) {
600 fos.close();
601 }
602 }
603 } catch (RemoteException e) {
604 }
605 }
606
607 private void setWallpaper(InputStream data, FileOutputStream fos)
608 throws IOException {
609 byte[] buffer = new byte[32768];
610 int amt;
611 while ((amt=data.read(buffer)) > 0) {
612 fos.write(buffer, 0, amt);
613 }
614 }
615
616 @Override
617 public void clearWallpaper() throws IOException {
618 try {
619 /* Set the wallpaper to the default values */
620 ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
621 if (fd != null) {
622 FileOutputStream fos = null;
623 try {
624 fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
625 setWallpaper(getResources().openRawResource(
626 com.android.internal.R.drawable.default_wallpaper),
627 fos);
628 } finally {
629 if (fos != null) {
630 fos.close();
631 }
632 }
633 }
634 } catch (RemoteException e) {
635 }
636 }
637
638 @Override
639 public void startActivity(Intent intent) {
640 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
641 throw new AndroidRuntimeException(
642 "Calling startActivity() from outside of an Activity "
643 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
644 + " Is this really what you want?");
645 }
646 mMainThread.getInstrumentation().execStartActivity(
647 getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
648 }
649
650 @Override
651 public void sendBroadcast(Intent intent) {
652 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
653 try {
654 ActivityManagerNative.getDefault().broadcastIntent(
655 mMainThread.getApplicationThread(), intent, resolvedType, null,
656 Activity.RESULT_OK, null, null, null, false, false);
657 } catch (RemoteException e) {
658 }
659 }
660
661 @Override
662 public void sendBroadcast(Intent intent, String receiverPermission) {
663 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
664 try {
665 ActivityManagerNative.getDefault().broadcastIntent(
666 mMainThread.getApplicationThread(), intent, resolvedType, null,
667 Activity.RESULT_OK, null, null, receiverPermission, false, false);
668 } catch (RemoteException e) {
669 }
670 }
671
672 @Override
673 public void sendOrderedBroadcast(Intent intent,
674 String receiverPermission) {
675 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
676 try {
677 ActivityManagerNative.getDefault().broadcastIntent(
678 mMainThread.getApplicationThread(), intent, resolvedType, null,
679 Activity.RESULT_OK, null, null, receiverPermission, true, false);
680 } catch (RemoteException e) {
681 }
682 }
683
684 @Override
685 public void sendOrderedBroadcast(Intent intent,
686 String receiverPermission, BroadcastReceiver resultReceiver,
687 Handler scheduler, int initialCode, String initialData,
688 Bundle initialExtras) {
689 IIntentReceiver rd = null;
690 if (resultReceiver != null) {
691 if (mPackageInfo != null) {
692 if (scheduler == null) {
693 scheduler = mMainThread.getHandler();
694 }
695 rd = mPackageInfo.getReceiverDispatcher(
696 resultReceiver, getOuterContext(), scheduler,
697 mMainThread.getInstrumentation(), false);
698 } else {
699 if (scheduler == null) {
700 scheduler = mMainThread.getHandler();
701 }
702 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
703 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
704 }
705 }
706 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
707 try {
708 ActivityManagerNative.getDefault().broadcastIntent(
709 mMainThread.getApplicationThread(), intent, resolvedType, rd,
710 initialCode, initialData, initialExtras, receiverPermission,
711 true, false);
712 } catch (RemoteException e) {
713 }
714 }
715
716 @Override
717 public void sendStickyBroadcast(Intent intent) {
718 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
719 try {
720 ActivityManagerNative.getDefault().broadcastIntent(
721 mMainThread.getApplicationThread(), intent, resolvedType, null,
722 Activity.RESULT_OK, null, null, null, false, true);
723 } catch (RemoteException e) {
724 }
725 }
726
727 @Override
728 public void removeStickyBroadcast(Intent intent) {
729 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
730 if (resolvedType != null) {
731 intent = new Intent(intent);
732 intent.setDataAndType(intent.getData(), resolvedType);
733 }
734 try {
735 ActivityManagerNative.getDefault().unbroadcastIntent(
736 mMainThread.getApplicationThread(), intent);
737 } catch (RemoteException e) {
738 }
739 }
740
741 @Override
742 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
743 return registerReceiver(receiver, filter, null, null);
744 }
745
746 @Override
747 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
748 String broadcastPermission, Handler scheduler) {
749 return registerReceiverInternal(receiver, filter, broadcastPermission,
750 scheduler, getOuterContext());
751 }
752
753 private Intent registerReceiverInternal(BroadcastReceiver receiver,
754 IntentFilter filter, String broadcastPermission,
755 Handler scheduler, Context context) {
756 IIntentReceiver rd = null;
757 if (receiver != null) {
758 if (mPackageInfo != null && context != null) {
759 if (scheduler == null) {
760 scheduler = mMainThread.getHandler();
761 }
762 rd = mPackageInfo.getReceiverDispatcher(
763 receiver, context, scheduler,
764 mMainThread.getInstrumentation(), true);
765 } else {
766 if (scheduler == null) {
767 scheduler = mMainThread.getHandler();
768 }
769 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
770 receiver, context, scheduler, null, false).getIIntentReceiver();
771 }
772 }
773 try {
774 return ActivityManagerNative.getDefault().registerReceiver(
775 mMainThread.getApplicationThread(),
776 rd, filter, broadcastPermission);
777 } catch (RemoteException e) {
778 return null;
779 }
780 }
781
782 @Override
783 public void unregisterReceiver(BroadcastReceiver receiver) {
784 if (mPackageInfo != null) {
785 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
786 getOuterContext(), receiver);
787 try {
788 ActivityManagerNative.getDefault().unregisterReceiver(rd);
789 } catch (RemoteException e) {
790 }
791 } else {
792 throw new RuntimeException("Not supported in system context");
793 }
794 }
795
796 @Override
797 public ComponentName startService(Intent service) {
798 try {
799 ComponentName cn = ActivityManagerNative.getDefault().startService(
800 mMainThread.getApplicationThread(), service,
801 service.resolveTypeIfNeeded(getContentResolver()));
802 if (cn != null && cn.getPackageName().equals("!")) {
803 throw new SecurityException(
804 "Not allowed to start service " + service
805 + " without permission " + cn.getClassName());
806 }
807 return cn;
808 } catch (RemoteException e) {
809 return null;
810 }
811 }
812
813 @Override
814 public boolean stopService(Intent service) {
815 try {
816 int res = ActivityManagerNative.getDefault().stopService(
817 mMainThread.getApplicationThread(), service,
818 service.resolveTypeIfNeeded(getContentResolver()));
819 if (res < 0) {
820 throw new SecurityException(
821 "Not allowed to stop service " + service);
822 }
823 return res != 0;
824 } catch (RemoteException e) {
825 return false;
826 }
827 }
828
829 @Override
830 public boolean bindService(Intent service, ServiceConnection conn,
831 int flags) {
832 IServiceConnection sd;
833 if (mPackageInfo != null) {
834 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
835 mMainThread.getHandler(), flags);
836 } else {
837 throw new RuntimeException("Not supported in system context");
838 }
839 try {
840 int res = ActivityManagerNative.getDefault().bindService(
841 mMainThread.getApplicationThread(), getActivityToken(),
842 service, service.resolveTypeIfNeeded(getContentResolver()),
843 sd, flags);
844 if (res < 0) {
845 throw new SecurityException(
846 "Not allowed to bind to service " + service);
847 }
848 return res != 0;
849 } catch (RemoteException e) {
850 return false;
851 }
852 }
853
854 @Override
855 public void unbindService(ServiceConnection conn) {
856 if (mPackageInfo != null) {
857 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
858 getOuterContext(), conn);
859 try {
860 ActivityManagerNative.getDefault().unbindService(sd);
861 } catch (RemoteException e) {
862 }
863 } else {
864 throw new RuntimeException("Not supported in system context");
865 }
866 }
867
868 @Override
869 public boolean startInstrumentation(ComponentName className,
870 String profileFile, Bundle arguments) {
871 try {
872 return ActivityManagerNative.getDefault().startInstrumentation(
873 className, profileFile, 0, arguments, null);
874 } catch (RemoteException e) {
875 // System has crashed, nothing we can do.
876 }
877 return false;
878 }
879
880 @Override
881 public Object getSystemService(String name) {
882 if (WINDOW_SERVICE.equals(name)) {
883 return WindowManagerImpl.getDefault();
884 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
885 synchronized (mSync) {
886 LayoutInflater inflater = mLayoutInflater;
887 if (inflater != null) {
888 return inflater;
889 }
890 mLayoutInflater = inflater =
891 PolicyManager.makeNewLayoutInflater(getOuterContext());
892 return inflater;
893 }
894 } else if (ACTIVITY_SERVICE.equals(name)) {
895 return getActivityManager();
896 } else if (ALARM_SERVICE.equals(name)) {
897 return getAlarmManager();
898 } else if (POWER_SERVICE.equals(name)) {
899 return getPowerManager();
900 } else if (CONNECTIVITY_SERVICE.equals(name)) {
901 return getConnectivityManager();
902 } else if (WIFI_SERVICE.equals(name)) {
903 return getWifiManager();
904 } else if (NOTIFICATION_SERVICE.equals(name)) {
905 return getNotificationManager();
906 } else if (KEYGUARD_SERVICE.equals(name)) {
907 return new KeyguardManager();
svetoslavganov75986cf2009-05-14 22:28:01 -0700908 } else if (ACCESSIBILITY_SERVICE.equals(name)) {
909 return AccessibilityManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 } else if (LOCATION_SERVICE.equals(name)) {
911 return getLocationManager();
912 } else if (SEARCH_SERVICE.equals(name)) {
913 return getSearchManager();
914 } else if ( SENSOR_SERVICE.equals(name)) {
915 return getSensorManager();
916 } else if (BLUETOOTH_SERVICE.equals(name)) {
917 return getBluetoothDevice();
918 } else if (VIBRATOR_SERVICE.equals(name)) {
919 return getVibrator();
920 } else if (STATUS_BAR_SERVICE.equals(name)) {
921 synchronized (mSync) {
922 if (mStatusBarManager == null) {
923 mStatusBarManager = new StatusBarManager(getOuterContext());
924 }
925 return mStatusBarManager;
926 }
927 } else if (AUDIO_SERVICE.equals(name)) {
928 return getAudioManager();
929 } else if (TELEPHONY_SERVICE.equals(name)) {
930 return getTelephonyManager();
931 } else if (CLIPBOARD_SERVICE.equals(name)) {
932 return getClipboardManager();
933 } else if (INPUT_METHOD_SERVICE.equals(name)) {
934 return InputMethodManager.getInstance(this);
935 }
936
937 return null;
938 }
939
940 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 }
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07002027 ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 Resources r = mContext.mMainThread.getTopLevelResources(
2029 app.uid == Process.myUid() ? app.sourceDir
Mitsuru Oshima8169dae2009-04-28 18:12:09 -07002030 : app.publicSourceDir,
2031 pi.getApplicationScale());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 if (r != null) {
2033 return r;
2034 }
2035 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2036 }
2037
2038 @Override public Resources getResourcesForApplication(
2039 String appPackageName) throws NameNotFoundException {
2040 return getResourcesForApplication(
2041 getApplicationInfo(appPackageName, 0));
2042 }
2043
2044 int mCachedSafeMode = -1;
2045 @Override public boolean isSafeMode() {
2046 try {
2047 if (mCachedSafeMode < 0) {
2048 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2049 }
2050 return mCachedSafeMode != 0;
2051 } catch (RemoteException e) {
2052 throw new RuntimeException("Package manager has died", e);
2053 }
2054 }
2055
2056 static void configurationChanged() {
2057 synchronized (sSync) {
2058 sIconCache.clear();
2059 sStringCache.clear();
2060 }
2061 }
2062
2063 ApplicationPackageManager(ApplicationContext context,
2064 IPackageManager pm) {
2065 mContext = context;
2066 mPM = pm;
2067 }
2068
2069 private Drawable getCachedIcon(ResourceName name) {
2070 synchronized (sSync) {
2071 WeakReference<Drawable> wr = sIconCache.get(name);
2072 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2073 + name + ": " + wr);
2074 if (wr != null) { // we have the activity
2075 Drawable dr = wr.get();
2076 if (dr != null) {
2077 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2078 + name + ": " + dr);
2079 return dr;
2080 }
2081 // our entry has been purged
2082 sIconCache.remove(name);
2083 }
2084 }
2085 return null;
2086 }
2087
2088 private void establishPackageRemovedReceiver() {
2089 // mContext.registerReceiverInternal() winds up acquiring the
2090 // main ActivityManagerService.this lock. If we hold our usual
2091 // sSync global lock at the same time, we impose a required ordering
2092 // on those two locks, which is not good for deadlock prevention.
2093 // Use a dedicated lock around initialization of
2094 // sPackageRemovedReceiver to avoid this.
2095 synchronized (sPackageRemovedSync) {
2096 if (sPackageRemovedReceiver == null) {
2097 sPackageRemovedReceiver = new PackageRemovedReceiver();
2098 IntentFilter filter = new IntentFilter(
2099 Intent.ACTION_PACKAGE_REMOVED);
2100 filter.addDataScheme("package");
2101 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2102 filter, null, null, null);
2103 }
2104 }
2105 }
2106
2107 private void putCachedIcon(ResourceName name, Drawable dr) {
2108 establishPackageRemovedReceiver();
2109
2110 synchronized (sSync) {
2111 sIconCache.put(name, new WeakReference<Drawable>(dr));
2112 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2113 + name + ": " + dr);
2114 }
2115 }
2116
2117 private static final class PackageRemovedReceiver extends BroadcastReceiver {
2118 @Override
2119 public void onReceive(Context context, Intent intent) {
2120 Uri data = intent.getData();
2121 String ssp;
2122 if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
2123 boolean needCleanup = false;
2124 synchronized (sSync) {
2125 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2126 while (it.hasNext()) {
2127 ResourceName nm = it.next();
2128 if (nm.packageName.equals(ssp)) {
2129 //Log.i(TAG, "Removing cached drawable for " + nm);
2130 it.remove();
2131 needCleanup = true;
2132 }
2133 }
2134 it = sStringCache.keySet().iterator();
2135 while (it.hasNext()) {
2136 ResourceName nm = it.next();
2137 if (nm.packageName.equals(ssp)) {
2138 //Log.i(TAG, "Removing cached string for " + nm);
2139 it.remove();
2140 needCleanup = true;
2141 }
2142 }
2143 }
2144 if (needCleanup || ActivityThread.currentActivityThread().hasPackageInfo(ssp)) {
2145 ActivityThread.currentActivityThread().scheduleGcIdler();
2146 }
2147 }
2148 }
2149 }
2150
2151 private static final class ResourceName {
2152 final String packageName;
2153 final int iconId;
2154
2155 ResourceName(String _packageName, int _iconId) {
2156 packageName = _packageName;
2157 iconId = _iconId;
2158 }
2159
2160 ResourceName(ApplicationInfo aInfo, int _iconId) {
2161 this(aInfo.packageName, _iconId);
2162 }
2163
2164 ResourceName(ComponentInfo cInfo, int _iconId) {
2165 this(cInfo.applicationInfo.packageName, _iconId);
2166 }
2167
2168 ResourceName(ResolveInfo rInfo, int _iconId) {
2169 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2170 }
2171
2172 @Override
2173 public boolean equals(Object o) {
2174 if (this == o) return true;
2175 if (o == null || getClass() != o.getClass()) return false;
2176
2177 ResourceName that = (ResourceName) o;
2178
2179 if (iconId != that.iconId) return false;
2180 return !(packageName != null ?
2181 !packageName.equals(that.packageName) : that.packageName != null);
2182
2183 }
2184
2185 @Override
2186 public int hashCode() {
2187 int result;
2188 result = packageName.hashCode();
2189 result = 31 * result + iconId;
2190 return result;
2191 }
2192
2193 @Override
2194 public String toString() {
2195 return "{ResourceName " + packageName + " / " + iconId + "}";
2196 }
2197 }
2198
2199 private CharSequence getCachedString(ResourceName name) {
2200 synchronized (sSync) {
2201 WeakReference<CharSequence> wr = sStringCache.get(name);
2202 if (wr != null) { // we have the activity
2203 CharSequence cs = wr.get();
2204 if (cs != null) {
2205 return cs;
2206 }
2207 // our entry has been purged
2208 sStringCache.remove(name);
2209 }
2210 }
2211 return null;
2212 }
2213
2214 private void putCachedString(ResourceName name, CharSequence cs) {
2215 establishPackageRemovedReceiver();
2216
2217 synchronized (sSync) {
2218 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2219 }
2220 }
2221
2222 private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
2223 CharSequence cs = getCachedString(name);
2224 if (cs != null) {
2225 return cs;
2226 }
2227 try {
2228 Resources r = getResourcesForApplication(app);
2229 cs = r.getText(id);
2230 putCachedString(name, cs);
2231 } catch (NameNotFoundException e) {
2232 Log.w("PackageManager", "Failure retrieving resources for"
2233 + app.packageName);
2234 } catch (RuntimeException e) {
2235 // If an exception was thrown, fall through to return null
2236 Log.w("ApplicationInfo", "Failure retrieving activity name", e);
2237 }
2238 return cs;
2239 }
2240
2241 @Override
2242 public CharSequence getText(String packageName, int resid,
2243 ApplicationInfo appInfo) {
2244 ResourceName name = new ResourceName(packageName, resid);
2245 CharSequence text = getCachedString(name);
2246 if (text != null) {
2247 return text;
2248 }
2249 if (appInfo == null) {
2250 try {
2251 appInfo = getApplicationInfo(packageName, 0);
2252 } catch (NameNotFoundException e) {
2253 return null;
2254 }
2255 }
2256 try {
2257 Resources r = getResourcesForApplication(appInfo);
2258 text = r.getText(resid);
2259 putCachedString(name, text);
2260 return text;
2261 } catch (NameNotFoundException e) {
2262 Log.w("PackageManager", "Failure retrieving resources for"
2263 + appInfo.packageName);
2264 } catch (RuntimeException e) {
2265 // If an exception was thrown, fall through to return
2266 // default icon.
2267 Log.w("PackageManager", "Failure retrieving text 0x"
2268 + Integer.toHexString(resid) + " in package "
2269 + packageName, e);
2270 }
2271 return null;
2272 }
2273
2274 @Override
2275 public XmlResourceParser getXml(String packageName, int resid,
2276 ApplicationInfo appInfo) {
2277 if (appInfo == null) {
2278 try {
2279 appInfo = getApplicationInfo(packageName, 0);
2280 } catch (NameNotFoundException e) {
2281 return null;
2282 }
2283 }
2284 try {
2285 Resources r = getResourcesForApplication(appInfo);
2286 return r.getXml(resid);
2287 } catch (RuntimeException e) {
2288 // If an exception was thrown, fall through to return
2289 // default icon.
2290 Log.w("PackageManager", "Failure retrieving xml 0x"
2291 + Integer.toHexString(resid) + " in package "
2292 + packageName, e);
2293 } catch (NameNotFoundException e) {
2294 Log.w("PackageManager", "Failure retrieving resources for"
2295 + appInfo.packageName);
2296 }
2297 return null;
2298 }
2299
2300 @Override
2301 public CharSequence getApplicationLabel(ApplicationInfo info) {
2302 if (info.nonLocalizedLabel != null) {
2303 return info.nonLocalizedLabel;
2304 }
2305 final int id = info.labelRes;
2306 if (id != 0) {
2307 CharSequence cs = getLabel(new ResourceName(info, id), info, id);
2308 if (cs != null) {
2309 return cs;
2310 }
2311 }
2312 return info.packageName;
2313 }
2314
2315 @Override
Jacek Surazskic64322c2009-04-28 15:26:38 +02002316 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2317 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002318 try {
Jacek Surazskic64322c2009-04-28 15:26:38 +02002319 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002320 } catch (RemoteException e) {
2321 // Should never happen!
2322 }
2323 }
2324
2325 @Override
Jacek Surazskic64322c2009-04-28 15:26:38 +02002326 public String getInstallerPackageName(String packageName) {
2327 try {
2328 return mPM.getInstallerPackageName(packageName);
2329 } catch (RemoteException e) {
2330 // Should never happen!
2331 }
2332 return null;
2333 }
2334
2335 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002336 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2337 try {
2338 mPM.deletePackage(packageName, observer, flags);
2339 } catch (RemoteException e) {
2340 // Should never happen!
2341 }
2342 }
2343 @Override
2344 public void clearApplicationUserData(String packageName,
2345 IPackageDataObserver observer) {
2346 try {
2347 mPM.clearApplicationUserData(packageName, observer);
2348 } catch (RemoteException e) {
2349 // Should never happen!
2350 }
2351 }
2352 @Override
2353 public void deleteApplicationCacheFiles(String packageName,
2354 IPackageDataObserver observer) {
2355 try {
2356 mPM.deleteApplicationCacheFiles(packageName, observer);
2357 } catch (RemoteException e) {
2358 // Should never happen!
2359 }
2360 }
2361 @Override
2362 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2363 try {
2364 mPM.freeStorageAndNotify(idealStorageSize, observer);
2365 } catch (RemoteException e) {
2366 // Should never happen!
2367 }
2368 }
2369
2370 @Override
2371 public void freeStorage(long idealStorageSize, PendingIntent opFinishedIntent) {
2372 try {
2373 mPM.freeStorage(idealStorageSize, opFinishedIntent);
2374 } catch (RemoteException e) {
2375 // Should never happen!
2376 }
2377 }
2378
2379 @Override
2380 public void getPackageSizeInfo(String packageName,
2381 IPackageStatsObserver observer) {
2382 try {
2383 mPM.getPackageSizeInfo(packageName, observer);
2384 } catch (RemoteException e) {
2385 // Should never happen!
2386 }
2387 }
2388 @Override
2389 public void addPackageToPreferred(String packageName) {
2390 try {
2391 mPM.addPackageToPreferred(packageName);
2392 } catch (RemoteException e) {
2393 // Should never happen!
2394 }
2395 }
2396
2397 @Override
2398 public void removePackageFromPreferred(String packageName) {
2399 try {
2400 mPM.removePackageFromPreferred(packageName);
2401 } catch (RemoteException e) {
2402 // Should never happen!
2403 }
2404 }
2405
2406 @Override
2407 public List<PackageInfo> getPreferredPackages(int flags) {
2408 try {
2409 return mPM.getPreferredPackages(flags);
2410 } catch (RemoteException e) {
2411 // Should never happen!
2412 }
2413 return new ArrayList<PackageInfo>();
2414 }
2415
2416 @Override
2417 public void addPreferredActivity(IntentFilter filter,
2418 int match, ComponentName[] set, ComponentName activity) {
2419 try {
2420 mPM.addPreferredActivity(filter, match, set, activity);
2421 } catch (RemoteException e) {
2422 // Should never happen!
2423 }
2424 }
2425
2426 @Override
2427 public void clearPackagePreferredActivities(String packageName) {
2428 try {
2429 mPM.clearPackagePreferredActivities(packageName);
2430 } catch (RemoteException e) {
2431 // Should never happen!
2432 }
2433 }
2434
2435 @Override
2436 public int getPreferredActivities(List<IntentFilter> outFilters,
2437 List<ComponentName> outActivities, String packageName) {
2438 try {
2439 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2440 } catch (RemoteException e) {
2441 // Should never happen!
2442 }
2443 return 0;
2444 }
2445
2446 @Override
2447 public void setComponentEnabledSetting(ComponentName componentName,
2448 int newState, int flags) {
2449 try {
2450 mPM.setComponentEnabledSetting(componentName, newState, flags);
2451 } catch (RemoteException e) {
2452 // Should never happen!
2453 }
2454 }
2455
2456 @Override
2457 public int getComponentEnabledSetting(ComponentName componentName) {
2458 try {
2459 return mPM.getComponentEnabledSetting(componentName);
2460 } catch (RemoteException e) {
2461 // Should never happen!
2462 }
2463 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2464 }
2465
2466 @Override
2467 public void setApplicationEnabledSetting(String packageName,
2468 int newState, int flags) {
2469 try {
2470 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2471 } catch (RemoteException e) {
2472 // Should never happen!
2473 }
2474 }
2475
2476 @Override
2477 public int getApplicationEnabledSetting(String packageName) {
2478 try {
2479 return mPM.getApplicationEnabledSetting(packageName);
2480 } catch (RemoteException e) {
2481 // Should never happen!
2482 }
2483 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2484 }
2485
2486 private final ApplicationContext mContext;
2487 private final IPackageManager mPM;
2488
2489 private static final Object sSync = new Object();
2490 private static final Object sPackageRemovedSync = new Object();
2491 private static BroadcastReceiver sPackageRemovedReceiver;
2492 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2493 = new HashMap<ResourceName, WeakReference<Drawable> >();
2494 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2495 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2496 }
2497
2498 // ----------------------------------------------------------------------
2499 // ----------------------------------------------------------------------
2500 // ----------------------------------------------------------------------
2501
2502 private static final class SharedPreferencesImpl implements SharedPreferences {
2503
2504 private final File mFile;
2505 private final File mBackupFile;
2506 private final int mMode;
2507 private Map mMap;
2508 private final FileStatus mFileStatus = new FileStatus();
2509 private long mTimestamp;
2510
The Android Open Source Project10592532009-03-18 17:39:46 -07002511 private static final Object mContent = new Object();
2512 private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513
2514 SharedPreferencesImpl(
2515 File file, int mode, Map initialContents) {
2516 mFile = file;
2517 mBackupFile = makeBackupFile(file);
2518 mMode = mode;
2519 mMap = initialContents != null ? initialContents : new HashMap();
2520 if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
2521 mTimestamp = mFileStatus.mtime;
2522 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002523 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 }
2525
2526 public boolean hasFileChanged() {
2527 synchronized (this) {
2528 if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2529 return true;
2530 }
2531 return mTimestamp != mFileStatus.mtime;
2532 }
2533 }
2534
2535 public void replace(Map newContents) {
2536 if (newContents != null) {
2537 synchronized (this) {
2538 mMap = newContents;
2539 }
2540 }
2541 }
2542
2543 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2544 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002545 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 }
2547 }
2548
2549 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2550 synchronized(this) {
2551 mListeners.remove(listener);
2552 }
2553 }
2554
2555 public Map<String, ?> getAll() {
2556 synchronized(this) {
2557 //noinspection unchecked
2558 return new HashMap(mMap);
2559 }
2560 }
2561
2562 public String getString(String key, String defValue) {
2563 synchronized (this) {
2564 String v = (String)mMap.get(key);
2565 return v != null ? v : defValue;
2566 }
2567 }
2568
2569 public int getInt(String key, int defValue) {
2570 synchronized (this) {
2571 Integer v = (Integer)mMap.get(key);
2572 return v != null ? v : defValue;
2573 }
2574 }
2575 public long getLong(String key, long defValue) {
2576 synchronized (this) {
2577 Long v = (Long) mMap.get(key);
2578 return v != null ? v : defValue;
2579 }
2580 }
2581 public float getFloat(String key, float defValue) {
2582 synchronized (this) {
2583 Float v = (Float)mMap.get(key);
2584 return v != null ? v : defValue;
2585 }
2586 }
2587 public boolean getBoolean(String key, boolean defValue) {
2588 synchronized (this) {
2589 Boolean v = (Boolean)mMap.get(key);
2590 return v != null ? v : defValue;
2591 }
2592 }
2593
2594 public boolean contains(String key) {
2595 synchronized (this) {
2596 return mMap.containsKey(key);
2597 }
2598 }
2599
2600 public final class EditorImpl implements Editor {
2601 private final Map<String, Object> mModified = Maps.newHashMap();
2602 private boolean mClear = false;
2603
2604 public Editor putString(String key, String value) {
2605 synchronized (this) {
2606 mModified.put(key, value);
2607 return this;
2608 }
2609 }
2610 public Editor putInt(String key, int value) {
2611 synchronized (this) {
2612 mModified.put(key, value);
2613 return this;
2614 }
2615 }
2616 public Editor putLong(String key, long value) {
2617 synchronized (this) {
2618 mModified.put(key, value);
2619 return this;
2620 }
2621 }
2622 public Editor putFloat(String key, float value) {
2623 synchronized (this) {
2624 mModified.put(key, value);
2625 return this;
2626 }
2627 }
2628 public Editor putBoolean(String key, boolean value) {
2629 synchronized (this) {
2630 mModified.put(key, value);
2631 return this;
2632 }
2633 }
2634
2635 public Editor remove(String key) {
2636 synchronized (this) {
2637 mModified.put(key, this);
2638 return this;
2639 }
2640 }
2641
2642 public Editor clear() {
2643 synchronized (this) {
2644 mClear = true;
2645 return this;
2646 }
2647 }
2648
2649 public boolean commit() {
2650 boolean returnValue;
2651
2652 boolean hasListeners;
2653 List<String> keysModified = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07002654 Set<OnSharedPreferenceChangeListener> listeners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655
2656 synchronized (SharedPreferencesImpl.this) {
2657 hasListeners = mListeners.size() > 0;
2658 if (hasListeners) {
2659 keysModified = new ArrayList<String>();
The Android Open Source Project10592532009-03-18 17:39:46 -07002660 listeners =
2661 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662 }
2663
2664 synchronized (this) {
2665 if (mClear) {
2666 mMap.clear();
2667 mClear = false;
2668 }
2669
The Android Open Source Project10592532009-03-18 17:39:46 -07002670 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002671 String k = e.getKey();
2672 Object v = e.getValue();
2673 if (v == this) {
2674 mMap.remove(k);
2675 } else {
2676 mMap.put(k, v);
2677 }
2678
2679 if (hasListeners) {
2680 keysModified.add(k);
2681 }
2682 }
2683
2684 mModified.clear();
2685 }
2686
2687 returnValue = writeFileLocked();
2688 }
2689
2690 if (hasListeners) {
2691 for (int i = keysModified.size() - 1; i >= 0; i--) {
2692 final String key = keysModified.get(i);
The Android Open Source Project10592532009-03-18 17:39:46 -07002693 for (OnSharedPreferenceChangeListener listener : listeners) {
2694 if (listener != null) {
2695 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
2696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
2698 }
2699 }
2700
2701 return returnValue;
2702 }
2703 }
2704
2705 public Editor edit() {
2706 return new EditorImpl();
2707 }
2708
2709 private FileOutputStream createFileOutputStream(File file) {
2710 FileOutputStream str = null;
2711 try {
2712 str = new FileOutputStream(file);
2713 } catch (FileNotFoundException e) {
2714 File parent = file.getParentFile();
2715 if (!parent.mkdir()) {
2716 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
2717 return null;
2718 }
2719 FileUtils.setPermissions(
2720 parent.getPath(),
2721 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2722 -1, -1);
2723 try {
2724 str = new FileOutputStream(file);
2725 } catch (FileNotFoundException e2) {
2726 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
2727 }
2728 }
2729 return str;
2730 }
2731
2732 private boolean writeFileLocked() {
2733 // Rename the current file so it may be used as a backup during the next read
2734 if (mFile.exists()) {
2735 if (!mFile.renameTo(mBackupFile)) {
2736 Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
2737 }
2738 }
2739
2740 // Attempt to write the file, delete the backup and return true as atomically as
2741 // possible. If any exception occurs, delete the new file; next time we will restore
2742 // from the backup.
2743 try {
2744 FileOutputStream str = createFileOutputStream(mFile);
2745 if (str == null) {
2746 return false;
2747 }
2748 XmlUtils.writeMapXml(mMap, str);
2749 str.close();
2750 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
2751 if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2752 mTimestamp = mFileStatus.mtime;
2753 }
2754
Dianne Hackborn1bf5e222009-03-24 19:11:58 -07002755 // Writing was successful, delete the backup file if there is one.
2756 mBackupFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002757 return true;
2758 } catch (XmlPullParserException e) {
2759 Log.w(TAG, "writeFileLocked: Got exception:", e);
2760 } catch (IOException e) {
2761 Log.w(TAG, "writeFileLocked: Got exception:", e);
2762 }
2763 // Clean up an unsuccessfully written file
2764 if (mFile.exists()) {
2765 if (!mFile.delete()) {
2766 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
2767 }
2768 }
2769 return false;
2770 }
2771 }
2772
2773 private static class WallpaperCallback extends IWallpaperServiceCallback.Stub {
2774 private WeakReference<ApplicationContext> mContext;
2775
2776 public WallpaperCallback(ApplicationContext context) {
2777 mContext = new WeakReference<ApplicationContext>(context);
2778 }
2779
2780 public synchronized void onWallpaperChanged() {
2781
2782 /* The wallpaper has changed but we shouldn't eagerly load the
2783 * wallpaper as that would be inefficient. Reset the cached wallpaper
2784 * to null so if the user requests the wallpaper again then we'll
2785 * fetch it.
2786 */
2787 final ApplicationContext applicationContext = mContext.get();
2788 if (applicationContext != null) {
2789 applicationContext.mWallpaper = null;
2790 }
2791 }
2792 }
2793}