Modify AppHeaderController to provide UI for notif settings

- The AppHeaderController is no longer a singleton. Each time appheader
  should be updated we will create a new controller. It acts as a
  builder/mutator, user provides customizable inputs, and the controller
  will bind everything to UI when calling done().

Bug: 32442716
Test: RunSettingsRoboTests
Change-Id: Icfc5bcd8bc170a02b57432d864eaddf71db0d5b4
This commit is contained in:
Fan Zhang
2016-10-27 15:50:36 -07:00
parent 6e3b964cf4
commit 1ff25ba7e6
9 changed files with 364 additions and 75 deletions

View File

@@ -29,7 +29,6 @@
<!-- App snippet with buttons --> <!-- App snippet with buttons -->
<ImageView <ImageView
android:id="@android:id/icon" android:id="@android:id/icon"
android:layout_marginTop="16dp"
android:layout_width="80dp" android:layout_width="80dp"
android:layout_height="80dp" android:layout_height="80dp"
android:scaleType="fitXY" android:scaleType="fitXY"

View File

@@ -455,9 +455,10 @@
<style name="AppHeader"> <style name="AppHeader">
<item name="android:background">@color/card_background_grey</item> <item name="android:background">@color/card_background_grey</item>
<item name="android:gravity">center_horizontal</item> <item name="android:gravity">center_horizontal</item>
<item name="android:paddingTop">16dp</item>
<item name="android:paddingStart">16dp</item> <item name="android:paddingStart">16dp</item>
<item name="android:paddingEnd">16dp</item> <item name="android:paddingEnd">16dp</item>
<item name="android:paddingBottom">16dp</item> <item name="android:paddingBottom">8dp</item>
</style> </style>
<style name="TextAppearance.AppHeaderTitle" <style name="TextAppearance.AppHeaderTitle"

View File

@@ -16,20 +16,26 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.annotation.IdRes;
import android.annotation.UserIdInt;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.android.settings.AppHeader;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
@@ -39,43 +45,126 @@ import java.lang.annotation.RetentionPolicy;
public class AppHeaderController { public class AppHeaderController {
@IntDef({ActionType.ACTION_APP_INFO, @IntDef({ActionType.ACTION_NONE,
ActionType.ACTION_APP_INFO,
ActionType.ACTION_APP_PREFERENCE, ActionType.ACTION_APP_PREFERENCE,
ActionType.ACTION_STORE_DEEP_LINK, ActionType.ACTION_STORE_DEEP_LINK,
ActionType.ACTION_NOTIF_PREFERENCE}) ActionType.ACTION_NOTIF_PREFERENCE})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@interface ActionType { public @interface ActionType {
int ACTION_APP_INFO = 0; int ACTION_NONE = 0;
int ACTION_STORE_DEEP_LINK = 1; int ACTION_APP_INFO = 1;
int ACTION_APP_PREFERENCE = 2; int ACTION_STORE_DEEP_LINK = 2;
int ACTION_NOTIF_PREFERENCE = 3; int ACTION_APP_PREFERENCE = 3;
int ACTION_NOTIF_PREFERENCE = 4;
} }
private static final String TAG = "AppDetailFeature"; private static final String TAG = "AppDetailFeature";
private final Context mContext; private final Context mContext;
private final Fragment mFragment;
private final View mAppHeader;
public AppHeaderController(Context context) { private Drawable mIcon;
private CharSequence mLabel;
private CharSequence mSummary;
private String mPackageName;
private Intent mAppNotifPrefIntent;
@UserIdInt
private int mUid = UserHandle.USER_NULL;
@ActionType
private int mLeftAction;
@ActionType
private int mRightAction;
public AppHeaderController(Context context, Fragment fragment, View appHeader) {
mContext = context; mContext = context;
mFragment = fragment;
if (appHeader != null) {
mAppHeader = appHeader;
} else {
mAppHeader = LayoutInflater.from(mContext)
.inflate(R.layout.app_details, null /* root */);
}
} }
public void bindAppHeader(View appSnippet, PackageInfo packageInfo, public AppHeaderController setIcon(Drawable icon) {
ApplicationsState.AppEntry appEntry) { if (icon != null) {
mIcon = icon.getConstantState().newDrawable(mContext.getResources());
}
return this;
}
public AppHeaderController setIcon(ApplicationsState.AppEntry appEntry) {
if (appEntry.icon != null) {
mIcon = appEntry.icon.getConstantState().newDrawable(mContext.getResources());
}
return this;
}
public AppHeaderController setLabel(CharSequence label) {
mLabel = label;
return this;
}
public AppHeaderController setLabel(ApplicationsState.AppEntry appEntry) {
mLabel = appEntry.label;
return this;
}
public AppHeaderController setSummary(CharSequence summary) {
mSummary = summary;
return this;
}
public AppHeaderController setSummary(PackageInfo packageInfo) {
if (packageInfo != null) {
mSummary = packageInfo.versionName;
}
return this;
}
public AppHeaderController setButtonActions(@ActionType int leftAction,
@ActionType int rightAction) {
mLeftAction = leftAction;
mRightAction = rightAction;
return this;
}
public AppHeaderController setPackageName(String packageName) {
mPackageName = packageName;
return this;
}
public AppHeaderController setUid(int uid) {
mUid = uid;
return this;
}
public AppHeaderController setAppNotifPrefIntent(Intent appNotifPrefIntent) {
mAppNotifPrefIntent = appNotifPrefIntent;
return this;
}
/**
* Binds app header view and data from {@code PackageInfo} and {@code AppEntry}.
*/
public void bindAppHeader(PackageInfo packageInfo, ApplicationsState.AppEntry appEntry) {
final String versionName = packageInfo == null ? null : packageInfo.versionName; final String versionName = packageInfo == null ? null : packageInfo.versionName;
final Resources res = appSnippet.getResources(); final Resources res = mAppHeader.getResources();
// Set Icon // Set Icon
final ImageView iconView = (ImageView) appSnippet.findViewById(android.R.id.icon); final ImageView iconView = (ImageView) mAppHeader.findViewById(android.R.id.icon);
if (appEntry.icon != null) { if (appEntry.icon != null) {
iconView.setImageDrawable(appEntry.icon.getConstantState().newDrawable(res)); iconView.setImageDrawable(appEntry.icon.getConstantState().newDrawable(res));
} }
// Set application name. // Set application name.
final TextView labelView = (TextView) appSnippet.findViewById(android.R.id.title); final TextView labelView = (TextView) mAppHeader.findViewById(android.R.id.title);
labelView.setText(appEntry.label); labelView.setText(appEntry.label);
// Version number of application // Version number of application
final TextView appVersion = (TextView) appSnippet.findViewById(android.R.id.summary); final TextView appVersion = (TextView) mAppHeader.findViewById(android.R.id.summary);
if (!TextUtils.isEmpty(versionName)) { if (!TextUtils.isEmpty(versionName)) {
appVersion.setSelected(true); appVersion.setSelected(true);
@@ -86,60 +175,97 @@ public class AppHeaderController {
} }
} }
public void bindAppHeaderButtons(Fragment fragment, View appLinkButtons, String packageName, /**
@ActionType int leftAction, @ActionType int rightAction) { * Done mutating appheader, rebinds everything.
ImageButton leftButton = (ImageButton) appLinkButtons.findViewById(R.id.left_button); */
ImageButton rightButton = (ImageButton) appLinkButtons.findViewById(R.id.right_button); public View done() {
return done(true);
bindAppDetailButton(fragment, packageName, leftButton, leftAction);
bindAppDetailButton(fragment, packageName, rightButton, rightAction);
} }
private void bindAppDetailButton(Fragment fragment, String packageName, /**
ImageButton button, @ActionType int action) { * Done mutating appheader, rebinds everything (optionally skip rebinding buttons).
*/
public View done(boolean rebindActions) {
ImageView iconView = (ImageView) mAppHeader.findViewById(android.R.id.icon);
if (iconView != null) {
iconView.setImageDrawable(mIcon);
}
setText(android.R.id.title, mLabel);
setText(android.R.id.summary, mSummary);
if (rebindActions) {
bindAppHeaderButtons();
}
return mAppHeader;
}
/**
* Only binds app header with button actions.
*/
public void bindAppHeaderButtons() {
ImageButton leftButton = (ImageButton) mAppHeader.findViewById(R.id.left_button);
ImageButton rightButton = (ImageButton) mAppHeader.findViewById(R.id.right_button);
bindButton(leftButton, mLeftAction);
bindButton(rightButton, mRightAction);
}
private void bindButton(ImageButton button, @ActionType int action) {
if (button == null) { if (button == null) {
return; return;
} }
switch (action) { switch (action) {
case ActionType.ACTION_APP_INFO: { case ActionType.ACTION_APP_INFO: {
if (packageName == null || packageName.equals(Utils.OS_PKG)) { if (mPackageName == null || mPackageName.equals(Utils.OS_PKG)
|| mUid == UserHandle.USER_NULL
|| !AppHeader.includeAppInfo(mFragment)) {
button.setVisibility(View.GONE); button.setVisibility(View.GONE);
} else { } else {
// TODO
button.setImageResource(com.android.settings.R.drawable.ic_info); button.setImageResource(com.android.settings.R.drawable.ic_info);
button.setOnClickListener(v -> AppInfoBase.startAppInfoFragment(
InstalledAppDetails.class, R.string.application_info_label,
mPackageName, mUid, mFragment, 0));
button.setVisibility(View.VISIBLE); button.setVisibility(View.VISIBLE);
} }
return; return;
} }
case ActionType.ACTION_STORE_DEEP_LINK: { case ActionType.ACTION_STORE_DEEP_LINK: {
final Intent intent = new Intent(Intent.ACTION_SHOW_APP_INFO) final Intent intent = new Intent(Intent.ACTION_SHOW_APP_INFO)
.setPackage(getInstallerPackageName(mContext, packageName)); .setPackage(getInstallerPackageName(mContext, mPackageName));
final Intent result = resolveIntent(intent); final Intent result = resolveIntent(intent);
if (result == null) { if (result == null) {
button.setVisibility(View.GONE); button.setVisibility(View.GONE);
} else { } else {
result.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); result.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
button.setImageResource(R.drawable.ic_sim_sd); button.setImageResource(R.drawable.ic_sim_sd);
button.setOnClickListener(v -> fragment.startActivity(intent)); button.setOnClickListener(v -> mFragment.startActivity(intent));
button.setVisibility(View.VISIBLE); button.setVisibility(View.VISIBLE);
} }
return; return;
} }
case ActionType.ACTION_NOTIF_PREFERENCE: { case ActionType.ACTION_NOTIF_PREFERENCE: {
// TODO if (mAppNotifPrefIntent == null) {
button.setVisibility(View.GONE);
} else {
button.setOnClickListener(v -> mFragment.startActivity(mAppNotifPrefIntent));
button.setVisibility(View.VISIBLE);
}
return; return;
} }
case ActionType.ACTION_APP_PREFERENCE: { case ActionType.ACTION_APP_PREFERENCE: {
final Intent intent = resolveIntent( final Intent intent = resolveIntent(
new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(packageName)); new Intent(Intent.ACTION_APPLICATION_PREFERENCES).setPackage(mPackageName));
if (intent == null) { if (intent == null) {
button.setVisibility(View.GONE); button.setVisibility(View.GONE);
return; return;
} }
button.setOnClickListener(v -> fragment.startActivity(intent)); button.setOnClickListener(v -> mFragment.startActivity(intent));
button.setVisibility(View.VISIBLE); button.setVisibility(View.VISIBLE);
return; return;
} }
case ActionType.ACTION_NONE: {
button.setVisibility(View.GONE);
return;
}
} }
} }
@@ -160,4 +286,12 @@ public class AppHeaderController {
} }
return null; return null;
} }
}
private void setText(@IdRes int id, CharSequence text) {
TextView textView = (TextView) mAppHeader.findViewById(id);
if (textView != null) {
textView.setText(text);
textView.setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE);
}
}
}

View File

@@ -16,8 +16,14 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.app.Fragment;
import android.view.View;
public interface ApplicationFeatureProvider { public interface ApplicationFeatureProvider {
AppHeaderController getAppHeaderController(); /**
* Returns a new {@link AppHeaderController} instance to customize app header.
*/
AppHeaderController newAppHeaderController(Fragment fragment, View appHeader);
} }

View File

@@ -16,23 +16,19 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.view.View;
public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider { public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
private final Context mContext; private final Context mContext;
private AppHeaderController mAppHeaderController;
public ApplicationFeatureProviderImpl(Context context) { public ApplicationFeatureProviderImpl(Context context) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
} }
@Override public AppHeaderController newAppHeaderController(Fragment fragment, View appHeader) {
public AppHeaderController getAppHeaderController() { return new AppHeaderController(mContext, fragment, appHeader);
if (mAppHeaderController == null) {
mAppHeaderController = new AppHeaderController(mContext);
}
return mAppHeaderController;
} }
} }

View File

@@ -154,7 +154,6 @@ public class InstalledAppDetails extends AppInfoBase
private final HashSet<String> mHomePackages = new HashSet<>(); private final HashSet<String> mHomePackages = new HashSet<>();
private DashboardFeatureProvider mDashboardFeatureProvider; private DashboardFeatureProvider mDashboardFeatureProvider;
private AppHeaderController mAppHeaderController;
private boolean mInitialized; private boolean mInitialized;
private boolean mShowUninstalled; private boolean mShowUninstalled;
@@ -317,8 +316,6 @@ public class InstalledAppDetails extends AppInfoBase
final Activity activity = getActivity(); final Activity activity = getActivity();
mDashboardFeatureProvider = mDashboardFeatureProvider =
FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity); FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
mAppHeaderController = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity).getAppHeaderController();
setHasOptionsMenu(true); setHasOptionsMenu(true);
addPreferencesFromResource(mDashboardFeatureProvider.isEnabled() addPreferencesFromResource(mDashboardFeatureProvider.isEnabled()
@@ -384,13 +381,15 @@ public class InstalledAppDetails extends AppInfoBase
if (!mDashboardFeatureProvider.isEnabled()) { if (!mDashboardFeatureProvider.isEnabled()) {
handleHeader(); handleHeader();
} else { } else {
final Activity activity = getActivity();
mHeader = (LayoutPreference) findPreference(KEY_HEADER); mHeader = (LayoutPreference) findPreference(KEY_HEADER);
mAppHeaderController.bindAppHeaderButtons( FeatureFactory.getFactory(activity)
this, .getApplicationFeatureProvider(activity)
mHeader.findViewById(R.id.app_detail_links), .newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
mPackageName, .setPackageName(mPackageName)
AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK, .setButtonActions(AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
AppHeaderController.ActionType.ACTION_APP_PREFERENCE); AppHeaderController.ActionType.ACTION_APP_PREFERENCE)
.bindAppHeaderButtons();
prepareUninstallAndStop(); prepareUninstallAndStop();
} }
@@ -544,7 +543,14 @@ public class InstalledAppDetails extends AppInfoBase
final View appSnippet = mHeader.findViewById(R.id.app_snippet); final View appSnippet = mHeader.findViewById(R.id.app_snippet);
mState.ensureIcon(mAppEntry); mState.ensureIcon(mAppEntry);
if (mDashboardFeatureProvider.isEnabled()) { if (mDashboardFeatureProvider.isEnabled()) {
mAppHeaderController.bindAppHeader(appSnippet, pkgInfo, mAppEntry); final Activity activity = getActivity();
FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this, appSnippet)
.setLabel(mAppEntry)
.setIcon(mAppEntry)
.setSummary(pkgInfo)
.done(false /* rebindActions */);
} else { } else {
setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon, setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon,
pkgInfo != null ? pkgInfo.versionName : null); pkgInfo != null ? pkgInfo.versionName : null);

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification; package com.android.settings.notification;
import android.app.Activity;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
@@ -24,20 +25,25 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceCategory;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.view.View;
import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.AppHeader; import com.android.settings.AppHeader;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.AppInfoBase; import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.notification.NotificationBackend.AppRow; import com.android.settings.notification.NotificationBackend.AppRow;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedPreference; import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import java.util.List; import java.util.List;
/** These settings are per app, so should not be returned in global search results. */ /** These settings are per app, so should not be returned in global search results. */
@@ -50,15 +56,20 @@ public class AppNotificationSettings extends NotificationSettingsBase {
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES); .addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES);
private static final String KEY_CHANNELS = "channels"; private static final String KEY_CHANNELS = "channels";
private DashboardFeatureProvider mDashboardFeatureProvider;
private PreferenceCategory mChannels; private PreferenceCategory mChannels;
List<NotificationChannel> mChannelList; private List<NotificationChannel> mChannelList;
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
if (mAppRow == null) return; if (mAppRow == null) return;
AppHeader.createAppHeader(this, mAppRow.icon, mAppRow.label, mAppRow.pkg, mAppRow.uid, if (!mDashboardFeatureProvider.isEnabled()) {
mAppRow.settingsIntent); AppHeader.createAppHeader(this, mAppRow.icon, mAppRow.label, mAppRow.pkg, mAppRow.uid,
mAppRow.settingsIntent);
}
} }
@Override @Override
@@ -69,8 +80,12 @@ public class AppNotificationSettings extends NotificationSettingsBase {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final Activity activity = getActivity();
mDashboardFeatureProvider =
FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
addPreferencesFromResource(R.xml.app_notification_settings); addPreferencesFromResource(R.xml.app_notification_settings);
mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE); mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE);
mPriority = mPriority =
(RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BYPASS_DND); (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BYPASS_DND);
@@ -118,6 +133,22 @@ public class AppNotificationSettings extends NotificationSettingsBase {
} }
updateDependents(mAppRow.appImportance); updateDependents(mAppRow.appImportance);
} }
if (mDashboardFeatureProvider.isEnabled()) {
final AppHeaderController appHeaderController = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this /* fragment */, null /* appHeader */);
final View appHeader = appHeaderController.setIcon(mAppRow.icon)
.setLabel(mAppRow.label)
.setPackageName(mAppRow.pkg)
.setUid(mAppRow.uid)
.setAppNotifPrefIntent(mAppRow.settingsIntent)
.setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
.done();
final Preference appHeaderPref = new LayoutPreference(getPrefContext(), appHeader);
appHeaderPref.setOrder(0);
getPreferenceScreen().addPreference(appHeaderPref);
}
} }
@Override @Override

View File

@@ -20,9 +20,14 @@ import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.AppHeader; import com.android.settings.AppHeader;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.RingtonePreference; import com.android.settings.RingtonePreference;
import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import android.app.Activity;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
@@ -30,6 +35,7 @@ import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.NotificationListenerService.Ranking; import android.service.notification.NotificationListenerService.Ranking;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.view.View;
public class ChannelNotificationSettings extends NotificationSettingsBase { public class ChannelNotificationSettings extends NotificationSettingsBase {
protected static final String KEY_LIGHTS = "lights"; protected static final String KEY_LIGHTS = "lights";
@@ -39,14 +45,18 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
protected RestrictedSwitchPreference mLights; protected RestrictedSwitchPreference mLights;
protected RestrictedSwitchPreference mVibrate; protected RestrictedSwitchPreference mVibrate;
protected DefaultNotificationTonePreference mRingtone; protected DefaultNotificationTonePreference mRingtone;
private DashboardFeatureProvider mDashboardFeatureProvider;
private int mMaxImportance; private int mMaxImportance;
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
if (mAppRow == null || mChannel == null) return; if (mAppRow == null || mChannel == null) return;
AppHeader.createAppHeader( if (!mDashboardFeatureProvider.isEnabled()) {
this, mAppRow.icon, mChannel.getName(), mAppRow.pkg, mAppRow.uid); AppHeader.createAppHeader(
this, mAppRow.icon, mChannel.getName(), mAppRow.pkg, mAppRow.uid);
}
} }
@Override @Override
@@ -57,6 +67,9 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final Activity activity = getActivity();
mDashboardFeatureProvider =
FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
addPreferencesFromResource(R.xml.channel_notification_settings); addPreferencesFromResource(R.xml.channel_notification_settings);
mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE); mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE);
@@ -88,6 +101,22 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
mChannel.getImportance() == NotificationManager.IMPORTANCE_NONE, mChannel.getImportance() == NotificationManager.IMPORTANCE_NONE,
mMaxImportance); mMaxImportance);
} }
if (mDashboardFeatureProvider.isEnabled()) {
final AppHeaderController appHeaderController = FeatureFactory.getFactory(activity)
.getApplicationFeatureProvider(activity)
.newAppHeaderController(this /* fragment */, null /* appHeader */);
final View appHeader = appHeaderController.setIcon(mAppRow.icon)
.setLabel(mAppRow.label)
.setSummary(mChannel.getName())
.setPackageName(mAppRow.pkg)
.setUid(mAppRow.uid)
.setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
AppHeaderController.ActionType.ACTION_NONE)
.done();
final Preference appHeaderPref = new LayoutPreference(getPrefContext(), appHeader);
appHeaderPref.setOrder(0);
getPreferenceScreen().addPreference(appHeaderPref);
}
} }
@Override @Override

View File

@@ -17,12 +17,14 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
@@ -44,6 +46,7 @@ import org.robolectric.shadows.ShadowApplication;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -57,6 +60,8 @@ public class AppHeaderControllerTest {
private ApplicationsState.AppEntry mAppEntry; private ApplicationsState.AppEntry mAppEntry;
@Mock @Mock
private Fragment mFragment; private Fragment mFragment;
@Mock
private View mAppHeader;
private Context mShadowContext; private Context mShadowContext;
private LayoutInflater mLayoutInflater; private LayoutInflater mLayoutInflater;
@@ -71,7 +76,23 @@ public class AppHeaderControllerTest {
mLayoutInflater = LayoutInflater.from(mShadowContext); mLayoutInflater = LayoutInflater.from(mShadowContext);
mInfo = new PackageInfo(); mInfo = new PackageInfo();
mInfo.versionName = "1234"; mInfo.versionName = "1234";
mController = new AppHeaderController(mContext); }
@Test
public void testBuildView_constructedWithoutView_shouldCreateNewView() {
mController = new AppHeaderController(mShadowContext, mFragment, null);
View view = mController.done();
assertThat(view).isNotNull();
}
@Test
public void testBuildView_constructedWithView_shouldReturnSameView() {
View inputView = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
mController = new AppHeaderController(mShadowContext, mFragment, inputView);
View view = mController.done();
assertThat(view).isSameAs(inputView);
} }
@Test @Test
@@ -80,14 +101,15 @@ public class AppHeaderControllerTest {
final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */); final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
final TextView label = (TextView) appHeader.findViewById(android.R.id.title); final TextView label = (TextView) appHeader.findViewById(android.R.id.title);
final TextView version = (TextView) appHeader.findViewById(android.R.id.summary); final TextView version = (TextView) appHeader.findViewById(android.R.id.summary);
label.setText(testString);
label.setText(testString);
mController.bindAppHeader(appHeader, mInfo, mAppEntry); mController = new AppHeaderController(mShadowContext, mFragment, appHeader);
mController.setLabel(testString);
mController.setSummary(testString);
mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
mController.done();
assertThat(label.getText()).isNotEqualTo(testString); assertThat(label.getText()).isEqualTo(testString);
assertThat(version.getText()) assertThat(version.getText()).isEqualTo(testString);
.isEqualTo(mShadowContext.getString(R.string.version_text, mInfo.versionName));
} }
@Test @Test
@@ -100,14 +122,17 @@ public class AppHeaderControllerTest {
.inflate(R.layout.app_details, null /* root */); .inflate(R.layout.app_details, null /* root */);
when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt())) when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
.thenReturn(info); .thenReturn(info);
mController.bindAppHeaderButtons(mFragment, appLinks,
mShadowContext.getPackageName(), mController = new AppHeaderController(mContext, mFragment, appLinks);
mController.setButtonActions(
AppHeaderController.ActionType.ACTION_APP_PREFERENCE, AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
AppHeaderController.ActionType.ACTION_APP_PREFERENCE); AppHeaderController.ActionType.ACTION_NONE);
mController.done();
assertThat(appLinks.findViewById(R.id.left_button).getVisibility()) assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
.isEqualTo(View.VISIBLE); .isEqualTo(View.VISIBLE);
assertThat(appLinks.findViewById(R.id.right_button).getVisibility()) assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
.isEqualTo(View.VISIBLE); .isEqualTo(View.GONE);
try { try {
appLinks.findViewById(R.id.left_button).performClick(); appLinks.findViewById(R.id.left_button).performClick();
} catch (Exception e) { } catch (Exception e) {
@@ -122,10 +147,13 @@ public class AppHeaderControllerTest {
.inflate(R.layout.app_details, null /* root */); .inflate(R.layout.app_details, null /* root */);
when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt())) when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
.thenReturn(null); .thenReturn(null);
mController.bindAppHeaderButtons(mFragment, appLinks,
mShadowContext.getPackageName(), mController = new AppHeaderController(mContext, mFragment, appLinks);
mController.setButtonActions(
AppHeaderController.ActionType.ACTION_APP_PREFERENCE, AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
AppHeaderController.ActionType.ACTION_APP_PREFERENCE); AppHeaderController.ActionType.ACTION_NONE);
mController.done();
assertThat(appLinks.findViewById(R.id.left_button).getVisibility()) assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
assertThat(appLinks.findViewById(R.id.right_button).getVisibility()) assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
@@ -138,13 +166,72 @@ public class AppHeaderControllerTest {
.inflate(R.layout.app_details, null /* root */); .inflate(R.layout.app_details, null /* root */);
when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt())) when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
.thenReturn(null); .thenReturn(null);
mController.bindAppHeaderButtons(mFragment, appLinks,
mShadowContext.getPackageName(), mController = new AppHeaderController(mContext, mFragment, appLinks);
mController.setButtonActions(
AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK, AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK); AppHeaderController.ActionType.ACTION_NONE);
mController.done();
assertThat(appLinks.findViewById(R.id.left_button).getVisibility()) assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
assertThat(appLinks.findViewById(R.id.right_button).getVisibility()) assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
.isEqualTo(View.GONE); .isEqualTo(View.GONE);
} }
@Test
public void bindButton_noAppInfo_shouldNotShowButton() {
final View appLinks = mLayoutInflater
.inflate(R.layout.app_details, null /* root */);
mController = new AppHeaderController(mContext, mFragment, appLinks);
mController.setPackageName(null)
.setButtonActions(
AppHeaderController.ActionType.ACTION_APP_INFO,
AppHeaderController.ActionType.ACTION_NONE);
mController.done();
assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
.isEqualTo(View.GONE);
assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void bindButton_hasAppInfo_shouldShowButton() {
final View appLinks = mLayoutInflater
.inflate(R.layout.app_details, null /* root */);
when(mFragment.getActivity()).thenReturn(mock(Activity.class));
mController = new AppHeaderController(mContext, mFragment, appLinks);
mController.setPackageName("123")
.setUid(UserHandle.USER_SYSTEM)
.setButtonActions(
AppHeaderController.ActionType.ACTION_APP_INFO,
AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
mController.done();
assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
.isEqualTo(View.VISIBLE);
assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
.isEqualTo(View.GONE);
}
@Test
public void bindButton_hasAppNotifIntent_shouldShowButton() {
final View appLinks = mLayoutInflater
.inflate(R.layout.app_details, null /* root */);
mController = new AppHeaderController(mContext, mFragment, appLinks);
mController.setAppNotifPrefIntent(new Intent())
.setButtonActions(
AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
AppHeaderController.ActionType.ACTION_NONE);
mController.done();
assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
.isEqualTo(View.VISIBLE);
assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
.isEqualTo(View.GONE);
}
} }