blob: 9b9cbd58cff8f518cbb3a1ed65b1578c0c154f81 [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 Mehatb1043402010-02-05 08:26:50 -080087import android.os.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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 private File mCacheDir;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800201 private File mExternalFilesDir;
202 private File mExternalCacheDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203
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
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800441 public File getExternalFilesDir(String type) {
442 synchronized (mSync) {
443 if (mExternalFilesDir == null) {
444 mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
445 getPackageName());
446 }
447 if (!mExternalFilesDir.exists()) {
448 try {
449 (new File(Environment.getExternalStorageAndroidDataDir(),
450 ".nomedia")).createNewFile();
451 } catch (IOException e) {
452 }
453 if (!mExternalFilesDir.mkdirs()) {
454 Log.w(TAG, "Unable to create external files directory");
455 return null;
456 }
457 }
458 if (type == null) {
459 return mExternalFilesDir;
460 }
461 File dir = new File(mExternalFilesDir, type);
462 if (!dir.exists()) {
463 if (!dir.mkdirs()) {
464 Log.w(TAG, "Unable to create external media directory " + dir);
465 return null;
466 }
467 }
468 return dir;
469 }
470 }
471
472 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 public File getCacheDir() {
474 synchronized (mSync) {
475 if (mCacheDir == null) {
476 mCacheDir = new File(getDataDirFile(), "cache");
477 }
478 if (!mCacheDir.exists()) {
479 if(!mCacheDir.mkdirs()) {
480 Log.w(TAG, "Unable to create cache directory");
481 return null;
482 }
483 FileUtils.setPermissions(
484 mCacheDir.getPath(),
485 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
486 -1, -1);
487 }
488 }
489 return mCacheDir;
490 }
491
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800492 @Override
493 public File getExternalCacheDir() {
494 synchronized (mSync) {
495 if (mExternalCacheDir == null) {
496 mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
497 getPackageName());
498 }
499 if (!mExternalCacheDir.exists()) {
500 try {
501 (new File(Environment.getExternalStorageAndroidDataDir(),
502 ".nomedia")).createNewFile();
503 } catch (IOException e) {
504 }
505 if (!mExternalCacheDir.mkdirs()) {
506 Log.w(TAG, "Unable to create external cache directory");
507 return null;
508 }
509 }
510 return mExternalCacheDir;
511 }
512 }
513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 @Override
515 public File getFileStreamPath(String name) {
516 return makeFilename(getFilesDir(), name);
517 }
518
519 @Override
520 public String[] fileList() {
521 final String[] list = getFilesDir().list();
522 return (list != null) ? list : EMPTY_FILE_LIST;
523 }
524
525 @Override
526 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800527 File f = validateFilePath(name, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
529 setFilePermissionsFromMode(f.getPath(), mode, 0);
530 return db;
531 }
532
533 @Override
534 public boolean deleteDatabase(String name) {
535 try {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800536 File f = validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 return f.delete();
538 } catch (Exception e) {
539 }
540 return false;
541 }
542
543 @Override
544 public File getDatabasePath(String name) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800545 return validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 }
547
548 @Override
549 public String[] databaseList() {
550 final String[] list = getDatabasesDir().list();
551 return (list != null) ? list : EMPTY_FILE_LIST;
552 }
553
554
555 private File getDatabasesDir() {
556 synchronized (mSync) {
557 if (mDatabasesDir == null) {
558 mDatabasesDir = new File(getDataDirFile(), "databases");
559 }
560 if (mDatabasesDir.getPath().equals("databases")) {
561 mDatabasesDir = new File("/data/system");
562 }
563 return mDatabasesDir;
564 }
565 }
566
567 @Override
568 public Drawable getWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700569 return getWallpaperManager().getDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571
572 @Override
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700573 public Drawable peekWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700574 return getWallpaperManager().peekDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 }
576
577 @Override
578 public int getWallpaperDesiredMinimumWidth() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700579 return getWallpaperManager().getDesiredMinimumWidth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 }
581
582 @Override
583 public int getWallpaperDesiredMinimumHeight() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700584 return getWallpaperManager().getDesiredMinimumHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800585 }
586
587 @Override
588 public void setWallpaper(Bitmap bitmap) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700589 getWallpaperManager().setBitmap(bitmap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591
592 @Override
593 public void setWallpaper(InputStream data) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700594 getWallpaperManager().setStream(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 }
596
597 @Override
598 public void clearWallpaper() throws IOException {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700599 getWallpaperManager().clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 }
601
602 @Override
603 public void startActivity(Intent intent) {
604 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
605 throw new AndroidRuntimeException(
606 "Calling startActivity() from outside of an Activity "
607 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
608 + " Is this really what you want?");
609 }
610 mMainThread.getInstrumentation().execStartActivity(
611 getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
612 }
613
614 @Override
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700615 public void startIntentSender(IntentSender intent,
616 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
617 throws IntentSender.SendIntentException {
618 try {
619 String resolvedType = null;
620 if (fillInIntent != null) {
621 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
622 }
623 int result = ActivityManagerNative.getDefault()
624 .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
625 fillInIntent, resolvedType, null, null,
626 0, flagsMask, flagsValues);
627 if (result == IActivityManager.START_CANCELED) {
628 throw new IntentSender.SendIntentException();
629 }
630 Instrumentation.checkStartActivityResult(result, null);
631 } catch (RemoteException e) {
632 }
633 }
634
635 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 public void sendBroadcast(Intent intent) {
637 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
638 try {
639 ActivityManagerNative.getDefault().broadcastIntent(
640 mMainThread.getApplicationThread(), intent, resolvedType, null,
641 Activity.RESULT_OK, null, null, null, false, false);
642 } catch (RemoteException e) {
643 }
644 }
645
646 @Override
647 public void sendBroadcast(Intent intent, String receiverPermission) {
648 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
649 try {
650 ActivityManagerNative.getDefault().broadcastIntent(
651 mMainThread.getApplicationThread(), intent, resolvedType, null,
652 Activity.RESULT_OK, null, null, receiverPermission, false, false);
653 } catch (RemoteException e) {
654 }
655 }
656
657 @Override
658 public void sendOrderedBroadcast(Intent intent,
659 String receiverPermission) {
660 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
661 try {
662 ActivityManagerNative.getDefault().broadcastIntent(
663 mMainThread.getApplicationThread(), intent, resolvedType, null,
664 Activity.RESULT_OK, null, null, receiverPermission, true, false);
665 } catch (RemoteException e) {
666 }
667 }
668
669 @Override
670 public void sendOrderedBroadcast(Intent intent,
671 String receiverPermission, BroadcastReceiver resultReceiver,
672 Handler scheduler, int initialCode, String initialData,
673 Bundle initialExtras) {
674 IIntentReceiver rd = null;
675 if (resultReceiver != null) {
676 if (mPackageInfo != null) {
677 if (scheduler == null) {
678 scheduler = mMainThread.getHandler();
679 }
680 rd = mPackageInfo.getReceiverDispatcher(
681 resultReceiver, getOuterContext(), scheduler,
682 mMainThread.getInstrumentation(), false);
683 } else {
684 if (scheduler == null) {
685 scheduler = mMainThread.getHandler();
686 }
687 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
688 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
689 }
690 }
691 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
692 try {
693 ActivityManagerNative.getDefault().broadcastIntent(
694 mMainThread.getApplicationThread(), intent, resolvedType, rd,
695 initialCode, initialData, initialExtras, receiverPermission,
696 true, false);
697 } catch (RemoteException e) {
698 }
699 }
700
701 @Override
702 public void sendStickyBroadcast(Intent intent) {
703 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
704 try {
705 ActivityManagerNative.getDefault().broadcastIntent(
706 mMainThread.getApplicationThread(), intent, resolvedType, null,
707 Activity.RESULT_OK, null, null, null, false, true);
708 } catch (RemoteException e) {
709 }
710 }
711
712 @Override
Dianne Hackbornefa199f2009-09-19 12:03:15 -0700713 public void sendStickyOrderedBroadcast(Intent intent,
714 BroadcastReceiver resultReceiver,
715 Handler scheduler, int initialCode, String initialData,
716 Bundle initialExtras) {
717 IIntentReceiver rd = null;
718 if (resultReceiver != null) {
719 if (mPackageInfo != null) {
720 if (scheduler == null) {
721 scheduler = mMainThread.getHandler();
722 }
723 rd = mPackageInfo.getReceiverDispatcher(
724 resultReceiver, getOuterContext(), scheduler,
725 mMainThread.getInstrumentation(), false);
726 } else {
727 if (scheduler == null) {
728 scheduler = mMainThread.getHandler();
729 }
730 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
731 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
732 }
733 }
734 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
735 try {
736 ActivityManagerNative.getDefault().broadcastIntent(
737 mMainThread.getApplicationThread(), intent, resolvedType, rd,
738 initialCode, initialData, initialExtras, null,
739 true, true);
740 } catch (RemoteException e) {
741 }
742 }
743
744 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 public void removeStickyBroadcast(Intent intent) {
746 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
747 if (resolvedType != null) {
748 intent = new Intent(intent);
749 intent.setDataAndType(intent.getData(), resolvedType);
750 }
751 try {
752 ActivityManagerNative.getDefault().unbroadcastIntent(
753 mMainThread.getApplicationThread(), intent);
754 } catch (RemoteException e) {
755 }
756 }
757
758 @Override
759 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
760 return registerReceiver(receiver, filter, null, null);
761 }
762
763 @Override
764 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
765 String broadcastPermission, Handler scheduler) {
766 return registerReceiverInternal(receiver, filter, broadcastPermission,
767 scheduler, getOuterContext());
768 }
769
770 private Intent registerReceiverInternal(BroadcastReceiver receiver,
771 IntentFilter filter, String broadcastPermission,
772 Handler scheduler, Context context) {
773 IIntentReceiver rd = null;
774 if (receiver != null) {
775 if (mPackageInfo != null && context != null) {
776 if (scheduler == null) {
777 scheduler = mMainThread.getHandler();
778 }
779 rd = mPackageInfo.getReceiverDispatcher(
780 receiver, context, scheduler,
781 mMainThread.getInstrumentation(), true);
782 } else {
783 if (scheduler == null) {
784 scheduler = mMainThread.getHandler();
785 }
786 rd = new ActivityThread.PackageInfo.ReceiverDispatcher(
787 receiver, context, scheduler, null, false).getIIntentReceiver();
788 }
789 }
790 try {
791 return ActivityManagerNative.getDefault().registerReceiver(
792 mMainThread.getApplicationThread(),
793 rd, filter, broadcastPermission);
794 } catch (RemoteException e) {
795 return null;
796 }
797 }
798
799 @Override
800 public void unregisterReceiver(BroadcastReceiver receiver) {
801 if (mPackageInfo != null) {
802 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
803 getOuterContext(), receiver);
804 try {
805 ActivityManagerNative.getDefault().unregisterReceiver(rd);
806 } catch (RemoteException e) {
807 }
808 } else {
809 throw new RuntimeException("Not supported in system context");
810 }
811 }
812
813 @Override
814 public ComponentName startService(Intent service) {
815 try {
816 ComponentName cn = ActivityManagerNative.getDefault().startService(
817 mMainThread.getApplicationThread(), service,
818 service.resolveTypeIfNeeded(getContentResolver()));
819 if (cn != null && cn.getPackageName().equals("!")) {
820 throw new SecurityException(
821 "Not allowed to start service " + service
822 + " without permission " + cn.getClassName());
823 }
824 return cn;
825 } catch (RemoteException e) {
826 return null;
827 }
828 }
829
830 @Override
831 public boolean stopService(Intent service) {
832 try {
833 int res = ActivityManagerNative.getDefault().stopService(
834 mMainThread.getApplicationThread(), service,
835 service.resolveTypeIfNeeded(getContentResolver()));
836 if (res < 0) {
837 throw new SecurityException(
838 "Not allowed to stop service " + service);
839 }
840 return res != 0;
841 } catch (RemoteException e) {
842 return false;
843 }
844 }
845
846 @Override
847 public boolean bindService(Intent service, ServiceConnection conn,
848 int flags) {
849 IServiceConnection sd;
850 if (mPackageInfo != null) {
851 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
852 mMainThread.getHandler(), flags);
853 } else {
854 throw new RuntimeException("Not supported in system context");
855 }
856 try {
857 int res = ActivityManagerNative.getDefault().bindService(
858 mMainThread.getApplicationThread(), getActivityToken(),
859 service, service.resolveTypeIfNeeded(getContentResolver()),
860 sd, flags);
861 if (res < 0) {
862 throw new SecurityException(
863 "Not allowed to bind to service " + service);
864 }
865 return res != 0;
866 } catch (RemoteException e) {
867 return false;
868 }
869 }
870
871 @Override
872 public void unbindService(ServiceConnection conn) {
873 if (mPackageInfo != null) {
874 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
875 getOuterContext(), conn);
876 try {
877 ActivityManagerNative.getDefault().unbindService(sd);
878 } catch (RemoteException e) {
879 }
880 } else {
881 throw new RuntimeException("Not supported in system context");
882 }
883 }
884
885 @Override
886 public boolean startInstrumentation(ComponentName className,
887 String profileFile, Bundle arguments) {
888 try {
889 return ActivityManagerNative.getDefault().startInstrumentation(
890 className, profileFile, 0, arguments, null);
891 } catch (RemoteException e) {
892 // System has crashed, nothing we can do.
893 }
894 return false;
895 }
896
897 @Override
898 public Object getSystemService(String name) {
899 if (WINDOW_SERVICE.equals(name)) {
900 return WindowManagerImpl.getDefault();
901 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
902 synchronized (mSync) {
903 LayoutInflater inflater = mLayoutInflater;
904 if (inflater != null) {
905 return inflater;
906 }
907 mLayoutInflater = inflater =
908 PolicyManager.makeNewLayoutInflater(getOuterContext());
909 return inflater;
910 }
911 } else if (ACTIVITY_SERVICE.equals(name)) {
912 return getActivityManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700913 } else if (INPUT_METHOD_SERVICE.equals(name)) {
914 return InputMethodManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 } else if (ALARM_SERVICE.equals(name)) {
916 return getAlarmManager();
Fred Quintana60307342009-03-24 22:48:12 -0700917 } else if (ACCOUNT_SERVICE.equals(name)) {
918 return getAccountManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 } else if (POWER_SERVICE.equals(name)) {
920 return getPowerManager();
921 } else if (CONNECTIVITY_SERVICE.equals(name)) {
922 return getConnectivityManager();
923 } else if (WIFI_SERVICE.equals(name)) {
924 return getWifiManager();
925 } else if (NOTIFICATION_SERVICE.equals(name)) {
926 return getNotificationManager();
927 } else if (KEYGUARD_SERVICE.equals(name)) {
928 return new KeyguardManager();
svetoslavganov75986cf2009-05-14 22:28:01 -0700929 } else if (ACCESSIBILITY_SERVICE.equals(name)) {
930 return AccessibilityManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 } else if (LOCATION_SERVICE.equals(name)) {
932 return getLocationManager();
933 } else if (SEARCH_SERVICE.equals(name)) {
934 return getSearchManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700935 } else if (SENSOR_SERVICE.equals(name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 return getSensorManager();
San Mehatc9d81752010-02-01 10:23:27 -0800937 } else if (STORAGE_SERVICE.equals(name)) {
938 return getStorageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 } else if (VIBRATOR_SERVICE.equals(name)) {
940 return getVibrator();
941 } else if (STATUS_BAR_SERVICE.equals(name)) {
942 synchronized (mSync) {
943 if (mStatusBarManager == null) {
944 mStatusBarManager = new StatusBarManager(getOuterContext());
945 }
946 return mStatusBarManager;
947 }
948 } else if (AUDIO_SERVICE.equals(name)) {
949 return getAudioManager();
950 } else if (TELEPHONY_SERVICE.equals(name)) {
951 return getTelephonyManager();
952 } else if (CLIPBOARD_SERVICE.equals(name)) {
953 return getClipboardManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700954 } else if (WALLPAPER_SERVICE.equals(name)) {
955 return getWallpaperManager();
Dan Egnor95240272009-10-27 18:23:39 -0700956 } else if (DROPBOX_SERVICE.equals(name)) {
Dan Egnorf18a01c2009-11-12 11:32:50 -0800957 return getDropBoxManager();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800958 } else if (DEVICE_POLICY_SERVICE.equals(name)) {
959 return getDevicePolicyManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 }
961
962 return null;
963 }
964
Fred Quintana60307342009-03-24 22:48:12 -0700965 private AccountManager getAccountManager() {
Fred Quintanae00a3112009-09-22 15:13:30 -0700966 synchronized (mSync) {
967 if (mAccountManager == null) {
Fred Quintana60307342009-03-24 22:48:12 -0700968 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
969 IAccountManager service = IAccountManager.Stub.asInterface(b);
Fred Quintanae00a3112009-09-22 15:13:30 -0700970 mAccountManager = new AccountManager(this, service);
Fred Quintana60307342009-03-24 22:48:12 -0700971 }
Fred Quintanae00a3112009-09-22 15:13:30 -0700972 return mAccountManager;
Fred Quintana60307342009-03-24 22:48:12 -0700973 }
Fred Quintana60307342009-03-24 22:48:12 -0700974 }
975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 private ActivityManager getActivityManager() {
977 synchronized (mSync) {
978 if (mActivityManager == null) {
979 mActivityManager = new ActivityManager(getOuterContext(),
980 mMainThread.getHandler());
981 }
982 }
983 return mActivityManager;
984 }
985
986 private AlarmManager getAlarmManager() {
987 synchronized (sSync) {
988 if (sAlarmManager == null) {
989 IBinder b = ServiceManager.getService(ALARM_SERVICE);
990 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
991 sAlarmManager = new AlarmManager(service);
992 }
993 }
994 return sAlarmManager;
995 }
996
997 private PowerManager getPowerManager() {
998 synchronized (sSync) {
999 if (sPowerManager == null) {
1000 IBinder b = ServiceManager.getService(POWER_SERVICE);
1001 IPowerManager service = IPowerManager.Stub.asInterface(b);
1002 sPowerManager = new PowerManager(service, mMainThread.getHandler());
1003 }
1004 }
1005 return sPowerManager;
1006 }
1007
1008 private ConnectivityManager getConnectivityManager()
1009 {
1010 synchronized (sSync) {
1011 if (sConnectivityManager == null) {
1012 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
1013 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
1014 sConnectivityManager = new ConnectivityManager(service);
1015 }
1016 }
1017 return sConnectivityManager;
1018 }
1019
1020 private WifiManager getWifiManager()
1021 {
1022 synchronized (sSync) {
1023 if (sWifiManager == null) {
1024 IBinder b = ServiceManager.getService(WIFI_SERVICE);
1025 IWifiManager service = IWifiManager.Stub.asInterface(b);
1026 sWifiManager = new WifiManager(service, mMainThread.getHandler());
1027 }
1028 }
1029 return sWifiManager;
1030 }
1031
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001032 private NotificationManager getNotificationManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 synchronized (mSync) {
1034 if (mNotificationManager == null) {
1035 mNotificationManager = new NotificationManager(
1036 new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
1037 mMainThread.getHandler());
1038 }
1039 }
1040 return mNotificationManager;
1041 }
1042
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001043 private WallpaperManager getWallpaperManager() {
1044 synchronized (mSync) {
1045 if (mWallpaperManager == null) {
1046 mWallpaperManager = new WallpaperManager(getOuterContext(),
1047 mMainThread.getHandler());
1048 }
1049 }
1050 return mWallpaperManager;
1051 }
1052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 private TelephonyManager getTelephonyManager() {
1054 synchronized (mSync) {
1055 if (mTelephonyManager == null) {
1056 mTelephonyManager = new TelephonyManager(getOuterContext());
1057 }
1058 }
1059 return mTelephonyManager;
1060 }
1061
1062 private ClipboardManager getClipboardManager() {
1063 synchronized (mSync) {
1064 if (mClipboardManager == null) {
1065 mClipboardManager = new ClipboardManager(getOuterContext(),
1066 mMainThread.getHandler());
1067 }
1068 }
1069 return mClipboardManager;
1070 }
1071
1072 private LocationManager getLocationManager() {
1073 synchronized (sSync) {
1074 if (sLocationManager == null) {
1075 IBinder b = ServiceManager.getService(LOCATION_SERVICE);
1076 ILocationManager service = ILocationManager.Stub.asInterface(b);
1077 sLocationManager = new LocationManager(service);
1078 }
1079 }
1080 return sLocationManager;
1081 }
1082
1083 private SearchManager getSearchManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 synchronized (mSync) {
1085 if (mSearchManager == null) {
1086 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
1087 }
1088 }
1089 return mSearchManager;
1090 }
1091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 private SensorManager getSensorManager() {
1093 synchronized (mSync) {
1094 if (mSensorManager == null) {
1095 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1096 }
1097 }
1098 return mSensorManager;
1099 }
1100
San Mehatc9d81752010-02-01 10:23:27 -08001101 private StorageManager getStorageManager() {
1102 synchronized (mSync) {
1103 if (mStorageManager == null) {
1104 try {
1105 mStorageManager = new StorageManager(mMainThread.getHandler().getLooper());
1106 } catch (RemoteException rex) {
1107 Log.e(TAG, "Failed to create StorageManager", rex);
1108 mStorageManager = null;
1109 }
1110 }
1111 }
1112 return mStorageManager;
1113 }
1114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 private Vibrator getVibrator() {
1116 synchronized (mSync) {
1117 if (mVibrator == null) {
1118 mVibrator = new Vibrator();
1119 }
1120 }
1121 return mVibrator;
1122 }
Dan Egnor95240272009-10-27 18:23:39 -07001123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 private AudioManager getAudioManager()
1125 {
1126 if (mAudioManager == null) {
1127 mAudioManager = new AudioManager(this);
1128 }
1129 return mAudioManager;
1130 }
1131
Dan Egnorf18a01c2009-11-12 11:32:50 -08001132 private DropBoxManager getDropBoxManager() {
Dan Egnor95240272009-10-27 18:23:39 -07001133 synchronized (mSync) {
Dan Egnorf18a01c2009-11-12 11:32:50 -08001134 if (mDropBoxManager == null) {
Dan Egnor95240272009-10-27 18:23:39 -07001135 IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
Dan Egnorf18a01c2009-11-12 11:32:50 -08001136 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1137 mDropBoxManager = new DropBoxManager(service);
Dan Egnor95240272009-10-27 18:23:39 -07001138 }
1139 }
Dan Egnorf18a01c2009-11-12 11:32:50 -08001140 return mDropBoxManager;
Dan Egnor95240272009-10-27 18:23:39 -07001141 }
1142
Dianne Hackbornd6847842010-01-12 18:14:19 -08001143 private DevicePolicyManager getDevicePolicyManager() {
1144 synchronized (mSync) {
1145 if (mDevicePolicyManager == null) {
1146 mDevicePolicyManager = new DevicePolicyManager(this,
1147 mMainThread.getHandler());
1148 }
1149 }
1150 return mDevicePolicyManager;
1151 }
1152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 @Override
1154 public int checkPermission(String permission, int pid, int uid) {
1155 if (permission == null) {
1156 throw new IllegalArgumentException("permission is null");
1157 }
1158
1159 if (!Process.supportsProcesses()) {
1160 return PackageManager.PERMISSION_GRANTED;
1161 }
1162 try {
1163 return ActivityManagerNative.getDefault().checkPermission(
1164 permission, pid, uid);
1165 } catch (RemoteException e) {
1166 return PackageManager.PERMISSION_DENIED;
1167 }
1168 }
1169
1170 @Override
1171 public int checkCallingPermission(String permission) {
1172 if (permission == null) {
1173 throw new IllegalArgumentException("permission is null");
1174 }
1175
1176 if (!Process.supportsProcesses()) {
1177 return PackageManager.PERMISSION_GRANTED;
1178 }
1179 int pid = Binder.getCallingPid();
1180 if (pid != Process.myPid()) {
1181 return checkPermission(permission, pid,
1182 Binder.getCallingUid());
1183 }
1184 return PackageManager.PERMISSION_DENIED;
1185 }
1186
1187 @Override
1188 public int checkCallingOrSelfPermission(String permission) {
1189 if (permission == null) {
1190 throw new IllegalArgumentException("permission is null");
1191 }
1192
1193 return checkPermission(permission, Binder.getCallingPid(),
1194 Binder.getCallingUid());
1195 }
1196
1197 private void enforce(
1198 String permission, int resultOfCheck,
1199 boolean selfToo, int uid, String message) {
1200 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1201 throw new SecurityException(
1202 (message != null ? (message + ": ") : "") +
1203 (selfToo
1204 ? "Neither user " + uid + " nor current process has "
1205 : "User " + uid + " does not have ") +
1206 permission +
1207 ".");
1208 }
1209 }
1210
1211 public void enforcePermission(
1212 String permission, int pid, int uid, String message) {
1213 enforce(permission,
1214 checkPermission(permission, pid, uid),
1215 false,
1216 uid,
1217 message);
1218 }
1219
1220 public void enforceCallingPermission(String permission, String message) {
1221 enforce(permission,
1222 checkCallingPermission(permission),
1223 false,
1224 Binder.getCallingUid(),
1225 message);
1226 }
1227
1228 public void enforceCallingOrSelfPermission(
1229 String permission, String message) {
1230 enforce(permission,
1231 checkCallingOrSelfPermission(permission),
1232 true,
1233 Binder.getCallingUid(),
1234 message);
1235 }
1236
1237 @Override
1238 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1239 try {
1240 ActivityManagerNative.getDefault().grantUriPermission(
1241 mMainThread.getApplicationThread(), toPackage, uri,
1242 modeFlags);
1243 } catch (RemoteException e) {
1244 }
1245 }
1246
1247 @Override
1248 public void revokeUriPermission(Uri uri, int modeFlags) {
1249 try {
1250 ActivityManagerNative.getDefault().revokeUriPermission(
1251 mMainThread.getApplicationThread(), uri,
1252 modeFlags);
1253 } catch (RemoteException e) {
1254 }
1255 }
1256
1257 @Override
1258 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1259 if (!Process.supportsProcesses()) {
1260 return PackageManager.PERMISSION_GRANTED;
1261 }
1262 try {
1263 return ActivityManagerNative.getDefault().checkUriPermission(
1264 uri, pid, uid, modeFlags);
1265 } catch (RemoteException e) {
1266 return PackageManager.PERMISSION_DENIED;
1267 }
1268 }
1269
1270 @Override
1271 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1272 if (!Process.supportsProcesses()) {
1273 return PackageManager.PERMISSION_GRANTED;
1274 }
1275 int pid = Binder.getCallingPid();
1276 if (pid != Process.myPid()) {
1277 return checkUriPermission(uri, pid,
1278 Binder.getCallingUid(), modeFlags);
1279 }
1280 return PackageManager.PERMISSION_DENIED;
1281 }
1282
1283 @Override
1284 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1285 return checkUriPermission(uri, Binder.getCallingPid(),
1286 Binder.getCallingUid(), modeFlags);
1287 }
1288
1289 @Override
1290 public int checkUriPermission(Uri uri, String readPermission,
1291 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001292 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1294 + readPermission + " writePermission=" + writePermission
1295 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1296 }
1297 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1298 if (readPermission == null
1299 || checkPermission(readPermission, pid, uid)
1300 == PackageManager.PERMISSION_GRANTED) {
1301 return PackageManager.PERMISSION_GRANTED;
1302 }
1303 }
1304 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1305 if (writePermission == null
1306 || checkPermission(writePermission, pid, uid)
1307 == PackageManager.PERMISSION_GRANTED) {
1308 return PackageManager.PERMISSION_GRANTED;
1309 }
1310 }
1311 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1312 : PackageManager.PERMISSION_DENIED;
1313 }
1314
1315 private String uriModeFlagToString(int uriModeFlags) {
1316 switch (uriModeFlags) {
1317 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1318 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1319 return "read and write";
1320 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1321 return "read";
1322 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1323 return "write";
1324 }
1325 throw new IllegalArgumentException(
1326 "Unknown permission mode flags: " + uriModeFlags);
1327 }
1328
1329 private void enforceForUri(
1330 int modeFlags, int resultOfCheck, boolean selfToo,
1331 int uid, Uri uri, String message) {
1332 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1333 throw new SecurityException(
1334 (message != null ? (message + ": ") : "") +
1335 (selfToo
1336 ? "Neither user " + uid + " nor current process has "
1337 : "User " + uid + " does not have ") +
1338 uriModeFlagToString(modeFlags) +
1339 " permission on " +
1340 uri +
1341 ".");
1342 }
1343 }
1344
1345 public void enforceUriPermission(
1346 Uri uri, int pid, int uid, int modeFlags, String message) {
1347 enforceForUri(
1348 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1349 false, uid, uri, message);
1350 }
1351
1352 public void enforceCallingUriPermission(
1353 Uri uri, int modeFlags, String message) {
1354 enforceForUri(
1355 modeFlags, checkCallingUriPermission(uri, modeFlags),
1356 false, Binder.getCallingUid(), uri, message);
1357 }
1358
1359 public void enforceCallingOrSelfUriPermission(
1360 Uri uri, int modeFlags, String message) {
1361 enforceForUri(
1362 modeFlags,
1363 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1364 Binder.getCallingUid(), uri, message);
1365 }
1366
1367 public void enforceUriPermission(
1368 Uri uri, String readPermission, String writePermission,
1369 int pid, int uid, int modeFlags, String message) {
1370 enforceForUri(modeFlags,
1371 checkUriPermission(
1372 uri, readPermission, writePermission, pid, uid,
1373 modeFlags),
1374 false,
1375 uid,
1376 uri,
1377 message);
1378 }
1379
1380 @Override
1381 public Context createPackageContext(String packageName, int flags)
1382 throws PackageManager.NameNotFoundException {
1383 if (packageName.equals("system") || packageName.equals("android")) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001384 return new ContextImpl(mMainThread.getSystemContext());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
1386
1387 ActivityThread.PackageInfo pi =
1388 mMainThread.getPackageInfo(packageName, flags);
1389 if (pi != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001390 ContextImpl c = new ContextImpl();
Romain Guy870e09f2009-07-06 16:35:25 -07001391 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001392 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 if (c.mResources != null) {
1394 return c;
1395 }
1396 }
1397
1398 // Should be a better exception.
1399 throw new PackageManager.NameNotFoundException(
1400 "Application package " + packageName + " not found");
1401 }
1402
Romain Guy870e09f2009-07-06 16:35:25 -07001403 @Override
1404 public boolean isRestricted() {
1405 return mRestricted;
1406 }
1407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 private File getDataDirFile() {
1409 if (mPackageInfo != null) {
1410 return mPackageInfo.getDataDirFile();
1411 }
1412 throw new RuntimeException("Not supported in system context");
1413 }
1414
1415 @Override
1416 public File getDir(String name, int mode) {
1417 name = "app_" + name;
1418 File file = makeFilename(getDataDirFile(), name);
1419 if (!file.exists()) {
1420 file.mkdir();
1421 setFilePermissionsFromMode(file.getPath(), mode,
1422 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1423 }
1424 return file;
1425 }
1426
Dianne Hackborn21556372010-02-04 16:34:40 -08001427 static ContextImpl createSystemContext(ActivityThread mainThread) {
1428 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 context.init(Resources.getSystem(), mainThread);
1430 return context;
1431 }
1432
Dianne Hackborn21556372010-02-04 16:34:40 -08001433 ContextImpl() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 ++sInstanceCount;
1435 mOuterContext = this;
1436 }
1437
1438 /**
1439 * Create a new ApplicationContext from an existing one. The new one
1440 * works and operates the same as the one it is copying.
1441 *
1442 * @param context Existing application context.
1443 */
Dianne Hackborn21556372010-02-04 16:34:40 -08001444 public ContextImpl(ContextImpl context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 ++sInstanceCount;
1446 mPackageInfo = context.mPackageInfo;
1447 mResources = context.mResources;
1448 mMainThread = context.mMainThread;
1449 mContentResolver = context.mContentResolver;
1450 mOuterContext = this;
1451 }
1452
1453 final void init(ActivityThread.PackageInfo packageInfo,
1454 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001455 init(packageInfo, activityToken, mainThread, null);
1456 }
1457
1458 final void init(ActivityThread.PackageInfo packageInfo,
1459 IBinder activityToken, ActivityThread mainThread,
1460 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 mPackageInfo = packageInfo;
1462 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001463
1464 if (container != null && container.getCompatibilityInfo().applicationScale !=
1465 mResources.getCompatibilityInfo().applicationScale) {
1466 if (DEBUG) {
1467 Log.d(TAG, "loaded context has different scaling. Using container's" +
1468 " compatiblity info:" + container.getDisplayMetrics());
1469 }
1470 mResources = mainThread.getTopLevelResources(
1471 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 mMainThread = mainThread;
1474 mContentResolver = new ApplicationContentResolver(this, mainThread);
1475
1476 setActivityToken(activityToken);
1477 }
1478
1479 final void init(Resources resources, ActivityThread mainThread) {
1480 mPackageInfo = null;
1481 mResources = resources;
1482 mMainThread = mainThread;
1483 mContentResolver = new ApplicationContentResolver(this, mainThread);
1484 }
1485
1486 final void scheduleFinalCleanup(String who, String what) {
1487 mMainThread.scheduleContextCleanup(this, who, what);
1488 }
1489
1490 final void performFinalCleanup(String who, String what) {
1491 //Log.i(TAG, "Cleanup up context: " + this);
1492 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1493 }
1494
1495 final Context getReceiverRestrictedContext() {
1496 if (mReceiverRestrictedContext != null) {
1497 return mReceiverRestrictedContext;
1498 }
1499 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1500 }
1501
1502 final void setActivityToken(IBinder token) {
1503 mActivityToken = token;
1504 }
1505
1506 final void setOuterContext(Context context) {
1507 mOuterContext = context;
1508 }
1509
1510 final Context getOuterContext() {
1511 return mOuterContext;
1512 }
1513
1514 final IBinder getActivityToken() {
1515 return mActivityToken;
1516 }
1517
1518 private static void setFilePermissionsFromMode(String name, int mode,
1519 int extraPermissions) {
1520 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1521 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1522 |extraPermissions;
1523 if ((mode&MODE_WORLD_READABLE) != 0) {
1524 perms |= FileUtils.S_IROTH;
1525 }
1526 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1527 perms |= FileUtils.S_IWOTH;
1528 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001529 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1531 + ", perms=0x" + Integer.toHexString(perms));
1532 }
1533 FileUtils.setPermissions(name, perms, -1, -1);
1534 }
1535
Oscar Montemayora8529f62009-11-18 10:14:20 -08001536 private File validateFilePath(String name, boolean createDirectory) {
1537 File dir;
1538 File f;
1539
1540 if (name.charAt(0) == File.separatorChar) {
1541 String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1542 dir = new File(dirPath);
1543 name = name.substring(name.lastIndexOf(File.separatorChar));
1544 f = new File(dir, name);
1545 } else {
1546 dir = getDatabasesDir();
1547 f = makeFilename(dir, name);
1548 }
1549
1550 if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1551 FileUtils.setPermissions(dir.getPath(),
1552 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1553 -1, -1);
1554 }
1555
1556 return f;
1557 }
1558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 private File makeFilename(File base, String name) {
1560 if (name.indexOf(File.separatorChar) < 0) {
1561 return new File(base, name);
1562 }
1563 throw new IllegalArgumentException(
Oscar Montemayora8529f62009-11-18 10:14:20 -08001564 "File " + name + " contains a path separator");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 }
1566
1567 // ----------------------------------------------------------------------
1568 // ----------------------------------------------------------------------
1569 // ----------------------------------------------------------------------
1570
1571 private static final class ApplicationContentResolver extends ContentResolver {
1572 public ApplicationContentResolver(Context context,
1573 ActivityThread mainThread)
1574 {
1575 super(context);
1576 mMainThread = mainThread;
1577 }
1578
1579 @Override
1580 protected IContentProvider acquireProvider(Context context, String name)
1581 {
1582 return mMainThread.acquireProvider(context, name);
1583 }
1584
1585 @Override
1586 public boolean releaseProvider(IContentProvider provider)
1587 {
1588 return mMainThread.releaseProvider(provider);
1589 }
1590
1591 private final ActivityThread mMainThread;
1592 }
1593
1594 // ----------------------------------------------------------------------
1595 // ----------------------------------------------------------------------
1596 // ----------------------------------------------------------------------
1597
1598 /*package*/
1599 static final class ApplicationPackageManager extends PackageManager {
1600 @Override
1601 public PackageInfo getPackageInfo(String packageName, int flags)
1602 throws NameNotFoundException {
1603 try {
1604 PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1605 if (pi != null) {
1606 return pi;
1607 }
1608 } catch (RemoteException e) {
1609 throw new RuntimeException("Package manager has died", e);
1610 }
1611
1612 throw new NameNotFoundException(packageName);
1613 }
1614
Mihai Predaeae850c2009-05-13 10:13:48 +02001615 @Override
1616 public Intent getLaunchIntentForPackage(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 // First see if the package has an INFO activity; the existence of
1618 // such an activity is implied to be the desired front-door for the
1619 // overall package (such as if it has multiple launcher entries).
Mihai Predaeae850c2009-05-13 10:13:48 +02001620 Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1621 intentToResolve.addCategory(Intent.CATEGORY_INFO);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001622 intentToResolve.setPackage(packageName);
1623 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
Mihai Predaeae850c2009-05-13 10:13:48 +02001624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 // Otherwise, try to find a main launcher activity.
Mihai Predaeae850c2009-05-13 10:13:48 +02001626 if (resolveInfo == null) {
1627 // reuse the intent instance
1628 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1629 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001630 intentToResolve.setPackage(packageName);
1631 resolveInfo = resolveActivity(intentToResolve, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001633 if (resolveInfo == null) {
1634 return null;
1635 }
1636 Intent intent = new Intent(Intent.ACTION_MAIN);
1637 intent.setClassName(packageName, resolveInfo.activityInfo.name);
1638 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1639 return intent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 @Override
1643 public int[] getPackageGids(String packageName)
1644 throws NameNotFoundException {
1645 try {
1646 int[] gids = mPM.getPackageGids(packageName);
1647 if (gids == null || gids.length > 0) {
1648 return gids;
1649 }
1650 } catch (RemoteException e) {
1651 throw new RuntimeException("Package manager has died", e);
1652 }
1653
1654 throw new NameNotFoundException(packageName);
1655 }
1656
1657 @Override
1658 public PermissionInfo getPermissionInfo(String name, int flags)
1659 throws NameNotFoundException {
1660 try {
1661 PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1662 if (pi != null) {
1663 return pi;
1664 }
1665 } catch (RemoteException e) {
1666 throw new RuntimeException("Package manager has died", e);
1667 }
1668
1669 throw new NameNotFoundException(name);
1670 }
1671
1672 @Override
1673 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1674 throws NameNotFoundException {
1675 try {
1676 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1677 if (pi != null) {
1678 return pi;
1679 }
1680 } catch (RemoteException e) {
1681 throw new RuntimeException("Package manager has died", e);
1682 }
1683
1684 throw new NameNotFoundException(group);
1685 }
1686
1687 @Override
1688 public PermissionGroupInfo getPermissionGroupInfo(String name,
1689 int flags) throws NameNotFoundException {
1690 try {
1691 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1692 if (pgi != null) {
1693 return pgi;
1694 }
1695 } catch (RemoteException e) {
1696 throw new RuntimeException("Package manager has died", e);
1697 }
1698
1699 throw new NameNotFoundException(name);
1700 }
1701
1702 @Override
1703 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1704 try {
1705 return mPM.getAllPermissionGroups(flags);
1706 } catch (RemoteException e) {
1707 throw new RuntimeException("Package manager has died", e);
1708 }
1709 }
1710
1711 @Override
1712 public ApplicationInfo getApplicationInfo(String packageName, int flags)
1713 throws NameNotFoundException {
1714 try {
1715 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
1716 if (ai != null) {
1717 return ai;
1718 }
1719 } catch (RemoteException e) {
1720 throw new RuntimeException("Package manager has died", e);
1721 }
1722
1723 throw new NameNotFoundException(packageName);
1724 }
1725
1726 @Override
1727 public ActivityInfo getActivityInfo(ComponentName className, int flags)
1728 throws NameNotFoundException {
1729 try {
1730 ActivityInfo ai = mPM.getActivityInfo(className, flags);
1731 if (ai != null) {
1732 return ai;
1733 }
1734 } catch (RemoteException e) {
1735 throw new RuntimeException("Package manager has died", e);
1736 }
1737
1738 throw new NameNotFoundException(className.toString());
1739 }
1740
1741 @Override
1742 public ActivityInfo getReceiverInfo(ComponentName className, int flags)
1743 throws NameNotFoundException {
1744 try {
1745 ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1746 if (ai != null) {
1747 return ai;
1748 }
1749 } catch (RemoteException e) {
1750 throw new RuntimeException("Package manager has died", e);
1751 }
1752
1753 throw new NameNotFoundException(className.toString());
1754 }
1755
1756 @Override
1757 public ServiceInfo getServiceInfo(ComponentName className, int flags)
1758 throws NameNotFoundException {
1759 try {
1760 ServiceInfo si = mPM.getServiceInfo(className, flags);
1761 if (si != null) {
1762 return si;
1763 }
1764 } catch (RemoteException e) {
1765 throw new RuntimeException("Package manager has died", e);
1766 }
1767
1768 throw new NameNotFoundException(className.toString());
1769 }
1770
1771 @Override
1772 public String[] getSystemSharedLibraryNames() {
1773 try {
1774 return mPM.getSystemSharedLibraryNames();
1775 } catch (RemoteException e) {
1776 throw new RuntimeException("Package manager has died", e);
1777 }
1778 }
1779
1780 @Override
Dianne Hackborn49237342009-08-27 20:08:01 -07001781 public FeatureInfo[] getSystemAvailableFeatures() {
1782 try {
1783 return mPM.getSystemAvailableFeatures();
1784 } catch (RemoteException e) {
1785 throw new RuntimeException("Package manager has died", e);
1786 }
1787 }
1788
1789 @Override
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001790 public boolean hasSystemFeature(String name) {
1791 try {
1792 return mPM.hasSystemFeature(name);
1793 } catch (RemoteException e) {
1794 throw new RuntimeException("Package manager has died", e);
1795 }
1796 }
1797
1798 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 public int checkPermission(String permName, String pkgName) {
1800 try {
1801 return mPM.checkPermission(permName, pkgName);
1802 } catch (RemoteException e) {
1803 throw new RuntimeException("Package manager has died", e);
1804 }
1805 }
1806
1807 @Override
1808 public boolean addPermission(PermissionInfo info) {
1809 try {
1810 return mPM.addPermission(info);
1811 } catch (RemoteException e) {
1812 throw new RuntimeException("Package manager has died", e);
1813 }
1814 }
1815
1816 @Override
1817 public void removePermission(String name) {
1818 try {
1819 mPM.removePermission(name);
1820 } catch (RemoteException e) {
1821 throw new RuntimeException("Package manager has died", e);
1822 }
1823 }
1824
1825 @Override
1826 public int checkSignatures(String pkg1, String pkg2) {
1827 try {
1828 return mPM.checkSignatures(pkg1, pkg2);
1829 } catch (RemoteException e) {
1830 throw new RuntimeException("Package manager has died", e);
1831 }
1832 }
1833
1834 @Override
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001835 public int checkSignatures(int uid1, int uid2) {
1836 try {
1837 return mPM.checkUidSignatures(uid1, uid2);
1838 } catch (RemoteException e) {
1839 throw new RuntimeException("Package manager has died", e);
1840 }
1841 }
1842
1843 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 public String[] getPackagesForUid(int uid) {
1845 try {
1846 return mPM.getPackagesForUid(uid);
1847 } catch (RemoteException e) {
1848 throw new RuntimeException("Package manager has died", e);
1849 }
1850 }
1851
1852 @Override
1853 public String getNameForUid(int uid) {
1854 try {
1855 return mPM.getNameForUid(uid);
1856 } catch (RemoteException e) {
1857 throw new RuntimeException("Package manager has died", e);
1858 }
1859 }
1860
1861 @Override
1862 public int getUidForSharedUser(String sharedUserName)
1863 throws NameNotFoundException {
1864 try {
1865 int uid = mPM.getUidForSharedUser(sharedUserName);
1866 if(uid != -1) {
1867 return uid;
1868 }
1869 } catch (RemoteException e) {
1870 throw new RuntimeException("Package manager has died", e);
1871 }
1872 throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1873 }
1874
1875 @Override
1876 public List<PackageInfo> getInstalledPackages(int flags) {
1877 try {
1878 return mPM.getInstalledPackages(flags);
1879 } catch (RemoteException e) {
1880 throw new RuntimeException("Package manager has died", e);
1881 }
1882 }
1883
1884 @Override
1885 public List<ApplicationInfo> getInstalledApplications(int flags) {
1886 try {
1887 return mPM.getInstalledApplications(flags);
1888 } catch (RemoteException e) {
1889 throw new RuntimeException("Package manager has died", e);
1890 }
1891 }
1892
1893 @Override
1894 public ResolveInfo resolveActivity(Intent intent, int flags) {
1895 try {
1896 return mPM.resolveIntent(
1897 intent,
1898 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1899 flags);
1900 } catch (RemoteException e) {
1901 throw new RuntimeException("Package manager has died", e);
1902 }
1903 }
1904
1905 @Override
1906 public List<ResolveInfo> queryIntentActivities(Intent intent,
1907 int flags) {
1908 try {
1909 return mPM.queryIntentActivities(
1910 intent,
1911 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1912 flags);
1913 } catch (RemoteException e) {
1914 throw new RuntimeException("Package manager has died", e);
1915 }
1916 }
1917
1918 @Override
1919 public List<ResolveInfo> queryIntentActivityOptions(
1920 ComponentName caller, Intent[] specifics, Intent intent,
1921 int flags) {
1922 final ContentResolver resolver = mContext.getContentResolver();
1923
1924 String[] specificTypes = null;
1925 if (specifics != null) {
1926 final int N = specifics.length;
1927 for (int i=0; i<N; i++) {
1928 Intent sp = specifics[i];
1929 if (sp != null) {
1930 String t = sp.resolveTypeIfNeeded(resolver);
1931 if (t != null) {
1932 if (specificTypes == null) {
1933 specificTypes = new String[N];
1934 }
1935 specificTypes[i] = t;
1936 }
1937 }
1938 }
1939 }
1940
1941 try {
1942 return mPM.queryIntentActivityOptions(caller, specifics,
1943 specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
1944 flags);
1945 } catch (RemoteException e) {
1946 throw new RuntimeException("Package manager has died", e);
1947 }
1948 }
1949
1950 @Override
1951 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
1952 try {
1953 return mPM.queryIntentReceivers(
1954 intent,
1955 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1956 flags);
1957 } catch (RemoteException e) {
1958 throw new RuntimeException("Package manager has died", e);
1959 }
1960 }
1961
1962 @Override
1963 public ResolveInfo resolveService(Intent intent, int flags) {
1964 try {
1965 return mPM.resolveService(
1966 intent,
1967 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1968 flags);
1969 } catch (RemoteException e) {
1970 throw new RuntimeException("Package manager has died", e);
1971 }
1972 }
1973
1974 @Override
1975 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
1976 try {
1977 return mPM.queryIntentServices(
1978 intent,
1979 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1980 flags);
1981 } catch (RemoteException e) {
1982 throw new RuntimeException("Package manager has died", e);
1983 }
1984 }
1985
1986 @Override
1987 public ProviderInfo resolveContentProvider(String name,
1988 int flags) {
1989 try {
1990 return mPM.resolveContentProvider(name, flags);
1991 } catch (RemoteException e) {
1992 throw new RuntimeException("Package manager has died", e);
1993 }
1994 }
1995
1996 @Override
1997 public List<ProviderInfo> queryContentProviders(String processName,
1998 int uid, int flags) {
1999 try {
2000 return mPM.queryContentProviders(processName, uid, flags);
2001 } catch (RemoteException e) {
2002 throw new RuntimeException("Package manager has died", e);
2003 }
2004 }
2005
2006 @Override
2007 public InstrumentationInfo getInstrumentationInfo(
2008 ComponentName className, int flags)
2009 throws NameNotFoundException {
2010 try {
2011 InstrumentationInfo ii = mPM.getInstrumentationInfo(
2012 className, flags);
2013 if (ii != null) {
2014 return ii;
2015 }
2016 } catch (RemoteException e) {
2017 throw new RuntimeException("Package manager has died", e);
2018 }
2019
2020 throw new NameNotFoundException(className.toString());
2021 }
2022
2023 @Override
2024 public List<InstrumentationInfo> queryInstrumentation(
2025 String targetPackage, int flags) {
2026 try {
2027 return mPM.queryInstrumentation(targetPackage, flags);
2028 } catch (RemoteException e) {
2029 throw new RuntimeException("Package manager has died", e);
2030 }
2031 }
2032
2033 @Override public Drawable getDrawable(String packageName, int resid,
2034 ApplicationInfo appInfo) {
2035 ResourceName name = new ResourceName(packageName, resid);
2036 Drawable dr = getCachedIcon(name);
2037 if (dr != null) {
2038 return dr;
2039 }
2040 if (appInfo == null) {
2041 try {
2042 appInfo = getApplicationInfo(packageName, 0);
2043 } catch (NameNotFoundException e) {
2044 return null;
2045 }
2046 }
2047 try {
2048 Resources r = getResourcesForApplication(appInfo);
2049 dr = r.getDrawable(resid);
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002050 if (false) {
2051 RuntimeException e = new RuntimeException("here");
2052 e.fillInStackTrace();
2053 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
2054 + " from package " + packageName
2055 + ": app scale=" + r.getCompatibilityInfo().applicationScale
2056 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
2057 e);
2058 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2060 + Integer.toHexString(resid) + " from " + r
2061 + ": " + dr);
2062 putCachedIcon(name, dr);
2063 return dr;
2064 } catch (NameNotFoundException e) {
2065 Log.w("PackageManager", "Failure retrieving resources for"
2066 + appInfo.packageName);
2067 } catch (RuntimeException e) {
2068 // If an exception was thrown, fall through to return
2069 // default icon.
2070 Log.w("PackageManager", "Failure retrieving icon 0x"
2071 + Integer.toHexString(resid) + " in package "
2072 + packageName, e);
2073 }
2074 return null;
2075 }
2076
2077 @Override public Drawable getActivityIcon(ComponentName activityName)
2078 throws NameNotFoundException {
2079 return getActivityInfo(activityName, 0).loadIcon(this);
2080 }
2081
2082 @Override public Drawable getActivityIcon(Intent intent)
2083 throws NameNotFoundException {
2084 if (intent.getComponent() != null) {
2085 return getActivityIcon(intent.getComponent());
2086 }
2087
2088 ResolveInfo info = resolveActivity(
2089 intent, PackageManager.MATCH_DEFAULT_ONLY);
2090 if (info != null) {
2091 return info.activityInfo.loadIcon(this);
2092 }
2093
2094 throw new NameNotFoundException(intent.toURI());
2095 }
2096
2097 @Override public Drawable getDefaultActivityIcon() {
2098 return Resources.getSystem().getDrawable(
2099 com.android.internal.R.drawable.sym_def_app_icon);
2100 }
2101
2102 @Override public Drawable getApplicationIcon(ApplicationInfo info) {
2103 final int icon = info.icon;
2104 if (icon != 0) {
2105 ResourceName name = new ResourceName(info, icon);
2106 Drawable dr = getCachedIcon(name);
2107 if (dr != null) {
2108 return dr;
2109 }
2110 try {
2111 Resources r = getResourcesForApplication(info);
2112 dr = r.getDrawable(icon);
2113 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2114 + Integer.toHexString(icon) + " from " + r
2115 + ": " + dr);
2116 putCachedIcon(name, dr);
2117 return dr;
2118 } catch (NameNotFoundException e) {
2119 Log.w("PackageManager", "Failure retrieving resources for"
2120 + info.packageName);
2121 } catch (RuntimeException e) {
2122 // If an exception was thrown, fall through to return
2123 // default icon.
2124 Log.w("PackageManager", "Failure retrieving app icon", e);
2125 }
2126 }
2127 return getDefaultActivityIcon();
2128 }
2129
2130 @Override public Drawable getApplicationIcon(String packageName)
2131 throws NameNotFoundException {
2132 return getApplicationIcon(getApplicationInfo(packageName, 0));
2133 }
2134
2135 @Override public Resources getResourcesForActivity(
2136 ComponentName activityName) throws NameNotFoundException {
2137 return getResourcesForApplication(
2138 getActivityInfo(activityName, 0).applicationInfo);
2139 }
2140
2141 @Override public Resources getResourcesForApplication(
2142 ApplicationInfo app) throws NameNotFoundException {
2143 if (app.packageName.equals("system")) {
2144 return mContext.mMainThread.getSystemContext().getResources();
2145 }
2146 Resources r = mContext.mMainThread.getTopLevelResources(
2147 app.uid == Process.myUid() ? app.sourceDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002148 : app.publicSourceDir, mContext.mPackageInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 if (r != null) {
2150 return r;
2151 }
2152 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2153 }
2154
2155 @Override public Resources getResourcesForApplication(
2156 String appPackageName) throws NameNotFoundException {
2157 return getResourcesForApplication(
2158 getApplicationInfo(appPackageName, 0));
2159 }
2160
2161 int mCachedSafeMode = -1;
2162 @Override public boolean isSafeMode() {
2163 try {
2164 if (mCachedSafeMode < 0) {
2165 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2166 }
2167 return mCachedSafeMode != 0;
2168 } catch (RemoteException e) {
2169 throw new RuntimeException("Package manager has died", e);
2170 }
2171 }
2172
2173 static void configurationChanged() {
2174 synchronized (sSync) {
2175 sIconCache.clear();
2176 sStringCache.clear();
2177 }
2178 }
2179
Dianne Hackborn21556372010-02-04 16:34:40 -08002180 ApplicationPackageManager(ContextImpl context,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 IPackageManager pm) {
2182 mContext = context;
2183 mPM = pm;
2184 }
2185
2186 private Drawable getCachedIcon(ResourceName name) {
2187 synchronized (sSync) {
2188 WeakReference<Drawable> wr = sIconCache.get(name);
2189 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2190 + name + ": " + wr);
2191 if (wr != null) { // we have the activity
2192 Drawable dr = wr.get();
2193 if (dr != null) {
2194 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2195 + name + ": " + dr);
2196 return dr;
2197 }
2198 // our entry has been purged
2199 sIconCache.remove(name);
2200 }
2201 }
2202 return null;
2203 }
2204
2205 private void establishPackageRemovedReceiver() {
2206 // mContext.registerReceiverInternal() winds up acquiring the
2207 // main ActivityManagerService.this lock. If we hold our usual
2208 // sSync global lock at the same time, we impose a required ordering
2209 // on those two locks, which is not good for deadlock prevention.
2210 // Use a dedicated lock around initialization of
2211 // sPackageRemovedReceiver to avoid this.
2212 synchronized (sPackageRemovedSync) {
2213 if (sPackageRemovedReceiver == null) {
2214 sPackageRemovedReceiver = new PackageRemovedReceiver();
2215 IntentFilter filter = new IntentFilter(
2216 Intent.ACTION_PACKAGE_REMOVED);
2217 filter.addDataScheme("package");
2218 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2219 filter, null, null, null);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002220 // Register for events related to sdcard installation.
2221 IntentFilter sdFilter = new IntentFilter();
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08002222 sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002223 mContext.registerReceiverInternal(sPackageRemovedReceiver,
2224 sdFilter, null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 }
2226 }
2227 }
2228
2229 private void putCachedIcon(ResourceName name, Drawable dr) {
2230 establishPackageRemovedReceiver();
2231
2232 synchronized (sSync) {
2233 sIconCache.put(name, new WeakReference<Drawable>(dr));
2234 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2235 + name + ": " + dr);
2236 }
2237 }
2238
2239 private static final class PackageRemovedReceiver extends BroadcastReceiver {
2240 @Override
2241 public void onReceive(Context context, Intent intent) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002242 String pkgList[] = null;
2243 String action = intent.getAction();
2244 boolean immediateGc = false;
Suchi Amalapurapub56ae202010-02-04 22:51:07 -08002245 if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002246 pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
2247 immediateGc = true;
2248 } else {
2249 Uri data = intent.getData();
2250 if (data != null) {
2251 String ssp = data.getSchemeSpecificPart();
2252 if (ssp != null) {
2253 pkgList = new String[] { ssp };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 }
2255 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002256 }
2257 if (pkgList != null && (pkgList.length > 0)) {
2258 boolean needCleanup = false;
2259 boolean hasPkgInfo = false;
2260 for (String ssp : pkgList) {
2261 synchronized (sSync) {
2262 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2263 while (it.hasNext()) {
2264 ResourceName nm = it.next();
2265 if (nm.packageName.equals(ssp)) {
2266 //Log.i(TAG, "Removing cached drawable for " + nm);
2267 it.remove();
2268 needCleanup = true;
2269 }
2270 }
2271 it = sStringCache.keySet().iterator();
2272 while (it.hasNext()) {
2273 ResourceName nm = it.next();
2274 if (nm.packageName.equals(ssp)) {
2275 //Log.i(TAG, "Removing cached string for " + nm);
2276 it.remove();
2277 needCleanup = true;
2278 }
2279 }
2280 }
2281 if (!hasPkgInfo) {
2282 hasPkgInfo = ActivityThread.currentActivityThread().hasPackageInfo(ssp);
2283 }
2284 }
2285 if (needCleanup || hasPkgInfo) {
2286 if (immediateGc) {
2287 // Schedule an immediate gc.
2288 Runtime.getRuntime().gc();
2289 } else {
2290 ActivityThread.currentActivityThread().scheduleGcIdler();
2291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 }
2293 }
2294 }
2295 }
2296
2297 private static final class ResourceName {
2298 final String packageName;
2299 final int iconId;
2300
2301 ResourceName(String _packageName, int _iconId) {
2302 packageName = _packageName;
2303 iconId = _iconId;
2304 }
2305
2306 ResourceName(ApplicationInfo aInfo, int _iconId) {
2307 this(aInfo.packageName, _iconId);
2308 }
2309
2310 ResourceName(ComponentInfo cInfo, int _iconId) {
2311 this(cInfo.applicationInfo.packageName, _iconId);
2312 }
2313
2314 ResourceName(ResolveInfo rInfo, int _iconId) {
2315 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2316 }
2317
2318 @Override
2319 public boolean equals(Object o) {
2320 if (this == o) return true;
2321 if (o == null || getClass() != o.getClass()) return false;
2322
2323 ResourceName that = (ResourceName) o;
2324
2325 if (iconId != that.iconId) return false;
2326 return !(packageName != null ?
2327 !packageName.equals(that.packageName) : that.packageName != null);
2328
2329 }
2330
2331 @Override
2332 public int hashCode() {
2333 int result;
2334 result = packageName.hashCode();
2335 result = 31 * result + iconId;
2336 return result;
2337 }
2338
2339 @Override
2340 public String toString() {
2341 return "{ResourceName " + packageName + " / " + iconId + "}";
2342 }
2343 }
2344
2345 private CharSequence getCachedString(ResourceName name) {
2346 synchronized (sSync) {
2347 WeakReference<CharSequence> wr = sStringCache.get(name);
2348 if (wr != null) { // we have the activity
2349 CharSequence cs = wr.get();
2350 if (cs != null) {
2351 return cs;
2352 }
2353 // our entry has been purged
2354 sStringCache.remove(name);
2355 }
2356 }
2357 return null;
2358 }
2359
2360 private void putCachedString(ResourceName name, CharSequence cs) {
2361 establishPackageRemovedReceiver();
2362
2363 synchronized (sSync) {
2364 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2365 }
2366 }
2367
2368 private CharSequence getLabel(ResourceName name, ApplicationInfo app, int id) {
2369 CharSequence cs = getCachedString(name);
2370 if (cs != null) {
2371 return cs;
2372 }
2373 try {
2374 Resources r = getResourcesForApplication(app);
2375 cs = r.getText(id);
2376 putCachedString(name, cs);
2377 } catch (NameNotFoundException e) {
2378 Log.w("PackageManager", "Failure retrieving resources for"
2379 + app.packageName);
2380 } catch (RuntimeException e) {
2381 // If an exception was thrown, fall through to return null
2382 Log.w("ApplicationInfo", "Failure retrieving activity name", e);
2383 }
2384 return cs;
2385 }
2386
2387 @Override
2388 public CharSequence getText(String packageName, int resid,
2389 ApplicationInfo appInfo) {
2390 ResourceName name = new ResourceName(packageName, resid);
2391 CharSequence text = getCachedString(name);
2392 if (text != null) {
2393 return text;
2394 }
2395 if (appInfo == null) {
2396 try {
2397 appInfo = getApplicationInfo(packageName, 0);
2398 } catch (NameNotFoundException e) {
2399 return null;
2400 }
2401 }
2402 try {
2403 Resources r = getResourcesForApplication(appInfo);
2404 text = r.getText(resid);
2405 putCachedString(name, text);
2406 return text;
2407 } catch (NameNotFoundException e) {
2408 Log.w("PackageManager", "Failure retrieving resources for"
2409 + appInfo.packageName);
2410 } catch (RuntimeException e) {
2411 // If an exception was thrown, fall through to return
2412 // default icon.
2413 Log.w("PackageManager", "Failure retrieving text 0x"
2414 + Integer.toHexString(resid) + " in package "
2415 + packageName, e);
2416 }
2417 return null;
2418 }
2419
2420 @Override
2421 public XmlResourceParser getXml(String packageName, int resid,
2422 ApplicationInfo appInfo) {
2423 if (appInfo == null) {
2424 try {
2425 appInfo = getApplicationInfo(packageName, 0);
2426 } catch (NameNotFoundException e) {
2427 return null;
2428 }
2429 }
2430 try {
2431 Resources r = getResourcesForApplication(appInfo);
2432 return r.getXml(resid);
2433 } catch (RuntimeException e) {
2434 // If an exception was thrown, fall through to return
2435 // default icon.
2436 Log.w("PackageManager", "Failure retrieving xml 0x"
2437 + Integer.toHexString(resid) + " in package "
2438 + packageName, e);
2439 } catch (NameNotFoundException e) {
2440 Log.w("PackageManager", "Failure retrieving resources for"
2441 + appInfo.packageName);
2442 }
2443 return null;
2444 }
2445
2446 @Override
2447 public CharSequence getApplicationLabel(ApplicationInfo info) {
2448 if (info.nonLocalizedLabel != null) {
2449 return info.nonLocalizedLabel;
2450 }
2451 final int id = info.labelRes;
2452 if (id != 0) {
2453 CharSequence cs = getLabel(new ResourceName(info, id), info, id);
2454 if (cs != null) {
2455 return cs;
2456 }
2457 }
2458 return info.packageName;
2459 }
2460
2461 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002462 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2463 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 try {
Jacek Surazski65e13172009-04-28 15:26:38 +02002465 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 } catch (RemoteException e) {
2467 // Should never happen!
2468 }
2469 }
2470
2471 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002472 public String getInstallerPackageName(String packageName) {
2473 try {
2474 return mPM.getInstallerPackageName(packageName);
2475 } catch (RemoteException e) {
2476 // Should never happen!
2477 }
2478 return null;
2479 }
2480
2481 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2483 try {
2484 mPM.deletePackage(packageName, observer, flags);
2485 } catch (RemoteException e) {
2486 // Should never happen!
2487 }
2488 }
2489 @Override
2490 public void clearApplicationUserData(String packageName,
2491 IPackageDataObserver observer) {
2492 try {
2493 mPM.clearApplicationUserData(packageName, observer);
2494 } catch (RemoteException e) {
2495 // Should never happen!
2496 }
2497 }
2498 @Override
2499 public void deleteApplicationCacheFiles(String packageName,
2500 IPackageDataObserver observer) {
2501 try {
2502 mPM.deleteApplicationCacheFiles(packageName, observer);
2503 } catch (RemoteException e) {
2504 // Should never happen!
2505 }
2506 }
2507 @Override
2508 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2509 try {
2510 mPM.freeStorageAndNotify(idealStorageSize, observer);
2511 } catch (RemoteException e) {
2512 // Should never happen!
2513 }
2514 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 @Override
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002517 public void freeStorage(long freeStorageSize, IntentSender pi) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 try {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002519 mPM.freeStorage(freeStorageSize, pi);
2520 } catch (RemoteException e) {
2521 // Should never happen!
2522 }
2523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524
2525 @Override
2526 public void getPackageSizeInfo(String packageName,
2527 IPackageStatsObserver observer) {
2528 try {
2529 mPM.getPackageSizeInfo(packageName, observer);
2530 } catch (RemoteException e) {
2531 // Should never happen!
2532 }
2533 }
2534 @Override
2535 public void addPackageToPreferred(String packageName) {
2536 try {
2537 mPM.addPackageToPreferred(packageName);
2538 } catch (RemoteException e) {
2539 // Should never happen!
2540 }
2541 }
2542
2543 @Override
2544 public void removePackageFromPreferred(String packageName) {
2545 try {
2546 mPM.removePackageFromPreferred(packageName);
2547 } catch (RemoteException e) {
2548 // Should never happen!
2549 }
2550 }
2551
2552 @Override
2553 public List<PackageInfo> getPreferredPackages(int flags) {
2554 try {
2555 return mPM.getPreferredPackages(flags);
2556 } catch (RemoteException e) {
2557 // Should never happen!
2558 }
2559 return new ArrayList<PackageInfo>();
2560 }
2561
2562 @Override
2563 public void addPreferredActivity(IntentFilter filter,
2564 int match, ComponentName[] set, ComponentName activity) {
2565 try {
2566 mPM.addPreferredActivity(filter, match, set, activity);
2567 } catch (RemoteException e) {
2568 // Should never happen!
2569 }
2570 }
2571
2572 @Override
Satish Sampath8dbe6122009-06-02 23:35:54 +01002573 public void replacePreferredActivity(IntentFilter filter,
2574 int match, ComponentName[] set, ComponentName activity) {
2575 try {
2576 mPM.replacePreferredActivity(filter, match, set, activity);
2577 } catch (RemoteException e) {
2578 // Should never happen!
2579 }
2580 }
2581
2582 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002583 public void clearPackagePreferredActivities(String packageName) {
2584 try {
2585 mPM.clearPackagePreferredActivities(packageName);
2586 } catch (RemoteException e) {
2587 // Should never happen!
2588 }
2589 }
2590
2591 @Override
2592 public int getPreferredActivities(List<IntentFilter> outFilters,
2593 List<ComponentName> outActivities, String packageName) {
2594 try {
2595 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2596 } catch (RemoteException e) {
2597 // Should never happen!
2598 }
2599 return 0;
2600 }
2601
2602 @Override
2603 public void setComponentEnabledSetting(ComponentName componentName,
2604 int newState, int flags) {
2605 try {
2606 mPM.setComponentEnabledSetting(componentName, newState, flags);
2607 } catch (RemoteException e) {
2608 // Should never happen!
2609 }
2610 }
2611
2612 @Override
2613 public int getComponentEnabledSetting(ComponentName componentName) {
2614 try {
2615 return mPM.getComponentEnabledSetting(componentName);
2616 } catch (RemoteException e) {
2617 // Should never happen!
2618 }
2619 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2620 }
2621
2622 @Override
2623 public void setApplicationEnabledSetting(String packageName,
2624 int newState, int flags) {
2625 try {
2626 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2627 } catch (RemoteException e) {
2628 // Should never happen!
2629 }
2630 }
2631
2632 @Override
2633 public int getApplicationEnabledSetting(String packageName) {
2634 try {
2635 return mPM.getApplicationEnabledSetting(packageName);
2636 } catch (RemoteException e) {
2637 // Should never happen!
2638 }
2639 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2640 }
2641
Oscar Montemayor539d3c42010-01-29 15:27:00 -08002642 // Constants related to app heuristics
2643 // No-installation limit for internal flash: 10% or less space available
2644 private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
2645
2646 // SD-to-internal app size threshold: currently set to 1 MB
2647 private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
2648
2649 @Override
2650 public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
2651 // Initial implementation:
2652 // Package size = code size + cache size + data size
2653 // If code size > 1 MB, install on SD card.
2654 // Else install on internal NAND flash, unless space on NAND is less than 10%
2655
2656 if ((packageURI == null) || (appInfo == null)) {
2657 return INSTALL_PARSE_FAILED_NOT_APK;
2658 }
2659
2660 StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
2661 StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
2662
2663 long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
2664 (long)internalFlashStats.getBlockSize();
2665 long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
2666 (long)internalFlashStats.getBlockSize();
2667 long availSDSize = (long)sdcardStats.getAvailableBlocks() *
2668 (long)sdcardStats.getBlockSize();
2669
2670 double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
2671
2672 final String archiveFilePath = packageURI.getPath();
2673 File apkFile = new File(archiveFilePath);
2674 long pkgLen = apkFile.length();
2675
2676 // Consider application flags preferences as well...
2677 boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
2678
2679 // These are not very precise measures, but I guess it is hard to estimate sizes
2680 // before installing the package.
2681 // As a shortcut, I am assuming that the package fits on NAND flash if the available
2682 // space is three times that of the APK size. For SD, we only worry about the APK size.
2683 // Since packages are downloaded into SD, this might not even be necessary.
2684 boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
2685 boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
2686
2687 // Does not fit, recommend no installation.
2688 if (!fitsOnSD && !fitsOnInternalFlash) {
2689 return INSTALL_FAILED_INSUFFICIENT_STORAGE;
2690 }
2691
2692 if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
2693 // recommend internal NAND likely
2694 if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
2695 // Low space on NAND (<10%) - install on SD
2696 return INSTALL_ON_SDCARD;
2697 }
2698 return INSTALL_ON_INTERNAL_FLASH;
2699 } else {
2700 if (fitsOnSD) {
2701 // Recommend SD card
2702 return INSTALL_ON_SDCARD;
2703 } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
2704 !(installOnlyOnSD)) {
2705 return INSTALL_ON_INTERNAL_FLASH;
2706 } else {
2707 return INSTALL_FAILED_INSUFFICIENT_STORAGE;
2708 }
2709 }
2710 }
2711
Dianne Hackborn21556372010-02-04 16:34:40 -08002712 private final ContextImpl mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 private final IPackageManager mPM;
2714
2715 private static final Object sSync = new Object();
2716 private static final Object sPackageRemovedSync = new Object();
2717 private static BroadcastReceiver sPackageRemovedReceiver;
2718 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2719 = new HashMap<ResourceName, WeakReference<Drawable> >();
2720 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2721 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2722 }
2723
2724 // ----------------------------------------------------------------------
2725 // ----------------------------------------------------------------------
2726 // ----------------------------------------------------------------------
2727
2728 private static final class SharedPreferencesImpl implements SharedPreferences {
2729
2730 private final File mFile;
2731 private final File mBackupFile;
2732 private final int mMode;
2733 private Map mMap;
2734 private final FileStatus mFileStatus = new FileStatus();
2735 private long mTimestamp;
2736
The Android Open Source Project10592532009-03-18 17:39:46 -07002737 private static final Object mContent = new Object();
2738 private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002739
2740 SharedPreferencesImpl(
2741 File file, int mode, Map initialContents) {
2742 mFile = file;
2743 mBackupFile = makeBackupFile(file);
2744 mMode = mode;
2745 mMap = initialContents != null ? initialContents : new HashMap();
2746 if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
2747 mTimestamp = mFileStatus.mtime;
2748 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002749 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 }
2751
2752 public boolean hasFileChanged() {
2753 synchronized (this) {
2754 if (!FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2755 return true;
2756 }
2757 return mTimestamp != mFileStatus.mtime;
2758 }
2759 }
2760
2761 public void replace(Map newContents) {
2762 if (newContents != null) {
2763 synchronized (this) {
2764 mMap = newContents;
2765 }
2766 }
2767 }
2768
2769 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2770 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002771 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002772 }
2773 }
2774
2775 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2776 synchronized(this) {
2777 mListeners.remove(listener);
2778 }
2779 }
2780
2781 public Map<String, ?> getAll() {
2782 synchronized(this) {
2783 //noinspection unchecked
2784 return new HashMap(mMap);
2785 }
2786 }
2787
2788 public String getString(String key, String defValue) {
2789 synchronized (this) {
2790 String v = (String)mMap.get(key);
2791 return v != null ? v : defValue;
2792 }
2793 }
2794
2795 public int getInt(String key, int defValue) {
2796 synchronized (this) {
2797 Integer v = (Integer)mMap.get(key);
2798 return v != null ? v : defValue;
2799 }
2800 }
2801 public long getLong(String key, long defValue) {
2802 synchronized (this) {
2803 Long v = (Long) mMap.get(key);
2804 return v != null ? v : defValue;
2805 }
2806 }
2807 public float getFloat(String key, float defValue) {
2808 synchronized (this) {
2809 Float v = (Float)mMap.get(key);
2810 return v != null ? v : defValue;
2811 }
2812 }
2813 public boolean getBoolean(String key, boolean defValue) {
2814 synchronized (this) {
2815 Boolean v = (Boolean)mMap.get(key);
2816 return v != null ? v : defValue;
2817 }
2818 }
2819
2820 public boolean contains(String key) {
2821 synchronized (this) {
2822 return mMap.containsKey(key);
2823 }
2824 }
2825
2826 public final class EditorImpl implements Editor {
2827 private final Map<String, Object> mModified = Maps.newHashMap();
2828 private boolean mClear = false;
2829
2830 public Editor putString(String key, String value) {
2831 synchronized (this) {
2832 mModified.put(key, value);
2833 return this;
2834 }
2835 }
2836 public Editor putInt(String key, int value) {
2837 synchronized (this) {
2838 mModified.put(key, value);
2839 return this;
2840 }
2841 }
2842 public Editor putLong(String key, long value) {
2843 synchronized (this) {
2844 mModified.put(key, value);
2845 return this;
2846 }
2847 }
2848 public Editor putFloat(String key, float value) {
2849 synchronized (this) {
2850 mModified.put(key, value);
2851 return this;
2852 }
2853 }
2854 public Editor putBoolean(String key, boolean value) {
2855 synchronized (this) {
2856 mModified.put(key, value);
2857 return this;
2858 }
2859 }
2860
2861 public Editor remove(String key) {
2862 synchronized (this) {
2863 mModified.put(key, this);
2864 return this;
2865 }
2866 }
2867
2868 public Editor clear() {
2869 synchronized (this) {
2870 mClear = true;
2871 return this;
2872 }
2873 }
2874
2875 public boolean commit() {
2876 boolean returnValue;
2877
2878 boolean hasListeners;
2879 List<String> keysModified = null;
The Android Open Source Project10592532009-03-18 17:39:46 -07002880 Set<OnSharedPreferenceChangeListener> listeners = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881
2882 synchronized (SharedPreferencesImpl.this) {
2883 hasListeners = mListeners.size() > 0;
2884 if (hasListeners) {
2885 keysModified = new ArrayList<String>();
The Android Open Source Project10592532009-03-18 17:39:46 -07002886 listeners =
2887 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 }
2889
2890 synchronized (this) {
2891 if (mClear) {
2892 mMap.clear();
2893 mClear = false;
2894 }
2895
The Android Open Source Project10592532009-03-18 17:39:46 -07002896 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002897 String k = e.getKey();
2898 Object v = e.getValue();
2899 if (v == this) {
2900 mMap.remove(k);
2901 } else {
2902 mMap.put(k, v);
2903 }
2904
2905 if (hasListeners) {
2906 keysModified.add(k);
2907 }
2908 }
2909
2910 mModified.clear();
2911 }
2912
2913 returnValue = writeFileLocked();
2914 }
2915
2916 if (hasListeners) {
2917 for (int i = keysModified.size() - 1; i >= 0; i--) {
2918 final String key = keysModified.get(i);
The Android Open Source Project10592532009-03-18 17:39:46 -07002919 for (OnSharedPreferenceChangeListener listener : listeners) {
2920 if (listener != null) {
2921 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
2922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002923 }
2924 }
2925 }
2926
2927 return returnValue;
2928 }
2929 }
2930
2931 public Editor edit() {
2932 return new EditorImpl();
2933 }
2934
2935 private FileOutputStream createFileOutputStream(File file) {
2936 FileOutputStream str = null;
2937 try {
2938 str = new FileOutputStream(file);
2939 } catch (FileNotFoundException e) {
2940 File parent = file.getParentFile();
2941 if (!parent.mkdir()) {
2942 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
2943 return null;
2944 }
2945 FileUtils.setPermissions(
2946 parent.getPath(),
2947 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
2948 -1, -1);
2949 try {
2950 str = new FileOutputStream(file);
2951 } catch (FileNotFoundException e2) {
2952 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
2953 }
2954 }
2955 return str;
2956 }
2957
2958 private boolean writeFileLocked() {
2959 // Rename the current file so it may be used as a backup during the next read
2960 if (mFile.exists()) {
2961 if (!mFile.renameTo(mBackupFile)) {
2962 Log.e(TAG, "Couldn't rename file " + mFile + " to backup file " + mBackupFile);
Suchi Amalapurapu8550f252009-09-29 15:20:32 -07002963 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 }
2965 }
2966
2967 // Attempt to write the file, delete the backup and return true as atomically as
2968 // possible. If any exception occurs, delete the new file; next time we will restore
2969 // from the backup.
2970 try {
2971 FileOutputStream str = createFileOutputStream(mFile);
2972 if (str == null) {
2973 return false;
2974 }
2975 XmlUtils.writeMapXml(mMap, str);
2976 str.close();
2977 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
2978 if (FileUtils.getFileStatus(mFile.getPath(), mFileStatus)) {
2979 mTimestamp = mFileStatus.mtime;
2980 }
2981
Dianne Hackborn51bf0772009-03-24 19:11:41 -07002982 // Writing was successful, delete the backup file if there is one.
2983 mBackupFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002984 return true;
2985 } catch (XmlPullParserException e) {
2986 Log.w(TAG, "writeFileLocked: Got exception:", e);
2987 } catch (IOException e) {
2988 Log.w(TAG, "writeFileLocked: Got exception:", e);
2989 }
2990 // Clean up an unsuccessfully written file
2991 if (mFile.exists()) {
2992 if (!mFile.delete()) {
2993 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
2994 }
2995 }
2996 return false;
2997 }
2998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999}