blob: ba301e9378b8d25ad40d3ced4e859d657414ce93 [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;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080020import com.android.internal.util.XmlUtils;
svetoslavganov75986cf2009-05-14 22:28:01 -070021import com.google.android.collect.Maps;
22
23import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024
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;
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -080045import android.content.pm.IPackageMoveObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.content.pm.IPackageManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070047import android.content.pm.IPackageStatsObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.content.pm.InstrumentationInfo;
49import android.content.pm.PackageInfo;
50import android.content.pm.PackageManager;
51import android.content.pm.PermissionGroupInfo;
52import android.content.pm.PermissionInfo;
53import android.content.pm.ProviderInfo;
54import android.content.pm.ResolveInfo;
55import android.content.pm.ServiceInfo;
56import android.content.res.AssetManager;
57import android.content.res.Resources;
58import android.content.res.XmlResourceParser;
Vasu Nori74f170f2010-06-01 18:06:18 -070059import android.database.DatabaseErrorHandler;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.database.sqlite.SQLiteDatabase;
61import android.database.sqlite.SQLiteDatabase.CursorFactory;
62import android.graphics.Bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.graphics.drawable.Drawable;
64import android.hardware.SensorManager;
Bai Taoa58a8752010-07-13 15:32:16 +080065import android.location.CountryDetector;
66import android.location.ICountryDetector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.location.ILocationManager;
68import android.location.LocationManager;
69import android.media.AudioManager;
70import android.net.ConnectivityManager;
71import android.net.IConnectivityManager;
Irfan Sheriffc9b68512010-04-08 14:12:33 -070072import android.net.ThrottleManager;
73import android.net.IThrottleManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074import android.net.Uri;
75import android.net.wifi.IWifiManager;
76import android.net.wifi.WifiManager;
77import android.os.Binder;
Adam Powellc63806d2010-09-23 16:21:30 -070078import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.os.Bundle;
Dan Egnorf18a01c2009-11-12 11:32:50 -080080import android.os.DropBoxManager;
Oscar Montemayor539d3c42010-01-29 15:27:00 -080081import android.os.Environment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.os.FileUtils;
83import android.os.Handler;
84import android.os.IBinder;
85import android.os.IPowerManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070086import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.os.PowerManager;
88import android.os.Process;
svetoslavganov75986cf2009-05-14 22:28:01 -070089import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import android.os.ServiceManager;
91import android.os.Vibrator;
92import android.os.FileUtils.FileStatus;
San Mehatb1043402010-02-05 08:26:50 -080093import android.os.storage.StorageManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094import android.telephony.TelephonyManager;
Dianne Hackborn9f531192010-08-04 17:48:03 -070095import android.content.ClipboardManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096import android.util.AndroidRuntimeException;
97import android.util.Log;
98import android.view.ContextThemeWrapper;
99import android.view.LayoutInflater;
100import android.view.WindowManagerImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -0700101import android.view.accessibility.AccessibilityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.view.inputmethod.InputMethodManager;
Fred Quintana60307342009-03-24 22:48:12 -0700103import android.accounts.AccountManager;
104import android.accounts.IAccountManager;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800105import android.app.admin.DevicePolicyManager;
Dan Egnorf18a01c2009-11-12 11:32:50 -0800106import com.android.internal.os.IDropBoxManagerService;
Dan Egnor95240272009-10-27 18:23:39 -0700107
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import java.io.File;
109import java.io.FileInputStream;
110import java.io.FileNotFoundException;
111import java.io.FileOutputStream;
112import java.io.IOException;
113import java.io.InputStream;
114import java.lang.ref.WeakReference;
115import java.util.ArrayList;
116import java.util.HashMap;
svetoslavganov75986cf2009-05-14 22:28:01 -0700117import java.util.HashSet;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import java.util.Iterator;
119import java.util.List;
120import java.util.Map;
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700121import java.util.Map.Entry;
The Android Open Source Project10592532009-03-18 17:39:46 -0700122import java.util.Set;
svetoslavganov75986cf2009-05-14 22:28:01 -0700123import java.util.WeakHashMap;
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700124import java.util.concurrent.CountDownLatch;
125import java.util.concurrent.ExecutorService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127class ReceiverRestrictedContext extends ContextWrapper {
128 ReceiverRestrictedContext(Context base) {
129 super(base);
130 }
131
132 @Override
133 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
134 return registerReceiver(receiver, filter, null, null);
135 }
136
137 @Override
138 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
139 String broadcastPermission, Handler scheduler) {
140 throw new ReceiverCallNotAllowedException(
141 "IntentReceiver components are not allowed to register to receive intents");
142 //ex.fillInStackTrace();
143 //Log.e("IntentReceiver", ex.getMessage(), ex);
144 //return mContext.registerReceiver(receiver, filter, broadcastPermission,
145 // scheduler);
146 }
147
148 @Override
149 public boolean bindService(Intent service, ServiceConnection conn, int flags) {
150 throw new ReceiverCallNotAllowedException(
151 "IntentReceiver components are not allowed to bind to services");
152 //ex.fillInStackTrace();
153 //Log.e("IntentReceiver", ex.getMessage(), ex);
154 //return mContext.bindService(service, interfaceName, conn, flags);
155 }
156}
157
158/**
Dianne Hackborn21556372010-02-04 16:34:40 -0800159 * Common implementation of Context API, which provides the base
160 * context object for Activity and other application components.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 */
Dianne Hackborn21556372010-02-04 16:34:40 -0800162class ContextImpl extends Context {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 private final static String TAG = "ApplicationContext";
Mitsuru Oshima569076c2009-07-02 20:06:08 -0700164 private final static boolean DEBUG = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 private final static boolean DEBUG_ICONS = false;
166
167 private static final Object sSync = new Object();
168 private static AlarmManager sAlarmManager;
169 private static PowerManager sPowerManager;
170 private static ConnectivityManager sConnectivityManager;
Irfan Sheriffc9b68512010-04-08 14:12:33 -0700171 private static ThrottleManager sThrottleManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 private static WifiManager sWifiManager;
173 private static LocationManager sLocationManager;
Bai Taoa58a8752010-07-13 15:32:16 +0800174 private static CountryDetector sCountryDetector;
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700175 private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
176 new HashMap<String, SharedPreferencesImpl>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177
178 private AudioManager mAudioManager;
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700179 /*package*/ LoadedApk mPackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 private Resources mResources;
181 /*package*/ ActivityThread mMainThread;
182 private Context mOuterContext;
183 private IBinder mActivityToken = null;
184 private ApplicationContentResolver mContentResolver;
185 private int mThemeResource = 0;
186 private Resources.Theme mTheme = null;
187 private PackageManager mPackageManager;
188 private NotificationManager mNotificationManager = null;
189 private ActivityManager mActivityManager = null;
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700190 private WallpaperManager mWallpaperManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 private Context mReceiverRestrictedContext = null;
192 private SearchManager mSearchManager = null;
193 private SensorManager mSensorManager = null;
San Mehatc9d81752010-02-01 10:23:27 -0800194 private StorageManager mStorageManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 private Vibrator mVibrator = null;
196 private LayoutInflater mLayoutInflater = null;
197 private StatusBarManager mStatusBarManager = null;
198 private TelephonyManager mTelephonyManager = null;
199 private ClipboardManager mClipboardManager = null;
Romain Guy870e09f2009-07-06 16:35:25 -0700200 private boolean mRestricted;
Fred Quintanae00a3112009-09-22 15:13:30 -0700201 private AccountManager mAccountManager; // protected by mSync
Dan Egnorf18a01c2009-11-12 11:32:50 -0800202 private DropBoxManager mDropBoxManager = null;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800203 private DevicePolicyManager mDevicePolicyManager = null;
Tobias Haamel53332882010-02-18 16:15:43 -0800204 private UiModeManager mUiModeManager = null;
Steve Howarda2709362010-07-02 17:12:48 -0700205 private DownloadManager mDownloadManager = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 private final Object mSync = new Object();
208
209 private File mDatabasesDir;
210 private File mPreferencesDir;
211 private File mFilesDir;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 private File mCacheDir;
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800213 private File mExternalFilesDir;
214 private File mExternalCacheDir;
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 private static final String[] EMPTY_FILE_LIST = {};
217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 @Override
219 public AssetManager getAssets() {
220 return mResources.getAssets();
221 }
222
223 @Override
224 public Resources getResources() {
225 return mResources;
226 }
227
228 @Override
229 public PackageManager getPackageManager() {
230 if (mPackageManager != null) {
231 return mPackageManager;
232 }
233
234 IPackageManager pm = ActivityThread.getPackageManager();
235 if (pm != null) {
236 // Doesn't matter if we make more than one instance.
237 return (mPackageManager = new ApplicationPackageManager(this, pm));
238 }
239
240 return null;
241 }
242
243 @Override
244 public ContentResolver getContentResolver() {
245 return mContentResolver;
246 }
247
248 @Override
249 public Looper getMainLooper() {
250 return mMainThread.getLooper();
251 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 @Override
254 public Context getApplicationContext() {
Christopher Tateeb9e9ec2010-03-23 17:14:36 -0700255 return (mPackageInfo != null) ?
256 mPackageInfo.getApplication() : mMainThread.getApplication();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 @Override
260 public void setTheme(int resid) {
261 mThemeResource = resid;
262 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 @Override
265 public Resources.Theme getTheme() {
266 if (mTheme == null) {
267 if (mThemeResource == 0) {
Joe Onorato170e5482010-10-29 13:26:11 -0700268 final Context outerContext = getOuterContext();
269 mThemeResource = (outerContext.getApplicationInfo().targetSdkVersion
270 >= Build.VERSION_CODES.HONEYCOMB)
271 ? com.android.internal.R.style.Theme_Holo
272 : com.android.internal.R.style.Theme;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 }
274 mTheme = mResources.newTheme();
275 mTheme.applyStyle(mThemeResource, true);
276 }
277 return mTheme;
278 }
279
280 @Override
281 public ClassLoader getClassLoader() {
282 return mPackageInfo != null ?
283 mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
284 }
285
286 @Override
287 public String getPackageName() {
288 if (mPackageInfo != null) {
289 return mPackageInfo.getPackageName();
290 }
291 throw new RuntimeException("Not supported in system context");
292 }
293
294 @Override
Dianne Hackborn5c1e00b2009-06-18 17:10:57 -0700295 public ApplicationInfo getApplicationInfo() {
296 if (mPackageInfo != null) {
297 return mPackageInfo.getApplicationInfo();
298 }
299 throw new RuntimeException("Not supported in system context");
300 }
301
302 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 public String getPackageResourcePath() {
304 if (mPackageInfo != null) {
305 return mPackageInfo.getResDir();
306 }
307 throw new RuntimeException("Not supported in system context");
308 }
309
310 @Override
311 public String getPackageCodePath() {
312 if (mPackageInfo != null) {
313 return mPackageInfo.getAppDir();
314 }
315 throw new RuntimeException("Not supported in system context");
316 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 private static File makeBackupFile(File prefsFile) {
319 return new File(prefsFile.getPath() + ".bak");
320 }
321
Joe Onorato23ecae32009-06-10 17:07:15 -0700322 public File getSharedPrefsFile(String name) {
323 return makeFilename(getPreferencesDir(), name + ".xml");
324 }
325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 @Override
327 public SharedPreferences getSharedPreferences(String name, int mode) {
328 SharedPreferencesImpl sp;
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700329 File prefsFile;
330 boolean needInitialLoad = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 synchronized (sSharedPrefs) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -0700332 sp = sSharedPrefs.get(name);
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700333 if (sp != null && !sp.hasFileChangedUnexpectedly()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 return sp;
335 }
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700336 prefsFile = getSharedPrefsFile(name);
337 if (sp == null) {
338 sp = new SharedPreferencesImpl(prefsFile, mode, null);
339 sSharedPrefs.put(name, sp);
340 needInitialLoad = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 }
342 }
343
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700344 synchronized (sp) {
345 if (needInitialLoad && sp.isLoaded()) {
346 // lost the race to load; another thread handled it
347 return sp;
348 }
349 File backup = makeBackupFile(prefsFile);
350 if (backup.exists()) {
351 prefsFile.delete();
352 backup.renameTo(prefsFile);
353 }
354
355 // Debugging
356 if (prefsFile.exists() && !prefsFile.canRead()) {
357 Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
358 }
359
360 Map map = null;
361 if (prefsFile.exists() && prefsFile.canRead()) {
362 try {
363 FileInputStream str = new FileInputStream(prefsFile);
364 map = XmlUtils.readMapXml(str);
365 str.close();
366 } catch (org.xmlpull.v1.XmlPullParserException e) {
367 Log.w(TAG, "getSharedPreferences", e);
368 } catch (FileNotFoundException e) {
369 Log.w(TAG, "getSharedPreferences", e);
370 } catch (IOException e) {
371 Log.w(TAG, "getSharedPreferences", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 }
373 }
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700374 sp.replace(map);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 }
Brad Fitzpatrick6194c532010-09-07 18:00:33 -0700376 return sp;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 }
378
379 private File getPreferencesDir() {
380 synchronized (mSync) {
381 if (mPreferencesDir == null) {
382 mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
383 }
384 return mPreferencesDir;
385 }
386 }
387
388 @Override
389 public FileInputStream openFileInput(String name)
390 throws FileNotFoundException {
391 File f = makeFilename(getFilesDir(), name);
392 return new FileInputStream(f);
393 }
394
395 @Override
396 public FileOutputStream openFileOutput(String name, int mode)
397 throws FileNotFoundException {
398 final boolean append = (mode&MODE_APPEND) != 0;
399 File f = makeFilename(getFilesDir(), name);
400 try {
401 FileOutputStream fos = new FileOutputStream(f, append);
402 setFilePermissionsFromMode(f.getPath(), mode, 0);
403 return fos;
404 } catch (FileNotFoundException e) {
405 }
406
407 File parent = f.getParentFile();
408 parent.mkdir();
409 FileUtils.setPermissions(
410 parent.getPath(),
411 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
412 -1, -1);
413 FileOutputStream fos = new FileOutputStream(f, append);
414 setFilePermissionsFromMode(f.getPath(), mode, 0);
415 return fos;
416 }
417
418 @Override
419 public boolean deleteFile(String name) {
420 File f = makeFilename(getFilesDir(), name);
421 return f.delete();
422 }
423
424 @Override
425 public File getFilesDir() {
426 synchronized (mSync) {
427 if (mFilesDir == null) {
428 mFilesDir = new File(getDataDirFile(), "files");
429 }
430 if (!mFilesDir.exists()) {
431 if(!mFilesDir.mkdirs()) {
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200432 Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 return null;
434 }
435 FileUtils.setPermissions(
436 mFilesDir.getPath(),
437 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
438 -1, -1);
439 }
440 return mFilesDir;
441 }
442 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 @Override
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800445 public File getExternalFilesDir(String type) {
446 synchronized (mSync) {
447 if (mExternalFilesDir == null) {
448 mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
449 getPackageName());
450 }
451 if (!mExternalFilesDir.exists()) {
452 try {
453 (new File(Environment.getExternalStorageAndroidDataDir(),
454 ".nomedia")).createNewFile();
455 } catch (IOException e) {
456 }
457 if (!mExternalFilesDir.mkdirs()) {
458 Log.w(TAG, "Unable to create external files directory");
459 return null;
460 }
461 }
462 if (type == null) {
463 return mExternalFilesDir;
464 }
465 File dir = new File(mExternalFilesDir, type);
466 if (!dir.exists()) {
467 if (!dir.mkdirs()) {
468 Log.w(TAG, "Unable to create external media directory " + dir);
469 return null;
470 }
471 }
472 return dir;
473 }
474 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200475
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800476 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477 public File getCacheDir() {
478 synchronized (mSync) {
479 if (mCacheDir == null) {
480 mCacheDir = new File(getDataDirFile(), "cache");
481 }
482 if (!mCacheDir.exists()) {
483 if(!mCacheDir.mkdirs()) {
484 Log.w(TAG, "Unable to create cache directory");
485 return null;
486 }
487 FileUtils.setPermissions(
488 mCacheDir.getPath(),
489 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
490 -1, -1);
491 }
492 }
493 return mCacheDir;
494 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200495
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800496 @Override
497 public File getExternalCacheDir() {
498 synchronized (mSync) {
499 if (mExternalCacheDir == null) {
500 mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
501 getPackageName());
502 }
503 if (!mExternalCacheDir.exists()) {
504 try {
505 (new File(Environment.getExternalStorageAndroidDataDir(),
506 ".nomedia")).createNewFile();
507 } catch (IOException e) {
508 }
509 if (!mExternalCacheDir.mkdirs()) {
510 Log.w(TAG, "Unable to create external cache directory");
511 return null;
512 }
513 }
514 return mExternalCacheDir;
515 }
516 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 @Override
519 public File getFileStreamPath(String name) {
520 return makeFilename(getFilesDir(), name);
521 }
522
523 @Override
524 public String[] fileList() {
525 final String[] list = getFilesDir().list();
526 return (list != null) ? list : EMPTY_FILE_LIST;
527 }
528
529 @Override
530 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800531 File f = validateFilePath(name, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
533 setFilePermissionsFromMode(f.getPath(), mode, 0);
534 return db;
535 }
536
537 @Override
Vasu Nori74f170f2010-06-01 18:06:18 -0700538 public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
539 DatabaseErrorHandler errorHandler) {
540 File f = validateFilePath(name, true);
541 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f.getPath(), factory, errorHandler);
542 setFilePermissionsFromMode(f.getPath(), mode, 0);
543 return db;
544 }
545
546 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547 public boolean deleteDatabase(String name) {
548 try {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800549 File f = validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 return f.delete();
551 } catch (Exception e) {
552 }
553 return false;
554 }
555
556 @Override
557 public File getDatabasePath(String name) {
Oscar Montemayora8529f62009-11-18 10:14:20 -0800558 return validateFilePath(name, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 }
560
561 @Override
562 public String[] databaseList() {
563 final String[] list = getDatabasesDir().list();
564 return (list != null) ? list : EMPTY_FILE_LIST;
565 }
566
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 private File getDatabasesDir() {
569 synchronized (mSync) {
570 if (mDatabasesDir == null) {
571 mDatabasesDir = new File(getDataDirFile(), "databases");
572 }
573 if (mDatabasesDir.getPath().equals("databases")) {
574 mDatabasesDir = new File("/data/system");
575 }
576 return mDatabasesDir;
577 }
578 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 @Override
581 public Drawable getWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700582 return getWallpaperManager().getDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583 }
584
585 @Override
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700586 public Drawable peekWallpaper() {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700587 return getWallpaperManager().peekDrawable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 }
589
590 @Override
591 public int getWallpaperDesiredMinimumWidth() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700592 return getWallpaperManager().getDesiredMinimumWidth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 }
594
595 @Override
596 public int getWallpaperDesiredMinimumHeight() {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700597 return getWallpaperManager().getDesiredMinimumHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 }
599
600 @Override
601 public void setWallpaper(Bitmap bitmap) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700602 getWallpaperManager().setBitmap(bitmap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 }
604
605 @Override
606 public void setWallpaper(InputStream data) throws IOException {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700607 getWallpaperManager().setStream(data);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 }
609
610 @Override
611 public void clearWallpaper() throws IOException {
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700612 getWallpaperManager().clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 }
614
615 @Override
616 public void startActivity(Intent intent) {
617 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
618 throw new AndroidRuntimeException(
619 "Calling startActivity() from outside of an Activity "
620 + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
621 + " Is this really what you want?");
622 }
623 mMainThread.getInstrumentation().execStartActivity(
Dianne Hackborn6e8304e2010-05-14 00:42:53 -0700624 getOuterContext(), mMainThread.getApplicationThread(), null,
625 (Activity)null, intent, -1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 }
627
628 @Override
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700629 public void startIntentSender(IntentSender intent,
630 Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
631 throws IntentSender.SendIntentException {
632 try {
633 String resolvedType = null;
634 if (fillInIntent != null) {
635 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
636 }
637 int result = ActivityManagerNative.getDefault()
638 .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
639 fillInIntent, resolvedType, null, null,
640 0, flagsMask, flagsValues);
641 if (result == IActivityManager.START_CANCELED) {
642 throw new IntentSender.SendIntentException();
643 }
644 Instrumentation.checkStartActivityResult(result, null);
645 } catch (RemoteException e) {
646 }
647 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +0200648
Dianne Hackbornfa82f222009-09-17 15:14:12 -0700649 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 public void sendBroadcast(Intent intent) {
651 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
652 try {
653 ActivityManagerNative.getDefault().broadcastIntent(
654 mMainThread.getApplicationThread(), intent, resolvedType, null,
655 Activity.RESULT_OK, null, null, null, false, false);
656 } catch (RemoteException e) {
657 }
658 }
659
660 @Override
661 public void sendBroadcast(Intent intent, String receiverPermission) {
662 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
663 try {
664 ActivityManagerNative.getDefault().broadcastIntent(
665 mMainThread.getApplicationThread(), intent, resolvedType, null,
666 Activity.RESULT_OK, null, null, receiverPermission, false, false);
667 } catch (RemoteException e) {
668 }
669 }
670
671 @Override
672 public void sendOrderedBroadcast(Intent intent,
673 String receiverPermission) {
674 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
675 try {
676 ActivityManagerNative.getDefault().broadcastIntent(
677 mMainThread.getApplicationThread(), intent, resolvedType, null,
678 Activity.RESULT_OK, null, null, receiverPermission, true, false);
679 } catch (RemoteException e) {
680 }
681 }
682
683 @Override
684 public void sendOrderedBroadcast(Intent intent,
685 String receiverPermission, BroadcastReceiver resultReceiver,
686 Handler scheduler, int initialCode, String initialData,
687 Bundle initialExtras) {
688 IIntentReceiver rd = null;
689 if (resultReceiver != null) {
690 if (mPackageInfo != null) {
691 if (scheduler == null) {
692 scheduler = mMainThread.getHandler();
693 }
694 rd = mPackageInfo.getReceiverDispatcher(
695 resultReceiver, getOuterContext(), scheduler,
696 mMainThread.getInstrumentation(), false);
697 } else {
698 if (scheduler == null) {
699 scheduler = mMainThread.getHandler();
700 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700701 rd = new LoadedApk.ReceiverDispatcher(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
703 }
704 }
705 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
706 try {
707 ActivityManagerNative.getDefault().broadcastIntent(
708 mMainThread.getApplicationThread(), intent, resolvedType, rd,
709 initialCode, initialData, initialExtras, receiverPermission,
710 true, false);
711 } catch (RemoteException e) {
712 }
713 }
714
715 @Override
716 public void sendStickyBroadcast(Intent intent) {
717 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
718 try {
719 ActivityManagerNative.getDefault().broadcastIntent(
720 mMainThread.getApplicationThread(), intent, resolvedType, null,
721 Activity.RESULT_OK, null, null, null, false, true);
722 } catch (RemoteException e) {
723 }
724 }
725
726 @Override
Dianne Hackbornefa199f2009-09-19 12:03:15 -0700727 public void sendStickyOrderedBroadcast(Intent intent,
728 BroadcastReceiver resultReceiver,
729 Handler scheduler, int initialCode, String initialData,
730 Bundle initialExtras) {
731 IIntentReceiver rd = null;
732 if (resultReceiver != null) {
733 if (mPackageInfo != null) {
734 if (scheduler == null) {
735 scheduler = mMainThread.getHandler();
736 }
737 rd = mPackageInfo.getReceiverDispatcher(
738 resultReceiver, getOuterContext(), scheduler,
739 mMainThread.getInstrumentation(), false);
740 } else {
741 if (scheduler == null) {
742 scheduler = mMainThread.getHandler();
743 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700744 rd = new LoadedApk.ReceiverDispatcher(
Dianne Hackbornefa199f2009-09-19 12:03:15 -0700745 resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
746 }
747 }
748 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
749 try {
750 ActivityManagerNative.getDefault().broadcastIntent(
751 mMainThread.getApplicationThread(), intent, resolvedType, rd,
752 initialCode, initialData, initialExtras, null,
753 true, true);
754 } catch (RemoteException e) {
755 }
756 }
757
758 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 public void removeStickyBroadcast(Intent intent) {
760 String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
761 if (resolvedType != null) {
762 intent = new Intent(intent);
763 intent.setDataAndType(intent.getData(), resolvedType);
764 }
765 try {
766 ActivityManagerNative.getDefault().unbroadcastIntent(
767 mMainThread.getApplicationThread(), intent);
768 } catch (RemoteException e) {
769 }
770 }
771
772 @Override
773 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
774 return registerReceiver(receiver, filter, null, null);
775 }
776
777 @Override
778 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
779 String broadcastPermission, Handler scheduler) {
780 return registerReceiverInternal(receiver, filter, broadcastPermission,
781 scheduler, getOuterContext());
782 }
783
784 private Intent registerReceiverInternal(BroadcastReceiver receiver,
785 IntentFilter filter, String broadcastPermission,
786 Handler scheduler, Context context) {
787 IIntentReceiver rd = null;
788 if (receiver != null) {
789 if (mPackageInfo != null && context != null) {
790 if (scheduler == null) {
791 scheduler = mMainThread.getHandler();
792 }
793 rd = mPackageInfo.getReceiverDispatcher(
794 receiver, context, scheduler,
795 mMainThread.getInstrumentation(), true);
796 } else {
797 if (scheduler == null) {
798 scheduler = mMainThread.getHandler();
799 }
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -0700800 rd = new LoadedApk.ReceiverDispatcher(
Dianne Hackborn399cccb2010-04-13 22:57:49 -0700801 receiver, context, scheduler, null, true).getIIntentReceiver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 }
803 }
804 try {
805 return ActivityManagerNative.getDefault().registerReceiver(
806 mMainThread.getApplicationThread(),
807 rd, filter, broadcastPermission);
808 } catch (RemoteException e) {
809 return null;
810 }
811 }
812
813 @Override
814 public void unregisterReceiver(BroadcastReceiver receiver) {
815 if (mPackageInfo != null) {
816 IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
817 getOuterContext(), receiver);
818 try {
819 ActivityManagerNative.getDefault().unregisterReceiver(rd);
820 } catch (RemoteException e) {
821 }
822 } else {
823 throw new RuntimeException("Not supported in system context");
824 }
825 }
826
827 @Override
828 public ComponentName startService(Intent service) {
829 try {
830 ComponentName cn = ActivityManagerNative.getDefault().startService(
831 mMainThread.getApplicationThread(), service,
832 service.resolveTypeIfNeeded(getContentResolver()));
833 if (cn != null && cn.getPackageName().equals("!")) {
834 throw new SecurityException(
835 "Not allowed to start service " + service
836 + " without permission " + cn.getClassName());
837 }
838 return cn;
839 } catch (RemoteException e) {
840 return null;
841 }
842 }
843
844 @Override
845 public boolean stopService(Intent service) {
846 try {
847 int res = ActivityManagerNative.getDefault().stopService(
848 mMainThread.getApplicationThread(), service,
849 service.resolveTypeIfNeeded(getContentResolver()));
850 if (res < 0) {
851 throw new SecurityException(
852 "Not allowed to stop service " + service);
853 }
854 return res != 0;
855 } catch (RemoteException e) {
856 return false;
857 }
858 }
859
860 @Override
861 public boolean bindService(Intent service, ServiceConnection conn,
862 int flags) {
863 IServiceConnection sd;
864 if (mPackageInfo != null) {
865 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
866 mMainThread.getHandler(), flags);
867 } else {
868 throw new RuntimeException("Not supported in system context");
869 }
870 try {
871 int res = ActivityManagerNative.getDefault().bindService(
872 mMainThread.getApplicationThread(), getActivityToken(),
873 service, service.resolveTypeIfNeeded(getContentResolver()),
874 sd, flags);
875 if (res < 0) {
876 throw new SecurityException(
877 "Not allowed to bind to service " + service);
878 }
879 return res != 0;
880 } catch (RemoteException e) {
881 return false;
882 }
883 }
884
885 @Override
886 public void unbindService(ServiceConnection conn) {
887 if (mPackageInfo != null) {
888 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
889 getOuterContext(), conn);
890 try {
891 ActivityManagerNative.getDefault().unbindService(sd);
892 } catch (RemoteException e) {
893 }
894 } else {
895 throw new RuntimeException("Not supported in system context");
896 }
897 }
898
899 @Override
900 public boolean startInstrumentation(ComponentName className,
901 String profileFile, Bundle arguments) {
902 try {
903 return ActivityManagerNative.getDefault().startInstrumentation(
904 className, profileFile, 0, arguments, null);
905 } catch (RemoteException e) {
906 // System has crashed, nothing we can do.
907 }
908 return false;
909 }
910
911 @Override
912 public Object getSystemService(String name) {
913 if (WINDOW_SERVICE.equals(name)) {
914 return WindowManagerImpl.getDefault();
915 } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
916 synchronized (mSync) {
917 LayoutInflater inflater = mLayoutInflater;
918 if (inflater != null) {
919 return inflater;
920 }
921 mLayoutInflater = inflater =
922 PolicyManager.makeNewLayoutInflater(getOuterContext());
923 return inflater;
924 }
925 } else if (ACTIVITY_SERVICE.equals(name)) {
926 return getActivityManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700927 } else if (INPUT_METHOD_SERVICE.equals(name)) {
928 return InputMethodManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800929 } else if (ALARM_SERVICE.equals(name)) {
930 return getAlarmManager();
Fred Quintana60307342009-03-24 22:48:12 -0700931 } else if (ACCOUNT_SERVICE.equals(name)) {
932 return getAccountManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 } else if (POWER_SERVICE.equals(name)) {
934 return getPowerManager();
935 } else if (CONNECTIVITY_SERVICE.equals(name)) {
936 return getConnectivityManager();
Irfan Sheriffc9b68512010-04-08 14:12:33 -0700937 } else if (THROTTLE_SERVICE.equals(name)) {
938 return getThrottleManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 } else if (WIFI_SERVICE.equals(name)) {
940 return getWifiManager();
941 } else if (NOTIFICATION_SERVICE.equals(name)) {
942 return getNotificationManager();
943 } else if (KEYGUARD_SERVICE.equals(name)) {
944 return new KeyguardManager();
svetoslavganov75986cf2009-05-14 22:28:01 -0700945 } else if (ACCESSIBILITY_SERVICE.equals(name)) {
946 return AccessibilityManager.getInstance(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 } else if (LOCATION_SERVICE.equals(name)) {
948 return getLocationManager();
Bai Taoa58a8752010-07-13 15:32:16 +0800949 } else if (COUNTRY_DETECTOR.equals(name)) {
950 return getCountryDetector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 } else if (SEARCH_SERVICE.equals(name)) {
952 return getSearchManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700953 } else if (SENSOR_SERVICE.equals(name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 return getSensorManager();
San Mehatc9d81752010-02-01 10:23:27 -0800955 } else if (STORAGE_SERVICE.equals(name)) {
956 return getStorageManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 } else if (VIBRATOR_SERVICE.equals(name)) {
958 return getVibrator();
959 } else if (STATUS_BAR_SERVICE.equals(name)) {
960 synchronized (mSync) {
961 if (mStatusBarManager == null) {
962 mStatusBarManager = new StatusBarManager(getOuterContext());
963 }
964 return mStatusBarManager;
965 }
966 } else if (AUDIO_SERVICE.equals(name)) {
967 return getAudioManager();
968 } else if (TELEPHONY_SERVICE.equals(name)) {
969 return getTelephonyManager();
970 } else if (CLIPBOARD_SERVICE.equals(name)) {
971 return getClipboardManager();
Dianne Hackborn8cc6a502009-08-05 21:29:42 -0700972 } else if (WALLPAPER_SERVICE.equals(name)) {
973 return getWallpaperManager();
Dan Egnor95240272009-10-27 18:23:39 -0700974 } else if (DROPBOX_SERVICE.equals(name)) {
Dan Egnorf18a01c2009-11-12 11:32:50 -0800975 return getDropBoxManager();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800976 } else if (DEVICE_POLICY_SERVICE.equals(name)) {
977 return getDevicePolicyManager();
Tobias Haamel69fb5742010-02-22 21:54:05 +0100978 } else if (UI_MODE_SERVICE.equals(name)) {
Tobias Haamel53332882010-02-18 16:15:43 -0800979 return getUiModeManager();
Steve Howarda2709362010-07-02 17:12:48 -0700980 } else if (DOWNLOAD_SERVICE.equals(name)) {
981 return getDownloadManager();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982 }
983
984 return null;
985 }
986
Fred Quintana60307342009-03-24 22:48:12 -0700987 private AccountManager getAccountManager() {
Fred Quintanae00a3112009-09-22 15:13:30 -0700988 synchronized (mSync) {
989 if (mAccountManager == null) {
Fred Quintana60307342009-03-24 22:48:12 -0700990 IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
991 IAccountManager service = IAccountManager.Stub.asInterface(b);
Fred Quintanae00a3112009-09-22 15:13:30 -0700992 mAccountManager = new AccountManager(this, service);
Fred Quintana60307342009-03-24 22:48:12 -0700993 }
Fred Quintanae00a3112009-09-22 15:13:30 -0700994 return mAccountManager;
Fred Quintana60307342009-03-24 22:48:12 -0700995 }
Fred Quintana60307342009-03-24 22:48:12 -0700996 }
997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 private ActivityManager getActivityManager() {
999 synchronized (mSync) {
1000 if (mActivityManager == null) {
1001 mActivityManager = new ActivityManager(getOuterContext(),
1002 mMainThread.getHandler());
1003 }
1004 }
1005 return mActivityManager;
1006 }
1007
1008 private AlarmManager getAlarmManager() {
1009 synchronized (sSync) {
1010 if (sAlarmManager == null) {
1011 IBinder b = ServiceManager.getService(ALARM_SERVICE);
1012 IAlarmManager service = IAlarmManager.Stub.asInterface(b);
1013 sAlarmManager = new AlarmManager(service);
1014 }
1015 }
1016 return sAlarmManager;
1017 }
1018
1019 private PowerManager getPowerManager() {
1020 synchronized (sSync) {
1021 if (sPowerManager == null) {
1022 IBinder b = ServiceManager.getService(POWER_SERVICE);
1023 IPowerManager service = IPowerManager.Stub.asInterface(b);
1024 sPowerManager = new PowerManager(service, mMainThread.getHandler());
1025 }
1026 }
1027 return sPowerManager;
1028 }
1029
1030 private ConnectivityManager getConnectivityManager()
1031 {
1032 synchronized (sSync) {
1033 if (sConnectivityManager == null) {
1034 IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
1035 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
1036 sConnectivityManager = new ConnectivityManager(service);
1037 }
1038 }
1039 return sConnectivityManager;
1040 }
1041
Irfan Sheriffc9b68512010-04-08 14:12:33 -07001042 private ThrottleManager getThrottleManager()
1043 {
1044 synchronized (sSync) {
1045 if (sThrottleManager == null) {
1046 IBinder b = ServiceManager.getService(THROTTLE_SERVICE);
1047 IThrottleManager service = IThrottleManager.Stub.asInterface(b);
1048 sThrottleManager = new ThrottleManager(service);
1049 }
1050 }
1051 return sThrottleManager;
1052 }
1053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 private WifiManager getWifiManager()
1055 {
1056 synchronized (sSync) {
1057 if (sWifiManager == null) {
1058 IBinder b = ServiceManager.getService(WIFI_SERVICE);
1059 IWifiManager service = IWifiManager.Stub.asInterface(b);
1060 sWifiManager = new WifiManager(service, mMainThread.getHandler());
1061 }
1062 }
1063 return sWifiManager;
1064 }
1065
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001066 private NotificationManager getNotificationManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 synchronized (mSync) {
1068 if (mNotificationManager == null) {
Adam Powellc63806d2010-09-23 16:21:30 -07001069 final Context outerContext = getOuterContext();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 mNotificationManager = new NotificationManager(
Adam Powellc63806d2010-09-23 16:21:30 -07001071 new ContextThemeWrapper(outerContext,
1072 outerContext.getApplicationInfo().targetSdkVersion >=
1073 Build.VERSION_CODES.HONEYCOMB
1074 ? com.android.internal.R.style.Theme_Holo_Dialog
1075 : com.android.internal.R.style.Theme_Dialog),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 mMainThread.getHandler());
1077 }
1078 }
1079 return mNotificationManager;
1080 }
1081
Dianne Hackborn8cc6a502009-08-05 21:29:42 -07001082 private WallpaperManager getWallpaperManager() {
1083 synchronized (mSync) {
1084 if (mWallpaperManager == null) {
1085 mWallpaperManager = new WallpaperManager(getOuterContext(),
1086 mMainThread.getHandler());
1087 }
1088 }
1089 return mWallpaperManager;
1090 }
1091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 private TelephonyManager getTelephonyManager() {
1093 synchronized (mSync) {
1094 if (mTelephonyManager == null) {
1095 mTelephonyManager = new TelephonyManager(getOuterContext());
1096 }
1097 }
1098 return mTelephonyManager;
1099 }
1100
1101 private ClipboardManager getClipboardManager() {
1102 synchronized (mSync) {
1103 if (mClipboardManager == null) {
1104 mClipboardManager = new ClipboardManager(getOuterContext(),
1105 mMainThread.getHandler());
1106 }
1107 }
1108 return mClipboardManager;
1109 }
1110
1111 private LocationManager getLocationManager() {
1112 synchronized (sSync) {
1113 if (sLocationManager == null) {
1114 IBinder b = ServiceManager.getService(LOCATION_SERVICE);
1115 ILocationManager service = ILocationManager.Stub.asInterface(b);
1116 sLocationManager = new LocationManager(service);
1117 }
1118 }
1119 return sLocationManager;
1120 }
1121
Bai Taoa58a8752010-07-13 15:32:16 +08001122 private CountryDetector getCountryDetector() {
1123 synchronized (sSync) {
1124 if (sCountryDetector == null) {
1125 IBinder b = ServiceManager.getService(COUNTRY_DETECTOR);
1126 ICountryDetector service = ICountryDetector.Stub.asInterface(b);
1127 sCountryDetector = new CountryDetector(service);
1128 }
1129 }
1130 return sCountryDetector;
1131 }
1132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 private SearchManager getSearchManager() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 synchronized (mSync) {
1135 if (mSearchManager == null) {
1136 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
1137 }
1138 }
1139 return mSearchManager;
1140 }
1141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 private SensorManager getSensorManager() {
1143 synchronized (mSync) {
1144 if (mSensorManager == null) {
1145 mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1146 }
1147 }
1148 return mSensorManager;
1149 }
1150
San Mehatc9d81752010-02-01 10:23:27 -08001151 private StorageManager getStorageManager() {
1152 synchronized (mSync) {
1153 if (mStorageManager == null) {
1154 try {
1155 mStorageManager = new StorageManager(mMainThread.getHandler().getLooper());
1156 } catch (RemoteException rex) {
1157 Log.e(TAG, "Failed to create StorageManager", rex);
1158 mStorageManager = null;
1159 }
1160 }
1161 }
1162 return mStorageManager;
1163 }
1164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 private Vibrator getVibrator() {
1166 synchronized (mSync) {
1167 if (mVibrator == null) {
1168 mVibrator = new Vibrator();
1169 }
1170 }
1171 return mVibrator;
1172 }
Dan Egnor95240272009-10-27 18:23:39 -07001173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 private AudioManager getAudioManager()
1175 {
1176 if (mAudioManager == null) {
1177 mAudioManager = new AudioManager(this);
1178 }
1179 return mAudioManager;
1180 }
1181
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001182 /* package */ static DropBoxManager createDropBoxManager() {
1183 IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1184 IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
Brad Fitzpatrickec062f62010-11-03 09:56:54 -07001185 if (service == null) {
1186 // Don't return a DropBoxManager that will NPE upon use.
1187 // This also avoids caching a broken DropBoxManager in
1188 // getDropBoxManager during early boot, before the
1189 // DROPBOX_SERVICE is registered.
1190 return null;
1191 }
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001192 return new DropBoxManager(service);
1193 }
1194
Dan Egnorf18a01c2009-11-12 11:32:50 -08001195 private DropBoxManager getDropBoxManager() {
Dan Egnor95240272009-10-27 18:23:39 -07001196 synchronized (mSync) {
Dan Egnorf18a01c2009-11-12 11:32:50 -08001197 if (mDropBoxManager == null) {
Brad Fitzpatrick438d0592010-06-10 12:19:19 -07001198 mDropBoxManager = createDropBoxManager();
Dan Egnor95240272009-10-27 18:23:39 -07001199 }
1200 }
Dan Egnorf18a01c2009-11-12 11:32:50 -08001201 return mDropBoxManager;
Dan Egnor95240272009-10-27 18:23:39 -07001202 }
1203
Dianne Hackbornd6847842010-01-12 18:14:19 -08001204 private DevicePolicyManager getDevicePolicyManager() {
1205 synchronized (mSync) {
1206 if (mDevicePolicyManager == null) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001207 mDevicePolicyManager = DevicePolicyManager.create(this,
Dianne Hackbornd6847842010-01-12 18:14:19 -08001208 mMainThread.getHandler());
1209 }
1210 }
1211 return mDevicePolicyManager;
1212 }
1213
Tobias Haamel53332882010-02-18 16:15:43 -08001214 private UiModeManager getUiModeManager() {
1215 synchronized (mSync) {
1216 if (mUiModeManager == null) {
1217 mUiModeManager = new UiModeManager();
1218 }
1219 }
1220 return mUiModeManager;
1221 }
1222
Steve Howarda2709362010-07-02 17:12:48 -07001223 private DownloadManager getDownloadManager() {
1224 synchronized (mSync) {
1225 if (mDownloadManager == null) {
Steve Howardb8e07a52010-07-21 14:53:21 -07001226 mDownloadManager = new DownloadManager(getContentResolver(), getPackageName());
Steve Howarda2709362010-07-02 17:12:48 -07001227 }
1228 }
1229 return mDownloadManager;
1230 }
1231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 @Override
1233 public int checkPermission(String permission, int pid, int uid) {
1234 if (permission == null) {
1235 throw new IllegalArgumentException("permission is null");
1236 }
1237
1238 if (!Process.supportsProcesses()) {
1239 return PackageManager.PERMISSION_GRANTED;
1240 }
1241 try {
1242 return ActivityManagerNative.getDefault().checkPermission(
1243 permission, pid, uid);
1244 } catch (RemoteException e) {
1245 return PackageManager.PERMISSION_DENIED;
1246 }
1247 }
1248
1249 @Override
1250 public int checkCallingPermission(String permission) {
1251 if (permission == null) {
1252 throw new IllegalArgumentException("permission is null");
1253 }
1254
1255 if (!Process.supportsProcesses()) {
1256 return PackageManager.PERMISSION_GRANTED;
1257 }
1258 int pid = Binder.getCallingPid();
1259 if (pid != Process.myPid()) {
1260 return checkPermission(permission, pid,
1261 Binder.getCallingUid());
1262 }
1263 return PackageManager.PERMISSION_DENIED;
1264 }
1265
1266 @Override
1267 public int checkCallingOrSelfPermission(String permission) {
1268 if (permission == null) {
1269 throw new IllegalArgumentException("permission is null");
1270 }
1271
1272 return checkPermission(permission, Binder.getCallingPid(),
1273 Binder.getCallingUid());
1274 }
1275
1276 private void enforce(
1277 String permission, int resultOfCheck,
1278 boolean selfToo, int uid, String message) {
1279 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1280 throw new SecurityException(
1281 (message != null ? (message + ": ") : "") +
1282 (selfToo
1283 ? "Neither user " + uid + " nor current process has "
1284 : "User " + uid + " does not have ") +
1285 permission +
1286 ".");
1287 }
1288 }
1289
1290 public void enforcePermission(
1291 String permission, int pid, int uid, String message) {
1292 enforce(permission,
1293 checkPermission(permission, pid, uid),
1294 false,
1295 uid,
1296 message);
1297 }
1298
1299 public void enforceCallingPermission(String permission, String message) {
1300 enforce(permission,
1301 checkCallingPermission(permission),
1302 false,
1303 Binder.getCallingUid(),
1304 message);
1305 }
1306
1307 public void enforceCallingOrSelfPermission(
1308 String permission, String message) {
1309 enforce(permission,
1310 checkCallingOrSelfPermission(permission),
1311 true,
1312 Binder.getCallingUid(),
1313 message);
1314 }
1315
1316 @Override
1317 public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1318 try {
1319 ActivityManagerNative.getDefault().grantUriPermission(
1320 mMainThread.getApplicationThread(), toPackage, uri,
1321 modeFlags);
1322 } catch (RemoteException e) {
1323 }
1324 }
1325
1326 @Override
1327 public void revokeUriPermission(Uri uri, int modeFlags) {
1328 try {
1329 ActivityManagerNative.getDefault().revokeUriPermission(
1330 mMainThread.getApplicationThread(), uri,
1331 modeFlags);
1332 } catch (RemoteException e) {
1333 }
1334 }
1335
1336 @Override
1337 public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1338 if (!Process.supportsProcesses()) {
1339 return PackageManager.PERMISSION_GRANTED;
1340 }
1341 try {
1342 return ActivityManagerNative.getDefault().checkUriPermission(
1343 uri, pid, uid, modeFlags);
1344 } catch (RemoteException e) {
1345 return PackageManager.PERMISSION_DENIED;
1346 }
1347 }
1348
1349 @Override
1350 public int checkCallingUriPermission(Uri uri, int modeFlags) {
1351 if (!Process.supportsProcesses()) {
1352 return PackageManager.PERMISSION_GRANTED;
1353 }
1354 int pid = Binder.getCallingPid();
1355 if (pid != Process.myPid()) {
1356 return checkUriPermission(uri, pid,
1357 Binder.getCallingUid(), modeFlags);
1358 }
1359 return PackageManager.PERMISSION_DENIED;
1360 }
1361
1362 @Override
1363 public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1364 return checkUriPermission(uri, Binder.getCallingPid(),
1365 Binder.getCallingUid(), modeFlags);
1366 }
1367
1368 @Override
1369 public int checkUriPermission(Uri uri, String readPermission,
1370 String writePermission, int pid, int uid, int modeFlags) {
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001371 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1373 + readPermission + " writePermission=" + writePermission
1374 + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1375 }
1376 if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1377 if (readPermission == null
1378 || checkPermission(readPermission, pid, uid)
1379 == PackageManager.PERMISSION_GRANTED) {
1380 return PackageManager.PERMISSION_GRANTED;
1381 }
1382 }
1383 if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1384 if (writePermission == null
1385 || checkPermission(writePermission, pid, uid)
1386 == PackageManager.PERMISSION_GRANTED) {
1387 return PackageManager.PERMISSION_GRANTED;
1388 }
1389 }
1390 return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1391 : PackageManager.PERMISSION_DENIED;
1392 }
1393
1394 private String uriModeFlagToString(int uriModeFlags) {
1395 switch (uriModeFlags) {
1396 case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1397 Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1398 return "read and write";
1399 case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1400 return "read";
1401 case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1402 return "write";
1403 }
1404 throw new IllegalArgumentException(
1405 "Unknown permission mode flags: " + uriModeFlags);
1406 }
1407
1408 private void enforceForUri(
1409 int modeFlags, int resultOfCheck, boolean selfToo,
1410 int uid, Uri uri, String message) {
1411 if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1412 throw new SecurityException(
1413 (message != null ? (message + ": ") : "") +
1414 (selfToo
1415 ? "Neither user " + uid + " nor current process has "
1416 : "User " + uid + " does not have ") +
1417 uriModeFlagToString(modeFlags) +
1418 " permission on " +
1419 uri +
1420 ".");
1421 }
1422 }
1423
1424 public void enforceUriPermission(
1425 Uri uri, int pid, int uid, int modeFlags, String message) {
1426 enforceForUri(
1427 modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1428 false, uid, uri, message);
1429 }
1430
1431 public void enforceCallingUriPermission(
1432 Uri uri, int modeFlags, String message) {
1433 enforceForUri(
1434 modeFlags, checkCallingUriPermission(uri, modeFlags),
1435 false, Binder.getCallingUid(), uri, message);
1436 }
1437
1438 public void enforceCallingOrSelfUriPermission(
1439 Uri uri, int modeFlags, String message) {
1440 enforceForUri(
1441 modeFlags,
1442 checkCallingOrSelfUriPermission(uri, modeFlags), true,
1443 Binder.getCallingUid(), uri, message);
1444 }
1445
1446 public void enforceUriPermission(
1447 Uri uri, String readPermission, String writePermission,
1448 int pid, int uid, int modeFlags, String message) {
1449 enforceForUri(modeFlags,
1450 checkUriPermission(
1451 uri, readPermission, writePermission, pid, uid,
1452 modeFlags),
1453 false,
1454 uid,
1455 uri,
1456 message);
1457 }
1458
1459 @Override
1460 public Context createPackageContext(String packageName, int flags)
1461 throws PackageManager.NameNotFoundException {
1462 if (packageName.equals("system") || packageName.equals("android")) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001463 return new ContextImpl(mMainThread.getSystemContext());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 }
1465
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001466 LoadedApk pi =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 mMainThread.getPackageInfo(packageName, flags);
1468 if (pi != null) {
Dianne Hackborn21556372010-02-04 16:34:40 -08001469 ContextImpl c = new ContextImpl();
Romain Guy870e09f2009-07-06 16:35:25 -07001470 c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001471 c.init(pi, null, mMainThread, mResources);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 if (c.mResources != null) {
1473 return c;
1474 }
1475 }
1476
1477 // Should be a better exception.
1478 throw new PackageManager.NameNotFoundException(
1479 "Application package " + packageName + " not found");
1480 }
1481
Romain Guy870e09f2009-07-06 16:35:25 -07001482 @Override
1483 public boolean isRestricted() {
1484 return mRestricted;
1485 }
1486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 private File getDataDirFile() {
1488 if (mPackageInfo != null) {
1489 return mPackageInfo.getDataDirFile();
1490 }
1491 throw new RuntimeException("Not supported in system context");
1492 }
1493
1494 @Override
1495 public File getDir(String name, int mode) {
1496 name = "app_" + name;
1497 File file = makeFilename(getDataDirFile(), name);
1498 if (!file.exists()) {
1499 file.mkdir();
1500 setFilePermissionsFromMode(file.getPath(), mode,
1501 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1502 }
1503 return file;
1504 }
1505
Dianne Hackborn21556372010-02-04 16:34:40 -08001506 static ContextImpl createSystemContext(ActivityThread mainThread) {
1507 ContextImpl context = new ContextImpl();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 context.init(Resources.getSystem(), mainThread);
1509 return context;
1510 }
1511
Dianne Hackborn21556372010-02-04 16:34:40 -08001512 ContextImpl() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 mOuterContext = this;
1514 }
1515
1516 /**
1517 * Create a new ApplicationContext from an existing one. The new one
1518 * works and operates the same as the one it is copying.
1519 *
1520 * @param context Existing application context.
1521 */
Dianne Hackborn21556372010-02-04 16:34:40 -08001522 public ContextImpl(ContextImpl context) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 mPackageInfo = context.mPackageInfo;
1524 mResources = context.mResources;
1525 mMainThread = context.mMainThread;
1526 mContentResolver = context.mContentResolver;
1527 mOuterContext = this;
1528 }
1529
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001530 final void init(LoadedApk packageInfo,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 IBinder activityToken, ActivityThread mainThread) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001532 init(packageInfo, activityToken, mainThread, null);
1533 }
1534
Dianne Hackborn01e4cfc2010-06-24 15:07:24 -07001535 final void init(LoadedApk packageInfo,
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001536 IBinder activityToken, ActivityThread mainThread,
1537 Resources container) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 mPackageInfo = packageInfo;
1539 mResources = mPackageInfo.getResources(mainThread);
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001540
Dianne Hackborn559a7872010-04-07 18:19:41 -07001541 if (mResources != null && container != null
1542 && container.getCompatibilityInfo().applicationScale !=
1543 mResources.getCompatibilityInfo().applicationScale) {
Mitsuru Oshimaba3ba572009-07-08 18:49:26 -07001544 if (DEBUG) {
1545 Log.d(TAG, "loaded context has different scaling. Using container's" +
1546 " compatiblity info:" + container.getDisplayMetrics());
1547 }
1548 mResources = mainThread.getTopLevelResources(
1549 mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1550 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 mMainThread = mainThread;
1552 mContentResolver = new ApplicationContentResolver(this, mainThread);
1553
1554 setActivityToken(activityToken);
1555 }
1556
1557 final void init(Resources resources, ActivityThread mainThread) {
1558 mPackageInfo = null;
1559 mResources = resources;
1560 mMainThread = mainThread;
1561 mContentResolver = new ApplicationContentResolver(this, mainThread);
1562 }
1563
1564 final void scheduleFinalCleanup(String who, String what) {
1565 mMainThread.scheduleContextCleanup(this, who, what);
1566 }
1567
1568 final void performFinalCleanup(String who, String what) {
1569 //Log.i(TAG, "Cleanup up context: " + this);
1570 mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1571 }
1572
1573 final Context getReceiverRestrictedContext() {
1574 if (mReceiverRestrictedContext != null) {
1575 return mReceiverRestrictedContext;
1576 }
1577 return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1578 }
1579
1580 final void setActivityToken(IBinder token) {
1581 mActivityToken = token;
1582 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 final void setOuterContext(Context context) {
1585 mOuterContext = context;
1586 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 final Context getOuterContext() {
1589 return mOuterContext;
1590 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 final IBinder getActivityToken() {
1593 return mActivityToken;
1594 }
1595
1596 private static void setFilePermissionsFromMode(String name, int mode,
1597 int extraPermissions) {
1598 int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1599 |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1600 |extraPermissions;
1601 if ((mode&MODE_WORLD_READABLE) != 0) {
1602 perms |= FileUtils.S_IROTH;
1603 }
1604 if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1605 perms |= FileUtils.S_IWOTH;
1606 }
Mitsuru Oshima569076c2009-07-02 20:06:08 -07001607 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1609 + ", perms=0x" + Integer.toHexString(perms));
1610 }
1611 FileUtils.setPermissions(name, perms, -1, -1);
1612 }
1613
Oscar Montemayora8529f62009-11-18 10:14:20 -08001614 private File validateFilePath(String name, boolean createDirectory) {
1615 File dir;
1616 File f;
1617
1618 if (name.charAt(0) == File.separatorChar) {
1619 String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1620 dir = new File(dirPath);
1621 name = name.substring(name.lastIndexOf(File.separatorChar));
1622 f = new File(dir, name);
1623 } else {
1624 dir = getDatabasesDir();
1625 f = makeFilename(dir, name);
1626 }
1627
1628 if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1629 FileUtils.setPermissions(dir.getPath(),
1630 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1631 -1, -1);
1632 }
1633
1634 return f;
1635 }
1636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 private File makeFilename(File base, String name) {
1638 if (name.indexOf(File.separatorChar) < 0) {
1639 return new File(base, name);
1640 }
1641 throw new IllegalArgumentException(
Oscar Montemayora8529f62009-11-18 10:14:20 -08001642 "File " + name + " contains a path separator");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 }
1644
1645 // ----------------------------------------------------------------------
1646 // ----------------------------------------------------------------------
1647 // ----------------------------------------------------------------------
1648
1649 private static final class ApplicationContentResolver extends ContentResolver {
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07001650 public ApplicationContentResolver(Context context, ActivityThread mainThread) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 super(context);
1652 mMainThread = mainThread;
1653 }
1654
1655 @Override
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07001656 protected IContentProvider acquireProvider(Context context, String name) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 return mMainThread.acquireProvider(context, name);
1658 }
1659
1660 @Override
Dianne Hackborncca1f0e2010-09-26 18:34:53 -07001661 protected IContentProvider acquireExistingProvider(Context context, String name) {
1662 return mMainThread.acquireExistingProvider(context, name);
1663 }
1664
1665 @Override
1666 public boolean releaseProvider(IContentProvider provider) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 return mMainThread.releaseProvider(provider);
1668 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 private final ActivityThread mMainThread;
1671 }
1672
1673 // ----------------------------------------------------------------------
1674 // ----------------------------------------------------------------------
1675 // ----------------------------------------------------------------------
1676
1677 /*package*/
1678 static final class ApplicationPackageManager extends PackageManager {
1679 @Override
1680 public PackageInfo getPackageInfo(String packageName, int flags)
1681 throws NameNotFoundException {
1682 try {
1683 PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1684 if (pi != null) {
1685 return pi;
1686 }
1687 } catch (RemoteException e) {
1688 throw new RuntimeException("Package manager has died", e);
1689 }
1690
1691 throw new NameNotFoundException(packageName);
1692 }
1693
Mihai Predaeae850c2009-05-13 10:13:48 +02001694 @Override
Dianne Hackborn47096932010-02-11 15:57:09 -08001695 public String[] currentToCanonicalPackageNames(String[] names) {
1696 try {
1697 return mPM.currentToCanonicalPackageNames(names);
1698 } catch (RemoteException e) {
1699 throw new RuntimeException("Package manager has died", e);
1700 }
1701 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001702
Dianne Hackborn47096932010-02-11 15:57:09 -08001703 @Override
1704 public String[] canonicalToCurrentPackageNames(String[] names) {
1705 try {
1706 return mPM.canonicalToCurrentPackageNames(names);
1707 } catch (RemoteException e) {
1708 throw new RuntimeException("Package manager has died", e);
1709 }
1710 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001711
Dianne Hackborn47096932010-02-11 15:57:09 -08001712 @Override
Mihai Predaeae850c2009-05-13 10:13:48 +02001713 public Intent getLaunchIntentForPackage(String packageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 // First see if the package has an INFO activity; the existence of
1715 // such an activity is implied to be the desired front-door for the
1716 // overall package (such as if it has multiple launcher entries).
Mihai Predaeae850c2009-05-13 10:13:48 +02001717 Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1718 intentToResolve.addCategory(Intent.CATEGORY_INFO);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001719 intentToResolve.setPackage(packageName);
1720 ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
Mihai Predaeae850c2009-05-13 10:13:48 +02001721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 // Otherwise, try to find a main launcher activity.
Mihai Predaeae850c2009-05-13 10:13:48 +02001723 if (resolveInfo == null) {
1724 // reuse the intent instance
1725 intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1726 intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
Dianne Hackbornc14b9cc2009-06-17 18:02:12 -07001727 intentToResolve.setPackage(packageName);
1728 resolveInfo = resolveActivity(intentToResolve, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001730 if (resolveInfo == null) {
1731 return null;
1732 }
Johan Erlandssondf4cfa362010-03-31 08:20:51 +02001733 Intent intent = new Intent(intentToResolve);
1734 intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
1735 resolveInfo.activityInfo.name);
Mihai Predaeae850c2009-05-13 10:13:48 +02001736 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1737 return intent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 }
Mihai Predaeae850c2009-05-13 10:13:48 +02001739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 @Override
1741 public int[] getPackageGids(String packageName)
1742 throws NameNotFoundException {
1743 try {
1744 int[] gids = mPM.getPackageGids(packageName);
1745 if (gids == null || gids.length > 0) {
1746 return gids;
1747 }
1748 } catch (RemoteException e) {
1749 throw new RuntimeException("Package manager has died", e);
1750 }
1751
1752 throw new NameNotFoundException(packageName);
1753 }
1754
1755 @Override
1756 public PermissionInfo getPermissionInfo(String name, int flags)
1757 throws NameNotFoundException {
1758 try {
1759 PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1760 if (pi != null) {
1761 return pi;
1762 }
1763 } catch (RemoteException e) {
1764 throw new RuntimeException("Package manager has died", e);
1765 }
1766
1767 throw new NameNotFoundException(name);
1768 }
1769
1770 @Override
1771 public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1772 throws NameNotFoundException {
1773 try {
1774 List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1775 if (pi != null) {
1776 return pi;
1777 }
1778 } catch (RemoteException e) {
1779 throw new RuntimeException("Package manager has died", e);
1780 }
1781
1782 throw new NameNotFoundException(group);
1783 }
1784
1785 @Override
1786 public PermissionGroupInfo getPermissionGroupInfo(String name,
1787 int flags) throws NameNotFoundException {
1788 try {
1789 PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1790 if (pgi != null) {
1791 return pgi;
1792 }
1793 } catch (RemoteException e) {
1794 throw new RuntimeException("Package manager has died", e);
1795 }
1796
1797 throw new NameNotFoundException(name);
1798 }
1799
1800 @Override
1801 public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1802 try {
1803 return mPM.getAllPermissionGroups(flags);
1804 } catch (RemoteException e) {
1805 throw new RuntimeException("Package manager has died", e);
1806 }
1807 }
1808
1809 @Override
1810 public ApplicationInfo getApplicationInfo(String packageName, int flags)
1811 throws NameNotFoundException {
1812 try {
1813 ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
1814 if (ai != null) {
1815 return ai;
1816 }
1817 } catch (RemoteException e) {
1818 throw new RuntimeException("Package manager has died", e);
1819 }
1820
1821 throw new NameNotFoundException(packageName);
1822 }
1823
1824 @Override
1825 public ActivityInfo getActivityInfo(ComponentName className, int flags)
1826 throws NameNotFoundException {
1827 try {
1828 ActivityInfo ai = mPM.getActivityInfo(className, flags);
1829 if (ai != null) {
1830 return ai;
1831 }
1832 } catch (RemoteException e) {
1833 throw new RuntimeException("Package manager has died", e);
1834 }
1835
1836 throw new NameNotFoundException(className.toString());
1837 }
1838
1839 @Override
1840 public ActivityInfo getReceiverInfo(ComponentName className, int flags)
1841 throws NameNotFoundException {
1842 try {
1843 ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1844 if (ai != null) {
1845 return ai;
1846 }
1847 } catch (RemoteException e) {
1848 throw new RuntimeException("Package manager has died", e);
1849 }
1850
1851 throw new NameNotFoundException(className.toString());
1852 }
1853
1854 @Override
1855 public ServiceInfo getServiceInfo(ComponentName className, int flags)
1856 throws NameNotFoundException {
1857 try {
1858 ServiceInfo si = mPM.getServiceInfo(className, flags);
1859 if (si != null) {
1860 return si;
1861 }
1862 } catch (RemoteException e) {
1863 throw new RuntimeException("Package manager has died", e);
1864 }
1865
1866 throw new NameNotFoundException(className.toString());
1867 }
1868
1869 @Override
Dianne Hackborn361199b2010-08-30 17:42:07 -07001870 public ProviderInfo getProviderInfo(ComponentName className, int flags)
1871 throws NameNotFoundException {
1872 try {
1873 ProviderInfo pi = mPM.getProviderInfo(className, flags);
1874 if (pi != null) {
1875 return pi;
1876 }
1877 } catch (RemoteException e) {
1878 throw new RuntimeException("Package manager has died", e);
1879 }
1880
1881 throw new NameNotFoundException(className.toString());
1882 }
1883
1884 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 public String[] getSystemSharedLibraryNames() {
1886 try {
1887 return mPM.getSystemSharedLibraryNames();
1888 } catch (RemoteException e) {
1889 throw new RuntimeException("Package manager has died", e);
1890 }
1891 }
1892
1893 @Override
Dianne Hackborn49237342009-08-27 20:08:01 -07001894 public FeatureInfo[] getSystemAvailableFeatures() {
1895 try {
1896 return mPM.getSystemAvailableFeatures();
1897 } catch (RemoteException e) {
1898 throw new RuntimeException("Package manager has died", e);
1899 }
1900 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001901
Dianne Hackborn49237342009-08-27 20:08:01 -07001902 @Override
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001903 public boolean hasSystemFeature(String name) {
1904 try {
1905 return mPM.hasSystemFeature(name);
1906 } catch (RemoteException e) {
1907 throw new RuntimeException("Package manager has died", e);
1908 }
1909 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001910
Dianne Hackborn039c68e2009-09-26 16:39:23 -07001911 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 public int checkPermission(String permName, String pkgName) {
1913 try {
1914 return mPM.checkPermission(permName, pkgName);
1915 } catch (RemoteException e) {
1916 throw new RuntimeException("Package manager has died", e);
1917 }
1918 }
1919
1920 @Override
1921 public boolean addPermission(PermissionInfo info) {
1922 try {
1923 return mPM.addPermission(info);
1924 } catch (RemoteException e) {
1925 throw new RuntimeException("Package manager has died", e);
1926 }
1927 }
1928
1929 @Override
Dianne Hackbornd7c09682010-03-30 10:42:20 -07001930 public boolean addPermissionAsync(PermissionInfo info) {
1931 try {
1932 return mPM.addPermissionAsync(info);
1933 } catch (RemoteException e) {
1934 throw new RuntimeException("Package manager has died", e);
1935 }
1936 }
1937
1938 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 public void removePermission(String name) {
1940 try {
1941 mPM.removePermission(name);
1942 } catch (RemoteException e) {
1943 throw new RuntimeException("Package manager has died", e);
1944 }
1945 }
1946
1947 @Override
1948 public int checkSignatures(String pkg1, String pkg2) {
1949 try {
1950 return mPM.checkSignatures(pkg1, pkg2);
1951 } catch (RemoteException e) {
1952 throw new RuntimeException("Package manager has died", e);
1953 }
1954 }
1955
1956 @Override
Dianne Hackborn766cbfe2009-08-12 18:33:39 -07001957 public int checkSignatures(int uid1, int uid2) {
1958 try {
1959 return mPM.checkUidSignatures(uid1, uid2);
1960 } catch (RemoteException e) {
1961 throw new RuntimeException("Package manager has died", e);
1962 }
1963 }
1964
1965 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 public String[] getPackagesForUid(int uid) {
1967 try {
1968 return mPM.getPackagesForUid(uid);
1969 } catch (RemoteException e) {
1970 throw new RuntimeException("Package manager has died", e);
1971 }
1972 }
1973
1974 @Override
1975 public String getNameForUid(int uid) {
1976 try {
1977 return mPM.getNameForUid(uid);
1978 } catch (RemoteException e) {
1979 throw new RuntimeException("Package manager has died", e);
1980 }
1981 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 @Override
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02001984 public int getUidForSharedUser(String sharedUserName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 throws NameNotFoundException {
1986 try {
1987 int uid = mPM.getUidForSharedUser(sharedUserName);
1988 if(uid != -1) {
1989 return uid;
1990 }
1991 } catch (RemoteException e) {
1992 throw new RuntimeException("Package manager has died", e);
1993 }
1994 throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1995 }
1996
1997 @Override
1998 public List<PackageInfo> getInstalledPackages(int flags) {
1999 try {
2000 return mPM.getInstalledPackages(flags);
2001 } catch (RemoteException e) {
2002 throw new RuntimeException("Package manager has died", e);
2003 }
2004 }
2005
2006 @Override
2007 public List<ApplicationInfo> getInstalledApplications(int flags) {
2008 try {
2009 return mPM.getInstalledApplications(flags);
2010 } catch (RemoteException e) {
2011 throw new RuntimeException("Package manager has died", e);
2012 }
2013 }
2014
2015 @Override
2016 public ResolveInfo resolveActivity(Intent intent, int flags) {
2017 try {
2018 return mPM.resolveIntent(
2019 intent,
2020 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2021 flags);
2022 } catch (RemoteException e) {
2023 throw new RuntimeException("Package manager has died", e);
2024 }
2025 }
2026
2027 @Override
2028 public List<ResolveInfo> queryIntentActivities(Intent intent,
2029 int flags) {
2030 try {
2031 return mPM.queryIntentActivities(
2032 intent,
2033 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2034 flags);
2035 } catch (RemoteException e) {
2036 throw new RuntimeException("Package manager has died", e);
2037 }
2038 }
2039
2040 @Override
2041 public List<ResolveInfo> queryIntentActivityOptions(
2042 ComponentName caller, Intent[] specifics, Intent intent,
2043 int flags) {
2044 final ContentResolver resolver = mContext.getContentResolver();
2045
2046 String[] specificTypes = null;
2047 if (specifics != null) {
2048 final int N = specifics.length;
2049 for (int i=0; i<N; i++) {
2050 Intent sp = specifics[i];
2051 if (sp != null) {
2052 String t = sp.resolveTypeIfNeeded(resolver);
2053 if (t != null) {
2054 if (specificTypes == null) {
2055 specificTypes = new String[N];
2056 }
2057 specificTypes[i] = t;
2058 }
2059 }
2060 }
2061 }
2062
2063 try {
2064 return mPM.queryIntentActivityOptions(caller, specifics,
2065 specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
2066 flags);
2067 } catch (RemoteException e) {
2068 throw new RuntimeException("Package manager has died", e);
2069 }
2070 }
2071
2072 @Override
2073 public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
2074 try {
2075 return mPM.queryIntentReceivers(
2076 intent,
2077 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2078 flags);
2079 } catch (RemoteException e) {
2080 throw new RuntimeException("Package manager has died", e);
2081 }
2082 }
2083
2084 @Override
2085 public ResolveInfo resolveService(Intent intent, int flags) {
2086 try {
2087 return mPM.resolveService(
2088 intent,
2089 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2090 flags);
2091 } catch (RemoteException e) {
2092 throw new RuntimeException("Package manager has died", e);
2093 }
2094 }
2095
2096 @Override
2097 public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
2098 try {
2099 return mPM.queryIntentServices(
2100 intent,
2101 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2102 flags);
2103 } catch (RemoteException e) {
2104 throw new RuntimeException("Package manager has died", e);
2105 }
2106 }
2107
2108 @Override
2109 public ProviderInfo resolveContentProvider(String name,
2110 int flags) {
2111 try {
2112 return mPM.resolveContentProvider(name, flags);
2113 } catch (RemoteException e) {
2114 throw new RuntimeException("Package manager has died", e);
2115 }
2116 }
2117
2118 @Override
2119 public List<ProviderInfo> queryContentProviders(String processName,
2120 int uid, int flags) {
2121 try {
2122 return mPM.queryContentProviders(processName, uid, flags);
2123 } catch (RemoteException e) {
2124 throw new RuntimeException("Package manager has died", e);
2125 }
2126 }
2127
2128 @Override
2129 public InstrumentationInfo getInstrumentationInfo(
2130 ComponentName className, int flags)
2131 throws NameNotFoundException {
2132 try {
2133 InstrumentationInfo ii = mPM.getInstrumentationInfo(
2134 className, flags);
2135 if (ii != null) {
2136 return ii;
2137 }
2138 } catch (RemoteException e) {
2139 throw new RuntimeException("Package manager has died", e);
2140 }
2141
2142 throw new NameNotFoundException(className.toString());
2143 }
2144
2145 @Override
2146 public List<InstrumentationInfo> queryInstrumentation(
2147 String targetPackage, int flags) {
2148 try {
2149 return mPM.queryInstrumentation(targetPackage, flags);
2150 } catch (RemoteException e) {
2151 throw new RuntimeException("Package manager has died", e);
2152 }
2153 }
2154
2155 @Override public Drawable getDrawable(String packageName, int resid,
2156 ApplicationInfo appInfo) {
2157 ResourceName name = new ResourceName(packageName, resid);
2158 Drawable dr = getCachedIcon(name);
2159 if (dr != null) {
2160 return dr;
2161 }
2162 if (appInfo == null) {
2163 try {
2164 appInfo = getApplicationInfo(packageName, 0);
2165 } catch (NameNotFoundException e) {
2166 return null;
2167 }
2168 }
2169 try {
2170 Resources r = getResourcesForApplication(appInfo);
2171 dr = r.getDrawable(resid);
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002172 if (false) {
2173 RuntimeException e = new RuntimeException("here");
2174 e.fillInStackTrace();
2175 Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
2176 + " from package " + packageName
2177 + ": app scale=" + r.getCompatibilityInfo().applicationScale
2178 + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
2179 e);
2180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2182 + Integer.toHexString(resid) + " from " + r
2183 + ": " + dr);
2184 putCachedIcon(name, dr);
2185 return dr;
2186 } catch (NameNotFoundException e) {
2187 Log.w("PackageManager", "Failure retrieving resources for"
2188 + appInfo.packageName);
2189 } catch (RuntimeException e) {
2190 // If an exception was thrown, fall through to return
2191 // default icon.
2192 Log.w("PackageManager", "Failure retrieving icon 0x"
2193 + Integer.toHexString(resid) + " in package "
2194 + packageName, e);
2195 }
2196 return null;
2197 }
2198
2199 @Override public Drawable getActivityIcon(ComponentName activityName)
2200 throws NameNotFoundException {
2201 return getActivityInfo(activityName, 0).loadIcon(this);
2202 }
2203
2204 @Override public Drawable getActivityIcon(Intent intent)
2205 throws NameNotFoundException {
2206 if (intent.getComponent() != null) {
2207 return getActivityIcon(intent.getComponent());
2208 }
2209
2210 ResolveInfo info = resolveActivity(
2211 intent, PackageManager.MATCH_DEFAULT_ONLY);
2212 if (info != null) {
2213 return info.activityInfo.loadIcon(this);
2214 }
2215
2216 throw new NameNotFoundException(intent.toURI());
2217 }
2218
2219 @Override public Drawable getDefaultActivityIcon() {
2220 return Resources.getSystem().getDrawable(
2221 com.android.internal.R.drawable.sym_def_app_icon);
2222 }
2223
2224 @Override public Drawable getApplicationIcon(ApplicationInfo info) {
Jeff Brown07330792010-03-30 19:57:08 -07002225 return info.loadIcon(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 }
2227
2228 @Override public Drawable getApplicationIcon(String packageName)
2229 throws NameNotFoundException {
2230 return getApplicationIcon(getApplicationInfo(packageName, 0));
2231 }
Adam Powell81cd2e92010-04-21 16:35:18 -07002232
2233 @Override
2234 public Drawable getActivityLogo(ComponentName activityName)
2235 throws NameNotFoundException {
2236 return getActivityInfo(activityName, 0).loadLogo(this);
2237 }
2238
2239 @Override
2240 public Drawable getActivityLogo(Intent intent)
2241 throws NameNotFoundException {
2242 if (intent.getComponent() != null) {
2243 return getActivityLogo(intent.getComponent());
2244 }
2245
2246 ResolveInfo info = resolveActivity(
2247 intent, PackageManager.MATCH_DEFAULT_ONLY);
2248 if (info != null) {
2249 return info.activityInfo.loadLogo(this);
2250 }
2251
2252 throw new NameNotFoundException(intent.toUri(0));
2253 }
2254
2255 @Override
2256 public Drawable getApplicationLogo(ApplicationInfo info) {
2257 return info.loadLogo(this);
2258 }
2259
2260 @Override
2261 public Drawable getApplicationLogo(String packageName)
2262 throws NameNotFoundException {
2263 return getApplicationLogo(getApplicationInfo(packageName, 0));
2264 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002265
2266 @Override public Resources getResourcesForActivity(
2267 ComponentName activityName) throws NameNotFoundException {
2268 return getResourcesForApplication(
2269 getActivityInfo(activityName, 0).applicationInfo);
2270 }
2271
2272 @Override public Resources getResourcesForApplication(
2273 ApplicationInfo app) throws NameNotFoundException {
2274 if (app.packageName.equals("system")) {
2275 return mContext.mMainThread.getSystemContext().getResources();
2276 }
2277 Resources r = mContext.mMainThread.getTopLevelResources(
2278 app.uid == Process.myUid() ? app.sourceDir
Dianne Hackborn11ea3342009-07-22 21:48:55 -07002279 : app.publicSourceDir, mContext.mPackageInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 if (r != null) {
2281 return r;
2282 }
2283 throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2284 }
2285
2286 @Override public Resources getResourcesForApplication(
2287 String appPackageName) throws NameNotFoundException {
2288 return getResourcesForApplication(
2289 getApplicationInfo(appPackageName, 0));
2290 }
2291
2292 int mCachedSafeMode = -1;
2293 @Override public boolean isSafeMode() {
2294 try {
2295 if (mCachedSafeMode < 0) {
2296 mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2297 }
2298 return mCachedSafeMode != 0;
2299 } catch (RemoteException e) {
2300 throw new RuntimeException("Package manager has died", e);
2301 }
2302 }
2303
2304 static void configurationChanged() {
2305 synchronized (sSync) {
2306 sIconCache.clear();
2307 sStringCache.clear();
2308 }
2309 }
2310
Dianne Hackborn21556372010-02-04 16:34:40 -08002311 ApplicationPackageManager(ContextImpl context,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 IPackageManager pm) {
2313 mContext = context;
2314 mPM = pm;
2315 }
2316
2317 private Drawable getCachedIcon(ResourceName name) {
2318 synchronized (sSync) {
2319 WeakReference<Drawable> wr = sIconCache.get(name);
2320 if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2321 + name + ": " + wr);
2322 if (wr != null) { // we have the activity
2323 Drawable dr = wr.get();
2324 if (dr != null) {
2325 if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2326 + name + ": " + dr);
2327 return dr;
2328 }
2329 // our entry has been purged
2330 sIconCache.remove(name);
2331 }
2332 }
2333 return null;
2334 }
2335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002336 private void putCachedIcon(ResourceName name, Drawable dr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 synchronized (sSync) {
2338 sIconCache.put(name, new WeakReference<Drawable>(dr));
2339 if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2340 + name + ": " + dr);
2341 }
2342 }
2343
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002344 static final void handlePackageBroadcast(int cmd, String[] pkgList,
2345 boolean hasPkgInfo) {
2346 boolean immediateGc = false;
2347 if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
2348 immediateGc = true;
2349 }
2350 if (pkgList != null && (pkgList.length > 0)) {
2351 boolean needCleanup = false;
2352 for (String ssp : pkgList) {
2353 synchronized (sSync) {
2354 if (sIconCache.size() > 0) {
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002355 Iterator<ResourceName> it = sIconCache.keySet().iterator();
2356 while (it.hasNext()) {
2357 ResourceName nm = it.next();
2358 if (nm.packageName.equals(ssp)) {
2359 //Log.i(TAG, "Removing cached drawable for " + nm);
2360 it.remove();
2361 needCleanup = true;
2362 }
2363 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002364 }
2365 if (sStringCache.size() > 0) {
2366 Iterator<ResourceName> it = sStringCache.keySet().iterator();
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002367 while (it.hasNext()) {
2368 ResourceName nm = it.next();
2369 if (nm.packageName.equals(ssp)) {
2370 //Log.i(TAG, "Removing cached string for " + nm);
2371 it.remove();
2372 needCleanup = true;
2373 }
2374 }
2375 }
Suchi Amalapurapu08675a32010-01-28 09:57:30 -08002376 }
Dianne Hackborn4416c3d2010-05-04 17:22:49 -07002377 }
2378 if (needCleanup || hasPkgInfo) {
2379 if (immediateGc) {
2380 // Schedule an immediate gc.
2381 Runtime.getRuntime().gc();
2382 } else {
2383 ActivityThread.currentActivityThread().scheduleGcIdler();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 }
2385 }
2386 }
2387 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 private static final class ResourceName {
2390 final String packageName;
2391 final int iconId;
2392
2393 ResourceName(String _packageName, int _iconId) {
2394 packageName = _packageName;
2395 iconId = _iconId;
2396 }
2397
2398 ResourceName(ApplicationInfo aInfo, int _iconId) {
2399 this(aInfo.packageName, _iconId);
2400 }
2401
2402 ResourceName(ComponentInfo cInfo, int _iconId) {
2403 this(cInfo.applicationInfo.packageName, _iconId);
2404 }
2405
2406 ResourceName(ResolveInfo rInfo, int _iconId) {
2407 this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2408 }
2409
2410 @Override
2411 public boolean equals(Object o) {
2412 if (this == o) return true;
2413 if (o == null || getClass() != o.getClass()) return false;
2414
2415 ResourceName that = (ResourceName) o;
2416
2417 if (iconId != that.iconId) return false;
2418 return !(packageName != null ?
2419 !packageName.equals(that.packageName) : that.packageName != null);
2420
2421 }
2422
2423 @Override
2424 public int hashCode() {
2425 int result;
2426 result = packageName.hashCode();
2427 result = 31 * result + iconId;
2428 return result;
2429 }
2430
2431 @Override
2432 public String toString() {
2433 return "{ResourceName " + packageName + " / " + iconId + "}";
2434 }
2435 }
2436
2437 private CharSequence getCachedString(ResourceName name) {
2438 synchronized (sSync) {
2439 WeakReference<CharSequence> wr = sStringCache.get(name);
2440 if (wr != null) { // we have the activity
2441 CharSequence cs = wr.get();
2442 if (cs != null) {
2443 return cs;
2444 }
2445 // our entry has been purged
2446 sStringCache.remove(name);
2447 }
2448 }
2449 return null;
2450 }
2451
2452 private void putCachedString(ResourceName name, CharSequence cs) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 synchronized (sSync) {
2454 sStringCache.put(name, new WeakReference<CharSequence>(cs));
2455 }
2456 }
2457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 @Override
2459 public CharSequence getText(String packageName, int resid,
2460 ApplicationInfo appInfo) {
2461 ResourceName name = new ResourceName(packageName, resid);
2462 CharSequence text = getCachedString(name);
2463 if (text != null) {
2464 return text;
2465 }
2466 if (appInfo == null) {
2467 try {
2468 appInfo = getApplicationInfo(packageName, 0);
2469 } catch (NameNotFoundException e) {
2470 return null;
2471 }
2472 }
2473 try {
2474 Resources r = getResourcesForApplication(appInfo);
2475 text = r.getText(resid);
2476 putCachedString(name, text);
2477 return text;
2478 } catch (NameNotFoundException e) {
2479 Log.w("PackageManager", "Failure retrieving resources for"
2480 + appInfo.packageName);
2481 } catch (RuntimeException e) {
2482 // If an exception was thrown, fall through to return
2483 // default icon.
2484 Log.w("PackageManager", "Failure retrieving text 0x"
2485 + Integer.toHexString(resid) + " in package "
2486 + packageName, e);
2487 }
2488 return null;
2489 }
2490
2491 @Override
2492 public XmlResourceParser getXml(String packageName, int resid,
2493 ApplicationInfo appInfo) {
2494 if (appInfo == null) {
2495 try {
2496 appInfo = getApplicationInfo(packageName, 0);
2497 } catch (NameNotFoundException e) {
2498 return null;
2499 }
2500 }
2501 try {
2502 Resources r = getResourcesForApplication(appInfo);
2503 return r.getXml(resid);
2504 } catch (RuntimeException e) {
2505 // If an exception was thrown, fall through to return
2506 // default icon.
2507 Log.w("PackageManager", "Failure retrieving xml 0x"
2508 + Integer.toHexString(resid) + " in package "
2509 + packageName, e);
2510 } catch (NameNotFoundException e) {
2511 Log.w("PackageManager", "Failure retrieving resources for"
2512 + appInfo.packageName);
2513 }
2514 return null;
2515 }
2516
2517 @Override
2518 public CharSequence getApplicationLabel(ApplicationInfo info) {
Jeff Brown07330792010-03-30 19:57:08 -07002519 return info.loadLabel(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002520 }
2521
2522 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002523 public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2524 String installerPackageName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 try {
Jacek Surazski65e13172009-04-28 15:26:38 +02002526 mPM.installPackage(packageURI, observer, flags, installerPackageName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002527 } catch (RemoteException e) {
2528 // Should never happen!
2529 }
2530 }
2531
2532 @Override
Suchi Amalapurapu8946dd32010-02-19 09:19:34 -08002533 public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
2534 try {
2535 mPM.movePackage(packageName, observer, flags);
2536 } catch (RemoteException e) {
2537 // Should never happen!
2538 }
2539 }
2540
2541 @Override
Jacek Surazski65e13172009-04-28 15:26:38 +02002542 public String getInstallerPackageName(String packageName) {
2543 try {
2544 return mPM.getInstallerPackageName(packageName);
2545 } catch (RemoteException e) {
2546 // Should never happen!
2547 }
2548 return null;
2549 }
2550
2551 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002552 public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2553 try {
2554 mPM.deletePackage(packageName, observer, flags);
2555 } catch (RemoteException e) {
2556 // Should never happen!
2557 }
2558 }
2559 @Override
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002560 public void clearApplicationUserData(String packageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 IPackageDataObserver observer) {
2562 try {
2563 mPM.clearApplicationUserData(packageName, observer);
2564 } catch (RemoteException e) {
2565 // Should never happen!
2566 }
2567 }
2568 @Override
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002569 public void deleteApplicationCacheFiles(String packageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 IPackageDataObserver observer) {
2571 try {
2572 mPM.deleteApplicationCacheFiles(packageName, observer);
2573 } catch (RemoteException e) {
2574 // Should never happen!
2575 }
2576 }
2577 @Override
2578 public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2579 try {
2580 mPM.freeStorageAndNotify(idealStorageSize, observer);
2581 } catch (RemoteException e) {
2582 // Should never happen!
2583 }
2584 }
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 @Override
Suchi Amalapurapubc806f62009-06-17 15:18:19 -07002587 public void freeStorage(long freeStorageSize, IntentSender pi) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002588 try {
Suchi Amalapurapu1ccac752009-06-12 10:09:58 -07002589 mPM.freeStorage(freeStorageSize, pi);
2590 } catch (RemoteException e) {
2591 // Should never happen!
2592 }
2593 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 @Override
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002596 public void getPackageSizeInfo(String packageName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597 IPackageStatsObserver observer) {
2598 try {
2599 mPM.getPackageSizeInfo(packageName, observer);
2600 } catch (RemoteException e) {
2601 // Should never happen!
2602 }
2603 }
2604 @Override
2605 public void addPackageToPreferred(String packageName) {
2606 try {
2607 mPM.addPackageToPreferred(packageName);
2608 } catch (RemoteException e) {
2609 // Should never happen!
2610 }
2611 }
2612
2613 @Override
2614 public void removePackageFromPreferred(String packageName) {
2615 try {
2616 mPM.removePackageFromPreferred(packageName);
2617 } catch (RemoteException e) {
2618 // Should never happen!
2619 }
2620 }
2621
2622 @Override
2623 public List<PackageInfo> getPreferredPackages(int flags) {
2624 try {
2625 return mPM.getPreferredPackages(flags);
2626 } catch (RemoteException e) {
2627 // Should never happen!
2628 }
2629 return new ArrayList<PackageInfo>();
2630 }
2631
2632 @Override
2633 public void addPreferredActivity(IntentFilter filter,
2634 int match, ComponentName[] set, ComponentName activity) {
2635 try {
2636 mPM.addPreferredActivity(filter, match, set, activity);
2637 } catch (RemoteException e) {
2638 // Should never happen!
2639 }
2640 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002642 @Override
Satish Sampath8dbe6122009-06-02 23:35:54 +01002643 public void replacePreferredActivity(IntentFilter filter,
2644 int match, ComponentName[] set, ComponentName activity) {
2645 try {
2646 mPM.replacePreferredActivity(filter, match, set, activity);
2647 } catch (RemoteException e) {
2648 // Should never happen!
2649 }
2650 }
2651
2652 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 public void clearPackagePreferredActivities(String packageName) {
2654 try {
2655 mPM.clearPackagePreferredActivities(packageName);
2656 } catch (RemoteException e) {
2657 // Should never happen!
2658 }
2659 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 @Override
2662 public int getPreferredActivities(List<IntentFilter> outFilters,
2663 List<ComponentName> outActivities, String packageName) {
2664 try {
2665 return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2666 } catch (RemoteException e) {
2667 // Should never happen!
2668 }
2669 return 0;
2670 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 @Override
2673 public void setComponentEnabledSetting(ComponentName componentName,
2674 int newState, int flags) {
2675 try {
2676 mPM.setComponentEnabledSetting(componentName, newState, flags);
2677 } catch (RemoteException e) {
2678 // Should never happen!
2679 }
2680 }
2681
2682 @Override
2683 public int getComponentEnabledSetting(ComponentName componentName) {
2684 try {
2685 return mPM.getComponentEnabledSetting(componentName);
2686 } catch (RemoteException e) {
2687 // Should never happen!
2688 }
2689 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2690 }
2691
2692 @Override
2693 public void setApplicationEnabledSetting(String packageName,
2694 int newState, int flags) {
2695 try {
2696 mPM.setApplicationEnabledSetting(packageName, newState, flags);
2697 } catch (RemoteException e) {
2698 // Should never happen!
2699 }
2700 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 @Override
2703 public int getApplicationEnabledSetting(String packageName) {
2704 try {
2705 return mPM.getApplicationEnabledSetting(packageName);
2706 } catch (RemoteException e) {
2707 // Should never happen!
2708 }
2709 return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2710 }
2711
Kenny Root93565c42010-06-18 15:46:06 -07002712 @Override
2713 public void setPackageObbPath(String packageName, String path) {
2714 try {
2715 mPM.setPackageObbPath(packageName, path);
2716 } catch (RemoteException e) {
2717 // Should never happen!
2718 }
2719 }
2720
Dianne Hackborn21556372010-02-04 16:34:40 -08002721 private final ContextImpl mContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 private final IPackageManager mPM;
2723
2724 private static final Object sSync = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002725 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2726 = new HashMap<ResourceName, WeakReference<Drawable> >();
2727 private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2728 = new HashMap<ResourceName, WeakReference<CharSequence> >();
2729 }
2730
2731 // ----------------------------------------------------------------------
2732 // ----------------------------------------------------------------------
2733 // ----------------------------------------------------------------------
2734
2735 private static final class SharedPreferencesImpl implements SharedPreferences {
2736
Brad Fitzpatrick6194c532010-09-07 18:00:33 -07002737 // Lock ordering rules:
2738 // - acquire SharedPreferencesImpl.this before EditorImpl.this
2739 // - acquire mWritingToDiskLock before EditorImpl.this
2740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 private final File mFile;
2742 private final File mBackupFile;
2743 private final int mMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002744
Brad Fitzpatrick9acdeb92010-10-08 15:20:11 -07002745 private Map<String, Object> mMap; // guarded by 'this'
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002746 private int mDiskWritesInFlight = 0; // guarded by 'this'
Brad Fitzpatrick9acdeb92010-10-08 15:20:11 -07002747 private boolean mLoaded = false; // guarded by 'this'
2748 private long mStatTimestamp; // guarded by 'this'
2749 private long mStatSize; // guarded by 'this'
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002750
2751 private final Object mWritingToDiskLock = new Object();
The Android Open Source Project10592532009-03-18 17:39:46 -07002752 private static final Object mContent = new Object();
Brad Fitzpatrick9acdeb92010-10-08 15:20:11 -07002753 private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002754
2755 SharedPreferencesImpl(
2756 File file, int mode, Map initialContents) {
2757 mFile = file;
2758 mBackupFile = makeBackupFile(file);
2759 mMode = mode;
Brad Fitzpatrick6194c532010-09-07 18:00:33 -07002760 mLoaded = initialContents != null;
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002761 mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
2762 FileStatus stat = new FileStatus();
2763 if (FileUtils.getFileStatus(file.getPath(), stat)) {
Brad Fitzpatrick9acdeb92010-10-08 15:20:11 -07002764 mStatTimestamp = stat.mtime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002766 mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 }
2768
Brad Fitzpatrick6194c532010-09-07 18:00:33 -07002769 // Has this SharedPreferences ever had values assigned to it?
2770 boolean isLoaded() {
2771 synchronized (this) {
2772 return mLoaded;
2773 }
2774 }
2775
2776 // Has the file changed out from under us? i.e. writes that
2777 // we didn't instigate.
2778 public boolean hasFileChangedUnexpectedly() {
2779 synchronized (this) {
2780 if (mDiskWritesInFlight > 0) {
2781 // If we know we caused it, it's not unexpected.
Brad Fitzpatrick90bc5ee2010-10-07 11:26:57 -07002782 if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected.");
Brad Fitzpatrick6194c532010-09-07 18:00:33 -07002783 return false;
2784 }
2785 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002786 FileStatus stat = new FileStatus();
2787 if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
2788 return true;
2789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 synchronized (this) {
Brad Fitzpatrick9acdeb92010-10-08 15:20:11 -07002791 return mStatTimestamp != stat.mtime || mStatSize != stat.size;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 }
2793 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002795 public void replace(Map newContents) {
Brad Fitzpatrick6194c532010-09-07 18:00:33 -07002796 synchronized (this) {
2797 mLoaded = true;
2798 if (newContents != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002799 mMap = newContents;
2800 }
2801 }
2802 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02002803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2805 synchronized(this) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002806 mListeners.put(listener, mContent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002807 }
2808 }
2809
2810 public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2811 synchronized(this) {
2812 mListeners.remove(listener);
2813 }
2814 }
2815
2816 public Map<String, ?> getAll() {
2817 synchronized(this) {
2818 //noinspection unchecked
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002819 return new HashMap<String, Object>(mMap);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002820 }
2821 }
2822
2823 public String getString(String key, String defValue) {
2824 synchronized (this) {
2825 String v = (String)mMap.get(key);
2826 return v != null ? v : defValue;
2827 }
2828 }
Adam Powell212db7d2010-04-08 16:24:46 -07002829
2830 public Set<String> getStringSet(String key, Set<String> defValues) {
2831 synchronized (this) {
2832 Set<String> v = (Set<String>) mMap.get(key);
2833 return v != null ? v : defValues;
2834 }
2835 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002836
2837 public int getInt(String key, int defValue) {
2838 synchronized (this) {
2839 Integer v = (Integer)mMap.get(key);
2840 return v != null ? v : defValue;
2841 }
2842 }
2843 public long getLong(String key, long defValue) {
2844 synchronized (this) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002845 Long v = (Long)mMap.get(key);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 return v != null ? v : defValue;
2847 }
2848 }
2849 public float getFloat(String key, float defValue) {
2850 synchronized (this) {
2851 Float v = (Float)mMap.get(key);
2852 return v != null ? v : defValue;
2853 }
2854 }
2855 public boolean getBoolean(String key, boolean defValue) {
2856 synchronized (this) {
2857 Boolean v = (Boolean)mMap.get(key);
2858 return v != null ? v : defValue;
2859 }
2860 }
2861
2862 public boolean contains(String key) {
2863 synchronized (this) {
2864 return mMap.containsKey(key);
2865 }
2866 }
2867
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002868 public Editor edit() {
2869 return new EditorImpl();
2870 }
2871
2872 // Return value from EditorImpl#commitToMemory()
2873 private static class MemoryCommitResult {
2874 public boolean changesMade; // any keys different?
2875 public List<String> keysModified; // may be null
2876 public Set<OnSharedPreferenceChangeListener> listeners; // may be null
2877 public Map<?, ?> mapToWriteToDisk;
2878 public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
2879 public volatile boolean writeToDiskResult = false;
2880
2881 public void setDiskWriteResult(boolean result) {
2882 writeToDiskResult = result;
2883 writtenToDiskLatch.countDown();
2884 }
2885 }
2886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 public final class EditorImpl implements Editor {
2888 private final Map<String, Object> mModified = Maps.newHashMap();
2889 private boolean mClear = false;
2890
2891 public Editor putString(String key, String value) {
2892 synchronized (this) {
2893 mModified.put(key, value);
2894 return this;
2895 }
2896 }
Adam Powell212db7d2010-04-08 16:24:46 -07002897 public Editor putStringSet(String key, Set<String> values) {
2898 synchronized (this) {
2899 mModified.put(key, values);
2900 return this;
2901 }
2902 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 public Editor putInt(String key, int value) {
2904 synchronized (this) {
2905 mModified.put(key, value);
2906 return this;
2907 }
2908 }
2909 public Editor putLong(String key, long value) {
2910 synchronized (this) {
2911 mModified.put(key, value);
2912 return this;
2913 }
2914 }
2915 public Editor putFloat(String key, float value) {
2916 synchronized (this) {
2917 mModified.put(key, value);
2918 return this;
2919 }
2920 }
2921 public Editor putBoolean(String key, boolean value) {
2922 synchronized (this) {
2923 mModified.put(key, value);
2924 return this;
2925 }
2926 }
2927
2928 public Editor remove(String key) {
2929 synchronized (this) {
2930 mModified.put(key, this);
2931 return this;
2932 }
2933 }
2934
2935 public Editor clear() {
2936 synchronized (this) {
2937 mClear = true;
2938 return this;
2939 }
2940 }
2941
Brad Fitzpatrick66fce502010-08-30 18:10:49 -07002942 public void apply() {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002943 final MemoryCommitResult mcr = commitToMemory();
2944 final Runnable awaitCommit = new Runnable() {
2945 public void run() {
2946 try {
2947 mcr.writtenToDiskLatch.await();
2948 } catch (InterruptedException ignored) {
2949 }
2950 }
2951 };
2952
2953 QueuedWork.add(awaitCommit);
2954
2955 Runnable postWriteRunnable = new Runnable() {
2956 public void run() {
2957 awaitCommit.run();
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002958 QueuedWork.remove(awaitCommit);
2959 }
2960 };
2961
2962 SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
2963
2964 // Okay to notify the listeners before it's hit disk
2965 // because the listeners should always get the same
2966 // SharedPreferences instance back, which has the
2967 // changes reflected in memory.
2968 notifyListeners(mcr);
Brad Fitzpatrickedf32d02010-08-25 13:13:36 -07002969 }
2970
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002971 // Returns true if any changes were made
2972 private MemoryCommitResult commitToMemory() {
2973 MemoryCommitResult mcr = new MemoryCommitResult();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 synchronized (SharedPreferencesImpl.this) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002975 // We optimistically don't make a deep copy until
2976 // a memory commit comes in when we're already
2977 // writing to disk.
2978 if (mDiskWritesInFlight > 0) {
2979 // We can't modify our mMap as a currently
2980 // in-flight write owns it. Clone it before
2981 // modifying it.
2982 // noinspection unchecked
2983 mMap = new HashMap<String, Object>(mMap);
2984 }
2985 mcr.mapToWriteToDisk = mMap;
2986 mDiskWritesInFlight++;
2987
2988 boolean hasListeners = mListeners.size() > 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002989 if (hasListeners) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002990 mcr.keysModified = new ArrayList<String>();
2991 mcr.listeners =
2992 new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 }
2994
2995 synchronized (this) {
2996 if (mClear) {
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07002997 if (!mMap.isEmpty()) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07002998 mcr.changesMade = true;
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07002999 mMap.clear();
3000 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 mClear = false;
3002 }
3003
The Android Open Source Project10592532009-03-18 17:39:46 -07003004 for (Entry<String, Object> e : mModified.entrySet()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 String k = e.getKey();
3006 Object v = e.getValue();
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07003007 if (v == this) { // magic value for a removal mutation
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003008 if (!mMap.containsKey(k)) {
3009 continue;
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07003010 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003011 mMap.remove(k);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 } else {
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07003013 boolean isSame = false;
3014 if (mMap.containsKey(k)) {
3015 Object existingValue = mMap.get(k);
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003016 if (existingValue != null && existingValue.equals(v)) {
3017 continue;
3018 }
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07003019 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003020 mMap.put(k, v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003021 }
3022
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003023 mcr.changesMade = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003024 if (hasListeners) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003025 mcr.keysModified.add(k);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 }
3027 }
3028
3029 mModified.clear();
3030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003031 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003032 return mcr;
3033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003035 public boolean commit() {
3036 MemoryCommitResult mcr = commitToMemory();
3037 SharedPreferencesImpl.this.enqueueDiskWrite(
3038 mcr, null /* sync write on this thread okay */);
3039 try {
3040 mcr.writtenToDiskLatch.await();
3041 } catch (InterruptedException e) {
3042 return false;
3043 }
3044 notifyListeners(mcr);
3045 return mcr.writeToDiskResult;
3046 }
3047
3048 private void notifyListeners(final MemoryCommitResult mcr) {
3049 if (mcr.listeners == null || mcr.keysModified == null ||
3050 mcr.keysModified.size() == 0) {
3051 return;
3052 }
3053 if (Looper.myLooper() == Looper.getMainLooper()) {
3054 for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
3055 final String key = mcr.keysModified.get(i);
3056 for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003057 if (listener != null) {
3058 listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
3059 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003060 }
3061 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003062 } else {
3063 // Run this function on the main thread.
3064 ActivityThread.sMainThreadHandler.post(new Runnable() {
3065 public void run() {
3066 notifyListeners(mcr);
3067 }
3068 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003069 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 }
3071 }
3072
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003073 /**
3074 * Enqueue an already-committed-to-memory result to be written
3075 * to disk.
3076 *
3077 * They will be written to disk one-at-a-time in the order
3078 * that they're enqueued.
3079 *
3080 * @param postWriteRunnable if non-null, we're being called
Brad Fitzpatrick66fce502010-08-30 18:10:49 -07003081 * from apply() and this is the runnable to run after
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003082 * the write proceeds. if null (from a regular commit()),
3083 * then we're allowed to do this disk write on the main
3084 * thread (which in addition to reducing allocations and
3085 * creating a background thread, this has the advantage that
3086 * we catch them in userdebug StrictMode reports to convert
Brad Fitzpatrick66fce502010-08-30 18:10:49 -07003087 * them where possible to apply() ...)
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003088 */
3089 private void enqueueDiskWrite(final MemoryCommitResult mcr,
3090 final Runnable postWriteRunnable) {
3091 final Runnable writeToDiskRunnable = new Runnable() {
3092 public void run() {
3093 synchronized (mWritingToDiskLock) {
3094 writeToFile(mcr);
3095 }
3096 synchronized (SharedPreferencesImpl.this) {
3097 mDiskWritesInFlight--;
3098 }
3099 if (postWriteRunnable != null) {
3100 postWriteRunnable.run();
3101 }
3102 }
3103 };
3104
3105 final boolean isFromSyncCommit = (postWriteRunnable == null);
3106
3107 // Typical #commit() path with fewer allocations, doing a write on
3108 // the current thread.
3109 if (isFromSyncCommit) {
3110 boolean wasEmpty = false;
3111 synchronized (SharedPreferencesImpl.this) {
3112 wasEmpty = mDiskWritesInFlight == 1;
3113 }
3114 if (wasEmpty) {
3115 writeToDiskRunnable.run();
3116 return;
3117 }
3118 }
3119
3120 QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02003122
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003123 private static FileOutputStream createFileOutputStream(File file) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003124 FileOutputStream str = null;
3125 try {
3126 str = new FileOutputStream(file);
3127 } catch (FileNotFoundException e) {
3128 File parent = file.getParentFile();
3129 if (!parent.mkdir()) {
3130 Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
3131 return null;
3132 }
3133 FileUtils.setPermissions(
3134 parent.getPath(),
3135 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3136 -1, -1);
3137 try {
3138 str = new FileOutputStream(file);
3139 } catch (FileNotFoundException e2) {
3140 Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
3141 }
3142 }
3143 return str;
3144 }
3145
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003146 // Note: must hold mWritingToDiskLock
3147 private void writeToFile(MemoryCommitResult mcr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 // Rename the current file so it may be used as a backup during the next read
3149 if (mFile.exists()) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003150 if (!mcr.changesMade) {
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07003151 // If the file already exists, but no changes were
3152 // made to the underlying map, it's wasteful to
3153 // re-write the file. Return as if we wrote it
3154 // out.
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003155 mcr.setDiskWriteResult(true);
3156 return;
Brad Fitzpatrick67fed012010-08-17 10:29:15 -07003157 }
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003158 if (!mBackupFile.exists()) {
3159 if (!mFile.renameTo(mBackupFile)) {
3160 Log.e(TAG, "Couldn't rename file " + mFile
3161 + " to backup file " + mBackupFile);
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003162 mcr.setDiskWriteResult(false);
3163 return;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -07003164 }
3165 } else {
3166 mFile.delete();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003167 }
3168 }
Christian Mehlmauer5f5acca2010-06-25 19:06:18 +02003169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003170 // Attempt to write the file, delete the backup and return true as atomically as
3171 // possible. If any exception occurs, delete the new file; next time we will restore
3172 // from the backup.
3173 try {
3174 FileOutputStream str = createFileOutputStream(mFile);
3175 if (str == null) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003176 mcr.setDiskWriteResult(false);
3177 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003179 XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
Dianne Hackborn8bdf5932010-10-15 12:54:40 -07003180 FileUtils.sync(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 str.close();
3182 setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003183 FileStatus stat = new FileStatus();
3184 if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
3185 synchronized (this) {
Brad Fitzpatrick9acdeb92010-10-08 15:20:11 -07003186 mStatTimestamp = stat.mtime;
3187 mStatSize = stat.size;
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 }
Dianne Hackborn51bf0772009-03-24 19:11:41 -07003190 // Writing was successful, delete the backup file if there is one.
3191 mBackupFile.delete();
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003192 mcr.setDiskWriteResult(true);
3193 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003194 } catch (XmlPullParserException e) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003195 Log.w(TAG, "writeToFile: Got exception:", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003196 } catch (IOException e) {
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003197 Log.w(TAG, "writeToFile: Got exception:", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198 }
3199 // Clean up an unsuccessfully written file
3200 if (mFile.exists()) {
3201 if (!mFile.delete()) {
3202 Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
3203 }
3204 }
Brad Fitzpatrick333b8cb2010-08-26 12:04:57 -07003205 mcr.setDiskWriteResult(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 }
3207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208}