blob: 5f894968ada5cb6adc30fa14be7c627105a100e3 [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;
Tom Taylord4a47292009-12-21 13:59:18 -080020import com.android.common.XmlUtils;
svetoslavganov75986cf2009-05-14 22:28:01 -070021import com.google.android.collect.Maps;
22
23import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.BroadcastReceiver;
26import android.content.ComponentName;
27import android.content.ContentResolver;
28import android.content.Context;
29import android.content.ContextWrapper;
30import android.content.IContentProvider;
31import android.content.Intent;
32import android.content.IntentFilter;
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -070033import android.content.IIntentReceiver;
34import android.content.IntentSender;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.ReceiverCallNotAllowedException;
36import android.content.ServiceConnection;
37import android.content.SharedPreferences;
38import android.content.pm.ActivityInfo;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.ComponentInfo;
Dianne Hackborn49237342009-08-27 20:08:01 -070041import android.content.pm.FeatureInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.content.pm.IPackageDataObserver;
43import android.content.pm.IPackageDeleteObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.content.pm.IPackageInstallObserver;
45import android.content.pm.IPackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070046import android.content.pm.IPackageStatsObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.content.pm.InstrumentationInfo;
48import android.content.pm.PackageInfo;
49import android.content.pm.PackageManager;
50import android.content.pm.PermissionGroupInfo;
51import android.content.pm.PermissionInfo;
52import android.content.pm.ProviderInfo;
53import android.content.pm.ResolveInfo;
54import android.content.pm.ServiceInfo;
55import android.content.res.AssetManager;
56import android.content.res.Resources;
57import android.content.res.XmlResourceParser;
58import android.database.sqlite.SQLiteDatabase;
59import android.database.sqlite.SQLiteDatabase.CursorFactory;
60import android.graphics.Bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import android.graphics.drawable.Drawable;
62import android.hardware.SensorManager;
63import android.location.ILocationManager;
64import android.location.LocationManager;
65import android.media.AudioManager;
66import android.net.ConnectivityManager;
67import android.net.IConnectivityManager;
68import android.net.Uri;
69import android.net.wifi.IWifiManager;
70import android.net.wifi.WifiManager;
71import android.os.Binder;
72import android.os.Bundle;
Dan Egnorf18a01c2009-11-12 11:32:50 -080073import android.os.DropBoxManager;
Oscar Montemayor539d3c42010-01-29 15:27:00 -080074import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.os.FileUtils;
76import android.os.Handler;
77import android.os.IBinder;
78import android.os.IPowerManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070079import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import 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;
Oscar Montemayor539d3c42010-01-29 15:27:00 -080084import android.os.StatFs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.os.Vibrator;
86import android.os.FileUtils.FileStatus;
San Mehat556d3502010-02-02 12:54:07 -080087import android.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import android.telephony.TelephonyManager;
89import android.text.ClipboardManager;
90import android.util.AndroidRuntimeException;
91import android.util.Log;
92import android.view.ContextThemeWrapper;
93import android.view.LayoutInflater;
94import android.view.WindowManagerImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070095import android.view.accessibility.AccessibilityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.view.inputmethod.InputMethodManager;
Fred Quintana60307342009-03-24 22:48:12 -070097import android.accounts.AccountManager;
98import android.accounts.IAccountManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099
Dan Egnorf18a01c2009-11-12 11:32:50 -0800100import com.android.internal.os.IDropBoxManagerService;
Dan Egnor95240272009-10-27 18:23:39 -0700101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import java.io.File;
103import java.io.FileInputStream;
104import java.io.FileNotFoundException;
105import java.io.FileOutputStream;
106import java.io.IOException;
107import java.io.InputStream;
108import java.lang.ref.WeakReference;
109import java.util.ArrayList;
110import java.util.HashMap;
svetoslavganov75986cf2009-05-14 22:28:01 -0700111import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112import java.util.Iterator;
113import java.util.List;
114import java.util.Map;
The Android Open Source Project10592532009-03-18 17:39:46 -0700115import java.util.Set;
svetoslavganov75986cf2009-05-14 22:28:01 -0700116import java.util.WeakHashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import java.util.Map.Entry;
118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119class ReceiverRestrictedContext extends ContextWrapper {
120 ReceiverRestrictedContext(Context base) {
121 super(base);
122 }
123
124 @Override
125 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
126 return registerReceiver(receiver, filter, null, null);
127 }
128
129 @Override
130 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
131 String broadcastPermission, Handler scheduler) {
132 throw new ReceiverCallNotAllowedException(
133 "IntentReceiver components are not allowed to register to receive intents");
134 //ex.fillInStackTrace();
135 //Log.e("IntentReceiver", ex.getMessage(), ex);
136 //return mContext.registerReceiver(receiver, filter, broadcastPermission,
137 // scheduler);
138 }
139
140 @Override
141 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
142 throw new ReceiverCallNotAllowedException(
143 "IntentReceiver components are not allowed to bind to services");
144 //ex.fillInStackTrace();
145 //Log.e("IntentReceiver", ex.getMessage(), ex);
146 //return mContext.bindService(service, interfaceName, conn, flags);
147 }
148}
149
150/**
Dianne Hackborn21556372010-02-04 16:34:40 -0800151 * Common implementation of Context API, which provides the base
152 * context object for Activity and other application components.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 */
Dianne Hackborn21556372010-02-04 16:34:40 -0800154class ContextImpl extends Context {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 private final static String TAG = "ApplicationContext";
Mitsuru Oshima569076c2009-07-02 20:06:08 -0700156 private final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 private final static boolean DEBUG_ICONS = false;
158
159 private static final Object sSync = new Object();
160 private static AlarmManager sAlarmManager;
161 private static PowerManager sPowerManager;
162 private static ConnectivityManager sConnectivityManager;
163 private static WifiManager sWifiManager;
164 private static LocationManager sLocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
166 new HashMap<File, SharedPreferencesImpl>();
167
168 private AudioManager mAudioManager;
169 /*package*/ ActivityThread.PackageInfo mPackageInfo;
170 private Resources mResources;
171 /*package*/ ActivityThread mMainThread;
172 private Context mOuterContext;
173 private IBinder mActivityToken = null;
174 private ApplicationContentResolver mContentResolver;
175 private int mThemeResource = 0;
176 private Resources.Theme mTheme = null;
177 private PackageManager mPackageManager;
178 private NotificationManager mNotificationManager = null;
179 private ActivityManager mActivityManager = null;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700180 private WallpaperManager mWallpaperManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 private Context mReceiverRestrictedContext = null;
182 private SearchManager mSearchManager = null;
183 private SensorManager mSensorManager = null;
San Mehatc9d81752010-02-01 10:23:27 -0800184 private StorageManager mStorageManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 private Vibrator mVibrator = null;
186 private LayoutInflater mLayoutInflater = null;
187 private StatusBarManager mStatusBarManager = null;
188 private TelephonyManager mTelephonyManager = null;
189 private ClipboardManager mClipboardManager = null;
Romain Guy870e09f2009-07-06 16:35:25 -0700190 private boolean mRestricted;
Fred Quintanae00a3112009-09-22 15:13:30 -0700191 private AccountManager mAccountManager; // protected by mSync
Dan Egnorf18a01c2009-11-12 11:32:50 -0800192 private DropBoxManager mDropBoxManager = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800193 private DevicePolicyManager mDevicePolicyManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
195 private final Object mSync = new Object();
196
197 private File mDatabasesDir;
198 private File mPreferencesDir;
199 private File mFilesDir;
200
201
202 private File mCacheDir;
203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 private static long sInstanceCount = 0;
205
206 private static final String[] EMPTY_FILE_LIST = {};
207
208 @Override
209 protected void finalize() throws Throwable {
210 super.finalize();
211 --sInstanceCount;
212 }
213
214 public static long getInstanceCount() {
215 return sInstanceCount;
216 }
217
218 @Override
219 public AssetManager getAssets() {
220 return mResources.getAssets();
221 }
222
223 @Override
224 public Resources getResources() {
225 return mResources;
226 }
227
228 @Override
229 public PackageManager getPackageManager() {
230 if (mPackageManager != null) {
231 return mPackageManager;
232 }
233
234 IPackageManager pm = ActivityThread.getPackageManager();
235 if (pm != null) {
236 // Doesn't matter if we make more than one instance.
237 return (mPackageManager = new ApplicationPackageManager(this, pm));
238 }
239
240 return null;
241 }
242
243 @Override
244 public ContentResolver getContentResolver() {
245 return mContentResolver;
246 }
247
248 @Override
249 public Looper getMainLooper() {
250 return mMainThread.getLooper();
251 }
252
253 @Override
254 public Context getApplicationContext() {
255 return mMainThread.getApplication();
256 }
257
258 @Override
259 public void setTheme(int resid) {
260 mThemeResource = resid;
261 }
262
263 @Override
264 public Resources.Theme getTheme() {
265 if (mTheme == null) {
266 if (mThemeResource == 0) {
267 mThemeResource = com.android.internal.R.style.Theme;
268 }
269 mTheme = mResources.newTheme();
270 mTheme.applyStyle(mThemeResource, true);
271 }
272 return mTheme;
273 }
274
275 @Override
276 public ClassLoader getClassLoader() {
277 return mPackageInfo != null ?
278 mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
279 }
280
281 @Override
282 public String getPackageName() {
283 if (mPackageInfo != null) {
284 return mPackageInfo.getPackageName();
285 }
286 throw new RuntimeException("Not supported in system context");
287 }
288
289 @Override
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700290 public ApplicationInfo getApplicationInfo() {
291 if (mPackageInfo != null) {
292 return mPackageInfo.getApplicationInfo();
293 }
294 throw new RuntimeException("Not supported in system context");
295 }
296
297 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 public String getPackageResourcePath() {
299 if (mPackageInfo != null) {
300 return mPackageInfo.getResDir();
301 }
302 throw new RuntimeException("Not supported in system context");
303 }
304
305 @Override
306 public String getPackageCodePath() {
307 if (mPackageInfo != null) {
308 return mPackageInfo.getAppDir();
309 }
310 throw new RuntimeException("Not supported in system context");
311 }
312
313 private static File makeBackupFile(File prefsFile) {
314 return new File(prefsFile.getPath() + ".bak");
315 }
316
Joe Onorato23ecae32009-06-10 17:07:15 -0700317 public File getSharedPrefsFile(String name) {
318 return makeFilename(getPreferencesDir(), name + ".xml");
319 }
320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 @Override
322 public SharedPreferences getSharedPreferences(String name, int mode) {
323 SharedPreferencesImpl sp;
Joe Onorato23ecae32009-06-10 17:07:15 -0700324 File f = getSharedPrefsFile(name);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 synchronized (sSharedPrefs) {
326 sp = sSharedPrefs.get(f);
327 if (sp != null && !sp.hasFileChanged()) {
328 //Log.i(TAG, "Returning existing prefs " + name + ": " + sp);
329 return sp;
330 }
331 }
332
333 FileInputStream str = null;
334 File backup = makeBackupFile(f);
335 if (backup.exists()) {
336 f.delete();
337 backup.renameTo(f);
338 }
339
340 // Debugging
341 if (f.exists() && !f.canRead()) {
342 Log.w(TAG, "Attempt to read preferences file " + f + " without permission");
343 }
344
345 Map map = null;
346 if (f.exists() && f.canRead()) {
347 try {
348 str = new FileInputStream(f);
349 map = XmlUtils.readMapXml(str);
350 str.close();
351 } catch (org.xmlpull.v1.XmlPullParserException e) {
352 Log.w(TAG, "getSharedPreferences", e);
353 } catch (FileNotFoundException e) {
354 Log.w(TAG, "getSharedPreferences", e);
355 } catch (IOException e) {
356 Log.w(TAG, "getSharedPreferences", e);
357 }
358 }
359
360 synchronized (sSharedPrefs) {
361 if (sp != null) {
362 //Log.i(TAG, "Updating existing prefs " + name + " " + sp + ": " + map);
363 sp.replace(map);
364 } else {
365 sp = sSharedPrefs.get(f);
366 if (sp == null) {
367 sp = new SharedPreferencesImpl(f, mode, map);
368 sSharedPrefs.put(f, sp);
369 }
370 }
371 return sp;
372 }
373 }
374
375 private File getPreferencesDir() {
376 synchronized (mSync) {
377 if (mPreferencesDir == null) {
378 mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
379 }
380 return mPreferencesDir;
381 }
382 }
383
384 @Override
385 public FileInputStream openFileInput(String name)
386 throws FileNotFoundException {
387 File f = makeFilename(getFilesDir(), name);
388 return new FileInputStream(f);
389 }
390
391 @Override
392 public FileOutputStream openFileOutput(String name, int mode)
393 throws FileNotFoundException {
394 final boolean append = (mode&MODE_APPEND) != 0;
395 File f = makeFilename(getFilesDir(), name);
396 try {
397 FileOutputStream fos = new FileOutputStream(f, append);
398 setFilePermissionsFromMode(f.getPath(), mode, 0);
399 return fos;
400 } catch (FileNotFoundException e) {
401 }
402
403 File parent = f.getParentFile();
404 parent.mkdir();
405 FileUtils.setPermissions(
406 parent.getPath(),
407 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
408 -1, -1);
409 FileOutputStream fos = new FileOutputStream(f, append);
410 setFilePermissionsFromMode(f.getPath(), mode, 0);
411 return fos;
412 }
413
414 @Override
415 public boolean deleteFile(String name) {
416 File f = makeFilename(getFilesDir(), name);
417 return f.delete();
418 }
419
420 @Override
421 public File getFilesDir() {
422 synchronized (mSync) {
423 if (mFilesDir == null) {
424 mFilesDir = new File(getDataDirFile(), "files");
425 }
426 if (!mFilesDir.exists()) {
427 if(!mFilesDir.mkdirs()) {
428 Log.w(TAG, "Unable to create files directory");
429 return null;
430 }
431 FileUtils.setPermissions(
432 mFilesDir.getPath(),
433 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
434 -1, -1);
435 }
436 return mFilesDir;
437 }
438 }
439
440 @Override
441 public File getCacheDir() {
442 synchronized (mSync) {
443 if (mCacheDir == null) {
444 mCacheDir = new File(getDataDirFile(), "cache");
445 }
446 if (!mCacheDir.exists()) {
447 if(!mCacheDir.mkdirs()) {
448 Log.w(TAG, "Unable to create cache directory");
449 return null;
450 }
451 FileUtils.setPermissions(
452 mCacheDir.getPath(),
453 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
454 -1, -1);
455 }
456 }
457 return mCacheDir;
458 }
459
460
461 @Override
462 public File getFileStreamPath(String name) {
463 return makeFilename(getFilesDir(), name);
464 }
465
466 @Override
467 public String[] fileList() {
468 final String[] list = getFilesDir().list();
469 return (list != null) ? list : EMPTY_FILE_LIST;
470 }
471
472 @Override
473 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800474 File f = validateFilePath(name, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
476 setFilePermissionsFromMode(f.getPath(), mode, 0);
477 return db;
478 }
479
480 @Override
481 public boolean deleteDatabase(String name) {
482 try {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800483 File f = validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 return f.delete();
485 } catch (Exception e) {
486 }
487 return false;
488 }
489
490 @Override
491 public File getDatabasePath(String name) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800492 return validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 }
494
495 @Override
496 public String[] databaseList() {
497 final String[] list = getDatabasesDir().list();
498 return (list != null) ? list : EMPTY_FILE_LIST;
499 }
500
501
502 private File getDatabasesDir() {
503 synchronized (mSync) {
504 if (mDatabasesDir == null) {
505 mDatabasesDir = new File(getDataDirFile(), "databases");
506 }
507 if (mDatabasesDir.getPath().equals("databases")) {
508 mDatabasesDir = new File("/data/system");
509 }
510 return mDatabasesDir;
511 }
512 }
513
514 @Override
515 public Drawable getWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700516 return getWallpaperManager().getDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517 }
518
519 @Override
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700520 public Drawable peekWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700521 return getWallpaperManager().peekDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 }
523
524 @Override
525 public int getWallpaperDesiredMinimumWidth() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700526 return getWallpaperManager().getDesiredMinimumWidth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 }
528
529 @Override
530 public int getWallpaperDesiredMinimumHeight() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700531 return getWallpaperManager().getDesiredMinimumHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 }
533
534 @Override
535 public void setWallpaper(Bitmap bitmap) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700536 getWallpaperManager().setBitmap(bitmap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 }
538
539 @Override
540 public void setWallpaper(InputStream data) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700541 getWallpaperManager().setStream(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
543
544 @Override
545 public void clearWallpaper() throws IOException {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700546 getWallpaperManager().clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 }
548
549 @Override
550 public void startActivity(Intent intent) {
551 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
552 throw new AndroidRuntimeException(
553 "Calling startActivity() from outside of an Activity "
554 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
555 + " Is this really what you want?");
556 }
557 mMainThread.getInstrumentation().execStartActivity(
558 getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
559 }
560
561 @Override
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700562 public void startIntentSender(IntentSender intent,
563 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
564 throws IntentSender.SendIntentException {
565 try {
566 String resolvedType = null;
567 if (fillInIntent != null) {
568 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
569 }
570 int result = ActivityManagerNative.getDefault()
571 .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
572 fillInIntent, resolvedType, null, null,
573 0, flagsMask, flagsValues);
574 if (result == IActivityManager.START_CANCELED) {
575 throw new IntentSender.SendIntentException();
576 }
577 Instrumentation.checkStartActivityResult(result, null);
578 } catch (RemoteException e) {
579 }
580 }
581
582 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 public void sendBroadcast(Intent intent) {
584 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
585 try {
586 ActivityManagerNative.getDefault().broadcastIntent(
587 mMainThread.getApplicationThread(), intent, resolvedType, null,
588 Activity.RESULT_OK, null, null, null, false, false);
589 } catch (RemoteException e) {
590 }
591 }
592
593 @Override
594 public void sendBroadcast(Intent intent, String receiverPermission) {
595 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
596 try {
597 ActivityManagerNative.getDefault().broadcastIntent(
598 mMainThread.getApplicationThread(), intent, resolvedType, null,
599 Activity.RESULT_OK, null, null, receiverPermission, false, false);
600 } catch (RemoteException e) {
601 }
602 }
603
604 @Override
605 public void sendOrderedBroadcast(Intent intent,
606 String receiverPermission) {
607 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
608 try {
609 ActivityManagerNative.getDefault().broadcastIntent(
610 mMainThread.getApplicationThread(), intent, resolvedType, null,
611 Activity.RESULT_OK, null, null, receiverPermission, true, false);
612 } catch (RemoteException e) {
613 }
614 }
615
616 @Override
617 public void sendOrderedBroadcast(Intent intent,
618 String receiverPermission, BroadcastReceiver resultReceiver,
619 Handler scheduler, int initialCode, String initialData,
620 Bundle initialExtras) {
621 IIntentReceiver rd = null;
622 if (resultReceiver != null) {
623 if (mPackageInfo != null) {
624 if (scheduler == null) {
625 scheduler = mMainThread.getHandler();
626 }
627 rd = mPackageInfo.getReceiverDispatcher(
628 resultReceiver, getOuterContext(), scheduler,
629 mMainThread.getInstrumentation(), false);
630 } else {
631 if (scheduler == null) {
632 scheduler = mMainThread.getHandler();
633 }
634 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
635 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
636 }
637 }
638 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
639 try {
640 ActivityManagerNative.getDefault().broadcastIntent(
641 mMainThread.getApplicationThread(), intent, resolvedType, rd,
642 initialCode, initialData, initialExtras, receiverPermission,
643 true, false);
644 } catch (RemoteException e) {
645 }
646 }
647
648 @Override
649 public void sendStickyBroadcast(Intent intent) {
650 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
651 try {
652 ActivityManagerNative.getDefault().broadcastIntent(
653 mMainThread.getApplicationThread(), intent, resolvedType, null,
654 Activity.RESULT_OK, null, null, null, false, true);
655 } catch (RemoteException e) {
656 }
657 }
658
659 @Override
Dianne Hackbornefa199f2009-09-19 12:03:15 -0700660 public void sendStickyOrderedBroadcast(Intent intent,
661 BroadcastReceiver resultReceiver,
662 Handler scheduler, int initialCode, String initialData,
663 Bundle initialExtras) {
664 IIntentReceiver rd = null;
665 if (resultReceiver != null) {
666 if (mPackageInfo != null) {
667 if (scheduler == null) {
668 scheduler = mMainThread.getHandler();
669 }
670 rd = mPackageInfo.getReceiverDispatcher(
671 resultReceiver, getOuterContext(), scheduler,
672 mMainThread.getInstrumentation(), false);
673 } else {
674 if (scheduler == null) {
675 scheduler = mMainThread.getHandler();
676 }
677 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
678 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
679 }
680 }
681 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
682 try {
683 ActivityManagerNative.getDefault().broadcastIntent(
684 mMainThread.getApplicationThread(), intent, resolvedType, rd,
685 initialCode, initialData, initialExtras, null,
686 true, true);
687 } catch (RemoteException e) {
688 }
689 }
690
691 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 public void removeStickyBroadcast(Intent intent) {
693 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
694 if (resolvedType != null) {
695 intent = new Intent(intent);
696 intent.setDataAndType(intent.getData(), resolvedType);
697 }
698 try {
699 ActivityManagerNative.getDefault().unbroadcastIntent(
700 mMainThread.getApplicationThread(), intent);
701 } catch (RemoteException e) {
702 }
703 }
704
705 @Override
706 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
707 return registerReceiver(receiver, filter, null, null);
708 }
709
710 @Override
711 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
712 String broadcastPermission, Handler scheduler) {
713 return registerReceiverInternal(receiver, filter, broadcastPermission,
714 scheduler, getOuterContext());
715 }
716
717 private Intent registerReceiverInternal(BroadcastReceiver receiver,
718 IntentFilter filter, String broadcastPermission,
719 Handler scheduler, Context context) {
720 IIntentReceiver rd = null;
721 if (receiver != null) {
722 if (mPackageInfo != null && context != null) {
723 if (scheduler == null) {
724 scheduler = mMainThread.getHandler();
725 }
726 rd = mPackageInfo.getReceiverDispatcher(
727 receiver, context, scheduler,
728 mMainThread.getInstrumentation(), true);
729 } else {
730 if (scheduler == null) {
731 scheduler = mMainThread.getHandler();
732 }
733 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
734 receiver, context, scheduler, null, false).getIIntentReceiver();
735 }
736 }
737 try {
738 return ActivityManagerNative.getDefault().registerReceiver(
739 mMainThread.getApplicationThread(),
740 rd, filter, broadcastPermission);
741 } catch (RemoteException e) {
742 return null;
743 }
744 }
745
746 @Override
747 public void unregisterReceiver(BroadcastReceiver receiver) {
748 if (mPackageInfo != null) {
749 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
750 getOuterContext(), receiver);
751 try {
752 ActivityManagerNative.getDefault().unregisterReceiver(rd);
753 } catch (RemoteException e) {
754 }
755 } else {
756 throw new RuntimeException("Not supported in system context");
757 }
758 }
759
760 @Override
761 public ComponentName startService(Intent service) {
762 try {
763 ComponentName cn = ActivityManagerNative.getDefault().startService(
764 mMainThread.getApplicationThread(), service,
765 service.resolveTypeIfNeeded(getContentResolver()));
766 if (cn != null && cn.getPackageName().equals("!")) {
767 throw new SecurityException(
768 "Not allowed to start service " + service
769 + " without permission " + cn.getClassName());
770 }
771 return cn;
772 } catch (RemoteException e) {
773 return null;
774 }
775 }
776
777 @Override
778 public boolean stopService(Intent service) {
779 try {
780 int res = ActivityManagerNative.getDefault().stopService(
781 mMainThread.getApplicationThread(), service,
782 service.resolveTypeIfNeeded(getContentResolver()));
783 if (res < 0) {
784 throw new SecurityException(
785 "Not allowed to stop service " + service);
786 }
787 return res != 0;
788 } catch (RemoteException e) {
789 return false;
790 }
791 }
792
793 @Override
794 public boolean bindService(Intent service, ServiceConnection conn,
795 int flags) {
796 IServiceConnection sd;
797 if (mPackageInfo != null) {
798 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
799 mMainThread.getHandler(), flags);
800 } else {
801 throw new RuntimeException("Not supported in system context");
802 }
803 try {
804 int res = ActivityManagerNative.getDefault().bindService(
805 mMainThread.getApplicationThread(), getActivityToken(),
806 service, service.resolveTypeIfNeeded(getContentResolver()),
807 sd, flags);
808 if (res < 0) {
809 throw new SecurityException(
810 "Not allowed to bind to service " + service);
811 }
812 return res != 0;
813 } catch (RemoteException e) {
814 return false;
815 }
816 }
817
818 @Override
819 public void unbindService(ServiceConnection conn) {
820 if (mPackageInfo != null) {
821 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
822 getOuterContext(), conn);
823 try {
824 ActivityManagerNative.getDefault().unbindService(sd);
825 } catch (RemoteException e) {
826 }
827 } else {
828 throw new RuntimeException("Not supported in system context");
829 }
830 }
831
832 @Override
833 public boolean startInstrumentation(ComponentName className,
834 String profileFile, Bundle arguments) {
835 try {
836 return ActivityManagerNative.getDefault().startInstrumentation(
837 className, profileFile, 0, arguments, null);
838 } catch (RemoteException e) {
839 // System has crashed, nothing we can do.
840 }
841 return false;
842 }
843
844 @Override
845 public Object getSystemService(String name) {
846 if (WINDOW_SERVICE.equals(name)) {
847 return WindowManagerImpl.getDefault();
848 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
849 synchronized (mSync) {
850 LayoutInflater inflater = mLayoutInflater;
851 if (inflater != null) {
852 return inflater;
853 }
854 mLayoutInflater = inflater =
855 PolicyManager.makeNewLayoutInflater(getOuterContext());
856 return inflater;
857 }
858 } else if (ACTIVITY_SERVICE.equals(name)) {
859 return getActivityManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700860 } else if (INPUT_METHOD_SERVICE.equals(name)) {
861 return InputMethodManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 } else if (ALARM_SERVICE.equals(name)) {
863 return getAlarmManager();
Fred Quintana60307342009-03-24 22:48:12 -0700864 } else if (ACCOUNT_SERVICE.equals(name)) {
865 return getAccountManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 } else if (POWER_SERVICE.equals(name)) {
867 return getPowerManager();
868 } else if (CONNECTIVITY_SERVICE.equals(name)) {
869 return getConnectivityManager();
870 } else if (WIFI_SERVICE.equals(name)) {
871 return getWifiManager();
872 } else if (NOTIFICATION_SERVICE.equals(name)) {
873 return getNotificationManager();
874 } else if (KEYGUARD_SERVICE.equals(name)) {
875 return new KeyguardManager();
svetoslavganov75986cf2009-05-14 22:28:01 -0700876 } else if (ACCESSIBILITY_SERVICE.equals(name)) {
877 return AccessibilityManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 } else if (LOCATION_SERVICE.equals(name)) {
879 return getLocationManager();
880 } else if (SEARCH_SERVICE.equals(name)) {
881 return getSearchManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700882 } else if (SENSOR_SERVICE.equals(name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 return getSensorManager();
San Mehatc9d81752010-02-01 10:23:27 -0800884 } else if (STORAGE_SERVICE.equals(name)) {
885 return getStorageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 } else if (VIBRATOR_SERVICE.equals(name)) {
887 return getVibrator();
888 } else if (STATUS_BAR_SERVICE.equals(name)) {
889 synchronized (mSync) {
890 if (mStatusBarManager == null) {
891 mStatusBarManager = new StatusBarManager(getOuterContext());
892 }
893 return mStatusBarManager;
894 }
895 } else if (AUDIO_SERVICE.equals(name)) {
896 return getAudioManager();
897 } else if (TELEPHONY_SERVICE.equals(name)) {
898 return getTelephonyManager();
899 } else if (CLIPBOARD_SERVICE.equals(name)) {
900 return getClipboardManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700901 } else if (WALLPAPER_SERVICE.equals(name)) {
902 return getWallpaperManager();
Dan Egnor95240272009-10-27 18:23:39 -0700903 } else if (DROPBOX_SERVICE.equals(name)) {
Dan Egnorf18a01c2009-11-12 11:32:50 -0800904 return getDropBoxManager();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800905 } else if (DEVICE_POLICY_SERVICE.equals(name)) {
906 return getDevicePolicyManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 }
908
909 return null;
910 }
911
Fred Quintana60307342009-03-24 22:48:12 -0700912 private AccountManager getAccountManager() {
Fred Quintanae00a3112009-09-22 15:13:30 -0700913 synchronized (mSync) {
914 if (mAccountManager == null) {
Fred Quintana60307342009-03-24 22:48:12 -0700915 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
916 IAccountManager service = IAccountManager.Stub.asInterface(b);
Fred Quintanae00a3112009-09-22 15:13:30 -0700917 mAccountManager = new AccountManager(this, service);
Fred Quintana60307342009-03-24 22:48:12 -0700918 }
Fred Quintanae00a3112009-09-22 15:13:30 -0700919 return mAccountManager;
Fred Quintana60307342009-03-24 22:48:12 -0700920 }
Fred Quintana60307342009-03-24 22:48:12 -0700921 }
922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 private ActivityManager getActivityManager() {
924 synchronized (mSync) {
925 if (mActivityManager == null) {
926 mActivityManager = new ActivityManager(getOuterContext(),
927 mMainThread.getHandler());
928 }
929 }
930 return mActivityManager;
931 }
932
933 private AlarmManager getAlarmManager() {
934 synchronized (sSync) {
935 if (sAlarmManager == null) {
936 IBinder b = ServiceManager.getService(ALARM_SERVICE);
937 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
938 sAlarmManager = new AlarmManager(service);
939 }
940 }
941 return sAlarmManager;
942 }
943
944 private PowerManager getPowerManager() {
945 synchronized (sSync) {
946 if (sPowerManager == null) {
947 IBinder b = ServiceManager.getService(POWER_SERVICE);
948 IPowerManager service = IPowerManager.Stub.asInterface(b);
949 sPowerManager = new PowerManager(service, mMainThread.getHandler());
950 }
951 }
952 return sPowerManager;
953 }
954
955 private ConnectivityManager getConnectivityManager()
956 {
957 synchronized (sSync) {
958 if (sConnectivityManager == null) {
959 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
960 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
961 sConnectivityManager = new ConnectivityManager(service);
962 }
963 }
964 return sConnectivityManager;
965 }
966
967 private WifiManager getWifiManager()
968 {
969 synchronized (sSync) {
970 if (sWifiManager == null) {
971 IBinder b = ServiceManager.getService(WIFI_SERVICE);
972 IWifiManager service = IWifiManager.Stub.asInterface(b);
973 sWifiManager = new WifiManager(service, mMainThread.getHandler());
974 }
975 }
976 return sWifiManager;
977 }
978
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700979 private NotificationManager getNotificationManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 synchronized (mSync) {
981 if (mNotificationManager == null) {
982 mNotificationManager = new NotificationManager(
983 new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
984 mMainThread.getHandler());
985 }
986 }
987 return mNotificationManager;
988 }
989
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700990 private WallpaperManager getWallpaperManager() {
991 synchronized (mSync) {
992 if (mWallpaperManager == null) {
993 mWallpaperManager = new WallpaperManager(getOuterContext(),
994 mMainThread.getHandler());
995 }
996 }
997 return mWallpaperManager;
998 }
999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 private TelephonyManager getTelephonyManager() {
1001 synchronized (mSync) {
1002 if (mTelephonyManager == null) {
1003 mTelephonyManager = new TelephonyManager(getOuterContext());
1004 }
1005 }
1006 return mTelephonyManager;
1007 }
1008
1009 private ClipboardManager getClipboardManager() {
1010 synchronized (mSync) {
1011 if (mClipboardManager == null) {
1012 mClipboardManager = new ClipboardManager(getOuterContext(),
1013 mMainThread.getHandler());
1014 }
1015 }
1016 return mClipboardManager;
1017 }
1018
1019 private LocationManager getLocationManager() {
1020 synchronized (sSync) {
1021 if (sLocationManager == null) {
1022 IBinder b = ServiceManager.getService(LOCATION_SERVICE);
1023 ILocationManager service = ILocationManager.Stub.asInterface(b);
1024 sLocationManager = new LocationManager(service);
1025 }
1026 }
1027 return sLocationManager;
1028 }
1029
1030 private SearchManager getSearchManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 synchronized (mSync) {
1032 if (mSearchManager == null) {
1033 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
1034 }
1035 }
1036 return mSearchManager;
1037 }
1038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 private SensorManager getSensorManager() {
1040 synchronized (mSync) {
1041 if (mSensorManager == null) {
1042 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1043 }
1044 }
1045 return mSensorManager;
1046 }
1047
San Mehatc9d81752010-02-01 10:23:27 -08001048 private StorageManager getStorageManager() {
1049 synchronized (mSync) {
1050 if (mStorageManager == null) {
1051 try {
1052 mStorageManager = new StorageManager(mMainThread.getHandler().getLooper());
1053 } catch (RemoteException rex) {
1054 Log.e(TAG, "Failed to create StorageManager", rex);
1055 mStorageManager = null;
1056 }
1057 }
1058 }
1059 return mStorageManager;
1060 }
1061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 private Vibrator getVibrator() {
1063 synchronized (mSync) {
1064 if (mVibrator == null) {
1065 mVibrator = new Vibrator();
1066 }
1067 }
1068 return mVibrator;
1069 }
Dan Egnor95240272009-10-27 18:23:39 -07001070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 private AudioManager getAudioManager()
1072 {
1073 if (mAudioManager == null) {
1074 mAudioManager = new AudioManager(this);
1075 }
1076 return mAudioManager;
1077 }
1078
Dan Egnorf18a01c2009-11-12 11:32:50 -08001079 private DropBoxManager getDropBoxManager() {
Dan Egnor95240272009-10-27 18:23:39 -07001080 synchronized (mSync) {
Dan Egnorf18a01c2009-11-12 11:32:50 -08001081 if (mDropBoxManager == null) {
Dan Egnor95240272009-10-27 18:23:39 -07001082 IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
Dan Egnorf18a01c2009-11-12 11:32:50 -08001083 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1084 mDropBoxManager = new DropBoxManager(service);
Dan Egnor95240272009-10-27 18:23:39 -07001085 }
1086 }
Dan Egnorf18a01c2009-11-12 11:32:50 -08001087 return mDropBoxManager;
Dan Egnor95240272009-10-27 18:23:39 -07001088 }
1089
Dianne Hackbornd6847842010-01-12 18:14:19 -08001090 private DevicePolicyManager getDevicePolicyManager() {
1091 synchronized (mSync) {
1092 if (mDevicePolicyManager == null) {
1093 mDevicePolicyManager = new DevicePolicyManager(this,
1094 mMainThread.getHandler());
1095 }
1096 }
1097 return mDevicePolicyManager;
1098 }
1099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 @Override
1101 public int checkPermission(String permission, int pid, int uid) {
1102 if (permission == null) {
1103 throw new IllegalArgumentException("permission is null");
1104 }
1105
1106 if (!Process.supportsProcesses()) {
1107 return PackageManager.PERMISSION_GRANTED;
1108 }
1109 try {
1110 return ActivityManagerNative.getDefault().checkPermission(
1111 permission, pid, uid);
1112 } catch (RemoteException e) {
1113 return PackageManager.PERMISSION_DENIED;
1114 }
1115 }
1116
1117 @Override
1118 public int checkCallingPermission(String permission) {
1119 if (permission == null) {
1120 throw new IllegalArgumentException("permission is null");
1121 }
1122
1123 if (!Process.supportsProcesses()) {
1124 return PackageManager.PERMISSION_GRANTED;
1125 }
1126 int pid = Binder.getCallingPid();
1127 if (pid != Process.myPid()) {
1128 return checkPermission(permission, pid,
1129 Binder.getCallingUid());
1130 }
1131 return PackageManager.PERMISSION_DENIED;
1132 }
1133
1134 @Override
1135 public int checkCallingOrSelfPermission(String permission) {
1136 if (permission == null) {
1137 throw new IllegalArgumentException("permission is null");
1138 }
1139
1140 return checkPermission(permission, Binder.getCallingPid(),
1141 Binder.getCallingUid());
1142 }
1143
1144 private void enforce(
1145 String permission, int resultOfCheck,
1146 boolean selfToo, int uid, String message) {
1147 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1148 throw new SecurityException(
1149 (message != null ? (message + ": ") : "") +
1150 (selfToo
1151 ? "Neither user " + uid + " nor current process has "
1152 : "User " + uid + " does not have ") +
1153 permission +
1154 ".");
1155 }
1156 }
1157
1158 public void enforcePermission(
1159 String permission, int pid, int uid, String message) {
1160 enforce(permission,
1161 checkPermission(permission, pid, uid),
1162 false,
1163 uid,
1164 message);
1165 }
1166
1167 public void enforceCallingPermission(String permission, String message) {
1168 enforce(permission,
1169 checkCallingPermission(permission),
1170 false,
1171 Binder.getCallingUid(),
1172 message);
1173 }
1174
1175 public void enforceCallingOrSelfPermission(
1176 String permission, String message) {
1177 enforce(permission,
1178 checkCallingOrSelfPermission(permission),
1179 true,
1180 Binder.getCallingUid(),
1181 message);
1182 }
1183
1184 @Override
1185 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1186 try {
1187 ActivityManagerNative.getDefault().grantUriPermission(
1188 mMainThread.getApplicationThread(), toPackage, uri,
1189 modeFlags);
1190 } catch (RemoteException e) {
1191 }
1192 }
1193
1194 @Override
1195 public void revokeUriPermission(Uri uri, int modeFlags) {
1196 try {
1197 ActivityManagerNative.getDefault().revokeUriPermission(
1198 mMainThread.getApplicationThread(), uri,
1199 modeFlags);
1200 } catch (RemoteException e) {
1201 }
1202 }
1203
1204 @Override
1205 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1206 if (!Process.supportsProcesses()) {
1207 return PackageManager.PERMISSION_GRANTED;
1208 }
1209 try {
1210 return ActivityManagerNative.getDefault().checkUriPermission(
1211 uri, pid, uid, modeFlags);
1212 } catch (RemoteException e) {
1213 return PackageManager.PERMISSION_DENIED;
1214 }
1215 }
1216
1217 @Override
1218 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1219 if (!Process.supportsProcesses()) {
1220 return PackageManager.PERMISSION_GRANTED;
1221 }
1222 int pid = Binder.getCallingPid();
1223 if (pid != Process.myPid()) {
1224 return checkUriPermission(uri, pid,
1225 Binder.getCallingUid(), modeFlags);
1226 }
1227 return PackageManager.PERMISSION_DENIED;
1228 }
1229
1230 @Override
1231 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1232 return checkUriPermission(uri, Binder.getCallingPid(),
1233 Binder.getCallingUid(), modeFlags);
1234 }
1235
1236 @Override
1237 public int checkUriPermission(Uri uri, String readPermission,
1238 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001239 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1241 + readPermission + " writePermission=" + writePermission
1242 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1243 }
1244 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1245 if (readPermission == null
1246 || checkPermission(readPermission, pid, uid)
1247 == PackageManager.PERMISSION_GRANTED) {
1248 return PackageManager.PERMISSION_GRANTED;
1249 }
1250 }
1251 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1252 if (writePermission == null
1253 || checkPermission(writePermission, pid, uid)
1254 == PackageManager.PERMISSION_GRANTED) {
1255 return PackageManager.PERMISSION_GRANTED;
1256 }
1257 }
1258 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1259 : PackageManager.PERMISSION_DENIED;
1260 }
1261
1262 private String uriModeFlagToString(int uriModeFlags) {
1263 switch (uriModeFlags) {
1264 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1265 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1266 return "read and write";
1267 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1268 return "read";
1269 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1270 return "write";
1271 }
1272 throw new IllegalArgumentException(
1273 "Unknown permission mode flags: " + uriModeFlags);
1274 }
1275
1276 private void enforceForUri(
1277 int modeFlags, int resultOfCheck, boolean selfToo,
1278 int uid, Uri uri, String message) {
1279 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1280 throw new SecurityException(
1281 (message != null ? (message + ": ") : "") +
1282 (selfToo
1283 ? "Neither user " + uid + " nor current process has "
1284 : "User " + uid + " does not have ") +
1285 uriModeFlagToString(modeFlags) +
1286 " permission on " +
1287 uri +
1288 ".");
1289 }
1290 }
1291
1292 public void enforceUriPermission(
1293 Uri uri, int pid, int uid, int modeFlags, String message) {
1294 enforceForUri(
1295 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1296 false, uid, uri, message);
1297 }
1298
1299 public void enforceCallingUriPermission(
1300 Uri uri, int modeFlags, String message) {
1301 enforceForUri(
1302 modeFlags, checkCallingUriPermission(uri, modeFlags),
1303 false, Binder.getCallingUid(), uri, message);
1304 }
1305
1306 public void enforceCallingOrSelfUriPermission(
1307 Uri uri, int modeFlags, String message) {
1308 enforceForUri(
1309 modeFlags,
1310 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1311 Binder.getCallingUid(), uri, message);
1312 }
1313
1314 public void enforceUriPermission(
1315 Uri uri, String readPermission, String writePermission,
1316 int pid, int uid, int modeFlags, String message) {
1317 enforceForUri(modeFlags,
1318 checkUriPermission(
1319 uri, readPermission, writePermission, pid, uid,
1320 modeFlags),
1321 false,
1322 uid,
1323 uri,
1324 message);
1325 }
1326
1327 @Override
1328 public Context createPackageContext(String packageName, int flags)
1329 throws PackageManager.NameNotFoundException {
1330 if (packageName.equals("system") || packageName.equals("android")) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001331 return new ContextImpl(mMainThread.getSystemContext());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 }
1333
1334 ActivityThread.PackageInfo pi =
1335 mMainThread.getPackageInfo(packageName, flags);
1336 if (pi != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001337 ContextImpl c = new ContextImpl();
Romain Guy870e09f2009-07-06 16:35:25 -07001338 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001339 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 if (c.mResources != null) {
1341 return c;
1342 }
1343 }
1344
1345 // Should be a better exception.
1346 throw new PackageManager.NameNotFoundException(
1347 "Application package " + packageName + " not found");
1348 }
1349
Romain Guy870e09f2009-07-06 16:35:25 -07001350 @Override
1351 public boolean isRestricted() {
1352 return mRestricted;
1353 }
1354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 private File getDataDirFile() {
1356 if (mPackageInfo != null) {
1357 return mPackageInfo.getDataDirFile();
1358 }
1359 throw new RuntimeException("Not supported in system context");
1360 }
1361
1362 @Override
1363 public File getDir(String name, int mode) {
1364 name = "app_" + name;
1365 File file = makeFilename(getDataDirFile(), name);
1366 if (!file.exists()) {
1367 file.mkdir();
1368 setFilePermissionsFromMode(file.getPath(), mode,
1369 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1370 }
1371 return file;
1372 }
1373
Dianne Hackborn21556372010-02-04 16:34:40 -08001374 static ContextImpl createSystemContext(ActivityThread mainThread) {
1375 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 context.init(Resources.getSystem(), mainThread);
1377 return context;
1378 }
1379
Dianne Hackborn21556372010-02-04 16:34:40 -08001380 ContextImpl() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 ++sInstanceCount;
1382 mOuterContext = this;
1383 }
1384
1385 /**
1386 * Create a new ApplicationContext from an existing one. The new one
1387 * works and operates the same as the one it is copying.
1388 *
1389 * @param context Existing application context.
1390 */
Dianne Hackborn21556372010-02-04 16:34:40 -08001391 public ContextImpl(ContextImpl context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 ++sInstanceCount;
1393 mPackageInfo = context.mPackageInfo;
1394 mResources = context.mResources;
1395 mMainThread = context.mMainThread;
1396 mContentResolver = context.mContentResolver;
1397 mOuterContext = this;
1398 }
1399
1400 final void init(ActivityThread.PackageInfo packageInfo,
1401 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001402 init(packageInfo, activityToken, mainThread, null);
1403 }
1404
1405 final void init(ActivityThread.PackageInfo packageInfo,
1406 IBinder activityToken, ActivityThread mainThread,
1407 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 mPackageInfo = packageInfo;
1409 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001410
1411 if (container != null && container.getCompatibilityInfo().applicationScale !=
1412 mResources.getCompatibilityInfo().applicationScale) {
1413 if (DEBUG) {
1414 Log.d(TAG, "loaded context has different scaling. Using container's" +
1415 " compatiblity info:" + container.getDisplayMetrics());
1416 }
1417 mResources = mainThread.getTopLevelResources(
1418 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 mMainThread = mainThread;
1421 mContentResolver = new ApplicationContentResolver(this, mainThread);
1422
1423 setActivityToken(activityToken);
1424 }
1425
1426 final void init(Resources resources, ActivityThread mainThread) {
1427 mPackageInfo = null;
1428 mResources = resources;
1429 mMainThread = mainThread;
1430 mContentResolver = new ApplicationContentResolver(this, mainThread);
1431 }
1432
1433 final void scheduleFinalCleanup(String who, String what) {
1434 mMainThread.scheduleContextCleanup(this, who, what);
1435 }
1436
1437 final void performFinalCleanup(String who, String what) {
1438 //Log.i(TAG, "Cleanup up context: " + this);
1439 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1440 }
1441
1442 final Context getReceiverRestrictedContext() {
1443 if (mReceiverRestrictedContext != null) {
1444 return mReceiverRestrictedContext;
1445 }
1446 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1447 }
1448
1449 final void setActivityToken(IBinder token) {
1450 mActivityToken = token;
1451 }
1452
1453 final void setOuterContext(Context context) {
1454 mOuterContext = context;
1455 }
1456
1457 final Context getOuterContext() {
1458 return mOuterContext;
1459 }
1460
1461 final IBinder getActivityToken() {
1462 return mActivityToken;
1463 }
1464
1465 private static void setFilePermissionsFromMode(String name, int mode,
1466 int extraPermissions) {
1467 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1468 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1469 |extraPermissions;
1470 if ((mode&MODE_WORLD_READABLE) != 0) {
1471 perms |= FileUtils.S_IROTH;
1472 }
1473 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1474 perms |= FileUtils.S_IWOTH;
1475 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001476 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1478 + ", perms=0x" + Integer.toHexString(perms));
1479 }
1480 FileUtils.setPermissions(name, perms, -1, -1);
1481 }
1482
Oscar Montemayora8529f62009-11-18 10:14:20 -08001483 private File validateFilePath(String name, boolean createDirectory) {
1484 File dir;
1485 File f;
1486
1487 if (name.charAt(0) == File.separatorChar) {
1488 String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1489 dir = new File(dirPath);
1490 name = name.substring(name.lastIndexOf(File.separatorChar));
1491 f = new File(dir, name);
1492 } else {
1493 dir = getDatabasesDir();
1494 f = makeFilename(dir, name);
1495 }
1496
1497 if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1498 FileUtils.setPermissions(dir.getPath(),
1499 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1500 -1, -1);
1501 }
1502
1503 return f;
1504 }
1505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 private File makeFilename(File base, String name) {
1507 if (name.indexOf(File.separatorChar) < 0) {
1508 return new File(base, name);
1509 }
1510 throw new IllegalArgumentException(
Oscar Montemayora8529f62009-11-18 10:14:20 -08001511 "File " + name + " contains a path separator");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 }
1513
1514 // ----------------------------------------------------------------------
1515 // ----------------------------------------------------------------------
1516 // ----------------------------------------------------------------------
1517
1518 private static final class ApplicationContentResolver extends ContentResolver {
1519 public ApplicationContentResolver(Context context,
1520 ActivityThread mainThread)
1521 {
1522 super(context);
1523 mMainThread = mainThread;
1524 }
1525
1526 @Override
1527 protected IContentProvider acquireProvider(Context context, String name)
1528 {
1529 return mMainThread.acquireProvider(context, name);
1530 }
1531
1532 @Override
1533 public boolean releaseProvider(IContentProvider provider)
1534 {
1535 return mMainThread.releaseProvider(provider);
1536 }
1537
1538 private final ActivityThread mMainThread;
1539 }
1540
1541 // ----------------------------------------------------------------------
1542 // ----------------------------------------------------------------------
1543 // ----------------------------------------------------------------------
1544
1545 /*package*/
1546 static final class ApplicationPackageManager extends PackageManager {
1547 @Override
1548 public PackageInfo getPackageInfo(String packageName, int flags)
1549 throws NameNotFoundException {
1550 try {
1551 PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1552 if (pi != null) {
1553 return pi;
1554 }
1555 } catch (RemoteException e) {
1556 throw new RuntimeException("Package manager has died", e);
1557 }
1558
1559 throw new NameNotFoundException(packageName);
1560 }
1561
Mihai Predaeae850c2009-05-13 10:13:48 +02001562 @Override
1563 public Intent getLaunchIntentForPackage(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 // First see if the package has an INFO activity; the existence of
1565 // such an activity is implied to be the desired front-door for the
1566 // overall package (such as if it has multiple launcher entries).
Mihai Predaeae850c2009-05-13 10:13:48 +02001567 Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1568 intentToResolve.addCategory(Intent.CATEGORY_INFO);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001569 intentToResolve.setPackage(packageName);
1570 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
Mihai Predaeae850c2009-05-13 10:13:48 +02001571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 // Otherwise, try to find a main launcher activity.
Mihai Predaeae850c2009-05-13 10:13:48 +02001573 if (resolveInfo == null) {
1574 // reuse the intent instance
1575 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1576 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001577 intentToResolve.setPackage(packageName);
1578 resolveInfo = resolveActivity(intentToResolve, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001580 if (resolveInfo == null) {
1581 return null;
1582 }
1583 Intent intent = new Intent(Intent.ACTION_MAIN);
1584 intent.setClassName(packageName, resolveInfo.activityInfo.name);
1585 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1586 return intent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 @Override
1590 public int[] getPackageGids(String packageName)
1591 throws NameNotFoundException {
1592 try {
1593 int[] gids = mPM.getPackageGids(packageName);
1594 if (gids == null || gids.length > 0) {
1595 return gids;
1596 }
1597 } catch (RemoteException e) {
1598 throw new RuntimeException("Package manager has died", e);
1599 }
1600
1601 throw new NameNotFoundException(packageName);
1602 }
1603
1604 @Override
1605 public PermissionInfo getPermissionInfo(String name, int flags)
1606 throws NameNotFoundException {
1607 try {
1608 PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1609 if (pi != null) {
1610 return pi;
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<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1621 throws NameNotFoundException {
1622 try {
1623 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1624 if (pi != null) {
1625 return pi;
1626 }
1627 } catch (RemoteException e) {
1628 throw new RuntimeException("Package manager has died", e);
1629 }
1630
1631 throw new NameNotFoundException(group);
1632 }
1633
1634 @Override
1635 public PermissionGroupInfo getPermissionGroupInfo(String name,
1636 int flags) throws NameNotFoundException {
1637 try {
1638 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1639 if (pgi != null) {
1640 return pgi;
1641 }
1642 } catch (RemoteException e) {
1643 throw new RuntimeException("Package manager has died", e);
1644 }
1645
1646 throw new NameNotFoundException(name);
1647 }
1648
1649 @Override
1650 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1651 try {
1652 return mPM.getAllPermissionGroups(flags);
1653 } catch (RemoteException e) {
1654 throw new RuntimeException("Package manager has died", e);
1655 }
1656 }
1657
1658 @Override
1659 public ApplicationInfo getApplicationInfo(String packageName, int flags)
1660 throws NameNotFoundException {
1661 try {
1662 ApplicationInfo ai = mPM.getApplicationInfo(packageName, 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(packageName);
1671 }
1672
1673 @Override
1674 public ActivityInfo getActivityInfo(ComponentName className, int flags)
1675 throws NameNotFoundException {
1676 try {
1677 ActivityInfo ai = mPM.getActivityInfo(className, flags);
1678 if (ai != null) {
1679 return ai;
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 ActivityInfo getReceiverInfo(ComponentName className, int flags)
1690 throws NameNotFoundException {
1691 try {
1692 ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1693 if (ai != null) {
1694 return ai;
1695 }
1696 } catch (RemoteException e) {
1697 throw new RuntimeException("Package manager has died", e);
1698 }
1699
1700 throw new NameNotFoundException(className.toString());
1701 }
1702
1703 @Override
1704 public ServiceInfo getServiceInfo(ComponentName className, int flags)
1705 throws NameNotFoundException {
1706 try {
1707 ServiceInfo si = mPM.getServiceInfo(className, flags);
1708 if (si != null) {
1709 return si;
1710 }
1711 } catch (RemoteException e) {
1712 throw new RuntimeException("Package manager has died", e);
1713 }
1714
1715 throw new NameNotFoundException(className.toString());
1716 }
1717
1718 @Override
1719 public String[] getSystemSharedLibraryNames() {
1720 try {
1721 return mPM.getSystemSharedLibraryNames();
1722 } catch (RemoteException e) {
1723 throw new RuntimeException("Package manager has died", e);
1724 }
1725 }
1726
1727 @Override
Dianne Hackborn49237342009-08-27 20:08:01 -07001728 public FeatureInfo[] getSystemAvailableFeatures() {
1729 try {
1730 return mPM.getSystemAvailableFeatures();
1731 } catch (RemoteException e) {
1732 throw new RuntimeException("Package manager has died", e);
1733 }
1734 }
1735
1736 @Override
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001737 public boolean hasSystemFeature(String name) {
1738 try {
1739 return mPM.hasSystemFeature(name);
1740 } catch (RemoteException e) {
1741 throw new RuntimeException("Package manager has died", e);
1742 }
1743 }
1744
1745 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 public int checkPermission(String permName, String pkgName) {
1747 try {
1748 return mPM.checkPermission(permName, pkgName);
1749 } catch (RemoteException e) {
1750 throw new RuntimeException("Package manager has died", e);
1751 }
1752 }
1753
1754 @Override
1755 public boolean addPermission(PermissionInfo info) {
1756 try {
1757 return mPM.addPermission(info);
1758 } catch (RemoteException e) {
1759 throw new RuntimeException("Package manager has died", e);
1760 }
1761 }
1762
1763 @Override
1764 public void removePermission(String name) {
1765 try {
1766 mPM.removePermission(name);
1767 } catch (RemoteException e) {
1768 throw new RuntimeException("Package manager has died", e);
1769 }
1770 }
1771
1772 @Override
1773 public int checkSignatures(String pkg1, String pkg2) {
1774 try {
1775 return mPM.checkSignatures(pkg1, pkg2);
1776 } catch (RemoteException e) {
1777 throw new RuntimeException("Package manager has died", e);
1778 }
1779 }
1780
1781 @Override
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001782 public int checkSignatures(int uid1, int uid2) {
1783 try {
1784 return mPM.checkUidSignatures(uid1, uid2);
1785 } catch (RemoteException e) {
1786 throw new RuntimeException("Package manager has died", e);
1787 }
1788 }
1789
1790 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 public String[] getPackagesForUid(int uid) {
1792 try {
1793 return mPM.getPackagesForUid(uid);
1794 } catch (RemoteException e) {
1795 throw new RuntimeException("Package manager has died", e);
1796 }
1797 }
1798
1799 @Override
1800 public String getNameForUid(int uid) {
1801 try {
1802 return mPM.getNameForUid(uid);
1803 } catch (RemoteException e) {
1804 throw new RuntimeException("Package manager has died", e);
1805 }
1806 }
1807
1808 @Override
1809 public int getUidForSharedUser(String sharedUserName)
1810 throws NameNotFoundException {
1811 try {
1812 int uid = mPM.getUidForSharedUser(sharedUserName);
1813 if(uid != -1) {
1814 return uid;
1815 }
1816 } catch (RemoteException e) {
1817 throw new RuntimeException("Package manager has died", e);
1818 }
1819 throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1820 }
1821
1822 @Override
1823 public List<PackageInfo> getInstalledPackages(int flags) {
1824 try {
1825 return mPM.getInstalledPackages(flags);
1826 } catch (RemoteException e) {
1827 throw new RuntimeException("Package manager has died", e);
1828 }
1829 }
1830
1831 @Override
1832 public List<ApplicationInfo> getInstalledApplications(int flags) {
1833 try {
1834 return mPM.getInstalledApplications(flags);
1835 } catch (RemoteException e) {
1836 throw new RuntimeException("Package manager has died", e);
1837 }
1838 }
1839
1840 @Override
1841 public ResolveInfo resolveActivity(Intent intent, int flags) {
1842 try {
1843 return mPM.resolveIntent(
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 List<ResolveInfo> queryIntentActivities(Intent intent,
1854 int flags) {
1855 try {
1856 return mPM.queryIntentActivities(
1857 intent,
1858 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1859 flags);
1860 } catch (RemoteException e) {
1861 throw new RuntimeException("Package manager has died", e);
1862 }
1863 }
1864
1865 @Override
1866 public List<ResolveInfo> queryIntentActivityOptions(
1867 ComponentName caller, Intent[] specifics, Intent intent,
1868 int flags) {
1869 final ContentResolver resolver = mContext.getContentResolver();
1870
1871 String[] specificTypes = null;
1872 if (specifics != null) {
1873 final int N = specifics.length;
1874 for (int i=0; i<N; i++) {
1875 Intent sp = specifics[i];
1876 if (sp != null) {
1877 String t = sp.resolveTypeIfNeeded(resolver);
1878 if (t != null) {
1879 if (specificTypes == null) {
1880 specificTypes = new String[N];
1881 }
1882 specificTypes[i] = t;
1883 }
1884 }
1885 }
1886 }
1887
1888 try {
1889 return mPM.queryIntentActivityOptions(caller, specifics,
1890 specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
1891 flags);
1892 } catch (RemoteException e) {
1893 throw new RuntimeException("Package manager has died", e);
1894 }
1895 }
1896
1897 @Override
1898 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
1899 try {
1900 return mPM.queryIntentReceivers(
1901 intent,
1902 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1903 flags);
1904 } catch (RemoteException e) {
1905 throw new RuntimeException("Package manager has died", e);
1906 }
1907 }
1908
1909 @Override
1910 public ResolveInfo resolveService(Intent intent, int flags) {
1911 try {
1912 return mPM.resolveService(
1913 intent,
1914 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1915 flags);
1916 } catch (RemoteException e) {
1917 throw new RuntimeException("Package manager has died", e);
1918 }
1919 }
1920
1921 @Override
1922 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
1923 try {
1924 return mPM.queryIntentServices(
1925 intent,
1926 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1927 flags);
1928 } catch (RemoteException e) {
1929 throw new RuntimeException("Package manager has died", e);
1930 }
1931 }
1932
1933 @Override
1934 public ProviderInfo resolveContentProvider(String name,
1935 int flags) {
1936 try {
1937 return mPM.resolveContentProvider(name, flags);
1938 } catch (RemoteException e) {
1939 throw new RuntimeException("Package manager has died", e);
1940 }
1941 }
1942
1943 @Override
1944 public List<ProviderInfo> queryContentProviders(String processName,
1945 int uid, int flags) {
1946 try {
1947 return mPM.queryContentProviders(processName, uid, flags);
1948 } catch (RemoteException e) {
1949 throw new RuntimeException("Package manager has died", e);
1950 }
1951 }
1952
1953 @Override
1954 public InstrumentationInfo getInstrumentationInfo(
1955 ComponentName className, int flags)
1956 throws NameNotFoundException {
1957 try {
1958 InstrumentationInfo ii = mPM.getInstrumentationInfo(
1959 className, flags);
1960 if (ii != null) {
1961 return ii;
1962 }
1963 } catch (RemoteException e) {
1964 throw new RuntimeException("Package manager has died", e);
1965 }
1966
1967 throw new NameNotFoundException(className.toString());
1968 }
1969
1970 @Override
1971 public List<InstrumentationInfo> queryInstrumentation(
1972 String targetPackage, int flags) {
1973 try {
1974 return mPM.queryInstrumentation(targetPackage, flags);
1975 } catch (RemoteException e) {
1976 throw new RuntimeException("Package manager has died", e);
1977 }
1978 }
1979
1980 @Override public Drawable getDrawable(String packageName, int resid,
1981 ApplicationInfo appInfo) {
1982 ResourceName name = new ResourceName(packageName, resid);
1983 Drawable dr = getCachedIcon(name);
1984 if (dr != null) {
1985 return dr;
1986 }
1987 if (appInfo == null) {
1988 try {
1989 appInfo = getApplicationInfo(packageName, 0);
1990 } catch (NameNotFoundException e) {
1991 return null;
1992 }
1993 }
1994 try {
1995 Resources r = getResourcesForApplication(appInfo);
1996 dr = r.getDrawable(resid);
Dianne Hackborn11ea3342009-07-22 21:48:55 -07001997 if (false) {
1998 RuntimeException e = new RuntimeException("here");
1999 e.fillInStackTrace();
2000 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
2001 + " from package " + packageName
2002 + ": app scale=" + r.getCompatibilityInfo().applicationScale
2003 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
2004 e);
2005 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2007 + Integer.toHexString(resid) + " from " + r
2008 + ": " + dr);
2009 putCachedIcon(name, dr);
2010 return dr;
2011 } catch (NameNotFoundException e) {
2012 Log.w("PackageManager", "Failure retrieving resources for"
2013 + appInfo.packageName);
2014 } catch (RuntimeException e) {
2015 // If an exception was thrown, fall through to return
2016 // default icon.
2017 Log.w("PackageManager", "Failure retrieving icon 0x"
2018 + Integer.toHexString(resid) + " in package "
2019 + packageName, e);
2020 }
2021 return null;
2022 }
2023
2024 @Override public Drawable getActivityIcon(ComponentName activityName)
2025 throws NameNotFoundException {
2026 return getActivityInfo(activityName, 0).loadIcon(this);
2027 }
2028
2029 @Override public Drawable getActivityIcon(Intent intent)
2030 throws NameNotFoundException {
2031 if (intent.getComponent() != null) {
2032 return getActivityIcon(intent.getComponent());
2033 }
2034
2035 ResolveInfo info = resolveActivity(
2036 intent, PackageManager.MATCH_DEFAULT_ONLY);
2037 if (info != null) {
2038 return info.activityInfo.loadIcon(this);
2039 }
2040
2041 throw new NameNotFoundException(intent.toURI());
2042 }
2043
2044 @Override public Drawable getDefaultActivityIcon() {
2045 return Resources.getSystem().getDrawable(
2046 com.android.internal.R.drawable.sym_def_app_icon);
2047 }
2048
2049 @Override public Drawable getApplicationIcon(ApplicationInfo info) {
2050 final int icon = info.icon;
2051 if (icon != 0) {
2052 ResourceName name = new ResourceName(info, icon);
2053 Drawable dr = getCachedIcon(name);
2054 if (dr != null) {
2055 return dr;
2056 }
2057 try {
2058 Resources r = getResourcesForApplication(info);
2059 dr = r.getDrawable(icon);
2060 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2061 + Integer.toHexString(icon) + " from " + r
2062 + ": " + dr);
2063 putCachedIcon(name, dr);
2064 return dr;
2065 } catch (NameNotFoundException e) {
2066 Log.w("PackageManager", "Failure retrieving resources for"
2067 + info.packageName);
2068 } catch (RuntimeException e) {
2069 // If an exception was thrown, fall through to return
2070 // default icon.
2071 Log.w("PackageManager", "Failure retrieving app icon", e);
2072 }
2073 }
2074 return getDefaultActivityIcon();
2075 }
2076
2077 @Override public Drawable getApplicationIcon(String packageName)
2078 throws NameNotFoundException {
2079 return getApplicationIcon(getApplicationInfo(packageName, 0));
2080 }
2081
2082 @Override public Resources getResourcesForActivity(
2083 ComponentName activityName) throws NameNotFoundException {
2084 return getResourcesForApplication(
2085 getActivityInfo(activityName, 0).applicationInfo);
2086 }
2087
2088 @Override public Resources getResourcesForApplication(
2089 ApplicationInfo app) throws NameNotFoundException {
2090 if (app.packageName.equals("system")) {
2091 return mContext.mMainThread.getSystemContext().getResources();
2092 }
2093 Resources r = mContext.mMainThread.getTopLevelResources(
2094 app.uid == Process.myUid() ? app.sourceDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002095 : app.publicSourceDir, mContext.mPackageInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 if (r != null) {
2097 return r;
2098 }
2099 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2100 }
2101
2102 @Override public Resources getResourcesForApplication(
2103 String appPackageName) throws NameNotFoundException {
2104 return getResourcesForApplication(
2105 getApplicationInfo(appPackageName, 0));
2106 }
2107
2108 int mCachedSafeMode = -1;
2109 @Override public boolean isSafeMode() {
2110 try {
2111 if (mCachedSafeMode < 0) {
2112 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2113 }
2114 return mCachedSafeMode != 0;
2115 } catch (RemoteException e) {
2116 throw new RuntimeException("Package manager has died", e);
2117 }
2118 }
2119
2120 static void configurationChanged() {
2121 synchronized (sSync) {
2122 sIconCache.clear();
2123 sStringCache.clear();
2124 }
2125 }
2126
Dianne Hackborn21556372010-02-04 16:34:40 -08002127 ApplicationPackageManager(ContextImpl context,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 IPackageManager pm) {
2129 mContext = context;
2130 mPM = pm;
2131 }
2132
2133 private Drawable getCachedIcon(ResourceName name) {
2134 synchronized (sSync) {
2135 WeakReference<Drawable> wr = sIconCache.get(name);
2136 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2137 + name + ": " + wr);
2138 if (wr != null) { // we have the activity
2139 Drawable dr = wr.get();
2140 if (dr != null) {
2141 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2142 + name + ": " + dr);
2143 return dr;
2144 }
2145 // our entry has been purged
2146 sIconCache.remove(name);
2147 }
2148 }
2149 return null;
2150 }
2151
2152 private void establishPackageRemovedReceiver() {
2153 // mContext.registerReceiverInternal() winds up acquiring the
2154 // main ActivityManagerService.this lock. If we hold our usual
2155 // sSync global lock at the same time, we impose a required ordering
2156 // on those two locks, which is not good for deadlock prevention.
2157 // Use a dedicated lock around initialization of
2158 // sPackageRemovedReceiver to avoid this.
2159 synchronized (sPackageRemovedSync) {
2160 if (sPackageRemovedReceiver == null) {
2161 sPackageRemovedReceiver = new PackageRemovedReceiver();
2162 IntentFilter filter = new IntentFilter(
2163 Intent.ACTION_PACKAGE_REMOVED);
2164 filter.addDataScheme("package");
2165 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2166 filter, null, null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002167 // Register for events related to sdcard installation.
2168 IntentFilter sdFilter = new IntentFilter();
2169 sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
2170 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2171 sdFilter, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 }
2173 }
2174 }
2175
2176 private void putCachedIcon(ResourceName name, Drawable dr) {
2177 establishPackageRemovedReceiver();
2178
2179 synchronized (sSync) {
2180 sIconCache.put(name, new WeakReference<Drawable>(dr));
2181 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2182 + name + ": " + dr);
2183 }
2184 }
2185
2186 private static final class PackageRemovedReceiver extends BroadcastReceiver {
2187 @Override
2188 public void onReceive(Context context, Intent intent) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002189 String pkgList[] = null;
2190 String action = intent.getAction();
2191 boolean immediateGc = false;
2192 if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
2193 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
2194 immediateGc = true;
2195 } else {
2196 Uri data = intent.getData();
2197 if (data != null) {
2198 String ssp = data.getSchemeSpecificPart();
2199 if (ssp != null) {
2200 pkgList = new String[] { ssp };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 }
2202 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002203 }
2204 if (pkgList != null && (pkgList.length > 0)) {
2205 boolean needCleanup = false;
2206 boolean hasPkgInfo = false;
2207 for (String ssp : pkgList) {
2208 synchronized (sSync) {
2209 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2210 while (it.hasNext()) {
2211 ResourceName nm = it.next();
2212 if (nm.packageName.equals(ssp)) {
2213 //Log.i(TAG, "Removing cached drawable for " + nm);
2214 it.remove();
2215 needCleanup = true;
2216 }
2217 }
2218 it = sStringCache.keySet().iterator();
2219 while (it.hasNext()) {
2220 ResourceName nm = it.next();
2221 if (nm.packageName.equals(ssp)) {
2222 //Log.i(TAG, "Removing cached string for " + nm);
2223 it.remove();
2224 needCleanup = true;
2225 }
2226 }
2227 }
2228 if (!hasPkgInfo) {
2229 hasPkgInfo = ActivityThread.currentActivityThread().hasPackageInfo(ssp);
2230 }
2231 }
2232 if (needCleanup || hasPkgInfo) {
2233 if (immediateGc) {
2234 // Schedule an immediate gc.
2235 Runtime.getRuntime().gc();
2236 } else {
2237 ActivityThread.currentActivityThread().scheduleGcIdler();
2238 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 }
2240 }
2241 }
2242 }
2243
2244 private static final class ResourceName {
2245 final String packageName;
2246 final int iconId;
2247
2248 ResourceName(String _packageName, int _iconId) {
2249 packageName = _packageName;
2250 iconId = _iconId;
2251 }
2252
2253 ResourceName(ApplicationInfo aInfo, int _iconId) {
2254 this(aInfo.packageName, _iconId);
2255 }
2256
2257 ResourceName(ComponentInfo cInfo, int _iconId) {
2258 this(cInfo.applicationInfo.packageName, _iconId);
2259 }
2260
2261 ResourceName(ResolveInfo rInfo, int _iconId) {
2262 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2263 }
2264
2265 @Override
2266 public boolean equals(Object o) {
2267 if (this == o) return true;
2268 if (o == null || getClass() != o.getClass()) return false;
2269
2270 ResourceName that = (ResourceName) o;
2271
2272 if (iconId != that.iconId) return false;
2273 return !(packageName != null ?
2274 !packageName.equals(that.packageName) : that.packageName != null);
2275
2276 }
2277
2278 @Override
2279 public int hashCode() {
2280 int result;
2281 result = packageName.hashCode();
2282 result = 31 * result + iconId;
2283 return result;
2284 }
2285
2286 @Override
2287 public String toString() {
2288 return "{ResourceName " + packageName + " / " + iconId + "}";
2289 }
2290 }
2291
2292 private CharSequence getCachedString(ResourceName name) {
2293 synchronized (sSync) {
2294 WeakReference<CharSequence> wr = sStringCache.get(name);
2295 if (wr != null) { // we have the activity
2296 CharSequence cs = wr.get();
2297 if (cs != null) {
2298 return cs;
2299 }
2300 // our entry has been purged
2301 sStringCache.remove(name);
2302 }
2303 }
2304 return null;
2305 }
2306
2307 private void putCachedString(ResourceName name, CharSequence cs) {
2308 establishPackageRemovedReceiver();
2309
2310 synchronized (sSync) {
2311 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2312 }
2313 }
2314
2315 private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
2316 CharSequence cs = getCachedString(name);
2317 if (cs != null) {
2318 return cs;
2319 }
2320 try {
2321 Resources r = getResourcesForApplication(app);
2322 cs = r.getText(id);
2323 putCachedString(name, cs);
2324 } catch (NameNotFoundException e) {
2325 Log.w("PackageManager", "Failure retrieving resources for"
2326 + app.packageName);
2327 } catch (RuntimeException e) {
2328 // If an exception was thrown, fall through to return null
2329 Log.w("ApplicationInfo", "Failure retrieving activity name", e);
2330 }
2331 return cs;
2332 }
2333
2334 @Override
2335 public CharSequence getText(String packageName, int resid,
2336 ApplicationInfo appInfo) {
2337 ResourceName name = new ResourceName(packageName, resid);
2338 CharSequence text = getCachedString(name);
2339 if (text != null) {
2340 return text;
2341 }
2342 if (appInfo == null) {
2343 try {
2344 appInfo = getApplicationInfo(packageName, 0);
2345 } catch (NameNotFoundException e) {
2346 return null;
2347 }
2348 }
2349 try {
2350 Resources r = getResourcesForApplication(appInfo);
2351 text = r.getText(resid);
2352 putCachedString(name, text);
2353 return text;
2354 } catch (NameNotFoundException e) {
2355 Log.w("PackageManager", "Failure retrieving resources for"
2356 + appInfo.packageName);
2357 } catch (RuntimeException e) {
2358 // If an exception was thrown, fall through to return
2359 // default icon.
2360 Log.w("PackageManager", "Failure retrieving text 0x"
2361 + Integer.toHexString(resid) + " in package "
2362 + packageName, e);
2363 }
2364 return null;
2365 }
2366
2367 @Override
2368 public XmlResourceParser getXml(String packageName, int resid,
2369 ApplicationInfo appInfo) {
2370 if (appInfo == null) {
2371 try {
2372 appInfo = getApplicationInfo(packageName, 0);
2373 } catch (NameNotFoundException e) {
2374 return null;
2375 }
2376 }
2377 try {
2378 Resources r = getResourcesForApplication(appInfo);
2379 return r.getXml(resid);
2380 } catch (RuntimeException e) {
2381 // If an exception was thrown, fall through to return
2382 // default icon.
2383 Log.w("PackageManager", "Failure retrieving xml 0x"
2384 + Integer.toHexString(resid) + " in package "
2385 + packageName, e);
2386 } catch (NameNotFoundException e) {
2387 Log.w("PackageManager", "Failure retrieving resources for"
2388 + appInfo.packageName);
2389 }
2390 return null;
2391 }
2392
2393 @Override
2394 public CharSequence getApplicationLabel(ApplicationInfo info) {
2395 if (info.nonLocalizedLabel != null) {
2396 return info.nonLocalizedLabel;
2397 }
2398 final int id = info.labelRes;
2399 if (id != 0) {
2400 CharSequence cs = getLabel(new ResourceName(info, id), info, id);
2401 if (cs != null) {
2402 return cs;
2403 }
2404 }
2405 return info.packageName;
2406 }
2407
2408 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002409 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2410 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 try {
Jacek Surazski65e13172009-04-28 15:26:38 +02002412 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 } catch (RemoteException e) {
2414 // Should never happen!
2415 }
2416 }
2417
2418 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002419 public String getInstallerPackageName(String packageName) {
2420 try {
2421 return mPM.getInstallerPackageName(packageName);
2422 } catch (RemoteException e) {
2423 // Should never happen!
2424 }
2425 return null;
2426 }
2427
2428 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2430 try {
2431 mPM.deletePackage(packageName, observer, flags);
2432 } catch (RemoteException e) {
2433 // Should never happen!
2434 }
2435 }
2436 @Override
2437 public void clearApplicationUserData(String packageName,
2438 IPackageDataObserver observer) {
2439 try {
2440 mPM.clearApplicationUserData(packageName, observer);
2441 } catch (RemoteException e) {
2442 // Should never happen!
2443 }
2444 }
2445 @Override
2446 public void deleteApplicationCacheFiles(String packageName,
2447 IPackageDataObserver observer) {
2448 try {
2449 mPM.deleteApplicationCacheFiles(packageName, observer);
2450 } catch (RemoteException e) {
2451 // Should never happen!
2452 }
2453 }
2454 @Override
2455 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2456 try {
2457 mPM.freeStorageAndNotify(idealStorageSize, observer);
2458 } catch (RemoteException e) {
2459 // Should never happen!
2460 }
2461 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002463 @Override
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002464 public void freeStorage(long freeStorageSize, IntentSender pi) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002465 try {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002466 mPM.freeStorage(freeStorageSize, pi);
2467 } catch (RemoteException e) {
2468 // Should never happen!
2469 }
2470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471
2472 @Override
2473 public void getPackageSizeInfo(String packageName,
2474 IPackageStatsObserver observer) {
2475 try {
2476 mPM.getPackageSizeInfo(packageName, observer);
2477 } catch (RemoteException e) {
2478 // Should never happen!
2479 }
2480 }
2481 @Override
2482 public void addPackageToPreferred(String packageName) {
2483 try {
2484 mPM.addPackageToPreferred(packageName);
2485 } catch (RemoteException e) {
2486 // Should never happen!
2487 }
2488 }
2489
2490 @Override
2491 public void removePackageFromPreferred(String packageName) {
2492 try {
2493 mPM.removePackageFromPreferred(packageName);
2494 } catch (RemoteException e) {
2495 // Should never happen!
2496 }
2497 }
2498
2499 @Override
2500 public List<PackageInfo> getPreferredPackages(int flags) {
2501 try {
2502 return mPM.getPreferredPackages(flags);
2503 } catch (RemoteException e) {
2504 // Should never happen!
2505 }
2506 return new ArrayList<PackageInfo>();
2507 }
2508
2509 @Override
2510 public void addPreferredActivity(IntentFilter filter,
2511 int match, ComponentName[] set, ComponentName activity) {
2512 try {
2513 mPM.addPreferredActivity(filter, match, set, activity);
2514 } catch (RemoteException e) {
2515 // Should never happen!
2516 }
2517 }
2518
2519 @Override
Satish Sampath8dbe6122009-06-02 23:35:54 +01002520 public void replacePreferredActivity(IntentFilter filter,
2521 int match, ComponentName[] set, ComponentName activity) {
2522 try {
2523 mPM.replacePreferredActivity(filter, match, set, activity);
2524 } catch (RemoteException e) {
2525 // Should never happen!
2526 }
2527 }
2528
2529 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002530 public void clearPackagePreferredActivities(String packageName) {
2531 try {
2532 mPM.clearPackagePreferredActivities(packageName);
2533 } catch (RemoteException e) {
2534 // Should never happen!
2535 }
2536 }
2537
2538 @Override
2539 public int getPreferredActivities(List<IntentFilter> outFilters,
2540 List<ComponentName> outActivities, String packageName) {
2541 try {
2542 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2543 } catch (RemoteException e) {
2544 // Should never happen!
2545 }
2546 return 0;
2547 }
2548
2549 @Override
2550 public void setComponentEnabledSetting(ComponentName componentName,
2551 int newState, int flags) {
2552 try {
2553 mPM.setComponentEnabledSetting(componentName, newState, flags);
2554 } catch (RemoteException e) {
2555 // Should never happen!
2556 }
2557 }
2558
2559 @Override
2560 public int getComponentEnabledSetting(ComponentName componentName) {
2561 try {
2562 return mPM.getComponentEnabledSetting(componentName);
2563 } catch (RemoteException e) {
2564 // Should never happen!
2565 }
2566 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2567 }
2568
2569 @Override
2570 public void setApplicationEnabledSetting(String packageName,
2571 int newState, int flags) {
2572 try {
2573 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2574 } catch (RemoteException e) {
2575 // Should never happen!
2576 }
2577 }
2578
2579 @Override
2580 public int getApplicationEnabledSetting(String packageName) {
2581 try {
2582 return mPM.getApplicationEnabledSetting(packageName);
2583 } catch (RemoteException e) {
2584 // Should never happen!
2585 }
2586 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2587 }
2588
Oscar Montemayor539d3c42010-01-29 15:27:00 -08002589 // Constants related to app heuristics
2590 // No-installation limit for internal flash: 10% or less space available
2591 private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
2592
2593 // SD-to-internal app size threshold: currently set to 1 MB
2594 private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
2595
2596 @Override
2597 public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
2598 // Initial implementation:
2599 // Package size = code size + cache size + data size
2600 // If code size > 1 MB, install on SD card.
2601 // Else install on internal NAND flash, unless space on NAND is less than 10%
2602
2603 if ((packageURI == null) || (appInfo == null)) {
2604 return INSTALL_PARSE_FAILED_NOT_APK;
2605 }
2606
2607 StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
2608 StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
2609
2610 long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
2611 (long)internalFlashStats.getBlockSize();
2612 long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
2613 (long)internalFlashStats.getBlockSize();
2614 long availSDSize = (long)sdcardStats.getAvailableBlocks() *
2615 (long)sdcardStats.getBlockSize();
2616
2617 double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
2618
2619 final String archiveFilePath = packageURI.getPath();
2620 File apkFile = new File(archiveFilePath);
2621 long pkgLen = apkFile.length();
2622
2623 // Consider application flags preferences as well...
2624 boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
2625
2626 // These are not very precise measures, but I guess it is hard to estimate sizes
2627 // before installing the package.
2628 // As a shortcut, I am assuming that the package fits on NAND flash if the available
2629 // space is three times that of the APK size. For SD, we only worry about the APK size.
2630 // Since packages are downloaded into SD, this might not even be necessary.
2631 boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
2632 boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
2633
2634 // Does not fit, recommend no installation.
2635 if (!fitsOnSD && !fitsOnInternalFlash) {
2636 return INSTALL_FAILED_INSUFFICIENT_STORAGE;
2637 }
2638
2639 if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
2640 // recommend internal NAND likely
2641 if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
2642 // Low space on NAND (<10%) - install on SD
2643 return INSTALL_ON_SDCARD;
2644 }
2645 return INSTALL_ON_INTERNAL_FLASH;
2646 } else {
2647 if (fitsOnSD) {
2648 // Recommend SD card
2649 return INSTALL_ON_SDCARD;
2650 } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
2651 !(installOnlyOnSD)) {
2652 return INSTALL_ON_INTERNAL_FLASH;
2653 } else {
2654 return INSTALL_FAILED_INSUFFICIENT_STORAGE;
2655 }
2656 }
2657 }
2658
Dianne Hackborn21556372010-02-04 16:34:40 -08002659 private final ContextImpl mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 private final IPackageManager mPM;
2661
2662 private static final Object sSync = new Object();
2663 private static final Object sPackageRemovedSync = new Object();
2664 private static BroadcastReceiver sPackageRemovedReceiver;
2665 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2666 = new HashMap<ResourceName, WeakReference<Drawable> >();
2667 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2668 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2669 }
2670
2671 // ----------------------------------------------------------------------
2672 // ----------------------------------------------------------------------
2673 // ----------------------------------------------------------------------
2674
2675 private static final class SharedPreferencesImpl implements SharedPreferences {
2676
2677 private final File mFile;
2678 private final File mBackupFile;
2679 private final int mMode;
2680 private Map mMap;
2681 private final FileStatus mFileStatus = new FileStatus();
2682 private long mTimestamp;
2683
The Android Open Source Project10592532009-03-18 17:39:46 -07002684 private static final Object mContent = new Object();
2685 private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686
2687 SharedPreferencesImpl(
2688 File file, int mode, Map initialContents) {
2689 mFile = file;
2690 mBackupFile = makeBackupFile(file);
2691 mMode = mode;
2692 mMap = initialContents != null ? initialContents : new HashMap();
2693 if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
2694 mTimestamp = mFileStatus.mtime;
2695 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002696 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
2698
2699 public boolean hasFileChanged() {
2700 synchronized (this) {
2701 if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2702 return true;
2703 }
2704 return mTimestamp != mFileStatus.mtime;
2705 }
2706 }
2707
2708 public void replace(Map newContents) {
2709 if (newContents != null) {
2710 synchronized (this) {
2711 mMap = newContents;
2712 }
2713 }
2714 }
2715
2716 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2717 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002718 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
2720 }
2721
2722 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2723 synchronized(this) {
2724 mListeners.remove(listener);
2725 }
2726 }
2727
2728 public Map<String, ?> getAll() {
2729 synchronized(this) {
2730 //noinspection unchecked
2731 return new HashMap(mMap);
2732 }
2733 }
2734
2735 public String getString(String key, String defValue) {
2736 synchronized (this) {
2737 String v = (String)mMap.get(key);
2738 return v != null ? v : defValue;
2739 }
2740 }
2741
2742 public int getInt(String key, int defValue) {
2743 synchronized (this) {
2744 Integer v = (Integer)mMap.get(key);
2745 return v != null ? v : defValue;
2746 }
2747 }
2748 public long getLong(String key, long defValue) {
2749 synchronized (this) {
2750 Long v = (Long) mMap.get(key);
2751 return v != null ? v : defValue;
2752 }
2753 }
2754 public float getFloat(String key, float defValue) {
2755 synchronized (this) {
2756 Float v = (Float)mMap.get(key);
2757 return v != null ? v : defValue;
2758 }
2759 }
2760 public boolean getBoolean(String key, boolean defValue) {
2761 synchronized (this) {
2762 Boolean v = (Boolean)mMap.get(key);
2763 return v != null ? v : defValue;
2764 }
2765 }
2766
2767 public boolean contains(String key) {
2768 synchronized (this) {
2769 return mMap.containsKey(key);
2770 }
2771 }
2772
2773 public final class EditorImpl implements Editor {
2774 private final Map<String, Object> mModified = Maps.newHashMap();
2775 private boolean mClear = false;
2776
2777 public Editor putString(String key, String value) {
2778 synchronized (this) {
2779 mModified.put(key, value);
2780 return this;
2781 }
2782 }
2783 public Editor putInt(String key, int value) {
2784 synchronized (this) {
2785 mModified.put(key, value);
2786 return this;
2787 }
2788 }
2789 public Editor putLong(String key, long value) {
2790 synchronized (this) {
2791 mModified.put(key, value);
2792 return this;
2793 }
2794 }
2795 public Editor putFloat(String key, float value) {
2796 synchronized (this) {
2797 mModified.put(key, value);
2798 return this;
2799 }
2800 }
2801 public Editor putBoolean(String key, boolean value) {
2802 synchronized (this) {
2803 mModified.put(key, value);
2804 return this;
2805 }
2806 }
2807
2808 public Editor remove(String key) {
2809 synchronized (this) {
2810 mModified.put(key, this);
2811 return this;
2812 }
2813 }
2814
2815 public Editor clear() {
2816 synchronized (this) {
2817 mClear = true;
2818 return this;
2819 }
2820 }
2821
2822 public boolean commit() {
2823 boolean returnValue;
2824
2825 boolean hasListeners;
2826 List<String> keysModified = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07002827 Set<OnSharedPreferenceChangeListener> listeners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828
2829 synchronized (SharedPreferencesImpl.this) {
2830 hasListeners = mListeners.size() > 0;
2831 if (hasListeners) {
2832 keysModified = new ArrayList<String>();
The Android Open Source Project10592532009-03-18 17:39:46 -07002833 listeners =
2834 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002835 }
2836
2837 synchronized (this) {
2838 if (mClear) {
2839 mMap.clear();
2840 mClear = false;
2841 }
2842
The Android Open Source Project10592532009-03-18 17:39:46 -07002843 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 String k = e.getKey();
2845 Object v = e.getValue();
2846 if (v == this) {
2847 mMap.remove(k);
2848 } else {
2849 mMap.put(k, v);
2850 }
2851
2852 if (hasListeners) {
2853 keysModified.add(k);
2854 }
2855 }
2856
2857 mModified.clear();
2858 }
2859
2860 returnValue = writeFileLocked();
2861 }
2862
2863 if (hasListeners) {
2864 for (int i = keysModified.size() - 1; i >= 0; i--) {
2865 final String key = keysModified.get(i);
The Android Open Source Project10592532009-03-18 17:39:46 -07002866 for (OnSharedPreferenceChangeListener listener : listeners) {
2867 if (listener != null) {
2868 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
2869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870 }
2871 }
2872 }
2873
2874 return returnValue;
2875 }
2876 }
2877
2878 public Editor edit() {
2879 return new EditorImpl();
2880 }
2881
2882 private FileOutputStream createFileOutputStream(File file) {
2883 FileOutputStream str = null;
2884 try {
2885 str = new FileOutputStream(file);
2886 } catch (FileNotFoundException e) {
2887 File parent = file.getParentFile();
2888 if (!parent.mkdir()) {
2889 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
2890 return null;
2891 }
2892 FileUtils.setPermissions(
2893 parent.getPath(),
2894 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2895 -1, -1);
2896 try {
2897 str = new FileOutputStream(file);
2898 } catch (FileNotFoundException e2) {
2899 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
2900 }
2901 }
2902 return str;
2903 }
2904
2905 private boolean writeFileLocked() {
2906 // Rename the current file so it may be used as a backup during the next read
2907 if (mFile.exists()) {
2908 if (!mFile.renameTo(mBackupFile)) {
2909 Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002910 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 }
2912 }
2913
2914 // Attempt to write the file, delete the backup and return true as atomically as
2915 // possible. If any exception occurs, delete the new file; next time we will restore
2916 // from the backup.
2917 try {
2918 FileOutputStream str = createFileOutputStream(mFile);
2919 if (str == null) {
2920 return false;
2921 }
2922 XmlUtils.writeMapXml(mMap, str);
2923 str.close();
2924 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
2925 if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2926 mTimestamp = mFileStatus.mtime;
2927 }
2928
Dianne Hackborn51bf0772009-03-24 19:11:41 -07002929 // Writing was successful, delete the backup file if there is one.
2930 mBackupFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002931 return true;
2932 } catch (XmlPullParserException e) {
2933 Log.w(TAG, "writeFileLocked: Got exception:", e);
2934 } catch (IOException e) {
2935 Log.w(TAG, "writeFileLocked: Got exception:", e);
2936 }
2937 // Clean up an unsuccessfully written file
2938 if (mFile.exists()) {
2939 if (!mFile.delete()) {
2940 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
2941 }
2942 }
2943 return false;
2944 }
2945 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946}