Move ApplicationsState to SettingsLib
Also take InterestingConfigChanges along for the ride
and delete unused AppPermissionSettings
b/21328967
Change-Id: I4d0c1a27054845a54cf68e95a92024d2e46f636e
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index b7f62a3..21a5019 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -16,8 +16,6 @@
package com.android.settings;
-import static android.content.Intent.EXTRA_USER;
-
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -70,8 +68,6 @@
import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.RawContacts;
import android.service.persistentdata.PersistentDataBlockManager;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -87,20 +83,21 @@
import com.android.internal.util.UserIcons;
import com.android.settings.UserAdapter.UserDetails;
-import com.android.settings.applications.ApplicationsState;
import com.android.settings.dashboard.DashboardTile;
import com.android.settings.drawable.CircleFramedDrawable;
+import com.android.settingslib.applications.ApplicationsState;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.text.NumberFormat;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import static android.content.Intent.EXTRA_USER;
+
public final class Utils {
private static final String TAG = "Settings";
diff --git a/src/com/android/settings/applications/AdvancedAppSettings.java b/src/com/android/settings/applications/AdvancedAppSettings.java
index f407cb1..c2966fe 100644
--- a/src/com/android/settings/applications/AdvancedAppSettings.java
+++ b/src/com/android/settings/applications/AdvancedAppSettings.java
@@ -23,10 +23,11 @@
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.Session;
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
import com.android.settings.fuelgauge.PowerWhitelistBackend;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.Session;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/AppInfoBase.java b/src/com/android/settings/applications/AppInfoBase.java
index 6dbeefd..ff618c2 100644
--- a/src/com/android/settings/applications/AppInfoBase.java
+++ b/src/com/android/settings/applications/AppInfoBase.java
@@ -38,7 +38,8 @@
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-import com.android.settings.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/AppPermissionSettings.java b/src/com/android/settings/applications/AppPermissionSettings.java
deleted file mode 100644
index 16757d9..0000000
--- a/src/com/android/settings/applications/AppPermissionSettings.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AppSecurityPermissions;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.telephony.ISms;
-import com.android.internal.telephony.SmsUsageMonitor;
-import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-
-import java.util.ArrayList;
-
-public class AppPermissionSettings extends AppInfoWithHeader {
-
- private ISms mSmsManager;
- private View mRootView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mSmsManager = ISms.Stub.asInterface(ServiceManager.getService("isms"));
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- final View view = inflater.inflate(R.layout.permission_settings, container, false);
-
- final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
- Utils.forceCustomPadding(allDetails, true /* additive padding */);
-
- mRootView = view;
- return view;
- }
-
- @Override
- protected boolean refreshUi() {
- retrieveAppEntry();
- // Security permissions section
- LinearLayout permsView = (LinearLayout) mRootView.findViewById(R.id.permissions_section);
- AppSecurityPermissions asp = new AppSecurityPermissions(getActivity(), mPackageName);
- int premiumSmsPermission = getPremiumSmsPermission(mPackageName);
- // Premium SMS permission implies the app also has SEND_SMS permission, so the original
- // application permissions list doesn't have to be shown/hidden separately. The premium
- // SMS subsection should only be visible if the app has tried to send to a premium SMS.
- if (asp.getPermissionCount() > 0
- || premiumSmsPermission != SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
- permsView.setVisibility(View.VISIBLE);
- } else {
- permsView.setVisibility(View.GONE);
- }
- // Premium SMS permission subsection
- TextView securityBillingDesc = (TextView) permsView.findViewById(
- R.id.security_settings_billing_desc);
- LinearLayout securityBillingList = (LinearLayout) permsView.findViewById(
- R.id.security_settings_billing_list);
- if (premiumSmsPermission != SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
- // Show the premium SMS permission selector
- securityBillingDesc.setVisibility(View.VISIBLE);
- securityBillingList.setVisibility(View.VISIBLE);
- Spinner spinner = (Spinner) permsView.findViewById(
- R.id.security_settings_premium_sms_list);
- ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(),
- R.array.security_settings_premium_sms_values,
- android.R.layout.simple_spinner_item);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinner.setAdapter(adapter);
- // List items are in the same order as SmsUsageMonitor constants, offset by 1.
- spinner.setSelection(premiumSmsPermission - 1);
- spinner.setOnItemSelectedListener(new PremiumSmsSelectionListener(
- mPackageName, mSmsManager));
- } else {
- // Hide the premium SMS permission selector
- securityBillingDesc.setVisibility(View.GONE);
- securityBillingList.setVisibility(View.GONE);
- }
- // App permissions subsection
- if (asp.getPermissionCount() > 0) {
- // Make the security sections header visible
- LinearLayout securityList = (LinearLayout) permsView.findViewById(
- R.id.security_settings_list);
- securityList.removeAllViews();
- securityList.addView(asp.getPermissionsViewWithRevokeButtons());
- // If this app is running under a shared user ID with other apps,
- // update the description to explain this.
- String[] packages = mPm.getPackagesForUid(mPackageInfo.applicationInfo.uid);
- if (packages != null && packages.length > 1) {
- ArrayList<CharSequence> pnames = new ArrayList<CharSequence>();
- for (int i=0; i<packages.length; i++) {
- String pkg = packages[i];
- if (mPackageInfo.packageName.equals(pkg)) {
- continue;
- }
- try {
- ApplicationInfo ainfo = mPm.getApplicationInfo(pkg, 0);
- pnames.add(ainfo.loadLabel(mPm));
- } catch (PackageManager.NameNotFoundException e) {
- }
- }
- final int N = pnames.size();
- if (N > 0) {
- final Resources res = getActivity().getResources();
- String appListStr;
- if (N == 1) {
- appListStr = pnames.get(0).toString();
- } else if (N == 2) {
- appListStr = res.getString(R.string.join_two_items, pnames.get(0),
- pnames.get(1));
- } else {
- appListStr = pnames.get(N-2).toString();
- for (int i=N-3; i>=0; i--) {
- appListStr = res.getString(i == 0 ? R.string.join_many_items_first
- : R.string.join_many_items_middle, pnames.get(i), appListStr);
- }
- appListStr = res.getString(R.string.join_many_items_last,
- appListStr, pnames.get(N-1));
- }
- TextView descr = (TextView) mRootView.findViewById(
- R.id.security_settings_desc);
- descr.setText(res.getString(R.string.security_settings_desc_multi,
- mPackageInfo.applicationInfo.loadLabel(mPm), appListStr));
- }
- }
- }
- return true;
- }
-
- private int getPremiumSmsPermission(String packageName) {
- try {
- if (mSmsManager != null) {
- return mSmsManager.getPremiumSmsPermission(packageName);
- }
- } catch (RemoteException ex) {
- // ignored
- }
- return SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN;
- }
-
- @Override
- protected AlertDialog createDialog(int id, int errorCode) {
- // No dialogs for Permissions screen.
- return null;
- }
-
- public static CharSequence getSummary(AppEntry appEntry, Context context) {
- if (appEntry.info.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
- AppPermissions appPerms = new AppPermissions(context, appEntry.info.packageName);
- int count = appPerms.getPermissionCount();
- int grantedCount = appPerms.getGrantedPermissionsCount();
- return context.getResources().getQuantityString(R.plurals.runtime_permissions_summary,
- count, grantedCount, count);
- }
- AppSecurityPermissions asp = new AppSecurityPermissions(context,
- appEntry.info.packageName);
- int count = asp.getPermissionCount();
- return context.getResources().getQuantityString(R.plurals.permissions_summary,
- count, count);
- }
-
- @Override
- protected int getMetricsCategory() {
- return MetricsLogger.APPLICATIONS_APP_PERMISSION;
- }
-
- private static class PremiumSmsSelectionListener implements AdapterView.OnItemSelectedListener {
- private final String mPackageName;
- private final ISms mSmsManager;
-
- PremiumSmsSelectionListener(String packageName, ISms smsManager) {
- mPackageName = packageName;
- mSmsManager = smsManager;
- }
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position,
- long id) {
- if (position >= 0 && position < 3) {
- if (localLOGV) Log.d(TAG, "Selected premium SMS policy " + position);
- setPremiumSmsPermission(mPackageName, (position + 1));
- } else {
- Log.e(TAG, "Error: unknown premium SMS policy " + position);
- }
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // Ignored
- }
-
- private void setPremiumSmsPermission(String packageName, int permission) {
- try {
- if (mSmsManager != null) {
- mSmsManager.setPremiumSmsPermission(packageName, permission);
- }
- } catch (RemoteException ex) {
- // ignored
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/src/com/android/settings/applications/AppStateBaseBridge.java b/src/com/android/settings/applications/AppStateBaseBridge.java
index 04eb77b..1e04e13 100644
--- a/src/com/android/settings/applications/AppStateBaseBridge.java
+++ b/src/com/android/settings/applications/AppStateBaseBridge.java
@@ -19,8 +19,9 @@
import android.os.Looper;
import android.os.Message;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.Session;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.Session;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/AppStateNotificationBridge.java b/src/com/android/settings/applications/AppStateNotificationBridge.java
index 4ac8650..5a8e811 100644
--- a/src/com/android/settings/applications/AppStateNotificationBridge.java
+++ b/src/com/android/settings/applications/AppStateNotificationBridge.java
@@ -17,10 +17,11 @@
import android.content.pm.PackageManager;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.AppFilter;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppFilter;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/AppStatePowerBridge.java b/src/com/android/settings/applications/AppStatePowerBridge.java
index 40163cb..3b1707f 100644
--- a/src/com/android/settings/applications/AppStatePowerBridge.java
+++ b/src/com/android/settings/applications/AppStatePowerBridge.java
@@ -15,9 +15,10 @@
*/
package com.android.settings.applications;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.AppFilter;
import com.android.settings.fuelgauge.PowerWhitelistBackend;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppFilter;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/AppStateUsageBridge.java b/src/com/android/settings/applications/AppStateUsageBridge.java
index 22f19b2..c06492c 100644
--- a/src/com/android/settings/applications/AppStateUsageBridge.java
+++ b/src/com/android/settings/applications/AppStateUsageBridge.java
@@ -30,8 +30,9 @@
import android.util.Log;
import android.util.SparseArray;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.AppFilter;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppFilter;
import java.util.List;
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index fe68cbc4..808f738 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -36,15 +36,15 @@
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
-import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.DropDownPreference;
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.Callbacks;
import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.Callbacks;
import java.util.Collections;
import java.util.List;
diff --git a/src/com/android/settings/applications/AppViewHolder.java b/src/com/android/settings/applications/AppViewHolder.java
index 34c9952..f58cf06 100644
--- a/src/com/android/settings/applications/AppViewHolder.java
+++ b/src/com/android/settings/applications/AppViewHolder.java
@@ -16,8 +16,6 @@
package com.android.settings.applications;
-import com.android.settings.R;
-
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -25,6 +23,9 @@
import android.widget.ImageView;
import android.widget.TextView;
+import com.android.settings.R;
+import com.android.settingslib.applications.ApplicationsState;
+
// View Holder used when displaying views
public class AppViewHolder {
public ApplicationsState.AppEntry entry;
diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java
deleted file mode 100644
index 055e415..0000000
--- a/src/com/android/settings/applications/ApplicationsState.java
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications;
-
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.Application;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.IPackageStatsObserver;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageStats;
-import android.content.pm.ParceledListSlice;
-import android.content.pm.ResolveInfo;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.text.format.Formatter;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.io.File;
-import java.text.Collator;
-import java.text.Normalizer;
-import java.text.Normalizer.Form;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * Keeps track of information about all installed applications, lazy-loading
- * as needed.
- */
-public class ApplicationsState {
- static final String TAG = "ApplicationsState";
- static final boolean DEBUG = false;
- static final boolean DEBUG_LOCKING = false;
-
- public static interface Callbacks {
- public void onRunningStateChanged(boolean running);
- public void onPackageListChanged();
- public void onRebuildComplete(ArrayList<AppEntry> apps);
- public void onPackageIconChanged();
- public void onPackageSizeChanged(String packageName);
- public void onAllSizesComputed();
- public void onLauncherInfoChanged();
- public void onLoadEntriesCompleted();
- }
-
- public static interface AppFilter {
- public void init();
- public boolean filterApp(AppEntry info);
- }
-
- static final int SIZE_UNKNOWN = -1;
- static final int SIZE_INVALID = -2;
-
- static final Pattern REMOVE_DIACRITICALS_PATTERN
- = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
-
- public static String normalize(String str) {
- String tmp = Normalizer.normalize(str, Form.NFD);
- return REMOVE_DIACRITICALS_PATTERN.matcher(tmp)
- .replaceAll("").toLowerCase();
- }
-
- public static class SizeInfo {
- long cacheSize;
- long codeSize;
- long dataSize;
- long externalCodeSize;
- long externalDataSize;
-
- // This is the part of externalDataSize that is in the cache
- // section of external storage. Note that we don't just combine
- // this with cacheSize because currently the platform can't
- // automatically trim this data when needed, so it is something
- // the user may need to manage. The externalDataSize also includes
- // this value, since what this is here is really the part of
- // externalDataSize that we can just consider to be "cache" files
- // for purposes of cleaning them up in the app details UI.
- long externalCacheSize;
- }
-
- public static class AppEntry extends SizeInfo {
- final File apkFile;
- final long id;
- String label;
- long size;
- long internalSize;
- long externalSize;
-
- boolean mounted;
-
- boolean hasLauncherEntry;
-
- String getNormalizedLabel() {
- if (normalizedLabel != null) {
- return normalizedLabel;
- }
- normalizedLabel = normalize(label);
- return normalizedLabel;
- }
-
- // Need to synchronize on 'this' for the following.
- public ApplicationInfo info;
- Drawable icon;
- String sizeStr;
- String internalSizeStr;
- String externalSizeStr;
- boolean sizeStale;
- long sizeLoadStart;
-
- String normalizedLabel;
-
- // A location where extra info can be placed to be used by custom filters.
- Object extraInfo;
-
- AppEntry(Context context, ApplicationInfo info, long id) {
- apkFile = new File(info.sourceDir);
- this.id = id;
- this.info = info;
- this.size = SIZE_UNKNOWN;
- this.sizeStale = true;
- ensureLabel(context);
- }
-
- void ensureLabel(Context context) {
- if (this.label == null || !this.mounted) {
- if (!this.apkFile.exists()) {
- this.mounted = false;
- this.label = info.packageName;
- } else {
- this.mounted = true;
- CharSequence label = info.loadLabel(context.getPackageManager());
- this.label = label != null ? label.toString() : info.packageName;
- }
- }
- }
-
- boolean ensureIconLocked(Context context, PackageManager pm) {
- if (this.icon == null) {
- if (this.apkFile.exists()) {
- this.icon = getBadgedIcon(pm);
- return true;
- } else {
- this.mounted = false;
- this.icon = context.getDrawable(
- com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon);
- }
- } else if (!this.mounted) {
- // If the app wasn't mounted but is now mounted, reload
- // its icon.
- if (this.apkFile.exists()) {
- this.mounted = true;
- this.icon = getBadgedIcon(pm);
- return true;
- }
- }
- return false;
- }
-
- private Drawable getBadgedIcon(PackageManager pm) {
- // Do badging ourself so that it comes from the user of the app not the current user.
- return pm.getUserBadgedIcon(pm.loadUnbadgedItemIcon(info, info),
- new UserHandle(UserHandle.getUserId(info.uid)));
- }
- }
-
- public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() {
- private final Collator sCollator = Collator.getInstance();
- @Override
- public int compare(AppEntry object1, AppEntry object2) {
- return sCollator.compare(object1.label, object2.label);
- }
- };
-
- public static final Comparator<AppEntry> SIZE_COMPARATOR
- = new Comparator<AppEntry>() {
- private final Collator sCollator = Collator.getInstance();
- @Override
- public int compare(AppEntry object1, AppEntry object2) {
- if (object1.size < object2.size) return 1;
- if (object1.size > object2.size) return -1;
- return sCollator.compare(object1.label, object2.label);
- }
- };
-
- public static final Comparator<AppEntry> INTERNAL_SIZE_COMPARATOR
- = new Comparator<AppEntry>() {
- private final Collator sCollator = Collator.getInstance();
- @Override
- public int compare(AppEntry object1, AppEntry object2) {
- if (object1.internalSize < object2.internalSize) return 1;
- if (object1.internalSize > object2.internalSize) return -1;
- return sCollator.compare(object1.label, object2.label);
- }
- };
-
- public static final Comparator<AppEntry> EXTERNAL_SIZE_COMPARATOR
- = new Comparator<AppEntry>() {
- private final Collator sCollator = Collator.getInstance();
- @Override
- public int compare(AppEntry object1, AppEntry object2) {
- if (object1.externalSize < object2.externalSize) return 1;
- if (object1.externalSize > object2.externalSize) return -1;
- return sCollator.compare(object1.label, object2.label);
- }
- };
-
- public static final AppFilter FILTER_PERSONAL = new AppFilter() {
- private int mCurrentUser;
-
- public void init() {
- mCurrentUser = ActivityManager.getCurrentUser();
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return UserHandle.getUserId(entry.info.uid) == mCurrentUser;
- }
- };
-
- public static final AppFilter FILTER_WORK = new AppFilter() {
- private int mCurrentUser;
-
- public void init() {
- mCurrentUser = ActivityManager.getCurrentUser();
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return UserHandle.getUserId(entry.info.uid) != mCurrentUser;
- }
- };
-
- public static final AppFilter FILTER_DOWNLOADED_AND_LAUNCHER = new AppFilter() {
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
- return true;
- } else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- return true;
- } else if (entry.hasLauncherEntry) {
- return true;
- }
- return false;
- }
- };
-
- public static final AppFilter FILTER_THIRD_PARTY = new AppFilter() {
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- if ((entry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
- return true;
- } else if ((entry.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- return true;
- }
- return false;
- }
- };
-
- public static final AppFilter FILTER_DISABLED = new AppFilter() {
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return !entry.info.enabled;
- }
- };
-
- public static final AppFilter FILTER_ALL_ENABLED = new AppFilter() {
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return entry.info.enabled;
- }
- };
-
- public static final AppFilter FILTER_EVERYTHING = new AppFilter() {
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return true;
- }
- };
-
- public static final AppFilter FILTER_WITH_DOMAIN_URLS = new AppFilter() {
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return (entry.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
- }
- };
-
- public static class VolumeFilter implements AppFilter {
- private final String mVolumeUuid;
-
- public VolumeFilter(String volumeUuid) {
- mVolumeUuid = volumeUuid;
- }
-
- @Override
- public void init() {
- }
-
- @Override
- public boolean filterApp(AppEntry info) {
- return Objects.equals(info.info.volumeUuid, mVolumeUuid);
- }
- }
-
- public static class CompoundFilter implements AppFilter {
- private final AppFilter mFirstFilter;
- private final AppFilter mSecondFilter;
-
- public CompoundFilter(AppFilter first, AppFilter second) {
- mFirstFilter = first;
- mSecondFilter = second;
- }
-
- @Override
- public void init() {
- mFirstFilter.init();
- mSecondFilter.init();
- }
-
- @Override
- public boolean filterApp(AppEntry info) {
- return mFirstFilter.filterApp(info) && mSecondFilter.filterApp(info);
- }
- }
-
- final Context mContext;
- final PackageManager mPm;
- final IPackageManager mIpm;
- final UserManager mUm;
- final int mOwnerRetrieveFlags;
- final int mRetrieveFlags;
- PackageIntentReceiver mPackageIntentReceiver;
-
- boolean mResumed;
- boolean mHaveDisabledApps;
-
- // Information about all applications. Synchronize on mEntriesMap
- // to protect access to these.
- final ArrayList<Session> mSessions = new ArrayList<Session>();
- final ArrayList<Session> mRebuildingSessions = new ArrayList<Session>();
- final InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges();
- // Map: userid => (Map: package name => AppEntry)
- final SparseArray<HashMap<String, AppEntry>> mEntriesMap =
- new SparseArray<HashMap<String, AppEntry>>();
- final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
- List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();
- long mCurId = 1;
- String mCurComputingSizePkg;
- int mCurComputingSizeUserId;
- boolean mSessionsChanged;
-
- // Temporary for dispatching session callbacks. Only touched by main thread.
- final ArrayList<Session> mActiveSessions = new ArrayList<Session>();
-
- /**
- * Receives notifications when applications are added/removed.
- */
- private class PackageIntentReceiver extends BroadcastReceiver {
- void registerReceiver() {
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addDataScheme("package");
- mContext.registerReceiver(this, filter);
- // Register for events related to sdcard installation.
- IntentFilter sdFilter = new IntentFilter();
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(this, sdFilter);
- // Register for events related to user creation/deletion.
- IntentFilter userFilter = new IntentFilter();
- userFilter.addAction(Intent.ACTION_USER_ADDED);
- userFilter.addAction(Intent.ACTION_USER_REMOVED);
- mContext.registerReceiver(this, userFilter);
- }
- void unregisterReceiver() {
- mContext.unregisterReceiver(this);
- }
- @Override
- public void onReceive(Context context, Intent intent) {
- String actionStr = intent.getAction();
- if (Intent.ACTION_PACKAGE_ADDED.equals(actionStr)) {
- Uri data = intent.getData();
- String pkgName = data.getEncodedSchemeSpecificPart();
- for (int i = 0; i < mEntriesMap.size(); i++) {
- addPackage(pkgName, mEntriesMap.keyAt(i));
- }
- } else if (Intent.ACTION_PACKAGE_REMOVED.equals(actionStr)) {
- Uri data = intent.getData();
- String pkgName = data.getEncodedSchemeSpecificPart();
- for (int i = 0; i < mEntriesMap.size(); i++) {
- removePackage(pkgName, mEntriesMap.keyAt(i));
- }
- } else if (Intent.ACTION_PACKAGE_CHANGED.equals(actionStr)) {
- Uri data = intent.getData();
- String pkgName = data.getEncodedSchemeSpecificPart();
- for (int i = 0; i < mEntriesMap.size(); i++) {
- invalidatePackage(pkgName, mEntriesMap.keyAt(i));
- }
- } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr) ||
- Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(actionStr)) {
- // When applications become available or unavailable (perhaps because
- // the SD card was inserted or ejected) we need to refresh the
- // AppInfo with new label, icon and size information as appropriate
- // given the newfound (un)availability of the application.
- // A simple way to do that is to treat the refresh as a package
- // removal followed by a package addition.
- String pkgList[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- if (pkgList == null || pkgList.length == 0) {
- // Ignore
- return;
- }
- boolean avail = Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr);
- if (avail) {
- for (String pkgName : pkgList) {
- for (int i = 0; i < mEntriesMap.size(); i++) {
- invalidatePackage(pkgName, mEntriesMap.keyAt(i));
- }
- }
- }
- } else if (Intent.ACTION_USER_ADDED.equals(actionStr)) {
- addUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
- } else if (Intent.ACTION_USER_REMOVED.equals(actionStr)) {
- removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
- }
- }
- }
-
- void rebuildActiveSessions() {
- synchronized (mEntriesMap) {
- if (!mSessionsChanged) {
- return;
- }
- mActiveSessions.clear();
- for (int i=0; i<mSessions.size(); i++) {
- Session s = mSessions.get(i);
- if (s.mResumed) {
- mActiveSessions.add(s);
- }
- }
- }
- }
-
- class MainHandler extends Handler {
- static final int MSG_REBUILD_COMPLETE = 1;
- static final int MSG_PACKAGE_LIST_CHANGED = 2;
- static final int MSG_PACKAGE_ICON_CHANGED = 3;
- static final int MSG_PACKAGE_SIZE_CHANGED = 4;
- static final int MSG_ALL_SIZES_COMPUTED = 5;
- static final int MSG_RUNNING_STATE_CHANGED = 6;
- static final int MSG_LAUNCHER_INFO_CHANGED = 7;
- static final int MSG_LOAD_ENTRIES_COMPLETE = 8;
-
- @Override
- public void handleMessage(Message msg) {
- rebuildActiveSessions();
- switch (msg.what) {
- case MSG_REBUILD_COMPLETE: {
- Session s = (Session)msg.obj;
- if (mActiveSessions.contains(s)) {
- s.mCallbacks.onRebuildComplete(s.mLastAppList);
- }
- } break;
- case MSG_PACKAGE_LIST_CHANGED: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onPackageListChanged();
- }
- } break;
- case MSG_PACKAGE_ICON_CHANGED: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onPackageIconChanged();
- }
- } break;
- case MSG_PACKAGE_SIZE_CHANGED: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onPackageSizeChanged(
- (String)msg.obj);
- }
- } break;
- case MSG_ALL_SIZES_COMPUTED: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onAllSizesComputed();
- }
- } break;
- case MSG_RUNNING_STATE_CHANGED: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onRunningStateChanged(
- msg.arg1 != 0);
- }
- } break;
- case MSG_LAUNCHER_INFO_CHANGED: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onLauncherInfoChanged();
- }
- } break;
- case MSG_LOAD_ENTRIES_COMPLETE: {
- for (int i=0; i<mActiveSessions.size(); i++) {
- mActiveSessions.get(i).mCallbacks.onLoadEntriesCompleted();
- }
- } break;
- }
- }
- }
-
- final MainHandler mMainHandler = new MainHandler();
-
- // --------------------------------------------------------------
-
- static final Object sLock = new Object();
- static ApplicationsState sInstance;
-
- static ApplicationsState getInstance(Application app) {
- synchronized (sLock) {
- if (sInstance == null) {
- sInstance = new ApplicationsState(app);
- }
- return sInstance;
- }
- }
-
- private ApplicationsState(Application app) {
- mContext = app;
- mPm = mContext.getPackageManager();
- mIpm = AppGlobals.getPackageManager();
- mUm = (UserManager) app.getSystemService(Context.USER_SERVICE);
- for (UserHandle user : mUm.getUserProfiles()) {
- mEntriesMap.put(user.getIdentifier(), new HashMap<String, AppEntry>());
- }
- mThread = new HandlerThread("ApplicationsState.Loader",
- Process.THREAD_PRIORITY_BACKGROUND);
- mThread.start();
- mBackgroundHandler = new BackgroundHandler(mThread.getLooper());
-
- // Only the owner can see all apps.
- mOwnerRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |
- PackageManager.GET_DISABLED_COMPONENTS |
- PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
- mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |
- PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;
-
- /**
- * This is a trick to prevent the foreground thread from being delayed.
- * The problem is that Dalvik monitors are initially spin locks, to keep
- * them lightweight. This leads to unfair contention -- Even though the
- * background thread only holds the lock for a short amount of time, if
- * it keeps running and locking again it can prevent the main thread from
- * acquiring its lock for a long time... sometimes even > 5 seconds
- * (leading to an ANR).
- *
- * Dalvik will promote a monitor to a "real" lock if it detects enough
- * contention on it. It doesn't figure this out fast enough for us
- * here, though, so this little trick will force it to turn into a real
- * lock immediately.
- */
- synchronized (mEntriesMap) {
- try {
- mEntriesMap.wait(1);
- } catch (InterruptedException e) {
- }
- }
- }
-
- Looper getBackgroundLooper() {
- return mThread.getLooper();
- }
-
- public class Session {
- final Callbacks mCallbacks;
- boolean mResumed;
-
- // Rebuilding of app list. Synchronized on mRebuildSync.
- final Object mRebuildSync = new Object();
- boolean mRebuildRequested;
- boolean mRebuildAsync;
- AppFilter mRebuildFilter;
- Comparator<AppEntry> mRebuildComparator;
- ArrayList<AppEntry> mRebuildResult;
- ArrayList<AppEntry> mLastAppList;
-
- Session(Callbacks callbacks) {
- mCallbacks = callbacks;
- }
-
- public void resume() {
- if (DEBUG_LOCKING) Log.v(TAG, "resume about to acquire lock...");
- synchronized (mEntriesMap) {
- if (!mResumed) {
- mResumed = true;
- mSessionsChanged = true;
- doResumeIfNeededLocked();
- }
- }
- if (DEBUG_LOCKING) Log.v(TAG, "...resume releasing lock");
- }
-
- public void pause() {
- if (DEBUG_LOCKING) Log.v(TAG, "pause about to acquire lock...");
- synchronized (mEntriesMap) {
- if (mResumed) {
- mResumed = false;
- mSessionsChanged = true;
- mBackgroundHandler.removeMessages(BackgroundHandler.MSG_REBUILD_LIST, this);
- doPauseIfNeededLocked();
- }
- if (DEBUG_LOCKING) Log.v(TAG, "...pause releasing lock");
- }
- }
-
- ArrayList<AppEntry> getAllApps() {
- synchronized (mEntriesMap) {
- return new ArrayList<>(mAppEntries);
- }
- }
-
- // Creates a new list of app entries with the given filter and comparator.
- ArrayList<AppEntry> rebuild(AppFilter filter, Comparator<AppEntry> comparator) {
- synchronized (mRebuildSync) {
- synchronized (mEntriesMap) {
- mRebuildingSessions.add(this);
- mRebuildRequested = true;
- mRebuildAsync = false;
- mRebuildFilter = filter;
- mRebuildComparator = comparator;
- mRebuildResult = null;
- if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_REBUILD_LIST)) {
- Message msg = mBackgroundHandler.obtainMessage(
- BackgroundHandler.MSG_REBUILD_LIST);
- mBackgroundHandler.sendMessage(msg);
- }
- }
-
- // We will wait for .25s for the list to be built.
- long waitend = SystemClock.uptimeMillis()+250;
-
- while (mRebuildResult == null) {
- long now = SystemClock.uptimeMillis();
- if (now >= waitend) {
- break;
- }
- try {
- mRebuildSync.wait(waitend - now);
- } catch (InterruptedException e) {
- }
- }
-
- mRebuildAsync = true;
-
- return mRebuildResult;
- }
- }
-
- void handleRebuildList() {
- AppFilter filter;
- Comparator<AppEntry> comparator;
- synchronized (mRebuildSync) {
- if (!mRebuildRequested) {
- return;
- }
-
- filter = mRebuildFilter;
- comparator = mRebuildComparator;
- mRebuildRequested = false;
- mRebuildFilter = null;
- mRebuildComparator = null;
- }
-
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
-
- if (filter != null) {
- filter.init();
- }
-
- List<AppEntry> apps;
- synchronized (mEntriesMap) {
- apps = new ArrayList<>(mAppEntries);
- }
-
- ArrayList<AppEntry> filteredApps = new ArrayList<AppEntry>();
- if (DEBUG) Log.i(TAG, "Rebuilding...");
- for (int i=0; i<apps.size(); i++) {
- AppEntry entry = apps.get(i);
- if (filter == null || filter.filterApp(entry)) {
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
- entry.ensureLabel(mContext);
- if (DEBUG) Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
- filteredApps.add(entry);
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");
- }
- }
- }
-
- Collections.sort(filteredApps, comparator);
-
- synchronized (mRebuildSync) {
- if (!mRebuildRequested) {
- mLastAppList = filteredApps;
- if (!mRebuildAsync) {
- mRebuildResult = filteredApps;
- mRebuildSync.notifyAll();
- } else {
- if (!mMainHandler.hasMessages(MainHandler.MSG_REBUILD_COMPLETE, this)) {
- Message msg = mMainHandler.obtainMessage(
- MainHandler.MSG_REBUILD_COMPLETE, this);
- mMainHandler.sendMessage(msg);
- }
- }
- }
- }
-
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
-
- public void release() {
- pause();
- synchronized (mEntriesMap) {
- mSessions.remove(this);
- }
- }
- }
-
- public Session newSession(Callbacks callbacks) {
- Session s = new Session(callbacks);
- synchronized (mEntriesMap) {
- mSessions.add(s);
- }
- return s;
- }
-
- void doResumeIfNeededLocked() {
- if (mResumed) {
- return;
- }
- mResumed = true;
- if (mPackageIntentReceiver == null) {
- mPackageIntentReceiver = new PackageIntentReceiver();
- mPackageIntentReceiver.registerReceiver();
- }
- mApplications = new ArrayList<ApplicationInfo>();
- for (UserHandle user : mUm.getUserProfiles()) {
- try {
- // If this user is new, it needs a map created.
- if (mEntriesMap.indexOfKey(user.getIdentifier()) < 0) {
- mEntriesMap.put(user.getIdentifier(), new HashMap<String, AppEntry>());
- }
- ParceledListSlice<ApplicationInfo> list =
- mIpm.getInstalledApplications(
- user.isOwner() ? mOwnerRetrieveFlags : mRetrieveFlags,
- user.getIdentifier());
- mApplications.addAll(list.getList());
- } catch (RemoteException e) {
- }
- }
-
- if (mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
- // If an interesting part of the configuration has changed, we
- // should completely reload the app entries.
- clearEntries();
- } else {
- for (int i=0; i<mAppEntries.size(); i++) {
- mAppEntries.get(i).sizeStale = true;
- }
- }
-
- mHaveDisabledApps = false;
- for (int i=0; i<mApplications.size(); i++) {
- final ApplicationInfo info = mApplications.get(i);
- // Need to trim out any applications that are disabled by
- // something different than the user.
- if (!info.enabled) {
- if (info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
- mApplications.remove(i);
- i--;
- continue;
- }
- mHaveDisabledApps = true;
- }
- int userId = UserHandle.getUserId(info.uid);
- final AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
- if (entry != null) {
- entry.info = info;
- }
- }
- if (mAppEntries.size() > mApplications.size()) {
- // There are less apps now, some must have been uninstalled.
- clearEntries();
- }
- mCurComputingSizePkg = null;
- if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
- mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
- }
- }
-
- private void clearEntries() {
- for (int i = 0; i < mEntriesMap.size(); i++) {
- mEntriesMap.valueAt(i).clear();
- }
- mAppEntries.clear();
- }
-
- public boolean haveDisabledApps() {
- return mHaveDisabledApps;
- }
-
- void doPauseIfNeededLocked() {
- if (!mResumed) {
- return;
- }
- for (int i=0; i<mSessions.size(); i++) {
- if (mSessions.get(i).mResumed) {
- return;
- }
- }
- doPauseLocked();
- }
-
- void doPauseLocked() {
- mResumed = false;
- if (mPackageIntentReceiver != null) {
- mPackageIntentReceiver.unregisterReceiver();
- mPackageIntentReceiver = null;
- }
- }
-
- AppEntry getEntry(String packageName, int userId) {
- if (DEBUG_LOCKING) Log.v(TAG, "getEntry about to acquire lock...");
- synchronized (mEntriesMap) {
- AppEntry entry = mEntriesMap.get(userId).get(packageName);
- if (entry == null) {
- ApplicationInfo info = getAppInfoLocked(packageName, userId);
- if (info == null) {
- try {
- info = mIpm.getApplicationInfo(packageName, 0, userId);
- } catch (RemoteException e) {
- Log.w(TAG, "getEntry couldn't reach PackageManager", e);
- return null;
- }
- }
- entry = getEntryLocked(info);
- }
- if (DEBUG_LOCKING) Log.v(TAG, "...getEntry releasing lock");
- return entry;
- }
- }
-
- private ApplicationInfo getAppInfoLocked(String pkg, int userId) {
- for (int i = 0; i < mApplications.size(); i++) {
- ApplicationInfo info = mApplications.get(i);
- if (pkg.equals(info.packageName)
- && userId == UserHandle.getUserId(info.uid)) {
- return info;
- }
- }
- return null;
- }
-
- void ensureIcon(AppEntry entry) {
- if (entry.icon != null) {
- return;
- }
- synchronized (entry) {
- entry.ensureIconLocked(mContext, mPm);
- }
- }
-
- void requestSize(String packageName, int userId) {
- if (DEBUG_LOCKING) Log.v(TAG, "requestSize about to acquire lock...");
- synchronized (mEntriesMap) {
- AppEntry entry = mEntriesMap.get(userId).get(packageName);
- if (entry != null) {
- mPm.getPackageSizeInfo(packageName, userId, mBackgroundHandler.mStatsObserver);
- }
- if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
- }
- }
-
- long sumCacheSizes() {
- long sum = 0;
- if (DEBUG_LOCKING) Log.v(TAG, "sumCacheSizes about to acquire lock...");
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "-> sumCacheSizes now has lock");
- for (int i=mAppEntries.size()-1; i>=0; i--) {
- sum += mAppEntries.get(i).cacheSize;
- }
- if (DEBUG_LOCKING) Log.v(TAG, "...sumCacheSizes releasing lock");
- }
- return sum;
- }
-
- int indexOfApplicationInfoLocked(String pkgName, int userId) {
- for (int i=mApplications.size()-1; i>=0; i--) {
- ApplicationInfo appInfo = mApplications.get(i);
- if (appInfo.packageName.equals(pkgName)
- && UserHandle.getUserId(appInfo.uid) == userId) {
- return i;
- }
- }
- return -1;
- }
-
- void addPackage(String pkgName, int userId) {
- try {
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "addPackage acquired lock");
- if (DEBUG) Log.i(TAG, "Adding package " + pkgName);
- if (!mResumed) {
- // If we are not resumed, we will do a full query the
- // next time we resume, so there is no reason to do work
- // here.
- if (DEBUG_LOCKING) Log.v(TAG, "addPackage release lock: not resumed");
- return;
- }
- if (indexOfApplicationInfoLocked(pkgName, userId) >= 0) {
- if (DEBUG) Log.i(TAG, "Package already exists!");
- if (DEBUG_LOCKING) Log.v(TAG, "addPackage release lock: already exists");
- return;
- }
- ApplicationInfo info = mIpm.getApplicationInfo(pkgName,
- userId == UserHandle.USER_OWNER ? mOwnerRetrieveFlags : mRetrieveFlags,
- userId);
- if (info == null) {
- return;
- }
- if (!info.enabled) {
- if (info.enabledSetting
- != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
- return;
- }
- mHaveDisabledApps = true;
- }
- mApplications.add(info);
- if (!mBackgroundHandler.hasMessages(BackgroundHandler.MSG_LOAD_ENTRIES)) {
- mBackgroundHandler.sendEmptyMessage(BackgroundHandler.MSG_LOAD_ENTRIES);
- }
- if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
- }
- if (DEBUG_LOCKING) Log.v(TAG, "addPackage releasing lock");
- }
- } catch (RemoteException e) {
- }
- }
-
- void removePackage(String pkgName, int userId) {
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "removePackage acquired lock");
- int idx = indexOfApplicationInfoLocked(pkgName, userId);
- if (DEBUG) Log.i(TAG, "removePackage: " + pkgName + " @ " + idx);
- if (idx >= 0) {
- AppEntry entry = mEntriesMap.get(userId).get(pkgName);
- if (DEBUG) Log.i(TAG, "removePackage: " + entry);
- if (entry != null) {
- mEntriesMap.get(userId).remove(pkgName);
- mAppEntries.remove(entry);
- }
- ApplicationInfo info = mApplications.get(idx);
- mApplications.remove(idx);
- if (!info.enabled) {
- mHaveDisabledApps = false;
- for (int i=0; i<mApplications.size(); i++) {
- if (!mApplications.get(i).enabled) {
- mHaveDisabledApps = true;
- break;
- }
- }
- }
- if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
- }
- }
- if (DEBUG_LOCKING) Log.v(TAG, "removePackage releasing lock");
- }
- }
-
- void invalidatePackage(String pkgName, int userId) {
- removePackage(pkgName, userId);
- addPackage(pkgName, userId);
- }
-
- void addUser(int userId) {
- if (mUm.getUserProfiles().contains(new UserHandle(userId))) {
- synchronized (mEntriesMap) {
- mEntriesMap.put(userId, new HashMap<String, AppEntry>());
- if (mResumed) {
- // If resumed, Manually pause, then cause a resume to repopulate the app list.
- // This is the simplest way to reload the packages so that the new user
- // is included. Otherwise the list will be repopulated on next resume.
- doPauseLocked();
- doResumeIfNeededLocked();
- }
- if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
- }
- }
- }
- }
-
- void removeUser(int userId) {
- synchronized (mEntriesMap) {
- HashMap<String, AppEntry> userMap = mEntriesMap.get(userId);
- if (userMap != null) {
- for (AppEntry appEntry : userMap.values()) {
- mAppEntries.remove(appEntry);
- mApplications.remove(appEntry.info);
- }
- mEntriesMap.remove(userId);
- if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_LIST_CHANGED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_LIST_CHANGED);
- }
- }
- }
- }
-
- AppEntry getEntryLocked(ApplicationInfo info) {
- int userId = UserHandle.getUserId(info.uid);
- AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
- if (DEBUG) Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
- if (entry == null) {
- if (DEBUG) Log.i(TAG, "Creating AppEntry for " + info.packageName);
- entry = new AppEntry(mContext, info, mCurId++);
- mEntriesMap.get(userId).put(info.packageName, entry);
- mAppEntries.add(entry);
- } else if (entry.info != info) {
- entry.info = info;
- }
- return entry;
- }
-
- // --------------------------------------------------------------
-
- private long getTotalInternalSize(PackageStats ps) {
- if (ps != null) {
- return ps.codeSize + ps.dataSize;
- }
- return SIZE_INVALID;
- }
-
- private long getTotalExternalSize(PackageStats ps) {
- if (ps != null) {
- // We also include the cache size here because for non-emulated
- // we don't automtically clean cache files.
- return ps.externalCodeSize + ps.externalDataSize
- + ps.externalCacheSize
- + ps.externalMediaSize + ps.externalObbSize;
- }
- return SIZE_INVALID;
- }
-
- private String getSizeStr(long size) {
- if (size >= 0) {
- return Formatter.formatFileSize(mContext, size);
- }
- return null;
- }
-
- final HandlerThread mThread;
- final BackgroundHandler mBackgroundHandler;
- class BackgroundHandler extends Handler {
- static final int MSG_REBUILD_LIST = 1;
- static final int MSG_LOAD_ENTRIES = 2;
- static final int MSG_LOAD_ICONS = 3;
- static final int MSG_LOAD_SIZES = 4;
- static final int MSG_LOAD_LAUNCHER = 5;
-
- boolean mRunning;
-
- final IPackageStatsObserver.Stub mStatsObserver = new IPackageStatsObserver.Stub() {
- public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
- boolean sizeChanged = false;
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "onGetStatsCompleted acquired lock");
- HashMap<String, AppEntry> userMap = mEntriesMap.get(stats.userHandle);
- if (userMap == null) {
- // The user must have been removed.
- return;
- }
- AppEntry entry = userMap.get(stats.packageName);
- if (entry != null) {
- synchronized (entry) {
- entry.sizeStale = false;
- entry.sizeLoadStart = 0;
- long externalCodeSize = stats.externalCodeSize
- + stats.externalObbSize;
- long externalDataSize = stats.externalDataSize
- + stats.externalMediaSize;
- long newSize = externalCodeSize + externalDataSize
- + getTotalInternalSize(stats);
- if (entry.size != newSize ||
- entry.cacheSize != stats.cacheSize ||
- entry.codeSize != stats.codeSize ||
- entry.dataSize != stats.dataSize ||
- entry.externalCodeSize != externalCodeSize ||
- entry.externalDataSize != externalDataSize ||
- entry.externalCacheSize != stats.externalCacheSize) {
- entry.size = newSize;
- entry.cacheSize = stats.cacheSize;
- entry.codeSize = stats.codeSize;
- entry.dataSize = stats.dataSize;
- entry.externalCodeSize = externalCodeSize;
- entry.externalDataSize = externalDataSize;
- entry.externalCacheSize = stats.externalCacheSize;
- entry.sizeStr = getSizeStr(entry.size);
- entry.internalSize = getTotalInternalSize(stats);
- entry.internalSizeStr = getSizeStr(entry.internalSize);
- entry.externalSize = getTotalExternalSize(stats);
- entry.externalSizeStr = getSizeStr(entry.externalSize);
- if (DEBUG) Log.i(TAG, "Set size of " + entry.label + " " + entry
- + ": " + entry.sizeStr);
- sizeChanged = true;
- }
- }
- if (sizeChanged) {
- Message msg = mMainHandler.obtainMessage(
- MainHandler.MSG_PACKAGE_SIZE_CHANGED, stats.packageName);
- mMainHandler.sendMessage(msg);
- }
- }
- if (mCurComputingSizePkg != null
- && (mCurComputingSizePkg.equals(stats.packageName)
- && mCurComputingSizeUserId == stats.userHandle)) {
- mCurComputingSizePkg = null;
- sendEmptyMessage(MSG_LOAD_SIZES);
- }
- if (DEBUG_LOCKING) Log.v(TAG, "onGetStatsCompleted releasing lock");
- }
- }
- };
-
- BackgroundHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- // Always try rebuilding list first thing, if needed.
- ArrayList<Session> rebuildingSessions = null;
- synchronized (mEntriesMap) {
- if (mRebuildingSessions.size() > 0) {
- rebuildingSessions = new ArrayList<Session>(mRebuildingSessions);
- mRebuildingSessions.clear();
- }
- }
- if (rebuildingSessions != null) {
- for (int i=0; i<rebuildingSessions.size(); i++) {
- rebuildingSessions.get(i).handleRebuildList();
- }
- }
-
- switch (msg.what) {
- case MSG_REBUILD_LIST: {
- } break;
- case MSG_LOAD_ENTRIES: {
- int numDone = 0;
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ENTRIES acquired lock");
- for (int i = 0; i < mApplications.size() && numDone < 6; i++) {
- if (!mRunning) {
- mRunning = true;
- Message m = mMainHandler.obtainMessage(
- MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
- mMainHandler.sendMessage(m);
- }
- ApplicationInfo info = mApplications.get(i);
- int userId = UserHandle.getUserId(info.uid);
- if (mEntriesMap.get(userId).get(info.packageName) == null) {
- numDone++;
- getEntryLocked(info);
- }
- }
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ENTRIES releasing lock");
- }
-
- if (numDone >= 6) {
- sendEmptyMessage(MSG_LOAD_ENTRIES);
- } else {
- if (!mMainHandler.hasMessages(MainHandler.MSG_LOAD_ENTRIES_COMPLETE)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_LOAD_ENTRIES_COMPLETE);
- }
- sendEmptyMessage(MSG_LOAD_LAUNCHER);
- }
- } break;
- case MSG_LOAD_LAUNCHER: {
- Intent launchIntent = new Intent(Intent.ACTION_MAIN, null)
- .addCategory(Intent.CATEGORY_LAUNCHER);
-
- for (int i = 0; i < mEntriesMap.size(); i++) {
- int userId = mEntriesMap.keyAt(i);
- List<ResolveInfo> intents = mPm.queryIntentActivitiesAsUser(launchIntent,
- PackageManager.GET_DISABLED_COMPONENTS, userId);
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_LAUNCHER acquired lock");
- HashMap<String, AppEntry> userEntries = mEntriesMap.valueAt(i);
- final int N = intents.size();
- for (int j = 0; j < N; j++) {
- String packageName = intents.get(j).activityInfo.packageName;
- AppEntry entry = userEntries.get(packageName);
- if (entry != null) {
- entry.hasLauncherEntry = true;
- } else {
- Log.w(TAG, "Cannot find pkg: " + packageName
- + " on user " + userId);
- }
- }
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_LAUNCHER releasing lock");
- }
- }
-
- if (!mMainHandler.hasMessages(MainHandler.MSG_LAUNCHER_INFO_CHANGED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_LAUNCHER_INFO_CHANGED);
- }
- sendEmptyMessage(MSG_LOAD_ICONS);
- } break;
- case MSG_LOAD_ICONS: {
- int numDone = 0;
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ICONS acquired lock");
- for (int i=0; i<mAppEntries.size() && numDone<2; i++) {
- AppEntry entry = mAppEntries.get(i);
- if (entry.icon == null || !entry.mounted) {
- synchronized (entry) {
- if (entry.ensureIconLocked(mContext, mPm)) {
- if (!mRunning) {
- mRunning = true;
- Message m = mMainHandler.obtainMessage(
- MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
- mMainHandler.sendMessage(m);
- }
- numDone++;
- }
- }
- }
- }
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_ICONS releasing lock");
- }
- if (numDone > 0) {
- if (!mMainHandler.hasMessages(MainHandler.MSG_PACKAGE_ICON_CHANGED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_PACKAGE_ICON_CHANGED);
- }
- }
- if (numDone >= 2) {
- sendEmptyMessage(MSG_LOAD_ICONS);
- } else {
- sendEmptyMessage(MSG_LOAD_SIZES);
- }
- } break;
- case MSG_LOAD_SIZES: {
- synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES acquired lock");
- if (mCurComputingSizePkg != null) {
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: currently computing");
- return;
- }
-
- long now = SystemClock.uptimeMillis();
- for (int i=0; i<mAppEntries.size(); i++) {
- AppEntry entry = mAppEntries.get(i);
- if (entry.size == SIZE_UNKNOWN || entry.sizeStale) {
- if (entry.sizeLoadStart == 0 ||
- (entry.sizeLoadStart < (now-20*1000))) {
- if (!mRunning) {
- mRunning = true;
- Message m = mMainHandler.obtainMessage(
- MainHandler.MSG_RUNNING_STATE_CHANGED, 1);
- mMainHandler.sendMessage(m);
- }
- entry.sizeLoadStart = now;
- mCurComputingSizePkg = entry.info.packageName;
- mCurComputingSizeUserId = UserHandle.getUserId(entry.info.uid);
- mPm.getPackageSizeInfo(mCurComputingSizePkg,
- mCurComputingSizeUserId, mStatsObserver);
- }
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing: now computing");
- return;
- }
- }
- if (!mMainHandler.hasMessages(MainHandler.MSG_ALL_SIZES_COMPUTED)) {
- mMainHandler.sendEmptyMessage(MainHandler.MSG_ALL_SIZES_COMPUTED);
- mRunning = false;
- Message m = mMainHandler.obtainMessage(
- MainHandler.MSG_RUNNING_STATE_CHANGED, 0);
- mMainHandler.sendMessage(m);
- }
- if (DEBUG_LOCKING) Log.v(TAG, "MSG_LOAD_SIZES releasing lock");
- }
- } break;
- }
- }
-
- }
-}
diff --git a/src/com/android/settings/applications/ClearDefaultsPreference.java b/src/com/android/settings/applications/ClearDefaultsPreference.java
index 1799cad..8be4be0 100644
--- a/src/com/android/settings/applications/ClearDefaultsPreference.java
+++ b/src/com/android/settings/applications/ClearDefaultsPreference.java
@@ -37,6 +37,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settingslib.applications.ApplicationsState;
public class ClearDefaultsPreference extends Preference {
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 26e3d49..6e96f6a 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -16,11 +16,11 @@
package com.android.settings.applications;
-import android.app.admin.DevicePolicyManager;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.LoaderManager.LoaderCallbacks;
+import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -66,7 +66,6 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
-import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
import com.android.settings.fuelgauge.BatteryEntry;
import com.android.settings.fuelgauge.PowerUsageDetail;
@@ -75,6 +74,8 @@
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/InterestingConfigChanges.java b/src/com/android/settings/applications/InterestingConfigChanges.java
deleted file mode 100644
index 816d169..0000000
--- a/src/com/android/settings/applications/InterestingConfigChanges.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications;
-
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-
-class InterestingConfigChanges {
- final Configuration mLastConfiguration = new Configuration();
- int mLastDensity;
-
- boolean applyNewConfig(Resources res) {
- int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
- boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
- if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE
- |ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
- mLastDensity = res.getDisplayMetrics().densityDpi;
- return true;
- }
- return false;
- }
-}
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 18a3f11..e18e9b6 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -62,14 +62,15 @@
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.AppStateUsageBridge.UsageState;
-import com.android.settings.applications.ApplicationsState.AppEntry;
-import com.android.settings.applications.ApplicationsState.AppFilter;
-import com.android.settings.applications.ApplicationsState.CompoundFilter;
-import com.android.settings.applications.ApplicationsState.VolumeFilter;
import com.android.settings.fuelgauge.HighPowerDetail;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppFilter;
+import com.android.settingslib.applications.ApplicationsState.CompoundFilter;
+import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/settings/applications/RunningState.java b/src/com/android/settings/applications/RunningState.java
index f0c33dd..2286a24 100644
--- a/src/com/android/settings/applications/RunningState.java
+++ b/src/com/android/settings/applications/RunningState.java
@@ -46,6 +46,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settingslib.applications.InterestingConfigChanges;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/settings/fuelgauge/HighPowerDetail.java b/src/com/android/settings/fuelgauge/HighPowerDetail.java
index bd18671..e399a34 100644
--- a/src/com/android/settings/fuelgauge/HighPowerDetail.java
+++ b/src/com/android/settings/fuelgauge/HighPowerDetail.java
@@ -24,10 +24,9 @@
import android.preference.SwitchPreference;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
-import com.android.settings.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
public class HighPowerDetail extends AppInfoWithHeader implements OnPreferenceChangeListener {