New UX for app usage screen

Now uses ManageApplications base, and has a details screen which has
a switch and a link to optional app settings.

Bug: 20290386
Change-Id: If32ce8d82e55f3908644c575925b3f6506a68e6e
This commit is contained in:
Jason Monk
2015-04-17 14:34:12 -04:00
parent 6d61061518
commit d8da51ccfe
13 changed files with 728 additions and 757 deletions

View File

@@ -58,8 +58,10 @@ import com.android.settings.Settings.AllApplicationsActivity;
import com.android.settings.Settings.DomainsURLsAppListActivity;
import com.android.settings.Settings.NotificationAppListActivity;
import com.android.settings.Settings.StorageUseActivity;
import com.android.settings.Settings.UsageAccessSettingsActivity;
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;
@@ -117,6 +119,7 @@ public class ManageApplications extends InstrumentedFragment
public static final int FILTER_APPS_PERSONAL = 9;
public static final int FILTER_APPS_WORK = 10;
public static final int FILTER_APPS_WITH_DOMAIN_URLS = 11;
public static final int FILTER_APPS_USAGE_ACCESS = 12;
// This is the string labels for the filter modes above, the order must be kept in sync.
public static final int[] FILTER_LABELS = new int[] {
@@ -132,6 +135,7 @@ public class ManageApplications extends InstrumentedFragment
R.string.filter_personal_apps, // Personal
R.string.filter_work_apps, // Work
R.string.filter_with_domain_urls_apps, // Domain URLs
R.string.filter_all_apps, // Usage access screen, never displayed
};
// This is the actual mapping to filters from FILTER_ constants above, the order must
// be kept in sync.
@@ -152,6 +156,7 @@ public class ManageApplications extends InstrumentedFragment
ApplicationsState.FILTER_PERSONAL, // Personal
ApplicationsState.FILTER_WORK, // Work
ApplicationsState.FILTER_WITH_DOMAIN_URLS, // Apps with Domain URLs
AppStateUsageBridge.FILTER_APP_USAGE, // Apps with Domain URLs
};
// sort order
@@ -190,6 +195,7 @@ public class ManageApplications extends InstrumentedFragment
public static final int LIST_TYPE_NOTIFICATION = 1;
public static final int LIST_TYPE_DOMAINS_URLS = 2;
public static final int LIST_TYPE_STORAGE = 3;
public static final int LIST_TYPE_USAGE_ACCESS = 4;
private View mRootView;
@@ -230,6 +236,9 @@ public class ManageApplications extends InstrumentedFragment
mListType = LIST_TYPE_MAIN;
mSortOrder = R.id.sort_order_size;
}
} else if (className.equals(UsageAccessSettingsActivity.class.getName())) {
mListType = LIST_TYPE_USAGE_ACCESS;
getActivity().getActionBar().setTitle(R.string.usage_access_title);
} else {
mListType = LIST_TYPE_MAIN;
}
@@ -300,7 +309,7 @@ public class ManageApplications extends InstrumentedFragment
contentParent.addView(mSpinnerHeader, 0);
mFilterAdapter.enableFilter(getDefaultFilter());
if (mListType != LIST_TYPE_STORAGE) {
if (mListType == LIST_TYPE_MAIN || mListType == LIST_TYPE_NOTIFICATION) {
if (UserManager.get(getActivity()).getUserProfiles().size() > 1) {
mFilterAdapter.enableFilter(FILTER_APPS_PERSONAL);
mFilterAdapter.enableFilter(FILTER_APPS_WORK);
@@ -331,6 +340,8 @@ public class ManageApplications extends InstrumentedFragment
return mShowSystem ? FILTER_APPS_ALL : FILTER_APPS_DOWNLOADED_AND_LAUNCHER;
case LIST_TYPE_DOMAINS_URLS:
return FILTER_APPS_WITH_DOMAIN_URLS;
case LIST_TYPE_USAGE_ACCESS:
return FILTER_APPS_USAGE_ACCESS;
default:
return FILTER_APPS_ALL;
}
@@ -347,6 +358,8 @@ public class ManageApplications extends InstrumentedFragment
return MetricsLogger.MANAGE_DOMAIN_URLS;
case LIST_TYPE_STORAGE:
return InstrumentedFragment.VIEW_CATEGORY_STORAGE_APPS;
case LIST_TYPE_USAGE_ACCESS:
return MetricsLogger.USAGE_ACCESS;
default:
return MetricsLogger.VIEW_UNKNOWN;
}
@@ -398,7 +411,7 @@ public class ManageApplications extends InstrumentedFragment
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
if (mListType == LIST_TYPE_NOTIFICATION) {
mApplications.mNotifBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
} else {
mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid));
}
@@ -408,30 +421,39 @@ public class ManageApplications extends InstrumentedFragment
// utility method used to start sub activity
private void startApplicationDetailsActivity() {
Activity activity = getActivity();
if (mListType == LIST_TYPE_NOTIFICATION) {
activity.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.putExtra(Settings.EXTRA_APP_PACKAGE, mCurrentPkgName)
.putExtra(Settings.EXTRA_APP_UID, mCurrentUid));
} else if (mListType == LIST_TYPE_DOMAINS_URLS) {
final String title = getString(R.string.auto_launch_label);
startAppInfoFragment(AppLaunchSettings.class, title);
} else {
switch (mListType) {
case LIST_TYPE_NOTIFICATION:
activity.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.putExtra(Settings.EXTRA_APP_PACKAGE, mCurrentPkgName)
.putExtra(Settings.EXTRA_APP_UID, mCurrentUid));
break;
case LIST_TYPE_DOMAINS_URLS:
startAppInfoFragment(AppLaunchSettings.class, R.string.auto_launch_label);
break;
case LIST_TYPE_USAGE_ACCESS:
startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
break;
case LIST_TYPE_STORAGE:
startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
break;
// TODO: Figure out if there is a way where we can spin up the profile's settings
// process ahead of time, to avoid a long load of data when user clicks on a managed app.
// Maybe when they load the list of apps that contains managed profile apps.
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", mCurrentPkgName, null));
activity.startActivityAsUser(intent, new UserHandle(UserHandle.getUserId(mCurrentUid)));
default:
startAppInfoFragment(InstalledAppDetails.class, R.string.application_info_label);
break;
}
}
private void startAppInfoFragment(Class<? extends AppInfoBase> fragment, CharSequence title) {
private void startAppInfoFragment(Class<? extends AppInfoBase> fragment, int titleRes) {
Bundle args = new Bundle();
args.putString("package", mCurrentPkgName);
args.putString(AppInfoBase.ARG_PACKAGE_NAME, mCurrentPkgName);
SettingsActivity sa = (SettingsActivity) getActivity();
sa.startPreferencePanel(fragment.getName(), args, -1, title, this, 0);
Intent intent = Utils.onBuildStartFragmentIntent(getActivity(), fragment.getName(), args,
null, titleRes, null, false);
getActivity().startActivityForResultAsUser(intent, INSTALLED_APP_DETAILS,
new UserHandle(UserHandle.getUserId(mCurrentUid)));
}
@Override
@@ -653,14 +675,14 @@ public class ManageApplications extends InstrumentedFragment
* The order of applications in the list is mirrored in mAppLocalList
*/
static class ApplicationsAdapter extends BaseAdapter implements Filterable,
ApplicationsState.Callbacks, AppStateNotificationBridge.Callback,
ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
AbsListView.RecyclerListener {
private final ApplicationsState mState;
private final ApplicationsState.Session mSession;
private final ManageApplications mManageApplications;
private final Context mContext;
private final ArrayList<View> mActive = new ArrayList<View>();
private final AppStateNotificationBridge mNotifBridge;
private final AppStateBaseBridge mExtraInfoBridge;
private int mFilterMode;
private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
private ArrayList<ApplicationsState.AppEntry> mEntries;
@@ -700,11 +722,12 @@ public class ManageApplications extends InstrumentedFragment
mPm = mContext.getPackageManager();
mFilterMode = filterMode;
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
mNotifBridge = new AppStateNotificationBridge(
mContext.getPackageManager(), mState,
manageApplications.mNotifBackend, this);
mExtraInfoBridge = new AppStateNotificationBridge(mContext.getPackageManager(),
mState, this, manageApplications.mNotifBackend);
} else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
} else {
mNotifBridge = null;
mExtraInfoBridge = null;
}
}
@@ -724,8 +747,8 @@ public class ManageApplications extends InstrumentedFragment
mResumed = true;
mSession.resume();
mLastSortMode = sort;
if (mNotifBridge != null) {
mNotifBridge.resume();
if (mExtraInfoBridge != null) {
mExtraInfoBridge.resume();
}
rebuild(true);
} else {
@@ -737,16 +760,16 @@ public class ManageApplications extends InstrumentedFragment
if (mResumed) {
mResumed = false;
mSession.pause();
if (mNotifBridge != null) {
mNotifBridge.pause();
if (mExtraInfoBridge != null) {
mExtraInfoBridge.pause();
}
}
}
public void release() {
mSession.release();
if (mNotifBridge != null) {
mNotifBridge.release();
if (mExtraInfoBridge != null) {
mExtraInfoBridge.release();
}
}
@@ -809,6 +832,10 @@ public class ManageApplications extends InstrumentedFragment
Utils.handleLoadingContainer(mManageApplications.mLoadingContainer,
mManageApplications.mListContainer, true, true);
}
if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
// No enabled or disabled filters for usage access.
return;
}
mManageApplications.setHasDisabled(hasDisabledApps());
}
@@ -849,10 +876,8 @@ public class ManageApplications extends InstrumentedFragment
}
@Override
public void onNotificationInfoUpdated() {
if (mFilterMode != mManageApplications.getDefaultFilter()) {
rebuild(false);
}
public void onExtraInfoUpdated() {
rebuild(false);
}
@Override
@@ -897,9 +922,7 @@ public class ManageApplications extends InstrumentedFragment
AppViewHolder holder = (AppViewHolder)mActive.get(i).getTag();
if (holder.entry.info.packageName.equals(packageName)) {
synchronized (holder.entry) {
if (mManageApplications.mListType != LIST_TYPE_NOTIFICATION) {
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
}
updateSummary(holder);
}
if (holder.entry.info.packageName.equals(mManageApplications.mCurrentPkgName)
&& mLastSortMode == R.id.sort_order_size) {
@@ -967,24 +990,7 @@ public class ManageApplications extends InstrumentedFragment
if (entry.icon != null) {
holder.appIcon.setImageDrawable(entry.icon);
}
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
if (entry.extraInfo != null) {
holder.summary.setText(InstalledAppDetails.getNotificationSummary(
(AppRow) entry.extraInfo, mContext));
} else {
holder.summary.setText("");
}
break;
case LIST_TYPE_DOMAINS_URLS:
holder.summary.setText(getDomainsSummary(entry.info.packageName));
break;
default:
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
break;
}
updateSummary(holder);
convertView.setEnabled(isAppEntryViewEnabled(entry));
if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
holder.disabled.setVisibility(View.VISIBLE);
@@ -1002,6 +1008,36 @@ public class ManageApplications extends InstrumentedFragment
return convertView;
}
private void updateSummary(AppViewHolder holder) {
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
if (holder.entry.extraInfo != null) {
holder.summary.setText(InstalledAppDetails.getNotificationSummary(
(AppRow) holder.entry.extraInfo, mContext));
} else {
holder.summary.setText(null);
}
break;
case LIST_TYPE_DOMAINS_URLS:
holder.summary.setText(getDomainsSummary(holder.entry.info.packageName));
break;
case LIST_TYPE_USAGE_ACCESS:
if (holder.entry.extraInfo != null) {
holder.summary.setText(((UsageState) holder.entry.extraInfo).hasAccess() ?
R.string.switch_on_text : R.string.switch_off_text);
} else {
holder.summary.setText(null);
}
break;
default:
holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
break;
}
}
@Override
public Filter getFilter() {
return mFilter;