ContextImpl.java revision 31fd85f39b554e09b2e6c1c2ccf5c186859880fa
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectpackage android.app;
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport com.android.internal.policy.PolicyManager;
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport com.android.internal.util.XmlUtils;
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport com.google.android.collect.Maps;
22ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.BroadcastReceiver;
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.ComponentName;
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.ContentResolver;
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.Context;
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.ContextWrapper;
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.IContentProvider;
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.Intent;
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.IntentFilter;
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.IIntentReceiver;
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.IntentSender;
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.ReceiverCallNotAllowedException;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.ServiceConnection;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.SharedPreferences;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.ActivityInfo;
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.ApplicationInfo;
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.ComponentInfo;
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.FeatureInfo;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.IPackageDataObserver;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.IPackageDeleteObserver;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.IPackageInstallObserver;
45b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savilleimport android.content.pm.IPackageMoveObserver;
46b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Savilleimport android.content.pm.IPackageManager;
472a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.IPackageStatsObserver;
482a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.InstrumentationInfo;
492a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.PackageInfo;
502a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.PackageManager;
512a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.PermissionGroupInfo;
522a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.PermissionInfo;
532a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.ProviderInfo;
542a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.content.pm.ResolveInfo;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.ServiceInfo;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.pm.PackageParser.Package;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.res.AssetManager;
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.res.Resources;
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.content.res.XmlResourceParser;
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase.CursorFactory;
622a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.graphics.Bitmap;
632a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetlandimport android.graphics.drawable.Drawable;
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.hardware.SensorManager;
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.location.ILocationManager;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.location.LocationManager;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.media.AudioManager;
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.net.ConnectivityManager;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.net.IConnectivityManager;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.net.ThrottleManager;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.net.IThrottleManager;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.net.Uri;
73ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuangimport android.net.wifi.IWifiManager;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.net.wifi.WifiManager;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Binder;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Bundle;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.DropBoxManager;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Environment;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.FileUtils;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Handler;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.IBinder;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.IPowerManager;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Looper;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.PowerManager;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Process;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.RemoteException;
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.ServiceManager;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.StatFs;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.Vibrator;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.FileUtils.FileStatus;
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.os.storage.StorageManager;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.provider.Settings;
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.telephony.TelephonyManager;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.text.ClipboardManager;
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.util.AndroidRuntimeException;
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.util.Log;
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.view.ContextThemeWrapper;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.view.LayoutInflater;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.view.WindowManagerImpl;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.view.accessibility.AccessibilityManager;
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.accounts.AccountManager;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport android.accounts.IAccountManager;
104ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuangimport android.app.admin.DevicePolicyManager;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport com.android.internal.os.IDropBoxManagerService;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.io.File;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.io.FileInputStream;
110ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuangimport java.io.FileNotFoundException;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.io.FileOutputStream;
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.io.IOException;
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.io.InputStream;
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.lang.ref.WeakReference;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.ArrayList;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.HashMap;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.HashSet;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.Iterator;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.List;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.Map;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.Map.Entry;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.Set;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.WeakHashMap;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.concurrent.CountDownLatch;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectimport java.util.concurrent.ExecutorService;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectclass ReceiverRestrictedContext extends ContextWrapper {
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ReceiverRestrictedContext(Context base) {
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        super(base);
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return registerReceiver(receiver, filter, null, null);
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            String broadcastPermission, Handler scheduler) {
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throw new ReceiverCallNotAllowedException(
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                "IntentReceiver components are not allowed to register to receive intents");
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //ex.fillInStackTrace();
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //Log.e("IntentReceiver", ex.getMessage(), ex);
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //return mContext.registerReceiver(receiver, filter, broadcastPermission,
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //        scheduler);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throw new ReceiverCallNotAllowedException(
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                "IntentReceiver components are not allowed to bind to services");
15209070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood        //ex.fillInStackTrace();
153f614d64d4b4dfcd20c77ac3ccf2d9c9090a49303The Android Open Source Project        //Log.e("IntentReceiver", ex.getMessage(), ex);
154e25ff1c682ae5cc87af5e76de7e31a2702b620f3Robert CH Chou        //return mContext.bindService(service, interfaceName, conn, flags);
155509f7399b8f246f506307b22039e63323ec09622Dima Zavin    }
156509f7399b8f246f506307b22039e63323ec09622Dima Zavin}
15709070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood
15837e9e904360d6a8757c958dacaab1343eacb7fa8Erik Gilling/**
159af82f21df7b87af2b378a46c8f338ebdd9c66175Xavier Ducrohet * Common implementation of Context API, which provides the base
16009070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood * context object for Activity and other application components.
16109070d9e8685645f4ca8ecca62ae489472aed646Mike Lockwood */
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectclass ContextImpl extends Context {
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private final static String TAG = "ApplicationContext";
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private final static boolean DEBUG = false;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private final static boolean DEBUG_ICONS = false;
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static final Object sSync = new Object();
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static AlarmManager sAlarmManager;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static PowerManager sPowerManager;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static ConnectivityManager sConnectivityManager;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static ThrottleManager sThrottleManager;
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static WifiManager sWifiManager;
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static LocationManager sLocationManager;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
175b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes            new HashMap<String, SharedPreferencesImpl>();
176b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes
177b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes    private AudioManager mAudioManager;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /*package*/ LoadedApk mPackageInfo;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private Resources mResources;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /*package*/ ActivityThread mMainThread;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private Context mOuterContext;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private IBinder mActivityToken = null;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private ApplicationContentResolver mContentResolver;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private int mThemeResource = 0;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private Resources.Theme mTheme = null;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private PackageManager mPackageManager;
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private NotificationManager mNotificationManager = null;
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private ActivityManager mActivityManager = null;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private WallpaperManager mWallpaperManager = null;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private Context mReceiverRestrictedContext = null;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private SearchManager mSearchManager = null;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private SensorManager mSensorManager = null;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private StorageManager mStorageManager = null;
194ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    private Vibrator mVibrator = null;
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private LayoutInflater mLayoutInflater = null;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private StatusBarManager mStatusBarManager = null;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private TelephonyManager mTelephonyManager = null;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private ClipboardManager mClipboardManager = null;
199ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    private boolean mRestricted;
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private AccountManager mAccountManager; // protected by mSync
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private DropBoxManager mDropBoxManager = null;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private DevicePolicyManager mDevicePolicyManager = null;
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private UiModeManager mUiModeManager = null;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private DownloadManager mDownloadManager = null;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private final Object mSync = new Object();
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File mDatabasesDir;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File mPreferencesDir;
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File mFilesDir;
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File mCacheDir;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File mExternalFilesDir;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File mExternalCacheDir;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static long sInstanceCount = 0;
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static final String[] EMPTY_FILE_LIST = {};
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // For debug only
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /*
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    protected void finalize() throws Throwable {
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        super.finalize();
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        --sInstanceCount;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    */
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22824ce4bc8d7c4706286ef0530870dea80a1a0cd11Bruce Beare    public static long getInstanceCount() {
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return sInstanceCount;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
231ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public AssetManager getAssets() {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return mResources.getAssets();
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Resources getResources() {
23995ec983887867a117f4ef87073495111aff4a506Dima Zavin        return mResources;
240931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin    }
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public PackageManager getPackageManager() {
244931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin        if (mPackageManager != null) {
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mPackageManager;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IPackageManager pm = ActivityThread.getPackageManager();
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (pm != null) {
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Doesn't matter if we make more than one instance.
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return (mPackageManager = new ApplicationPackageManager(this, pm));
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return null;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public ContentResolver getContentResolver() {
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return mContentResolver;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
262ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    @Override
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Looper getMainLooper() {
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return mMainThread.getLooper();
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
266ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Context getApplicationContext() {
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return (mPackageInfo != null) ?
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mPackageInfo.getApplication() : mMainThread.getApplication();
271ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void setTheme(int resid) {
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mThemeResource = resid;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Resources.Theme getTheme() {
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mTheme == null) {
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mThemeResource == 0) {
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mThemeResource = com.android.internal.R.style.Theme;
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            mTheme = mResources.newTheme();
285931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin            mTheme.applyStyle(mThemeResource, true);
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return mTheme;
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public ClassLoader getClassLoader() {
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return mPackageInfo != null ?
293ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang                mPackageInfo.getClassLoader() : ClassLoader.getSystemClassLoader();
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public String getPackageName() {
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mPackageInfo != null) {
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mPackageInfo.getPackageName();
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throw new RuntimeException("Not supported in system context");
302ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public ApplicationInfo getApplicationInfo() {
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mPackageInfo != null) {
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mPackageInfo.getApplicationInfo();
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throw new RuntimeException("Not supported in system context");
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public String getPackageResourcePath() {
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mPackageInfo != null) {
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mPackageInfo.getResDir();
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throw new RuntimeException("Not supported in system context");
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public String getPackageCodePath() {
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (mPackageInfo != null) {
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mPackageInfo.getAppDir();
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throw new RuntimeException("Not supported in system context");
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private static File makeBackupFile(File prefsFile) {
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return new File(prefsFile.getPath() + ".bak");
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getSharedPrefsFile(String name) {
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return makeFilename(getPreferencesDir(), name + ".xml");
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public SharedPreferences getSharedPreferences(String name, int mode) {
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SharedPreferencesImpl sp;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        File prefsFile;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        boolean needInitialLoad = false;
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (sSharedPrefs) {
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sp = sSharedPrefs.get(name);
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sp != null && !sp.hasFileChangedUnexpectedly()) {
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return sp;
345b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            }
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            prefsFile = getSharedPrefsFile(name);
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (sp == null) {
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                sp = new SharedPreferencesImpl(prefsFile, mode, null);
349ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang                sSharedPrefs.put(name, sp);
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                needInitialLoad = true;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (sp) {
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (needInitialLoad && sp.isLoaded()) {
356b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                // lost the race to load; another thread handled it
357b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                return sp;
358b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            }
359b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            File backup = makeBackupFile(prefsFile);
360b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            if (backup.exists()) {
361b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                prefsFile.delete();
362b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                backup.renameTo(prefsFile);
363b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville            }
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Debugging
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (prefsFile.exists() && !prefsFile.canRead()) {
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                Log.w(TAG, "Attempt to read preferences file " + prefsFile + " without permission");
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Map map = null;
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (prefsFile.exists() && prefsFile.canRead()) {
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                try {
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    FileInputStream str = new FileInputStream(prefsFile);
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    map = XmlUtils.readMapXml(str);
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    str.close();
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } catch (org.xmlpull.v1.XmlPullParserException e) {
377ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang                    Log.w(TAG, "getSharedPreferences", e);
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } catch (FileNotFoundException e) {
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "getSharedPreferences", e);
380ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang                } catch (IOException e) {
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "getSharedPreferences", e);
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            sp.replace(map);
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return sp;
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File getPreferencesDir() {
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (mSync) {
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mPreferencesDir == null) {
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mPreferencesDir = new File(getDataDirFile(), "shared_prefs");
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mPreferencesDir;
395b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville        }
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public FileInputStream openFileInput(String name)
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throws FileNotFoundException {
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        File f = makeFilename(getFilesDir(), name);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return new FileInputStream(f);
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public FileOutputStream openFileOutput(String name, int mode)
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        throws FileNotFoundException {
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        final boolean append = (mode&MODE_APPEND) != 0;
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        File f = makeFilename(getFilesDir(), name);
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FileOutputStream fos = new FileOutputStream(f, append);
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            setFilePermissionsFromMode(f.getPath(), mode, 0);
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return fos;
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (FileNotFoundException e) {
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        File parent = f.getParentFile();
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parent.mkdir();
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FileUtils.setPermissions(
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parent.getPath(),
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            -1, -1);
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        FileOutputStream fos = new FileOutputStream(f, append);
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        setFilePermissionsFromMode(f.getPath(), mode, 0);
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return fos;
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public boolean deleteFile(String name) {
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        File f = makeFilename(getFilesDir(), name);
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return f.delete();
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getFilesDir() {
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (mSync) {
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mFilesDir == null) {
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mFilesDir = new File(getDataDirFile(), "files");
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!mFilesDir.exists()) {
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(!mFilesDir.mkdirs()) {
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "Unable to create files directory");
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return null;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                FileUtils.setPermissions(
446b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                        mFilesDir.getPath(),
447b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        -1, -1);
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mFilesDir;
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getExternalFilesDir(String type) {
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (mSync) {
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mExternalFilesDir == null) {
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mExternalFilesDir = Environment.getExternalStorageAppFilesDirectory(
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        getPackageName());
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!mExternalFilesDir.exists()) {
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                try {
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    (new File(Environment.getExternalStorageAndroidDataDir(),
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            ".nomedia")).createNewFile();
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } catch (IOException e) {
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (!mExternalFilesDir.mkdirs()) {
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "Unable to create external files directory");
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return null;
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (type == null) {
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return mExternalFilesDir;
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            File dir = new File(mExternalFilesDir, type);
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!dir.exists()) {
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (!dir.mkdirs()) {
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "Unable to create external media directory " + dir);
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return null;
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return dir;
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getCacheDir() {
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (mSync) {
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mCacheDir == null) {
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mCacheDir = new File(getDataDirFile(), "cache");
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!mCacheDir.exists()) {
493ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang                if(!mCacheDir.mkdirs()) {
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "Unable to create cache directory");
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return null;
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
497ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang                FileUtils.setPermissions(
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        mCacheDir.getPath(),
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        -1, -1);
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return mCacheDir;
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getExternalCacheDir() {
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        synchronized (mSync) {
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mExternalCacheDir == null) {
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mExternalCacheDir = Environment.getExternalStorageAppCacheDirectory(
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        getPackageName());
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!mExternalCacheDir.exists()) {
514b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                try {
515b98762f7824c291dc5d9a9b757af434ef31d8c81Wink Saville                    (new File(Environment.getExternalStorageAndroidDataDir(),
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            ".nomedia")).createNewFile();
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } catch (IOException e) {
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (!mExternalCacheDir.mkdirs()) {
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    Log.w(TAG, "Unable to create external cache directory");
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return null;
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mExternalCacheDir;
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getFileStreamPath(String name) {
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return makeFilename(getFilesDir(), name);
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public String[] fileList() {
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        final String[] list = getFilesDir().list();
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return (list != null) ? list : EMPTY_FILE_LIST;
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
539ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    @Override
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        File f = validateFilePath(name, true);
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
5432d13d1408bef9e26cc418e6fc2579dfd12378a3cJP Abgrall        setFilePermissionsFromMode(f.getPath(), mode, 0);
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return db;
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public boolean deleteDatabase(String name) {
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
550ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang            File f = validateFilePath(name, false);
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return f.delete();
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (Exception e) {
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return false;
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public File getDatabasePath(String name) {
559ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang        return validateFilePath(name, false);
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public String[] databaseList() {
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        final String[] list = getDatabasesDir().list();
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return (list != null) ? list : EMPTY_FILE_LIST;
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    private File getDatabasesDir() {
570931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin        synchronized (mSync) {
571eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom            if (mDatabasesDir == null) {
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mDatabasesDir = new File(getDataDirFile(), "databases");
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mDatabasesDir.getPath().equals("databases")) {
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mDatabasesDir = new File("/data/system");
576eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom            }
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return mDatabasesDir;
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public Drawable getWallpaper() {
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return getWallpaperManager().getDrawable();
584ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
585ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
586ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    @Override
587ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    public Drawable peekWallpaper() {
588ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang        return getWallpaperManager().peekDrawable();
589ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang    }
59031dbed7b60d8237d6d05dc6bf230167a5854b77aElliott Hughes
59131dbed7b60d8237d6d05dc6bf230167a5854b77aElliott Hughes    @Override
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public int getWallpaperDesiredMinimumWidth() {
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return getWallpaperManager().getDesiredMinimumWidth();
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
5962a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    @Override
5972a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    public int getWallpaperDesiredMinimumHeight() {
5982a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland        return getWallpaperManager().getDesiredMinimumHeight();
5992a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    }
600931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin
601931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin    @Override
602931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin    public void setWallpaper(Bitmap bitmap) throws IOException  {
603931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin        getWallpaperManager().setBitmap(bitmap);
604931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin    }
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void setWallpaper(InputStream data) throws IOException {
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        getWallpaperManager().setStream(data);
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void clearWallpaper() throws IOException {
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        getWallpaperManager().clear();
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void startActivity(Intent intent) {
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            throw new AndroidRuntimeException(
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    "Calling startActivity() from outside of an Activity "
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    + " Is this really what you want?");
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        mMainThread.getInstrumentation().execStartActivity(
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void startIntentSender(IntentSender intent,
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            throws IntentSender.SendIntentException {
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            String resolvedType = null;
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (fillInIntent != null) {
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int result = ActivityManagerNative.getDefault()
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        fillInIntent, resolvedType, null, null,
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        0, flagsMask, flagsValues);
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (result == IActivityManager.START_CANCELED) {
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                throw new IntentSender.SendIntentException();
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Instrumentation.checkStartActivityResult(result, null);
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (RemoteException e) {
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void sendBroadcast(Intent intent) {
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ActivityManagerNative.getDefault().broadcastIntent(
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mMainThread.getApplicationThread(), intent, resolvedType, null,
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                Activity.RESULT_OK, null, null, null, false, false);
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (RemoteException e) {
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void sendBroadcast(Intent intent, String receiverPermission) {
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
664931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin            ActivityManagerNative.getDefault().broadcastIntent(
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mMainThread.getApplicationThread(), intent, resolvedType, null,
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                Activity.RESULT_OK, null, null, receiverPermission, false, false);
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (RemoteException e) {
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void sendOrderedBroadcast(Intent intent,
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            String receiverPermission) {
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ActivityManagerNative.getDefault().broadcastIntent(
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mMainThread.getApplicationThread(), intent, resolvedType, null,
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                Activity.RESULT_OK, null, null, receiverPermission, true, false);
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (RemoteException e) {
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void sendOrderedBroadcast(Intent intent,
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            String receiverPermission, BroadcastReceiver resultReceiver,
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Handler scheduler, int initialCode, String initialData,
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Bundle initialExtras) {
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IIntentReceiver rd = null;
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (resultReceiver != null) {
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (mPackageInfo != null) {
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (scheduler == null) {
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    scheduler = mMainThread.getHandler();
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
694931175a1c5f01f57781c9fcf64beade6ed5148ffDima Zavin                rd = mPackageInfo.getReceiverDispatcher(
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    resultReceiver, getOuterContext(), scheduler,
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    mMainThread.getInstrumentation(), false);
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (scheduler == null) {
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    scheduler = mMainThread.getHandler();
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                rd = new LoadedApk.ReceiverDispatcher(
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ActivityManagerNative.getDefault().broadcastIntent(
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mMainThread.getApplicationThread(), intent, resolvedType, rd,
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                initialCode, initialData, initialExtras, receiverPermission,
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                true, false);
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (RemoteException e) {
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
714ee52055ae5eeb951bb4805bd8aa57d63718e1ce7Tsu Chiang Chuang
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void sendStickyBroadcast(Intent intent) {
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        try {
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ActivityManagerNative.getDefault().broadcastIntent(
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                mMainThread.getApplicationThread(), intent, resolvedType, null,
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                Activity.RESULT_OK, null, null, null, false, true);
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } catch (RemoteException e) {
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    @Override
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    public void sendStickyOrderedBroadcast(Intent intent,
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            BroadcastReceiver resultReceiver,
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            Handler scheduler, int initialCode, String initialData,
730eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom            Bundle initialExtras) {
731eb31c0bdc0eac0898f01cdc1737cea94269f8f27Brian Carlstrom        IIntentReceiver rd = null;
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        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                }
744                rd = new LoadedApk.ReceiverDispatcher(
745                        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
759    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                }
800                rd = new LoadedApk.ReceiverDispatcher(
801                        receiver, context, scheduler, null, true).getIIntentReceiver();
802            }
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();
927        } else if (INPUT_METHOD_SERVICE.equals(name)) {
928            return InputMethodManager.getInstance(this);
929        } else if (ALARM_SERVICE.equals(name)) {
930            return getAlarmManager();
931        } else if (ACCOUNT_SERVICE.equals(name)) {
932            return getAccountManager();
933        } else if (POWER_SERVICE.equals(name)) {
934            return getPowerManager();
935        } else if (CONNECTIVITY_SERVICE.equals(name)) {
936            return getConnectivityManager();
937        } else if (THROTTLE_SERVICE.equals(name)) {
938            return getThrottleManager();
939        } 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();
945        } else if (ACCESSIBILITY_SERVICE.equals(name)) {
946            return AccessibilityManager.getInstance(this);
947        } else if (LOCATION_SERVICE.equals(name)) {
948            return getLocationManager();
949        } else if (SEARCH_SERVICE.equals(name)) {
950            return getSearchManager();
951        } else if (SENSOR_SERVICE.equals(name)) {
952            return getSensorManager();
953        } else if (STORAGE_SERVICE.equals(name)) {
954            return getStorageManager();
955        } else if (VIBRATOR_SERVICE.equals(name)) {
956            return getVibrator();
957        } else if (STATUS_BAR_SERVICE.equals(name)) {
958            synchronized (mSync) {
959                if (mStatusBarManager == null) {
960                    mStatusBarManager = new StatusBarManager(getOuterContext());
961                }
962                return mStatusBarManager;
963            }
964        } else if (AUDIO_SERVICE.equals(name)) {
965            return getAudioManager();
966        } else if (TELEPHONY_SERVICE.equals(name)) {
967            return getTelephonyManager();
968        } else if (CLIPBOARD_SERVICE.equals(name)) {
969            return getClipboardManager();
970        } else if (WALLPAPER_SERVICE.equals(name)) {
971            return getWallpaperManager();
972        } else if (DROPBOX_SERVICE.equals(name)) {
973            return getDropBoxManager();
974        } else if (DEVICE_POLICY_SERVICE.equals(name)) {
975            return getDevicePolicyManager();
976        } else if (UI_MODE_SERVICE.equals(name)) {
977            return getUiModeManager();
978        } else if (DOWNLOAD_SERVICE.equals(name)) {
979            return getDownloadManager();
980        }
981
982        return null;
983    }
984
985    private AccountManager getAccountManager() {
986        synchronized (mSync) {
987            if (mAccountManager == null) {
988                IBinder b = ServiceManager.getService(ACCOUNT_SERVICE);
989                IAccountManager service = IAccountManager.Stub.asInterface(b);
990                mAccountManager = new AccountManager(this, service);
991            }
992            return mAccountManager;
993        }
994    }
995
996    private ActivityManager getActivityManager() {
997        synchronized (mSync) {
998            if (mActivityManager == null) {
999                mActivityManager = new ActivityManager(getOuterContext(),
1000                        mMainThread.getHandler());
1001            }
1002        }
1003        return mActivityManager;
1004    }
1005
1006    private AlarmManager getAlarmManager() {
1007        synchronized (sSync) {
1008            if (sAlarmManager == null) {
1009                IBinder b = ServiceManager.getService(ALARM_SERVICE);
1010                IAlarmManager service = IAlarmManager.Stub.asInterface(b);
1011                sAlarmManager = new AlarmManager(service);
1012            }
1013        }
1014        return sAlarmManager;
1015    }
1016
1017    private PowerManager getPowerManager() {
1018        synchronized (sSync) {
1019            if (sPowerManager == null) {
1020                IBinder b = ServiceManager.getService(POWER_SERVICE);
1021                IPowerManager service = IPowerManager.Stub.asInterface(b);
1022                sPowerManager = new PowerManager(service, mMainThread.getHandler());
1023            }
1024        }
1025        return sPowerManager;
1026    }
1027
1028    private ConnectivityManager getConnectivityManager()
1029    {
1030        synchronized (sSync) {
1031            if (sConnectivityManager == null) {
1032                IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
1033                IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
1034                sConnectivityManager = new ConnectivityManager(service);
1035            }
1036        }
1037        return sConnectivityManager;
1038    }
1039
1040    private ThrottleManager getThrottleManager()
1041    {
1042        synchronized (sSync) {
1043            if (sThrottleManager == null) {
1044                IBinder b = ServiceManager.getService(THROTTLE_SERVICE);
1045                IThrottleManager service = IThrottleManager.Stub.asInterface(b);
1046                sThrottleManager = new ThrottleManager(service);
1047            }
1048        }
1049        return sThrottleManager;
1050    }
1051
1052    private WifiManager getWifiManager()
1053    {
1054        synchronized (sSync) {
1055            if (sWifiManager == null) {
1056                IBinder b = ServiceManager.getService(WIFI_SERVICE);
1057                IWifiManager service = IWifiManager.Stub.asInterface(b);
1058                sWifiManager = new WifiManager(service, mMainThread.getHandler());
1059            }
1060        }
1061        return sWifiManager;
1062    }
1063
1064    private NotificationManager getNotificationManager() {
1065        synchronized (mSync) {
1066            if (mNotificationManager == null) {
1067                mNotificationManager = new NotificationManager(
1068                        new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
1069                        mMainThread.getHandler());
1070            }
1071        }
1072        return mNotificationManager;
1073    }
1074
1075    private WallpaperManager getWallpaperManager() {
1076        synchronized (mSync) {
1077            if (mWallpaperManager == null) {
1078                mWallpaperManager = new WallpaperManager(getOuterContext(),
1079                        mMainThread.getHandler());
1080            }
1081        }
1082        return mWallpaperManager;
1083    }
1084
1085    private TelephonyManager getTelephonyManager() {
1086        synchronized (mSync) {
1087            if (mTelephonyManager == null) {
1088                mTelephonyManager = new TelephonyManager(getOuterContext());
1089            }
1090        }
1091        return mTelephonyManager;
1092    }
1093
1094    private ClipboardManager getClipboardManager() {
1095        synchronized (mSync) {
1096            if (mClipboardManager == null) {
1097                mClipboardManager = new ClipboardManager(getOuterContext(),
1098                        mMainThread.getHandler());
1099            }
1100        }
1101        return mClipboardManager;
1102    }
1103
1104    private LocationManager getLocationManager() {
1105        synchronized (sSync) {
1106            if (sLocationManager == null) {
1107                IBinder b = ServiceManager.getService(LOCATION_SERVICE);
1108                ILocationManager service = ILocationManager.Stub.asInterface(b);
1109                sLocationManager = new LocationManager(service);
1110            }
1111        }
1112        return sLocationManager;
1113    }
1114
1115    private SearchManager getSearchManager() {
1116        synchronized (mSync) {
1117            if (mSearchManager == null) {
1118                mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
1119            }
1120        }
1121        return mSearchManager;
1122    }
1123
1124    private SensorManager getSensorManager() {
1125        synchronized (mSync) {
1126            if (mSensorManager == null) {
1127                mSensorManager = new SensorManager(mMainThread.getHandler().getLooper());
1128            }
1129        }
1130        return mSensorManager;
1131    }
1132
1133    private StorageManager getStorageManager() {
1134        synchronized (mSync) {
1135            if (mStorageManager == null) {
1136                try {
1137                    mStorageManager = new StorageManager(mMainThread.getHandler().getLooper());
1138                } catch (RemoteException rex) {
1139                    Log.e(TAG, "Failed to create StorageManager", rex);
1140                    mStorageManager = null;
1141                }
1142            }
1143        }
1144        return mStorageManager;
1145    }
1146
1147    private Vibrator getVibrator() {
1148        synchronized (mSync) {
1149            if (mVibrator == null) {
1150                mVibrator = new Vibrator();
1151            }
1152        }
1153        return mVibrator;
1154    }
1155
1156    private AudioManager getAudioManager()
1157    {
1158        if (mAudioManager == null) {
1159            mAudioManager = new AudioManager(this);
1160        }
1161        return mAudioManager;
1162    }
1163
1164    /* package */ static DropBoxManager createDropBoxManager() {
1165        IBinder b = ServiceManager.getService(DROPBOX_SERVICE);
1166        IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b);
1167        return new DropBoxManager(service);
1168    }
1169
1170    private DropBoxManager getDropBoxManager() {
1171        synchronized (mSync) {
1172            if (mDropBoxManager == null) {
1173                mDropBoxManager = createDropBoxManager();
1174            }
1175        }
1176        return mDropBoxManager;
1177    }
1178
1179    private DevicePolicyManager getDevicePolicyManager() {
1180        synchronized (mSync) {
1181            if (mDevicePolicyManager == null) {
1182                mDevicePolicyManager = DevicePolicyManager.create(this,
1183                        mMainThread.getHandler());
1184            }
1185        }
1186        return mDevicePolicyManager;
1187    }
1188
1189    private UiModeManager getUiModeManager() {
1190        synchronized (mSync) {
1191            if (mUiModeManager == null) {
1192                mUiModeManager = new UiModeManager();
1193            }
1194        }
1195        return mUiModeManager;
1196    }
1197
1198    private DownloadManager getDownloadManager() {
1199        synchronized (mSync) {
1200            if (mDownloadManager == null) {
1201                mDownloadManager = new DownloadManager(getContentResolver(), getPackageName());
1202            }
1203        }
1204        return mDownloadManager;
1205    }
1206
1207    @Override
1208    public int checkPermission(String permission, int pid, int uid) {
1209        if (permission == null) {
1210            throw new IllegalArgumentException("permission is null");
1211        }
1212
1213        if (!Process.supportsProcesses()) {
1214            return PackageManager.PERMISSION_GRANTED;
1215        }
1216        try {
1217            return ActivityManagerNative.getDefault().checkPermission(
1218                    permission, pid, uid);
1219        } catch (RemoteException e) {
1220            return PackageManager.PERMISSION_DENIED;
1221        }
1222    }
1223
1224    @Override
1225    public int checkCallingPermission(String permission) {
1226        if (permission == null) {
1227            throw new IllegalArgumentException("permission is null");
1228        }
1229
1230        if (!Process.supportsProcesses()) {
1231            return PackageManager.PERMISSION_GRANTED;
1232        }
1233        int pid = Binder.getCallingPid();
1234        if (pid != Process.myPid()) {
1235            return checkPermission(permission, pid,
1236                    Binder.getCallingUid());
1237        }
1238        return PackageManager.PERMISSION_DENIED;
1239    }
1240
1241    @Override
1242    public int checkCallingOrSelfPermission(String permission) {
1243        if (permission == null) {
1244            throw new IllegalArgumentException("permission is null");
1245        }
1246
1247        return checkPermission(permission, Binder.getCallingPid(),
1248                Binder.getCallingUid());
1249    }
1250
1251    private void enforce(
1252            String permission, int resultOfCheck,
1253            boolean selfToo, int uid, String message) {
1254        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1255            throw new SecurityException(
1256                    (message != null ? (message + ": ") : "") +
1257                    (selfToo
1258                     ? "Neither user " + uid + " nor current process has "
1259                     : "User " + uid + " does not have ") +
1260                    permission +
1261                    ".");
1262        }
1263    }
1264
1265    public void enforcePermission(
1266            String permission, int pid, int uid, String message) {
1267        enforce(permission,
1268                checkPermission(permission, pid, uid),
1269                false,
1270                uid,
1271                message);
1272    }
1273
1274    public void enforceCallingPermission(String permission, String message) {
1275        enforce(permission,
1276                checkCallingPermission(permission),
1277                false,
1278                Binder.getCallingUid(),
1279                message);
1280    }
1281
1282    public void enforceCallingOrSelfPermission(
1283            String permission, String message) {
1284        enforce(permission,
1285                checkCallingOrSelfPermission(permission),
1286                true,
1287                Binder.getCallingUid(),
1288                message);
1289    }
1290
1291    @Override
1292    public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
1293         try {
1294            ActivityManagerNative.getDefault().grantUriPermission(
1295                    mMainThread.getApplicationThread(), toPackage, uri,
1296                    modeFlags);
1297        } catch (RemoteException e) {
1298        }
1299    }
1300
1301    @Override
1302    public void revokeUriPermission(Uri uri, int modeFlags) {
1303         try {
1304            ActivityManagerNative.getDefault().revokeUriPermission(
1305                    mMainThread.getApplicationThread(), uri,
1306                    modeFlags);
1307        } catch (RemoteException e) {
1308        }
1309    }
1310
1311    @Override
1312    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
1313        if (!Process.supportsProcesses()) {
1314            return PackageManager.PERMISSION_GRANTED;
1315        }
1316        try {
1317            return ActivityManagerNative.getDefault().checkUriPermission(
1318                    uri, pid, uid, modeFlags);
1319        } catch (RemoteException e) {
1320            return PackageManager.PERMISSION_DENIED;
1321        }
1322    }
1323
1324    @Override
1325    public int checkCallingUriPermission(Uri uri, int modeFlags) {
1326        if (!Process.supportsProcesses()) {
1327            return PackageManager.PERMISSION_GRANTED;
1328        }
1329        int pid = Binder.getCallingPid();
1330        if (pid != Process.myPid()) {
1331            return checkUriPermission(uri, pid,
1332                    Binder.getCallingUid(), modeFlags);
1333        }
1334        return PackageManager.PERMISSION_DENIED;
1335    }
1336
1337    @Override
1338    public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) {
1339        return checkUriPermission(uri, Binder.getCallingPid(),
1340                Binder.getCallingUid(), modeFlags);
1341    }
1342
1343    @Override
1344    public int checkUriPermission(Uri uri, String readPermission,
1345            String writePermission, int pid, int uid, int modeFlags) {
1346        if (DEBUG) {
1347            Log.i("foo", "checkUriPermission: uri=" + uri + "readPermission="
1348                    + readPermission + " writePermission=" + writePermission
1349                    + " pid=" + pid + " uid=" + uid + " mode" + modeFlags);
1350        }
1351        if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
1352            if (readPermission == null
1353                    || checkPermission(readPermission, pid, uid)
1354                    == PackageManager.PERMISSION_GRANTED) {
1355                return PackageManager.PERMISSION_GRANTED;
1356            }
1357        }
1358        if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
1359            if (writePermission == null
1360                    || checkPermission(writePermission, pid, uid)
1361                    == PackageManager.PERMISSION_GRANTED) {
1362                return PackageManager.PERMISSION_GRANTED;
1363            }
1364        }
1365        return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
1366                : PackageManager.PERMISSION_DENIED;
1367    }
1368
1369    private String uriModeFlagToString(int uriModeFlags) {
1370        switch (uriModeFlags) {
1371            case Intent.FLAG_GRANT_READ_URI_PERMISSION |
1372                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1373                return "read and write";
1374            case Intent.FLAG_GRANT_READ_URI_PERMISSION:
1375                return "read";
1376            case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
1377                return "write";
1378        }
1379        throw new IllegalArgumentException(
1380                "Unknown permission mode flags: " + uriModeFlags);
1381    }
1382
1383    private void enforceForUri(
1384            int modeFlags, int resultOfCheck, boolean selfToo,
1385            int uid, Uri uri, String message) {
1386        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
1387            throw new SecurityException(
1388                    (message != null ? (message + ": ") : "") +
1389                    (selfToo
1390                     ? "Neither user " + uid + " nor current process has "
1391                     : "User " + uid + " does not have ") +
1392                    uriModeFlagToString(modeFlags) +
1393                    " permission on " +
1394                    uri +
1395                    ".");
1396        }
1397    }
1398
1399    public void enforceUriPermission(
1400            Uri uri, int pid, int uid, int modeFlags, String message) {
1401        enforceForUri(
1402                modeFlags, checkUriPermission(uri, pid, uid, modeFlags),
1403                false, uid, uri, message);
1404    }
1405
1406    public void enforceCallingUriPermission(
1407            Uri uri, int modeFlags, String message) {
1408        enforceForUri(
1409                modeFlags, checkCallingUriPermission(uri, modeFlags),
1410                false, Binder.getCallingUid(), uri, message);
1411    }
1412
1413    public void enforceCallingOrSelfUriPermission(
1414            Uri uri, int modeFlags, String message) {
1415        enforceForUri(
1416                modeFlags,
1417                checkCallingOrSelfUriPermission(uri, modeFlags), true,
1418                Binder.getCallingUid(), uri, message);
1419    }
1420
1421    public void enforceUriPermission(
1422            Uri uri, String readPermission, String writePermission,
1423            int pid, int uid, int modeFlags, String message) {
1424        enforceForUri(modeFlags,
1425                      checkUriPermission(
1426                              uri, readPermission, writePermission, pid, uid,
1427                              modeFlags),
1428                      false,
1429                      uid,
1430                      uri,
1431                      message);
1432    }
1433
1434    @Override
1435    public Context createPackageContext(String packageName, int flags)
1436        throws PackageManager.NameNotFoundException {
1437        if (packageName.equals("system") || packageName.equals("android")) {
1438            return new ContextImpl(mMainThread.getSystemContext());
1439        }
1440
1441        LoadedApk pi =
1442            mMainThread.getPackageInfo(packageName, flags);
1443        if (pi != null) {
1444            ContextImpl c = new ContextImpl();
1445            c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
1446            c.init(pi, null, mMainThread, mResources);
1447            if (c.mResources != null) {
1448                return c;
1449            }
1450        }
1451
1452        // Should be a better exception.
1453        throw new PackageManager.NameNotFoundException(
1454            "Application package " + packageName + " not found");
1455    }
1456
1457    @Override
1458    public boolean isRestricted() {
1459        return mRestricted;
1460    }
1461
1462    private File getDataDirFile() {
1463        if (mPackageInfo != null) {
1464            return mPackageInfo.getDataDirFile();
1465        }
1466        throw new RuntimeException("Not supported in system context");
1467    }
1468
1469    @Override
1470    public File getDir(String name, int mode) {
1471        name = "app_" + name;
1472        File file = makeFilename(getDataDirFile(), name);
1473        if (!file.exists()) {
1474            file.mkdir();
1475            setFilePermissionsFromMode(file.getPath(), mode,
1476                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH);
1477        }
1478        return file;
1479    }
1480
1481    static ContextImpl createSystemContext(ActivityThread mainThread) {
1482        ContextImpl context = new ContextImpl();
1483        context.init(Resources.getSystem(), mainThread);
1484        return context;
1485    }
1486
1487    ContextImpl() {
1488        // For debug only
1489        //++sInstanceCount;
1490        mOuterContext = this;
1491    }
1492
1493    /**
1494     * Create a new ApplicationContext from an existing one.  The new one
1495     * works and operates the same as the one it is copying.
1496     *
1497     * @param context Existing application context.
1498     */
1499    public ContextImpl(ContextImpl context) {
1500        ++sInstanceCount;
1501        mPackageInfo = context.mPackageInfo;
1502        mResources = context.mResources;
1503        mMainThread = context.mMainThread;
1504        mContentResolver = context.mContentResolver;
1505        mOuterContext = this;
1506    }
1507
1508    final void init(LoadedApk packageInfo,
1509            IBinder activityToken, ActivityThread mainThread) {
1510        init(packageInfo, activityToken, mainThread, null);
1511    }
1512
1513    final void init(LoadedApk packageInfo,
1514                IBinder activityToken, ActivityThread mainThread,
1515                Resources container) {
1516        mPackageInfo = packageInfo;
1517        mResources = mPackageInfo.getResources(mainThread);
1518
1519        if (mResources != null && container != null
1520                && container.getCompatibilityInfo().applicationScale !=
1521                        mResources.getCompatibilityInfo().applicationScale) {
1522            if (DEBUG) {
1523                Log.d(TAG, "loaded context has different scaling. Using container's" +
1524                        " compatiblity info:" + container.getDisplayMetrics());
1525            }
1526            mResources = mainThread.getTopLevelResources(
1527                    mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
1528        }
1529        mMainThread = mainThread;
1530        mContentResolver = new ApplicationContentResolver(this, mainThread);
1531
1532        setActivityToken(activityToken);
1533    }
1534
1535    final void init(Resources resources, ActivityThread mainThread) {
1536        mPackageInfo = null;
1537        mResources = resources;
1538        mMainThread = mainThread;
1539        mContentResolver = new ApplicationContentResolver(this, mainThread);
1540    }
1541
1542    final void scheduleFinalCleanup(String who, String what) {
1543        mMainThread.scheduleContextCleanup(this, who, what);
1544    }
1545
1546    final void performFinalCleanup(String who, String what) {
1547        //Log.i(TAG, "Cleanup up context: " + this);
1548        mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
1549    }
1550
1551    final Context getReceiverRestrictedContext() {
1552        if (mReceiverRestrictedContext != null) {
1553            return mReceiverRestrictedContext;
1554        }
1555        return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
1556    }
1557
1558    final void setActivityToken(IBinder token) {
1559        mActivityToken = token;
1560    }
1561
1562    final void setOuterContext(Context context) {
1563        mOuterContext = context;
1564    }
1565
1566    final Context getOuterContext() {
1567        return mOuterContext;
1568    }
1569
1570    final IBinder getActivityToken() {
1571        return mActivityToken;
1572    }
1573
1574    private static void setFilePermissionsFromMode(String name, int mode,
1575            int extraPermissions) {
1576        int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
1577            |FileUtils.S_IRGRP|FileUtils.S_IWGRP
1578            |extraPermissions;
1579        if ((mode&MODE_WORLD_READABLE) != 0) {
1580            perms |= FileUtils.S_IROTH;
1581        }
1582        if ((mode&MODE_WORLD_WRITEABLE) != 0) {
1583            perms |= FileUtils.S_IWOTH;
1584        }
1585        if (DEBUG) {
1586            Log.i(TAG, "File " + name + ": mode=0x" + Integer.toHexString(mode)
1587                  + ", perms=0x" + Integer.toHexString(perms));
1588        }
1589        FileUtils.setPermissions(name, perms, -1, -1);
1590    }
1591
1592    private File validateFilePath(String name, boolean createDirectory) {
1593        File dir;
1594        File f;
1595
1596        if (name.charAt(0) == File.separatorChar) {
1597            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
1598            dir = new File(dirPath);
1599            name = name.substring(name.lastIndexOf(File.separatorChar));
1600            f = new File(dir, name);
1601        } else {
1602            dir = getDatabasesDir();
1603            f = makeFilename(dir, name);
1604        }
1605
1606        if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
1607            FileUtils.setPermissions(dir.getPath(),
1608                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
1609                -1, -1);
1610        }
1611
1612        return f;
1613    }
1614
1615    private File makeFilename(File base, String name) {
1616        if (name.indexOf(File.separatorChar) < 0) {
1617            return new File(base, name);
1618        }
1619        throw new IllegalArgumentException(
1620                "File " + name + " contains a path separator");
1621    }
1622
1623    // ----------------------------------------------------------------------
1624    // ----------------------------------------------------------------------
1625    // ----------------------------------------------------------------------
1626
1627    private static final class ApplicationContentResolver extends ContentResolver {
1628        public ApplicationContentResolver(Context context, ActivityThread mainThread) {
1629            super(context);
1630            mMainThread = mainThread;
1631        }
1632
1633        @Override
1634        protected IContentProvider acquireProvider(Context context, String name) {
1635            return mMainThread.acquireProvider(context, name);
1636        }
1637
1638        @Override
1639        protected IContentProvider acquireExistingProvider(Context context, String name) {
1640            return mMainThread.acquireExistingProvider(context, name);
1641        }
1642
1643        @Override
1644        public boolean releaseProvider(IContentProvider provider) {
1645            return mMainThread.releaseProvider(provider);
1646        }
1647
1648        private final ActivityThread mMainThread;
1649    }
1650
1651    // ----------------------------------------------------------------------
1652    // ----------------------------------------------------------------------
1653    // ----------------------------------------------------------------------
1654
1655    /*package*/
1656    static final class ApplicationPackageManager extends PackageManager {
1657        @Override
1658        public PackageInfo getPackageInfo(String packageName, int flags)
1659                throws NameNotFoundException {
1660            try {
1661                PackageInfo pi = mPM.getPackageInfo(packageName, flags);
1662                if (pi != null) {
1663                    return pi;
1664                }
1665            } catch (RemoteException e) {
1666                throw new RuntimeException("Package manager has died", e);
1667            }
1668
1669            throw new NameNotFoundException(packageName);
1670        }
1671
1672        @Override
1673        public String[] currentToCanonicalPackageNames(String[] names) {
1674            try {
1675                return mPM.currentToCanonicalPackageNames(names);
1676            } catch (RemoteException e) {
1677                throw new RuntimeException("Package manager has died", e);
1678            }
1679        }
1680
1681        @Override
1682        public String[] canonicalToCurrentPackageNames(String[] names) {
1683            try {
1684                return mPM.canonicalToCurrentPackageNames(names);
1685            } catch (RemoteException e) {
1686                throw new RuntimeException("Package manager has died", e);
1687            }
1688        }
1689
1690        @Override
1691        public Intent getLaunchIntentForPackage(String packageName) {
1692            // First see if the package has an INFO activity; the existence of
1693            // such an activity is implied to be the desired front-door for the
1694            // overall package (such as if it has multiple launcher entries).
1695            Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
1696            intentToResolve.addCategory(Intent.CATEGORY_INFO);
1697            intentToResolve.setPackage(packageName);
1698            ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
1699
1700            // Otherwise, try to find a main launcher activity.
1701            if (resolveInfo == null) {
1702                // reuse the intent instance
1703                intentToResolve.removeCategory(Intent.CATEGORY_INFO);
1704                intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
1705                intentToResolve.setPackage(packageName);
1706                resolveInfo = resolveActivity(intentToResolve, 0);
1707            }
1708            if (resolveInfo == null) {
1709                return null;
1710            }
1711            Intent intent = new Intent(Intent.ACTION_MAIN);
1712            intent.setClassName(packageName, resolveInfo.activityInfo.name);
1713            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1714            return intent;
1715        }
1716
1717        @Override
1718        public int[] getPackageGids(String packageName)
1719            throws NameNotFoundException {
1720            try {
1721                int[] gids = mPM.getPackageGids(packageName);
1722                if (gids == null || gids.length > 0) {
1723                    return gids;
1724                }
1725            } catch (RemoteException e) {
1726                throw new RuntimeException("Package manager has died", e);
1727            }
1728
1729            throw new NameNotFoundException(packageName);
1730        }
1731
1732        @Override
1733        public PermissionInfo getPermissionInfo(String name, int flags)
1734            throws NameNotFoundException {
1735            try {
1736                PermissionInfo pi = mPM.getPermissionInfo(name, flags);
1737                if (pi != null) {
1738                    return pi;
1739                }
1740            } catch (RemoteException e) {
1741                throw new RuntimeException("Package manager has died", e);
1742            }
1743
1744            throw new NameNotFoundException(name);
1745        }
1746
1747        @Override
1748        public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
1749                throws NameNotFoundException {
1750            try {
1751                List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
1752                if (pi != null) {
1753                    return pi;
1754                }
1755            } catch (RemoteException e) {
1756                throw new RuntimeException("Package manager has died", e);
1757            }
1758
1759            throw new NameNotFoundException(group);
1760        }
1761
1762        @Override
1763        public PermissionGroupInfo getPermissionGroupInfo(String name,
1764                int flags) throws NameNotFoundException {
1765            try {
1766                PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
1767                if (pgi != null) {
1768                    return pgi;
1769                }
1770            } catch (RemoteException e) {
1771                throw new RuntimeException("Package manager has died", e);
1772            }
1773
1774            throw new NameNotFoundException(name);
1775        }
1776
1777        @Override
1778        public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
1779            try {
1780                return mPM.getAllPermissionGroups(flags);
1781            } catch (RemoteException e) {
1782                throw new RuntimeException("Package manager has died", e);
1783            }
1784        }
1785
1786        @Override
1787        public ApplicationInfo getApplicationInfo(String packageName, int flags)
1788            throws NameNotFoundException {
1789            try {
1790                ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
1791                if (ai != null) {
1792                    return ai;
1793                }
1794            } catch (RemoteException e) {
1795                throw new RuntimeException("Package manager has died", e);
1796            }
1797
1798            throw new NameNotFoundException(packageName);
1799        }
1800
1801        @Override
1802        public ActivityInfo getActivityInfo(ComponentName className, int flags)
1803            throws NameNotFoundException {
1804            try {
1805                ActivityInfo ai = mPM.getActivityInfo(className, flags);
1806                if (ai != null) {
1807                    return ai;
1808                }
1809            } catch (RemoteException e) {
1810                throw new RuntimeException("Package manager has died", e);
1811            }
1812
1813            throw new NameNotFoundException(className.toString());
1814        }
1815
1816        @Override
1817        public ActivityInfo getReceiverInfo(ComponentName className, int flags)
1818            throws NameNotFoundException {
1819            try {
1820                ActivityInfo ai = mPM.getReceiverInfo(className, flags);
1821                if (ai != null) {
1822                    return ai;
1823                }
1824            } catch (RemoteException e) {
1825                throw new RuntimeException("Package manager has died", e);
1826            }
1827
1828            throw new NameNotFoundException(className.toString());
1829        }
1830
1831        @Override
1832        public ServiceInfo getServiceInfo(ComponentName className, int flags)
1833            throws NameNotFoundException {
1834            try {
1835                ServiceInfo si = mPM.getServiceInfo(className, flags);
1836                if (si != null) {
1837                    return si;
1838                }
1839            } catch (RemoteException e) {
1840                throw new RuntimeException("Package manager has died", e);
1841            }
1842
1843            throw new NameNotFoundException(className.toString());
1844        }
1845
1846        @Override
1847        public ProviderInfo getProviderInfo(ComponentName className, int flags)
1848            throws NameNotFoundException {
1849            try {
1850                ProviderInfo pi = mPM.getProviderInfo(className, flags);
1851                if (pi != null) {
1852                    return pi;
1853                }
1854            } catch (RemoteException e) {
1855                throw new RuntimeException("Package manager has died", e);
1856            }
1857
1858            throw new NameNotFoundException(className.toString());
1859        }
1860
1861        @Override
1862        public String[] getSystemSharedLibraryNames() {
1863             try {
1864                 return mPM.getSystemSharedLibraryNames();
1865             } catch (RemoteException e) {
1866                 throw new RuntimeException("Package manager has died", e);
1867             }
1868        }
1869
1870        @Override
1871        public FeatureInfo[] getSystemAvailableFeatures() {
1872            try {
1873                return mPM.getSystemAvailableFeatures();
1874            } catch (RemoteException e) {
1875                throw new RuntimeException("Package manager has died", e);
1876            }
1877        }
1878
1879        @Override
1880        public boolean hasSystemFeature(String name) {
1881            try {
1882                return mPM.hasSystemFeature(name);
1883            } catch (RemoteException e) {
1884                throw new RuntimeException("Package manager has died", e);
1885            }
1886        }
1887
1888        @Override
1889        public int checkPermission(String permName, String pkgName) {
1890            try {
1891                return mPM.checkPermission(permName, pkgName);
1892            } catch (RemoteException e) {
1893                throw new RuntimeException("Package manager has died", e);
1894            }
1895        }
1896
1897        @Override
1898        public boolean addPermission(PermissionInfo info) {
1899            try {
1900                return mPM.addPermission(info);
1901            } catch (RemoteException e) {
1902                throw new RuntimeException("Package manager has died", e);
1903            }
1904        }
1905
1906        @Override
1907        public boolean addPermissionAsync(PermissionInfo info) {
1908            try {
1909                return mPM.addPermissionAsync(info);
1910            } catch (RemoteException e) {
1911                throw new RuntimeException("Package manager has died", e);
1912            }
1913        }
1914
1915        @Override
1916        public void removePermission(String name) {
1917            try {
1918                mPM.removePermission(name);
1919            } catch (RemoteException e) {
1920                throw new RuntimeException("Package manager has died", e);
1921            }
1922        }
1923
1924        @Override
1925        public int checkSignatures(String pkg1, String pkg2) {
1926            try {
1927                return mPM.checkSignatures(pkg1, pkg2);
1928            } catch (RemoteException e) {
1929                throw new RuntimeException("Package manager has died", e);
1930            }
1931        }
1932
1933        @Override
1934        public int checkSignatures(int uid1, int uid2) {
1935            try {
1936                return mPM.checkUidSignatures(uid1, uid2);
1937            } catch (RemoteException e) {
1938                throw new RuntimeException("Package manager has died", e);
1939            }
1940        }
1941
1942        @Override
1943        public String[] getPackagesForUid(int uid) {
1944            try {
1945                return mPM.getPackagesForUid(uid);
1946            } catch (RemoteException e) {
1947                throw new RuntimeException("Package manager has died", e);
1948            }
1949        }
1950
1951        @Override
1952        public String getNameForUid(int uid) {
1953            try {
1954                return mPM.getNameForUid(uid);
1955            } catch (RemoteException e) {
1956                throw new RuntimeException("Package manager has died", e);
1957            }
1958        }
1959
1960        @Override
1961        public int getUidForSharedUser(String sharedUserName)
1962                throws NameNotFoundException {
1963            try {
1964                int uid = mPM.getUidForSharedUser(sharedUserName);
1965                if(uid != -1) {
1966                    return uid;
1967                }
1968            } catch (RemoteException e) {
1969                throw new RuntimeException("Package manager has died", e);
1970            }
1971            throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
1972        }
1973
1974        @Override
1975        public List<PackageInfo> getInstalledPackages(int flags) {
1976            try {
1977                return mPM.getInstalledPackages(flags);
1978            } catch (RemoteException e) {
1979                throw new RuntimeException("Package manager has died", e);
1980            }
1981        }
1982
1983        @Override
1984        public List<ApplicationInfo> getInstalledApplications(int flags) {
1985            try {
1986                return mPM.getInstalledApplications(flags);
1987            } catch (RemoteException e) {
1988                throw new RuntimeException("Package manager has died", e);
1989            }
1990        }
1991
1992        @Override
1993        public ResolveInfo resolveActivity(Intent intent, int flags) {
1994            try {
1995                return mPM.resolveIntent(
1996                    intent,
1997                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
1998                    flags);
1999            } catch (RemoteException e) {
2000                throw new RuntimeException("Package manager has died", e);
2001            }
2002        }
2003
2004        @Override
2005        public List<ResolveInfo> queryIntentActivities(Intent intent,
2006                int flags) {
2007            try {
2008                return mPM.queryIntentActivities(
2009                    intent,
2010                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2011                    flags);
2012            } catch (RemoteException e) {
2013                throw new RuntimeException("Package manager has died", e);
2014            }
2015        }
2016
2017        @Override
2018        public List<ResolveInfo> queryIntentActivityOptions(
2019                ComponentName caller, Intent[] specifics, Intent intent,
2020                int flags) {
2021            final ContentResolver resolver = mContext.getContentResolver();
2022
2023            String[] specificTypes = null;
2024            if (specifics != null) {
2025                final int N = specifics.length;
2026                for (int i=0; i<N; i++) {
2027                    Intent sp = specifics[i];
2028                    if (sp != null) {
2029                        String t = sp.resolveTypeIfNeeded(resolver);
2030                        if (t != null) {
2031                            if (specificTypes == null) {
2032                                specificTypes = new String[N];
2033                            }
2034                            specificTypes[i] = t;
2035                        }
2036                    }
2037                }
2038            }
2039
2040            try {
2041                return mPM.queryIntentActivityOptions(caller, specifics,
2042                    specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
2043                    flags);
2044            } catch (RemoteException e) {
2045                throw new RuntimeException("Package manager has died", e);
2046            }
2047        }
2048
2049        @Override
2050        public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
2051            try {
2052                return mPM.queryIntentReceivers(
2053                    intent,
2054                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2055                    flags);
2056            } catch (RemoteException e) {
2057                throw new RuntimeException("Package manager has died", e);
2058            }
2059        }
2060
2061        @Override
2062        public ResolveInfo resolveService(Intent intent, int flags) {
2063            try {
2064                return mPM.resolveService(
2065                    intent,
2066                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2067                    flags);
2068            } catch (RemoteException e) {
2069                throw new RuntimeException("Package manager has died", e);
2070            }
2071        }
2072
2073        @Override
2074        public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
2075            try {
2076                return mPM.queryIntentServices(
2077                    intent,
2078                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
2079                    flags);
2080            } catch (RemoteException e) {
2081                throw new RuntimeException("Package manager has died", e);
2082            }
2083        }
2084
2085        @Override
2086        public ProviderInfo resolveContentProvider(String name,
2087                int flags) {
2088            try {
2089                return mPM.resolveContentProvider(name, flags);
2090            } catch (RemoteException e) {
2091                throw new RuntimeException("Package manager has died", e);
2092            }
2093        }
2094
2095        @Override
2096        public List<ProviderInfo> queryContentProviders(String processName,
2097                int uid, int flags) {
2098            try {
2099                return mPM.queryContentProviders(processName, uid, flags);
2100            } catch (RemoteException e) {
2101                throw new RuntimeException("Package manager has died", e);
2102            }
2103        }
2104
2105        @Override
2106        public InstrumentationInfo getInstrumentationInfo(
2107                ComponentName className, int flags)
2108                throws NameNotFoundException {
2109            try {
2110                InstrumentationInfo ii = mPM.getInstrumentationInfo(
2111                        className, flags);
2112                if (ii != null) {
2113                    return ii;
2114                }
2115            } catch (RemoteException e) {
2116                throw new RuntimeException("Package manager has died", e);
2117            }
2118
2119            throw new NameNotFoundException(className.toString());
2120        }
2121
2122        @Override
2123        public List<InstrumentationInfo> queryInstrumentation(
2124                String targetPackage, int flags) {
2125            try {
2126                return mPM.queryInstrumentation(targetPackage, flags);
2127            } catch (RemoteException e) {
2128                throw new RuntimeException("Package manager has died", e);
2129            }
2130        }
2131
2132        @Override public Drawable getDrawable(String packageName, int resid,
2133                ApplicationInfo appInfo) {
2134            ResourceName name = new ResourceName(packageName, resid);
2135            Drawable dr = getCachedIcon(name);
2136            if (dr != null) {
2137                return dr;
2138            }
2139            if (appInfo == null) {
2140                try {
2141                    appInfo = getApplicationInfo(packageName, 0);
2142                } catch (NameNotFoundException e) {
2143                    return null;
2144                }
2145            }
2146            try {
2147                Resources r = getResourcesForApplication(appInfo);
2148                dr = r.getDrawable(resid);
2149                if (false) {
2150                    RuntimeException e = new RuntimeException("here");
2151                    e.fillInStackTrace();
2152                    Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
2153                            + " from package " + packageName
2154                            + ": app scale=" + r.getCompatibilityInfo().applicationScale
2155                            + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
2156                            e);
2157                }
2158                if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
2159                        + Integer.toHexString(resid) + " from " + r
2160                        + ": " + dr);
2161                putCachedIcon(name, dr);
2162                return dr;
2163            } catch (NameNotFoundException e) {
2164                Log.w("PackageManager", "Failure retrieving resources for"
2165                        + appInfo.packageName);
2166            } catch (RuntimeException e) {
2167                // If an exception was thrown, fall through to return
2168                // default icon.
2169                Log.w("PackageManager", "Failure retrieving icon 0x"
2170                        + Integer.toHexString(resid) + " in package "
2171                        + packageName, e);
2172            }
2173            return null;
2174        }
2175
2176        @Override public Drawable getActivityIcon(ComponentName activityName)
2177                throws NameNotFoundException {
2178            return getActivityInfo(activityName, 0).loadIcon(this);
2179        }
2180
2181        @Override public Drawable getActivityIcon(Intent intent)
2182                throws NameNotFoundException {
2183            if (intent.getComponent() != null) {
2184                return getActivityIcon(intent.getComponent());
2185            }
2186
2187            ResolveInfo info = resolveActivity(
2188                intent, PackageManager.MATCH_DEFAULT_ONLY);
2189            if (info != null) {
2190                return info.activityInfo.loadIcon(this);
2191            }
2192
2193            throw new NameNotFoundException(intent.toURI());
2194        }
2195
2196        @Override public Drawable getDefaultActivityIcon() {
2197            return Resources.getSystem().getDrawable(
2198                com.android.internal.R.drawable.sym_def_app_icon);
2199        }
2200
2201        @Override public Drawable getApplicationIcon(ApplicationInfo info) {
2202            return info.loadIcon(this);
2203        }
2204
2205        @Override public Drawable getApplicationIcon(String packageName)
2206                throws NameNotFoundException {
2207            return getApplicationIcon(getApplicationInfo(packageName, 0));
2208        }
2209
2210        @Override
2211        public Drawable getActivityLogo(ComponentName activityName)
2212                throws NameNotFoundException {
2213            return getActivityInfo(activityName, 0).loadLogo(this);
2214        }
2215
2216        @Override
2217        public Drawable getActivityLogo(Intent intent)
2218                throws NameNotFoundException {
2219            if (intent.getComponent() != null) {
2220                return getActivityLogo(intent.getComponent());
2221            }
2222
2223            ResolveInfo info = resolveActivity(
2224                    intent, PackageManager.MATCH_DEFAULT_ONLY);
2225            if (info != null) {
2226                return info.activityInfo.loadLogo(this);
2227            }
2228
2229            throw new NameNotFoundException(intent.toUri(0));
2230        }
2231
2232        @Override
2233        public Drawable getApplicationLogo(ApplicationInfo info) {
2234            return info.loadLogo(this);
2235        }
2236
2237        @Override
2238        public Drawable getApplicationLogo(String packageName)
2239                throws NameNotFoundException {
2240            return getApplicationLogo(getApplicationInfo(packageName, 0));
2241        }
2242
2243        @Override public Resources getResourcesForActivity(
2244                ComponentName activityName) throws NameNotFoundException {
2245            return getResourcesForApplication(
2246                getActivityInfo(activityName, 0).applicationInfo);
2247        }
2248
2249        @Override public Resources getResourcesForApplication(
2250                ApplicationInfo app) throws NameNotFoundException {
2251            if (app.packageName.equals("system")) {
2252                return mContext.mMainThread.getSystemContext().getResources();
2253            }
2254            Resources r = mContext.mMainThread.getTopLevelResources(
2255                    app.uid == Process.myUid() ? app.sourceDir
2256                    : app.publicSourceDir, mContext.mPackageInfo);
2257            if (r != null) {
2258                return r;
2259            }
2260            throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
2261        }
2262
2263        @Override public Resources getResourcesForApplication(
2264                String appPackageName) throws NameNotFoundException {
2265            return getResourcesForApplication(
2266                getApplicationInfo(appPackageName, 0));
2267        }
2268
2269        int mCachedSafeMode = -1;
2270        @Override public boolean isSafeMode() {
2271            try {
2272                if (mCachedSafeMode < 0) {
2273                    mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
2274                }
2275                return mCachedSafeMode != 0;
2276            } catch (RemoteException e) {
2277                throw new RuntimeException("Package manager has died", e);
2278            }
2279        }
2280
2281        static void configurationChanged() {
2282            synchronized (sSync) {
2283                sIconCache.clear();
2284                sStringCache.clear();
2285            }
2286        }
2287
2288        ApplicationPackageManager(ContextImpl context,
2289                IPackageManager pm) {
2290            mContext = context;
2291            mPM = pm;
2292        }
2293
2294        private Drawable getCachedIcon(ResourceName name) {
2295            synchronized (sSync) {
2296                WeakReference<Drawable> wr = sIconCache.get(name);
2297                if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
2298                        + name + ": " + wr);
2299                if (wr != null) {   // we have the activity
2300                    Drawable dr = wr.get();
2301                    if (dr != null) {
2302                        if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
2303                                + name + ": " + dr);
2304                        return dr;
2305                    }
2306                    // our entry has been purged
2307                    sIconCache.remove(name);
2308                }
2309            }
2310            return null;
2311        }
2312
2313        private void putCachedIcon(ResourceName name, Drawable dr) {
2314            synchronized (sSync) {
2315                sIconCache.put(name, new WeakReference<Drawable>(dr));
2316                if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
2317                        + name + ": " + dr);
2318            }
2319        }
2320
2321        static final void handlePackageBroadcast(int cmd, String[] pkgList,
2322                boolean hasPkgInfo) {
2323            boolean immediateGc = false;
2324            if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
2325                immediateGc = true;
2326            }
2327            if (pkgList != null && (pkgList.length > 0)) {
2328                boolean needCleanup = false;
2329                for (String ssp : pkgList) {
2330                    synchronized (sSync) {
2331                        if (sIconCache.size() > 0) {
2332                            Iterator<ResourceName> it = sIconCache.keySet().iterator();
2333                            while (it.hasNext()) {
2334                                ResourceName nm = it.next();
2335                                if (nm.packageName.equals(ssp)) {
2336                                    //Log.i(TAG, "Removing cached drawable for " + nm);
2337                                    it.remove();
2338                                    needCleanup = true;
2339                                }
2340                            }
2341                        }
2342                        if (sStringCache.size() > 0) {
2343                            Iterator<ResourceName> it = sStringCache.keySet().iterator();
2344                            while (it.hasNext()) {
2345                                ResourceName nm = it.next();
2346                                if (nm.packageName.equals(ssp)) {
2347                                    //Log.i(TAG, "Removing cached string for " + nm);
2348                                    it.remove();
2349                                    needCleanup = true;
2350                                }
2351                            }
2352                        }
2353                    }
2354                }
2355                if (needCleanup || hasPkgInfo) {
2356                    if (immediateGc) {
2357                        // Schedule an immediate gc.
2358                        Runtime.getRuntime().gc();
2359                    } else {
2360                        ActivityThread.currentActivityThread().scheduleGcIdler();
2361                    }
2362                }
2363            }
2364        }
2365
2366        private static final class ResourceName {
2367            final String packageName;
2368            final int iconId;
2369
2370            ResourceName(String _packageName, int _iconId) {
2371                packageName = _packageName;
2372                iconId = _iconId;
2373            }
2374
2375            ResourceName(ApplicationInfo aInfo, int _iconId) {
2376                this(aInfo.packageName, _iconId);
2377            }
2378
2379            ResourceName(ComponentInfo cInfo, int _iconId) {
2380                this(cInfo.applicationInfo.packageName, _iconId);
2381            }
2382
2383            ResourceName(ResolveInfo rInfo, int _iconId) {
2384                this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
2385            }
2386
2387            @Override
2388            public boolean equals(Object o) {
2389                if (this == o) return true;
2390                if (o == null || getClass() != o.getClass()) return false;
2391
2392                ResourceName that = (ResourceName) o;
2393
2394                if (iconId != that.iconId) return false;
2395                return !(packageName != null ?
2396                        !packageName.equals(that.packageName) : that.packageName != null);
2397
2398            }
2399
2400            @Override
2401            public int hashCode() {
2402                int result;
2403                result = packageName.hashCode();
2404                result = 31 * result + iconId;
2405                return result;
2406            }
2407
2408            @Override
2409            public String toString() {
2410                return "{ResourceName " + packageName + " / " + iconId + "}";
2411            }
2412        }
2413
2414        private CharSequence getCachedString(ResourceName name) {
2415            synchronized (sSync) {
2416                WeakReference<CharSequence> wr = sStringCache.get(name);
2417                if (wr != null) {   // we have the activity
2418                    CharSequence cs = wr.get();
2419                    if (cs != null) {
2420                        return cs;
2421                    }
2422                    // our entry has been purged
2423                    sStringCache.remove(name);
2424                }
2425            }
2426            return null;
2427        }
2428
2429        private void putCachedString(ResourceName name, CharSequence cs) {
2430            synchronized (sSync) {
2431                sStringCache.put(name, new WeakReference<CharSequence>(cs));
2432            }
2433        }
2434
2435        @Override
2436        public CharSequence getText(String packageName, int resid,
2437                ApplicationInfo appInfo) {
2438            ResourceName name = new ResourceName(packageName, resid);
2439            CharSequence text = getCachedString(name);
2440            if (text != null) {
2441                return text;
2442            }
2443            if (appInfo == null) {
2444                try {
2445                    appInfo = getApplicationInfo(packageName, 0);
2446                } catch (NameNotFoundException e) {
2447                    return null;
2448                }
2449            }
2450            try {
2451                Resources r = getResourcesForApplication(appInfo);
2452                text = r.getText(resid);
2453                putCachedString(name, text);
2454                return text;
2455            } catch (NameNotFoundException e) {
2456                Log.w("PackageManager", "Failure retrieving resources for"
2457                        + appInfo.packageName);
2458            } catch (RuntimeException e) {
2459                // If an exception was thrown, fall through to return
2460                // default icon.
2461                Log.w("PackageManager", "Failure retrieving text 0x"
2462                        + Integer.toHexString(resid) + " in package "
2463                        + packageName, e);
2464            }
2465            return null;
2466        }
2467
2468        @Override
2469        public XmlResourceParser getXml(String packageName, int resid,
2470                ApplicationInfo appInfo) {
2471            if (appInfo == null) {
2472                try {
2473                    appInfo = getApplicationInfo(packageName, 0);
2474                } catch (NameNotFoundException e) {
2475                    return null;
2476                }
2477            }
2478            try {
2479                Resources r = getResourcesForApplication(appInfo);
2480                return r.getXml(resid);
2481            } catch (RuntimeException e) {
2482                // If an exception was thrown, fall through to return
2483                // default icon.
2484                Log.w("PackageManager", "Failure retrieving xml 0x"
2485                        + Integer.toHexString(resid) + " in package "
2486                        + packageName, e);
2487            } catch (NameNotFoundException e) {
2488                Log.w("PackageManager", "Failure retrieving resources for"
2489                        + appInfo.packageName);
2490            }
2491            return null;
2492        }
2493
2494        @Override
2495        public CharSequence getApplicationLabel(ApplicationInfo info) {
2496            return info.loadLabel(this);
2497        }
2498
2499        @Override
2500        public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
2501                String installerPackageName) {
2502            try {
2503                mPM.installPackage(packageURI, observer, flags, installerPackageName);
2504            } catch (RemoteException e) {
2505                // Should never happen!
2506            }
2507        }
2508
2509        @Override
2510        public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
2511            try {
2512                mPM.movePackage(packageName, observer, flags);
2513            } catch (RemoteException e) {
2514                // Should never happen!
2515            }
2516        }
2517
2518        @Override
2519        public String getInstallerPackageName(String packageName) {
2520            try {
2521                return mPM.getInstallerPackageName(packageName);
2522            } catch (RemoteException e) {
2523                // Should never happen!
2524            }
2525            return null;
2526        }
2527
2528        @Override
2529        public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
2530            try {
2531                mPM.deletePackage(packageName, observer, flags);
2532            } catch (RemoteException e) {
2533                // Should never happen!
2534            }
2535        }
2536        @Override
2537        public void clearApplicationUserData(String packageName,
2538                IPackageDataObserver observer) {
2539            try {
2540                mPM.clearApplicationUserData(packageName, observer);
2541            } catch (RemoteException e) {
2542                // Should never happen!
2543            }
2544        }
2545        @Override
2546        public void deleteApplicationCacheFiles(String packageName,
2547                IPackageDataObserver observer) {
2548            try {
2549                mPM.deleteApplicationCacheFiles(packageName, observer);
2550            } catch (RemoteException e) {
2551                // Should never happen!
2552            }
2553        }
2554        @Override
2555        public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
2556            try {
2557                mPM.freeStorageAndNotify(idealStorageSize, observer);
2558            } catch (RemoteException e) {
2559                // Should never happen!
2560            }
2561        }
2562
2563        @Override
2564        public void freeStorage(long freeStorageSize, IntentSender pi) {
2565            try {
2566                mPM.freeStorage(freeStorageSize, pi);
2567            } catch (RemoteException e) {
2568                // Should never happen!
2569            }
2570        }
2571
2572        @Override
2573        public void getPackageSizeInfo(String packageName,
2574                IPackageStatsObserver observer) {
2575            try {
2576                mPM.getPackageSizeInfo(packageName, observer);
2577            } catch (RemoteException e) {
2578                // Should never happen!
2579            }
2580        }
2581        @Override
2582        public void addPackageToPreferred(String packageName) {
2583            try {
2584                mPM.addPackageToPreferred(packageName);
2585            } catch (RemoteException e) {
2586                // Should never happen!
2587            }
2588        }
2589
2590        @Override
2591        public void removePackageFromPreferred(String packageName) {
2592            try {
2593                mPM.removePackageFromPreferred(packageName);
2594            } catch (RemoteException e) {
2595                // Should never happen!
2596            }
2597        }
2598
2599        @Override
2600        public List<PackageInfo> getPreferredPackages(int flags) {
2601            try {
2602                return mPM.getPreferredPackages(flags);
2603            } catch (RemoteException e) {
2604                // Should never happen!
2605            }
2606            return new ArrayList<PackageInfo>();
2607        }
2608
2609        @Override
2610        public void addPreferredActivity(IntentFilter filter,
2611                int match, ComponentName[] set, ComponentName activity) {
2612            try {
2613                mPM.addPreferredActivity(filter, match, set, activity);
2614            } catch (RemoteException e) {
2615                // Should never happen!
2616            }
2617        }
2618
2619        @Override
2620        public void replacePreferredActivity(IntentFilter filter,
2621                int match, ComponentName[] set, ComponentName activity) {
2622            try {
2623                mPM.replacePreferredActivity(filter, match, set, activity);
2624            } catch (RemoteException e) {
2625                // Should never happen!
2626            }
2627        }
2628
2629        @Override
2630        public void clearPackagePreferredActivities(String packageName) {
2631            try {
2632                mPM.clearPackagePreferredActivities(packageName);
2633            } catch (RemoteException e) {
2634                // Should never happen!
2635            }
2636        }
2637
2638        @Override
2639        public int getPreferredActivities(List<IntentFilter> outFilters,
2640                List<ComponentName> outActivities, String packageName) {
2641            try {
2642                return mPM.getPreferredActivities(outFilters, outActivities, packageName);
2643            } catch (RemoteException e) {
2644                // Should never happen!
2645            }
2646            return 0;
2647        }
2648
2649        @Override
2650        public void setComponentEnabledSetting(ComponentName componentName,
2651                int newState, int flags) {
2652            try {
2653                mPM.setComponentEnabledSetting(componentName, newState, flags);
2654            } catch (RemoteException e) {
2655                // Should never happen!
2656            }
2657        }
2658
2659        @Override
2660        public int getComponentEnabledSetting(ComponentName componentName) {
2661            try {
2662                return mPM.getComponentEnabledSetting(componentName);
2663            } catch (RemoteException e) {
2664                // Should never happen!
2665            }
2666            return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2667        }
2668
2669        @Override
2670        public void setApplicationEnabledSetting(String packageName,
2671                int newState, int flags) {
2672            try {
2673                mPM.setApplicationEnabledSetting(packageName, newState, flags);
2674            } catch (RemoteException e) {
2675                // Should never happen!
2676            }
2677        }
2678
2679        @Override
2680        public int getApplicationEnabledSetting(String packageName) {
2681            try {
2682                return mPM.getApplicationEnabledSetting(packageName);
2683            } catch (RemoteException e) {
2684                // Should never happen!
2685            }
2686            return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
2687        }
2688
2689        @Override
2690        public void setPackageObbPath(String packageName, String path) {
2691            try {
2692                mPM.setPackageObbPath(packageName, path);
2693            } catch (RemoteException e) {
2694                // Should never happen!
2695            }
2696        }
2697
2698        private final ContextImpl mContext;
2699        private final IPackageManager mPM;
2700
2701        private static final Object sSync = new Object();
2702        private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
2703                = new HashMap<ResourceName, WeakReference<Drawable> >();
2704        private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
2705                = new HashMap<ResourceName, WeakReference<CharSequence> >();
2706    }
2707
2708    // ----------------------------------------------------------------------
2709    // ----------------------------------------------------------------------
2710    // ----------------------------------------------------------------------
2711
2712    private static final class SharedPreferencesImpl implements SharedPreferences {
2713
2714        // Lock ordering rules:
2715        //  - acquire SharedPreferencesImpl.this before EditorImpl.this
2716        //  - acquire mWritingToDiskLock before EditorImpl.this
2717
2718        private final File mFile;
2719        private final File mBackupFile;
2720        private final int mMode;
2721
2722        private Map<String, Object> mMap;  // guarded by 'this'
2723        private long mTimestamp;  // guarded by 'this'
2724        private int mDiskWritesInFlight = 0;  // guarded by 'this'
2725        private boolean mLoaded = false;  // guarded by 'this'
2726
2727        private final Object mWritingToDiskLock = new Object();
2728        private static final Object mContent = new Object();
2729        private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
2730
2731        SharedPreferencesImpl(
2732            File file, int mode, Map initialContents) {
2733            mFile = file;
2734            mBackupFile = makeBackupFile(file);
2735            mMode = mode;
2736            mLoaded = initialContents != null;
2737            mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
2738            FileStatus stat = new FileStatus();
2739            if (FileUtils.getFileStatus(file.getPath(), stat)) {
2740                mTimestamp = stat.mtime;
2741            }
2742            mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
2743        }
2744
2745        // Has this SharedPreferences ever had values assigned to it?
2746        boolean isLoaded() {
2747            synchronized (this) {
2748                return mLoaded;
2749            }
2750        }
2751
2752        // Has the file changed out from under us?  i.e. writes that
2753        // we didn't instigate.
2754        public boolean hasFileChangedUnexpectedly() {
2755            synchronized (this) {
2756                if (mDiskWritesInFlight > 0) {
2757                    // If we know we caused it, it's not unexpected.
2758                    Log.d(TAG, "disk write in flight, not unexpected.");
2759                    return false;
2760                }
2761            }
2762            FileStatus stat = new FileStatus();
2763            if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
2764                return true;
2765            }
2766            synchronized (this) {
2767                return mTimestamp != stat.mtime;
2768            }
2769        }
2770
2771        public void replace(Map newContents) {
2772            synchronized (this) {
2773                mLoaded = true;
2774                if (newContents != null) {
2775                    mMap = newContents;
2776                }
2777            }
2778        }
2779
2780        public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2781            synchronized(this) {
2782                mListeners.put(listener, mContent);
2783            }
2784        }
2785
2786        public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
2787            synchronized(this) {
2788                mListeners.remove(listener);
2789            }
2790        }
2791
2792        public Map<String, ?> getAll() {
2793            synchronized(this) {
2794                //noinspection unchecked
2795                return new HashMap<String, Object>(mMap);
2796            }
2797        }
2798
2799        public String getString(String key, String defValue) {
2800            synchronized (this) {
2801                String v = (String)mMap.get(key);
2802                return v != null ? v : defValue;
2803            }
2804        }
2805
2806        public int getInt(String key, int defValue) {
2807            synchronized (this) {
2808                Integer v = (Integer)mMap.get(key);
2809                return v != null ? v : defValue;
2810            }
2811        }
2812        public long getLong(String key, long defValue) {
2813            synchronized (this) {
2814                Long v = (Long)mMap.get(key);
2815                return v != null ? v : defValue;
2816            }
2817        }
2818        public float getFloat(String key, float defValue) {
2819            synchronized (this) {
2820                Float v = (Float)mMap.get(key);
2821                return v != null ? v : defValue;
2822            }
2823        }
2824        public boolean getBoolean(String key, boolean defValue) {
2825            synchronized (this) {
2826                Boolean v = (Boolean)mMap.get(key);
2827                return v != null ? v : defValue;
2828            }
2829        }
2830
2831        public boolean contains(String key) {
2832            synchronized (this) {
2833                return mMap.containsKey(key);
2834            }
2835        }
2836
2837        public Editor edit() {
2838            return new EditorImpl();
2839        }
2840
2841        // Return value from EditorImpl#commitToMemory()
2842        private static class MemoryCommitResult {
2843            public boolean changesMade;  // any keys different?
2844            public List<String> keysModified;  // may be null
2845            public Set<OnSharedPreferenceChangeListener> listeners;  // may be null
2846            public Map<?, ?> mapToWriteToDisk;
2847            public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
2848            public volatile boolean writeToDiskResult = false;
2849
2850            public void setDiskWriteResult(boolean result) {
2851                writeToDiskResult = result;
2852                writtenToDiskLatch.countDown();
2853            }
2854        }
2855
2856        public final class EditorImpl implements Editor {
2857            private final Map<String, Object> mModified = Maps.newHashMap();
2858            private boolean mClear = false;
2859
2860            public Editor putString(String key, String value) {
2861                synchronized (this) {
2862                    mModified.put(key, value);
2863                    return this;
2864                }
2865            }
2866            public Editor putInt(String key, int value) {
2867                synchronized (this) {
2868                    mModified.put(key, value);
2869                    return this;
2870                }
2871            }
2872            public Editor putLong(String key, long value) {
2873                synchronized (this) {
2874                    mModified.put(key, value);
2875                    return this;
2876                }
2877            }
2878            public Editor putFloat(String key, float value) {
2879                synchronized (this) {
2880                    mModified.put(key, value);
2881                    return this;
2882                }
2883            }
2884            public Editor putBoolean(String key, boolean value) {
2885                synchronized (this) {
2886                    mModified.put(key, value);
2887                    return this;
2888                }
2889            }
2890
2891            public Editor remove(String key) {
2892                synchronized (this) {
2893                    mModified.put(key, this);
2894                    return this;
2895                }
2896            }
2897
2898            public Editor clear() {
2899                synchronized (this) {
2900                    mClear = true;
2901                    return this;
2902                }
2903            }
2904
2905            public void apply() {
2906                final MemoryCommitResult mcr = commitToMemory();
2907                final Runnable awaitCommit = new Runnable() {
2908                        public void run() {
2909                            try {
2910                                mcr.writtenToDiskLatch.await();
2911                            } catch (InterruptedException ignored) {
2912                            }
2913                        }
2914                    };
2915
2916                QueuedWork.add(awaitCommit);
2917
2918                Runnable postWriteRunnable = new Runnable() {
2919                        public void run() {
2920                            awaitCommit.run();
2921                            QueuedWork.remove(awaitCommit);
2922                        }
2923                    };
2924
2925                SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
2926
2927                // Okay to notify the listeners before it's hit disk
2928                // because the listeners should always get the same
2929                // SharedPreferences instance back, which has the
2930                // changes reflected in memory.
2931                notifyListeners(mcr);
2932            }
2933
2934            // Returns true if any changes were made
2935            private MemoryCommitResult commitToMemory() {
2936                MemoryCommitResult mcr = new MemoryCommitResult();
2937                synchronized (SharedPreferencesImpl.this) {
2938                    // We optimistically don't make a deep copy until
2939                    // a memory commit comes in when we're already
2940                    // writing to disk.
2941                    if (mDiskWritesInFlight > 0) {
2942                        // We can't modify our mMap as a currently
2943                        // in-flight write owns it.  Clone it before
2944                        // modifying it.
2945                        // noinspection unchecked
2946                        mMap = new HashMap<String, Object>(mMap);
2947                    }
2948                    mcr.mapToWriteToDisk = mMap;
2949                    mDiskWritesInFlight++;
2950
2951                    boolean hasListeners = mListeners.size() > 0;
2952                    if (hasListeners) {
2953                        mcr.keysModified = new ArrayList<String>();
2954                        mcr.listeners =
2955                            new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
2956                    }
2957
2958                    synchronized (this) {
2959                        if (mClear) {
2960                            if (!mMap.isEmpty()) {
2961                                mcr.changesMade = true;
2962                                mMap.clear();
2963                            }
2964                            mClear = false;
2965                        }
2966
2967                        for (Entry<String, Object> e : mModified.entrySet()) {
2968                            String k = e.getKey();
2969                            Object v = e.getValue();
2970                            if (v == this) {  // magic value for a removal mutation
2971                                if (!mMap.containsKey(k)) {
2972                                    continue;
2973                                }
2974                                mMap.remove(k);
2975                            } else {
2976                                boolean isSame = false;
2977                                if (mMap.containsKey(k)) {
2978                                    Object existingValue = mMap.get(k);
2979                                    if (existingValue != null && existingValue.equals(v)) {
2980                                        continue;
2981                                    }
2982                                }
2983                                mMap.put(k, v);
2984                            }
2985
2986                            mcr.changesMade = true;
2987                            if (hasListeners) {
2988                                mcr.keysModified.add(k);
2989                            }
2990                        }
2991
2992                        mModified.clear();
2993                    }
2994                }
2995                return mcr;
2996            }
2997
2998            public boolean commit() {
2999                MemoryCommitResult mcr = commitToMemory();
3000                SharedPreferencesImpl.this.enqueueDiskWrite(
3001                    mcr, null /* sync write on this thread okay */);
3002                try {
3003                    mcr.writtenToDiskLatch.await();
3004                } catch (InterruptedException e) {
3005                    return false;
3006                }
3007                notifyListeners(mcr);
3008                return mcr.writeToDiskResult;
3009            }
3010
3011            private void notifyListeners(final MemoryCommitResult mcr) {
3012                if (mcr.listeners == null || mcr.keysModified == null ||
3013                    mcr.keysModified.size() == 0) {
3014                    return;
3015                }
3016                if (Looper.myLooper() == Looper.getMainLooper()) {
3017                    for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
3018                        final String key = mcr.keysModified.get(i);
3019                        for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
3020                            if (listener != null) {
3021                                listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
3022                            }
3023                        }
3024                    }
3025                } else {
3026                    // Run this function on the main thread.
3027                    ActivityThread.sMainThreadHandler.post(new Runnable() {
3028                            public void run() {
3029                                notifyListeners(mcr);
3030                            }
3031                        });
3032                }
3033            }
3034        }
3035
3036        /**
3037         * Enqueue an already-committed-to-memory result to be written
3038         * to disk.
3039         *
3040         * They will be written to disk one-at-a-time in the order
3041         * that they're enqueued.
3042         *
3043         * @param postWriteRunnable if non-null, we're being called
3044         *   from apply() and this is the runnable to run after
3045         *   the write proceeds.  if null (from a regular commit()),
3046         *   then we're allowed to do this disk write on the main
3047         *   thread (which in addition to reducing allocations and
3048         *   creating a background thread, this has the advantage that
3049         *   we catch them in userdebug StrictMode reports to convert
3050         *   them where possible to apply() ...)
3051         */
3052        private void enqueueDiskWrite(final MemoryCommitResult mcr,
3053                                      final Runnable postWriteRunnable) {
3054            final Runnable writeToDiskRunnable = new Runnable() {
3055                    public void run() {
3056                        synchronized (mWritingToDiskLock) {
3057                            writeToFile(mcr);
3058                        }
3059                        synchronized (SharedPreferencesImpl.this) {
3060                            mDiskWritesInFlight--;
3061                        }
3062                        if (postWriteRunnable != null) {
3063                            postWriteRunnable.run();
3064                        }
3065                    }
3066                };
3067
3068            final boolean isFromSyncCommit = (postWriteRunnable == null);
3069
3070            // Typical #commit() path with fewer allocations, doing a write on
3071            // the current thread.
3072            if (isFromSyncCommit) {
3073                boolean wasEmpty = false;
3074                synchronized (SharedPreferencesImpl.this) {
3075                    wasEmpty = mDiskWritesInFlight == 1;
3076                }
3077                if (wasEmpty) {
3078                    writeToDiskRunnable.run();
3079                    return;
3080                }
3081            }
3082
3083            QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
3084        }
3085
3086        private static FileOutputStream createFileOutputStream(File file) {
3087            FileOutputStream str = null;
3088            try {
3089                str = new FileOutputStream(file);
3090            } catch (FileNotFoundException e) {
3091                File parent = file.getParentFile();
3092                if (!parent.mkdir()) {
3093                    Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
3094                    return null;
3095                }
3096                FileUtils.setPermissions(
3097                    parent.getPath(),
3098                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
3099                    -1, -1);
3100                try {
3101                    str = new FileOutputStream(file);
3102                } catch (FileNotFoundException e2) {
3103                    Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
3104                }
3105            }
3106            return str;
3107        }
3108
3109        // Note: must hold mWritingToDiskLock
3110        private void writeToFile(MemoryCommitResult mcr) {
3111            // Rename the current file so it may be used as a backup during the next read
3112            if (mFile.exists()) {
3113                if (!mcr.changesMade) {
3114                    // If the file already exists, but no changes were
3115                    // made to the underlying map, it's wasteful to
3116                    // re-write the file.  Return as if we wrote it
3117                    // out.
3118                    mcr.setDiskWriteResult(true);
3119                    return;
3120                }
3121                if (!mBackupFile.exists()) {
3122                    if (!mFile.renameTo(mBackupFile)) {
3123                        Log.e(TAG, "Couldn't rename file " + mFile
3124                                + " to backup file " + mBackupFile);
3125                        mcr.setDiskWriteResult(false);
3126                        return;
3127                    }
3128                } else {
3129                    mFile.delete();
3130                }
3131            }
3132
3133            // Attempt to write the file, delete the backup and return true as atomically as
3134            // possible.  If any exception occurs, delete the new file; next time we will restore
3135            // from the backup.
3136            try {
3137                FileOutputStream str = createFileOutputStream(mFile);
3138                if (str == null) {
3139                    mcr.setDiskWriteResult(false);
3140                    return;
3141                }
3142                XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
3143                str.close();
3144                setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
3145                FileStatus stat = new FileStatus();
3146                if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
3147                    synchronized (this) {
3148                        mTimestamp = stat.mtime;
3149                    }
3150                }
3151                // Writing was successful, delete the backup file if there is one.
3152                mBackupFile.delete();
3153                mcr.setDiskWriteResult(true);
3154                return;
3155            } catch (XmlPullParserException e) {
3156                Log.w(TAG, "writeToFile: Got exception:", e);
3157            } catch (IOException e) {
3158                Log.w(TAG, "writeToFile: Got exception:", e);
3159            }
3160            // Clean up an unsuccessfully written file
3161            if (mFile.exists()) {
3162                if (!mFile.delete()) {
3163                    Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
3164                }
3165            }
3166            mcr.setDiskWriteResult(false);
3167        }
3168    }
3169}
3170