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