}
private final ActivityThread mMainThread;
}
<<<<<<< HEAD
=======
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
/*package*/
static final class ApplicationPackageManager extends PackageManager {
@Override
public PackageInfo getPackageInfo(String packageName, int flags)
throws NameNotFoundException {
try {
PackageInfo pi = mPM.getPackageInfo(packageName, flags);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(packageName);
}
@Override
public String[] currentToCanonicalPackageNames(String[] names) {
try {
return mPM.currentToCanonicalPackageNames(names);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public String[] canonicalToCurrentPackageNames(String[] names) {
try {
return mPM.canonicalToCurrentPackageNames(names);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public Intent getLaunchIntentForPackage(String packageName) {
// First see if the package has an INFO activity; the existence of
// such an activity is implied to be the desired front-door for the
// overall package (such as if it has multiple launcher entries).
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(Intent.CATEGORY_INFO);
intentToResolve.setPackage(packageName);
ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
// Otherwise, try to find a main launcher activity.
if (resolveInfo == null) {
// reuse the intent instance
intentToResolve.removeCategory(Intent.CATEGORY_INFO);
intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
intentToResolve.setPackage(packageName);
resolveInfo = resolveActivity(intentToResolve, 0);
}
if (resolveInfo == null) {
return null;
}
Intent intent = new Intent(intentToResolve);
return ai;
intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
resolveInfo.activityInfo.name);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
@Override
public int[] getPackageGids(String packageName)
throws NameNotFoundException {
try {
int[] gids = mPM.getPackageGids(packageName);
if (gids == null || gids.length > 0) {
return gids;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(packageName);
}
@Override
public PermissionInfo getPermissionInfo(String name, int flags)
throws NameNotFoundException {
try {
PermissionInfo pi = mPM.getPermissionInfo(name, flags);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(name);
}
@Override
public List queryPermissionsByGroup(String group, int flags)
throws NameNotFoundException {
try {
List pi = mPM.queryPermissionsByGroup(group, flags);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(group);
@Override
public PermissionGroupInfo getPermissionGroupInfo(String name,
int flags) throws NameNotFoundException {
try {
PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
if (pgi != null) {
return pgi;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(name);
}
@Override
public List getAllPermissionGroups(int flags) {
try {
return mPM.getAllPermissionGroups(flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags)
throws NameNotFoundException {
try {
ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
if (ai != null) {
return ai;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(packageName);
}
@Override
public ActivityInfo getActivityInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
ActivityInfo ai = mPM.getActivityInfo(className, flags);
if (ai != null) {
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(className.toString());
}
@Override
public ActivityInfo getReceiverInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
ActivityInfo ai = mPM.getReceiverInfo(className, flags);
if (ai != null) {
return ai;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(className.toString());
}
@Override
public ServiceInfo getServiceInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
ServiceInfo si = mPM.getServiceInfo(className, flags);
if (si != null) {
return si;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(className.toString());
}
@Override
public ProviderInfo getProviderInfo(ComponentName className, int flags)
throws NameNotFoundException {
try {
ProviderInfo pi = mPM.getProviderInfo(className, flags);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
throw new NameNotFoundException(className.toString());
}
@Override
public String[] getSystemSharedLibraryNames() {
try {
return mPM.getSystemSharedLibraryNames();
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public FeatureInfo[] getSystemAvailableFeatures() {
try {
return mPM.getSystemAvailableFeatures();
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public boolean hasSystemFeature(String name) {
try {
return mPM.hasSystemFeature(name);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public int checkPermission(String permName, String pkgName) {
try {
return mPM.checkPermission(permName, pkgName);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public boolean addPermission(PermissionInfo info) {
try {
return mPM.addPermission(info);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public boolean addPermissionAsync(PermissionInfo info) {
try {
return mPM.addPermissionAsync(info);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public void removePermission(String name) {
try {
mPM.removePermission(name);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public int checkSignatures(String pkg1, String pkg2) {
try {
return mPM.checkSignatures(pkg1, pkg2);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public int checkSignatures(int uid1, int uid2) {
try {
return mPM.checkUidSignatures(uid1, uid2);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public String[] getPackagesForUid(int uid) {
try {
return mPM.getPackagesForUid(uid);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public String getNameForUid(int uid) {
try {
return mPM.getNameForUid(uid);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@Override
public int getUidForSharedUser(String sharedUserName)
throws NameNotFoundException {
try {
int uid = mPM.getUidForSharedUser(sharedUserName);
if(uid != -1) {
return uid;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
}
@SuppressWarnings("unchecked")
@Override
public List getInstalledPackages(int flags) {
try {
final List packageInfos = new ArrayList();
PackageInfo lastItem = null;
ParceledListSlice slice;
do {
final String lastKey = lastItem != null ? lastItem.packageName : null;
slice = mPM.getInstalledPackages(flags, lastKey);
lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
} while (!slice.isLastSlice());
return packageInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@SuppressWarnings("unchecked")
@Override
public List getInstalledApplications(int flags) {
try {
final List applicationInfos = new ArrayList();
ApplicationInfo lastItem = null;
ParceledListSlice slice;
do {
try {
final String lastKey = lastItem != null ? lastItem.packageName : null;
slice = mPM.getInstalledApplications(flags, lastKey);
lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
} while (!slice.isLastSlice());
return applicationInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public ResolveInfo resolveActivity(Intent intent, int flags) {
try {
return mPM.resolveIntent(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public List queryIntentActivities(Intent intent,
int flags) {
try {
return mPM.queryIntentActivities(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public List queryIntentActivityOptions(
ComponentName caller, Intent[] specifics, Intent intent,
int flags) {
final ContentResolver resolver = mContext.getContentResolver();
String[] specificTypes = null;
if (specifics != null) {
final int N = specifics.length;
for (int i=0; i queryBroadcastReceivers(Intent intent, int flags) {
try {
return mPM.queryIntentReceivers(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public ResolveInfo resolveService(Intent intent, int flags) {
try {
return mPM.resolveService(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public List queryIntentServices(Intent intent, int flags) {
return mPM.queryIntentServices(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public ProviderInfo resolveContentProvider(String name,
int flags) {
try {
return mPM.resolveContentProvider(name, flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public List queryContentProviders(String processName,
int uid, int flags) {
try {
return mPM.queryContentProviders(processName, uid, flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public InstrumentationInfo getInstrumentationInfo(
ComponentName className, int flags)
throws NameNotFoundException {
try {
InstrumentationInfo ii = mPM.getInstrumentationInfo(
className, flags);
if (ii != null) {
return ii;
}
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
throw new NameNotFoundException(className.toString());
}
@Override
public List queryInstrumentation(
String targetPackage, int flags) {
try {
return mPM.queryInstrumentation(targetPackage, flags);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override public Drawable getDrawable(String packageName, int resid,
ApplicationInfo appInfo) {
ResourceName name = new ResourceName(packageName, resid);
Drawable dr = getCachedIcon(name);
if (dr != null) {
return dr;
}
if (appInfo == null) {
try {
appInfo = getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
return null;
}
}
try {
Resources r = getResourcesForApplication(appInfo);
dr = r.getDrawable(resid);
if (false) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
+ " from package " + packageName
+ ": app scale=" + r.getCompatibilityInfo().applicationScale
+ ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
e);
}
if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
+ Integer.toHexString(resid) + " from " + r
+ ": " + dr);
putCachedIcon(name, dr);
return dr;
} catch (NameNotFoundException e) {
Log.w("PackageManager", "Failure retrieving resources for"
+ appInfo.packageName);
} catch (RuntimeException e) {
// If an exception was thrown, fall through to return
// default icon.
Log.w("PackageManager", "Failure retrieving icon 0x"
+ Integer.toHexString(resid) + " in package "
+ packageName, e);
}
return null;
}
@Override public Drawable getActivityIcon(ComponentName activityName)
throws NameNotFoundException {
return getActivityInfo(activityName, 0).loadIcon(this);
}
@Override public Drawable getActivityIcon(Intent intent)
throws NameNotFoundException {
if (intent.getComponent() != null) {
return getActivityIcon(intent.getComponent());
}
ResolveInfo info = resolveActivity(
intent, PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) {
return info.activityInfo.loadIcon(this);
}
throw new NameNotFoundException(intent.toURI());
}
@Override public Drawable getDefaultActivityIcon() {
return Resources.getSystem().getDrawable(
com.android.internal.R.drawable.sym_def_app_icon);
}
@Override public Drawable getApplicationIcon(ApplicationInfo info) {
return info.loadIcon(this);
}
@Override public Drawable getApplicationIcon(String packageName)
throws NameNotFoundException {
return getApplicationIcon(getApplicationInfo(packageName, 0));
}
@Override
public Drawable getActivityLogo(ComponentName activityName)
throws NameNotFoundException {
return getActivityInfo(activityName, 0).loadLogo(this);
}
@Override
public Drawable getActivityLogo(Intent intent)
throws NameNotFoundException {
if (intent.getComponent() != null) {
return getActivityLogo(intent.getComponent());
}
ResolveInfo info = resolveActivity(
intent, PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) {
return info.activityInfo.loadLogo(this);
}
throw new NameNotFoundException(intent.toUri(0));
}
@Override
public Drawable getApplicationLogo(ApplicationInfo info) {
return info.loadLogo(this);
}
@Override
public Drawable getApplicationLogo(String packageName)
throws NameNotFoundException {
return getApplicationLogo(getApplicationInfo(packageName, 0));
}
@Override public Resources getResourcesForActivity(
ComponentName activityName) throws NameNotFoundException {
return getResourcesForApplication(
getActivityInfo(activityName, 0).applicationInfo);
}
@Override public Resources getResourcesForApplication(
ApplicationInfo app) throws NameNotFoundException {
if (app.packageName.equals("system")) {
return mContext.mMainThread.getSystemContext().getResources();
}
Resources r = mContext.mMainThread.getTopLevelResources(
app.uid == Process.myUid() ? app.sourceDir
: app.publicSourceDir, mContext.mPackageInfo);
if (r != null) {
return r;
}
throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
}
}
@Override public Resources getResourcesForApplication(
String appPackageName) throws NameNotFoundException {
return getResourcesForApplication(
getApplicationInfo(appPackageName, 0));
}
int mCachedSafeMode = -1;
@Override public boolean isSafeMode() {
try {
if (mCachedSafeMode < 0) {
mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
}
return mCachedSafeMode != 0;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
static void configurationChanged() {
synchronized (sSync) {
sIconCache.clear();
sStringCache.clear();
}
}
ApplicationPackageManager(ContextImpl context,
IPackageManager pm) {
mContext = context;
mPM = pm;
}
private Drawable getCachedIcon(ResourceName name) {
synchronized (sSync) {
WeakReference wr = sIconCache.get(name);
if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+ name + ": " + wr);
if (wr != null) { // we have the activity
Drawable dr = wr.get();
if (dr != null) {
if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
+ name + ": " + dr);
return dr;
}
// our entry has been purged
sIconCache.remove(name);
}
}
return null;
}
private void putCachedIcon(ResourceName name, Drawable dr) {
synchronized (sSync) {
sIconCache.put(name, new WeakReference(dr));
if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
+ name + ": " + dr);
}
}
static final void handlePackageBroadcast(int cmd, String[] pkgList,
boolean hasPkgInfo) {
boolean immediateGc = false;
if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
immediateGc = true;
}
if (pkgList != null && (pkgList.length > 0)) {
boolean needCleanup = false;
for (String ssp : pkgList) {
synchronized (sSync) {
if (sIconCache.size() > 0) {
Iterator it = sIconCache.keySet().iterator();
while (it.hasNext()) {
ResourceName nm = it.next();
if (nm.packageName.equals(ssp)) {
//Log.i(TAG, "Removing cached drawable for " + nm);
it.remove();
needCleanup = true;
}
}
}
if (sStringCache.size() > 0) {
Iterator it = sStringCache.keySet().iterator();
while (it.hasNext()) {
ResourceName nm = it.next();
if (nm.packageName.equals(ssp)) {
//Log.i(TAG, "Removing cached string for " + nm);
it.remove();
needCleanup = true;
}
}
}
}
if (needCleanup || hasPkgInfo) {
if (immediateGc) {
// Schedule an immediate gc.
Runtime.getRuntime().gc();
} else {
ActivityThread.currentActivityThread().scheduleGcIdler();
}
}
}
}
private static final class ResourceName {
final String packageName;
final int iconId;
ResourceName(String _packageName, int _iconId) {
packageName = _packageName;
iconId = _iconId;
}
ResourceName(ApplicationInfo aInfo, int _iconId) {
this(aInfo.packageName, _iconId);
}
ResourceName(ComponentInfo cInfo, int _iconId) {
this(cInfo.applicationInfo.packageName, _iconId);
}
ResourceName(ResolveInfo rInfo, int _iconId) {
this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ResourceName that = (ResourceName) o;
if (iconId != that.iconId) return false;
return !(packageName != null ?
!packageName.equals(that.packageName) : that.packageName != null);
}
@Override
public int hashCode() {
int result;
result = packageName.hashCode();
result = 31 * result + iconId;
return result;
}
@Override
public String toString() {
return "{ResourceName " + packageName + " / " + iconId + "}";
}
}
private CharSequence getCachedString(ResourceName name) {
synchronized (sSync) {
WeakReference wr = sStringCache.get(name);
if (wr != null) { // we have the activity
CharSequence cs = wr.get();
if (cs != null) {
return cs;
}
// our entry has been purged
sStringCache.remove(name);
}
}
return null;
}
private void putCachedString(ResourceName name, CharSequence cs) {
synchronized (sSync) {
sStringCache.put(name, new WeakReference(cs));
}
}
@Override
public CharSequence getText(String packageName, int resid,
ApplicationInfo appInfo) {
ResourceName name = new ResourceName(packageName, resid);
CharSequence text = getCachedString(name);
if (text != null) {
return text;
}
if (appInfo == null) {
try {
appInfo = getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
return null;
}
}
try {
Resources r = getResourcesForApplication(appInfo);
text = r.getText(resid);
try {
putCachedString(name, text);
return text;
} catch (NameNotFoundException e) {
Log.w("PackageManager", "Failure retrieving resources for"
+ appInfo.packageName);
} catch (RuntimeException e) {
// If an exception was thrown, fall through to return
// default icon.
Log.w("PackageManager", "Failure retrieving text 0x"
+ Integer.toHexString(resid) + " in package "
+ packageName, e);
}
return null;
}
@Override
public XmlResourceParser getXml(String packageName, int resid,
ApplicationInfo appInfo) {
if (appInfo == null) {
try {
appInfo = getApplicationInfo(packageName, 0);
} catch (NameNotFoundException e) {
return null;
}
}
try {
Resources r = getResourcesForApplication(appInfo);
return r.getXml(resid);
} catch (RuntimeException e) {
// If an exception was thrown, fall through to return
// default icon.
Log.w("PackageManager", "Failure retrieving xml 0x"
+ Integer.toHexString(resid) + " in package "
+ packageName, e);
} catch (NameNotFoundException e) {
Log.w("PackageManager", "Failure retrieving resources for"
+ appInfo.packageName);
}
return null;
}
@Override
public CharSequence getApplicationLabel(ApplicationInfo info) {
return info.loadLabel(this);
}
@Override
synchronized(this) {
public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName) {
try {
mPM.installPackage(packageURI, observer, flags, installerPackageName);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
try {
mPM.movePackage(packageName, observer, flags);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public String getInstallerPackageName(String packageName) {
try {
return mPM.getInstallerPackageName(packageName);
} catch (RemoteException e) {
// Should never happen!
}
return null;
}
@Override
public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
try {
mPM.deletePackage(packageName, observer, flags);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void clearApplicationUserData(String packageName,
IPackageDataObserver observer) {
try {
mPM.clearApplicationUserData(packageName, observer);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void deleteApplicationCacheFiles(String packageName,
IPackageDataObserver observer) {
mPM.deleteApplicationCacheFiles(packageName, observer);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
try {
mPM.freeStorageAndNotify(idealStorageSize, observer);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void freeStorage(long freeStorageSize, IntentSender pi) {
try {
mPM.freeStorage(freeStorageSize, pi);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void getPackageSizeInfo(String packageName,
IPackageStatsObserver observer) {
try {
mPM.getPackageSizeInfo(packageName, observer);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void addPackageToPreferred(String packageName) {
try {
mPM.addPackageToPreferred(packageName);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void removePackageFromPreferred(String packageName) {
try {
mPM.removePackageFromPreferred(packageName);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public List getPreferredPackages(int flags) {
try {
return mPM.getPreferredPackages(flags);
} catch (RemoteException e) {
// Should never happen!
}
return new ArrayList();
}
@Override
public void addPreferredActivity(IntentFilter filter,
int match, ComponentName[] set, ComponentName activity) {
try {
mPM.addPreferredActivity(filter, match, set, activity);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void replacePreferredActivity(IntentFilter filter,
int match, ComponentName[] set, ComponentName activity) {
try {
mPM.replacePreferredActivity(filter, match, set, activity);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public void clearPackagePreferredActivities(String packageName) {
try {
mPM.clearPackagePreferredActivities(packageName);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public int getPreferredActivities(List outFilters,
List outActivities, String packageName) {
try {
return mPM.getPreferredActivities(outFilters, outActivities, packageName);
} catch (RemoteException e) {
// Should never happen!
}
return 0;
}
@Override
public void setComponentEnabledSetting(ComponentName componentName,
int newState, int flags) {
try {
mPM.setComponentEnabledSetting(componentName, newState, flags);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public int getComponentEnabledSetting(ComponentName componentName) {
try {
return mPM.getComponentEnabledSetting(componentName);
} catch (RemoteException e) {
// Should never happen!
}
return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
@Override
public void setApplicationEnabledSetting(String packageName,
int newState, int flags) {
try {
mPM.setApplicationEnabledSetting(packageName, newState, flags);
} catch (RemoteException e) {
// Should never happen!
}
}
@Override
public int getApplicationEnabledSetting(String packageName) {
try {
return mPM.getApplicationEnabledSetting(packageName);
} catch (RemoteException e) {
// Should never happen!
}
return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
private final ContextImpl mContext;
private final IPackageManager mPM;
private static final Object sSync = new Object();
private static HashMap > sIconCache
= new HashMap >();
private static HashMap > sStringCache
= new HashMap >();
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
private static final class SharedPreferencesImpl implements SharedPreferences {
// Lock ordering rules:
// - acquire SharedPreferencesImpl.this before EditorImpl.this
// - acquire mWritingToDiskLock before EditorImpl.this
private final File mFile;
private final File mBackupFile;
private final int mMode;
private Map mMap; // guarded by 'this'
private int mDiskWritesInFlight = 0; // guarded by 'this'
private boolean mLoaded = false; // guarded by 'this'
private long mStatTimestamp; // guarded by 'this'
private long mStatSize; // guarded by 'this'
private final Object mWritingToDiskLock = new Object();
private static final Object mContent = new Object();
private final WeakHashMap mListeners;
SharedPreferencesImpl(
File file, int mode, Map initialContents) {
mFile = file;
mBackupFile = makeBackupFile(file);
mMode = mode;
mLoaded = initialContents != null;
mMap = initialContents != null ? initialContents : new HashMap();
FileStatus stat = new FileStatus();
if (FileUtils.getFileStatus(file.getPath(), stat)) {
mStatTimestamp = stat.mtime;
}
mListeners = new WeakHashMap();
}
// Has this SharedPreferences ever had values assigned to it?
boolean isLoaded() {
synchronized (this) {
return mLoaded;
}
}
// Has the file changed out from under us? i.e. writes that
// we didn't instigate.
public boolean hasFileChangedUnexpectedly() {
synchronized (this) {
if (mDiskWritesInFlight > 0) {
// If we know we caused it, it's not unexpected.
if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected.");
return false;
}
}
FileStatus stat = new FileStatus();
if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
return true;
}
synchronized (this) {
return mStatTimestamp != stat.mtime || mStatSize != stat.size;
}
}
/* package */ void replace(Map newContents, FileStatus stat) {
synchronized (this) {
mLoaded = true;
if (newContents != null) {
mMap = newContents;
}
if (stat != null) {
mStatTimestamp = stat.mtime;
mStatSize = stat.size;
}
}
}
public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.put(listener, mContent);
}
}
public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.remove(listener);
}
}
public Map getAll() {
//noinspection unchecked
return new HashMap(mMap);
}
}
public String getString(String key, String defValue) {
synchronized (this) {
String v = (String)mMap.get(key);
return v != null ? v : defValue;
}
}
public int getInt(String key, int defValue) {
synchronized (this) {
Integer v = (Integer)mMap.get(key);
return v != null ? v : defValue;
}
}
public long getLong(String key, long defValue) {
synchronized (this) {
Long v = (Long)mMap.get(key);
return v != null ? v : defValue;
}
}
public float getFloat(String key, float defValue) {
synchronized (this) {
Float v = (Float)mMap.get(key);
return v != null ? v : defValue;
}
}
public boolean getBoolean(String key, boolean defValue) {
synchronized (this) {
Boolean v = (Boolean)mMap.get(key);
return v != null ? v : defValue;
}
}
public boolean contains(String key) {
synchronized (this) {
return mMap.containsKey(key);
}
}
public Editor edit() {
return new EditorImpl();
}
// Return value from EditorImpl#commitToMemory()
private static class MemoryCommitResult {
public boolean changesMade; // any keys different?
public List keysModified; // may be null
public Set listeners; // may be null
public Map, ?> mapToWriteToDisk;
public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
public volatile boolean writeToDiskResult = false;
public void setDiskWriteResult(boolean result) {
writeToDiskResult = result;
writtenToDiskLatch.countDown();
}
}
public final class EditorImpl implements Editor {
private final Map mModified = Maps.newHashMap();
private boolean mClear = false;
public Editor putString(String key, String value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putInt(String key, int value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putLong(String key, long value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putFloat(String key, float value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor putBoolean(String key, boolean value) {
synchronized (this) {
mModified.put(key, value);
return this;
}
}
public Editor remove(String key) {
synchronized (this) {
mModified.put(key, this);
return this;
}
}
public Editor clear() {
synchronized (this) {
mClear = true;
return this;
}
}
public void apply() {
final MemoryCommitResult mcr = commitToMemory();
final Runnable awaitCommit = new Runnable() {
public void run() {
try {
mcr.writtenToDiskLatch.await();
} catch (InterruptedException ignored) {
}
}
};
QueuedWork.add(awaitCommit);
Runnable postWriteRunnable = new Runnable() {
public void run() {
awaitCommit.run();
QueuedWork.remove(awaitCommit);
}
};
SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
// Okay to notify the listeners before it's hit disk
// because the listeners should always get the same
// SharedPreferences instance back, which has the
// changes reflected in memory.
notifyListeners(mcr);
}
// Returns true if any changes were made
private MemoryCommitResult commitToMemory() {
MemoryCommitResult mcr = new MemoryCommitResult();
synchronized (SharedPreferencesImpl.this) {
// We optimistically don't make a deep copy until
// a memory commit comes in when we're already
// writing to disk.
if (mDiskWritesInFlight > 0) {
// We can't modify our mMap as a currently
// in-flight write owns it. Clone it before
// modifying it.
// noinspection unchecked
mMap = new HashMap(mMap);
}
mcr.mapToWriteToDisk = mMap;
mDiskWritesInFlight++;
boolean hasListeners = mListeners.size() > 0;
if (hasListeners) {
mcr.keysModified = new ArrayList();
mcr.listeners =
new HashSet(mListeners.keySet());
}
synchronized (this) {
if (mClear) {
if (!mMap.isEmpty()) {
mcr.changesMade = true;
mMap.clear();
}
mClear = false;
}
for (Entry e : mModified.entrySet()) {
String k = e.getKey();
Object v = e.getValue();
if (v == this) { // magic value for a removal mutation
if (!mMap.containsKey(k)) {
continue;
}
mMap.remove(k);
} else {
boolean isSame = false;
if (mMap.containsKey(k)) {
Object existingValue = mMap.get(k);
if (existingValue != null && existingValue.equals(v)) {
continue;
}
}
mMap.put(k, v);
}
mcr.changesMade = true;
if (hasListeners) {
mcr.keysModified.add(k);
}
}
mModified.clear();
}
}
return mcr;
}
public boolean commit() {
MemoryCommitResult mcr = commitToMemory();
SharedPreferencesImpl.this.enqueueDiskWrite(
mcr, null /* sync write on this thread okay */);
try {
mcr.writtenToDiskLatch.await();
} catch (InterruptedException e) {
return false;
}
notifyListeners(mcr);
return mcr.writeToDiskResult;
}
private void notifyListeners(final MemoryCommitResult mcr) {
if (mcr.listeners == null || mcr.keysModified == null ||
mcr.keysModified.size() == 0) {
return;
}
if (Looper.myLooper() == Looper.getMainLooper()) {
for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
final String key = mcr.keysModified.get(i);
for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
if (listener != null) {
listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
}
}
}
} else {
// Run this function on the main thread.
ActivityThread.sMainThreadHandler.post(new Runnable() {
public void run() {
notifyListeners(mcr);
}
});
}
}
}
/**
* Enqueue an already-committed-to-memory result to be written
* to disk.
*
* They will be written to disk one-at-a-time in the order
* that they're enqueued.
*
* @param postWriteRunnable if non-null, we're being called
* from apply() and this is the runnable to run after
* the write proceeds. if null (from a regular commit()),
* then we're allowed to do this disk write on the main
* thread (which in addition to reducing allocations and
* creating a background thread, this has the advantage that
* we catch them in userdebug StrictMode reports to convert
* them where possible to apply() ...)
*/
private void enqueueDiskWrite(final MemoryCommitResult mcr,
final Runnable postWriteRunnable) {
final Runnable writeToDiskRunnable = new Runnable() {
public void run() {
synchronized (mWritingToDiskLock) {
writeToFile(mcr);
}
synchronized (SharedPreferencesImpl.this) {
mDiskWritesInFlight--;
}
if (postWriteRunnable != null) {
postWriteRunnable.run();
}
}
};
final boolean isFromSyncCommit = (postWriteRunnable == null);
// Typical #commit() path with fewer allocations, doing a write on
// the current thread.
if (isFromSyncCommit) {
boolean wasEmpty = false;
synchronized (SharedPreferencesImpl.this) {
wasEmpty = mDiskWritesInFlight == 1;
}
if (wasEmpty) {
writeToDiskRunnable.run();
return;
}
}
QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
}
private static FileOutputStream createFileOutputStream(File file) {
FileOutputStream str = null;
try {
str = new FileOutputStream(file);
} catch (FileNotFoundException e) {
File parent = file.getParentFile();
if (!parent.mkdir()) {
Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
return null;
}
FileUtils.setPermissions(
parent.getPath(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-1, -1);
try {
str = new FileOutputStream(file);
} catch (FileNotFoundException e2) {
Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
}
}
return str;
}
// Note: must hold mWritingToDiskLock
private void writeToFile(MemoryCommitResult mcr) {
// Rename the current file so it may be used as a backup during the next read
if (mFile.exists()) {
if (!mcr.changesMade) {
// If the file already exists, but no changes were
// made to the underlying map, it's wasteful to
// re-write the file. Return as if we wrote it
// out.
mcr.setDiskWriteResult(true);
return;
}
if (!mBackupFile.exists()) {
if (!mFile.renameTo(mBackupFile)) {
Log.e(TAG, "Couldn't rename file " + mFile
+ " to backup file " + mBackupFile);
mcr.setDiskWriteResult(false);
return;
}
} else {
mFile.delete();
}
}
// Attempt to write the file, delete the backup and return true as atomically as
// possible. If any exception occurs, delete the new file; next time we will restore
// from the backup.
try {
FileOutputStream str = createFileOutputStream(mFile);
if (str == null) {
mcr.setDiskWriteResult(false);
return;
}
XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
FileUtils.sync(str);
str.close();
setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
FileStatus stat = new FileStatus();
if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
synchronized (this) {
mStatTimestamp = stat.mtime;
mStatSize = stat.size;
}
}
// Writing was successful, delete the backup file if there is one.
mBackupFile.delete();
mcr.setDiskWriteResult(true);
return;
} catch (XmlPullParserException e) {
Log.w(TAG, "writeToFile: Got exception:", e);
} catch (IOException e) {
Log.w(TAG, "writeToFile: Got exception:", e);
}
// Clean up an unsuccessfully written file
if (mFile.exists()) {
if (!mFile.delete()) {
Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
}
}
mcr.setDiskWriteResult(false);
}
}
>>>>>>> 2433c443bb5fe96d9a39b59e10e3c03d791e2278
} |