Merge "Allow app lists to have a toggle" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2c18bbbd75
@@ -20,8 +20,12 @@ import android.app.usage.UsageStatsManager;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Switch;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.notification.NotificationBackend;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
import com.android.settingslib.applications.ApplicationsState.AppFilter;
|
import com.android.settingslib.applications.ApplicationsState.AppFilter;
|
||||||
@@ -37,13 +41,18 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class AppStateNotificationBridge extends AppStateBaseBridge {
|
public class AppStateNotificationBridge extends AppStateBaseBridge {
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
private UsageStatsManager mUsageStatsManager;
|
private UsageStatsManager mUsageStatsManager;
|
||||||
|
private NotificationBackend mBackend;
|
||||||
private static final int DAYS_TO_CHECK = 7;
|
private static final int DAYS_TO_CHECK = 7;
|
||||||
|
|
||||||
public AppStateNotificationBridge(ApplicationsState appState,
|
public AppStateNotificationBridge(Context context, ApplicationsState appState,
|
||||||
Callback callback, UsageStatsManager usageStatsManager) {
|
Callback callback, UsageStatsManager usageStatsManager,
|
||||||
|
NotificationBackend backend) {
|
||||||
super(appState, callback);
|
super(appState, callback);
|
||||||
|
mContext = context;
|
||||||
mUsageStatsManager = usageStatsManager;
|
mUsageStatsManager = usageStatsManager;
|
||||||
|
mBackend = backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -55,6 +64,7 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
|||||||
for (AppEntry entry : apps) {
|
for (AppEntry entry : apps) {
|
||||||
NotificationsSentState stats = map.get(entry.info.packageName);
|
NotificationsSentState stats = map.get(entry.info.packageName);
|
||||||
calculateAvgSentCounts(stats);
|
calculateAvgSentCounts(stats);
|
||||||
|
addBlockStatus(entry, stats);
|
||||||
entry.extraInfo = stats;
|
entry.extraInfo = stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +74,7 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
|||||||
Map<String, NotificationsSentState> map = getAggregatedUsageEvents();
|
Map<String, NotificationsSentState> map = getAggregatedUsageEvents();
|
||||||
NotificationsSentState stats = map.get(entry.info.packageName);
|
NotificationsSentState stats = map.get(entry.info.packageName);
|
||||||
calculateAvgSentCounts(stats);
|
calculateAvgSentCounts(stats);
|
||||||
|
addBlockStatus(entry, stats);
|
||||||
entry.extraInfo = stats;
|
entry.extraInfo = stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +94,14 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addBlockStatus(AppEntry entry, NotificationsSentState stats) {
|
||||||
|
if (stats != null) {
|
||||||
|
stats.blocked = mBackend.getNotificationsBanned(entry.info.packageName, entry.info.uid);
|
||||||
|
stats.systemApp = mBackend.isSystemApp(mContext, entry.info);
|
||||||
|
stats.blockable = !stats.systemApp || (stats.systemApp && stats.blocked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void calculateAvgSentCounts(NotificationsSentState stats) {
|
private void calculateAvgSentCounts(NotificationsSentState stats) {
|
||||||
if (stats != null) {
|
if (stats != null) {
|
||||||
stats.avgSentDaily = Math.round((float) stats.sentCount / DAYS_TO_CHECK);
|
stats.avgSentDaily = Math.round((float) stats.sentCount / DAYS_TO_CHECK);
|
||||||
@@ -130,6 +149,28 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public View.OnClickListener getSwitchOnClickListener(final AppEntry entry) {
|
||||||
|
if (entry != null) {
|
||||||
|
return v -> {
|
||||||
|
ViewGroup view = (ViewGroup) v;
|
||||||
|
Switch toggle = view.findViewById(R.id.switchWidget);
|
||||||
|
if (toggle != null) {
|
||||||
|
if (!toggle.isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toggle.toggle();
|
||||||
|
mBackend.setNotificationsEnabledForPackage(
|
||||||
|
entry.info.packageName, entry.info.uid, toggle.isChecked());
|
||||||
|
NotificationsSentState stats = getNotificationsSentState(entry);
|
||||||
|
if (stats != null) {
|
||||||
|
stats.blocked = !toggle.isChecked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static final AppFilter FILTER_APP_NOTIFICATION_RECENCY = new AppFilter() {
|
public static final AppFilter FILTER_APP_NOTIFICATION_RECENCY = new AppFilter() {
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
@@ -192,6 +233,24 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final boolean enableSwitch(AppEntry entry) {
|
||||||
|
NotificationsSentState stats = getNotificationsSentState(entry);
|
||||||
|
if (stats == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats.blockable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final boolean checkSwitch(AppEntry entry) {
|
||||||
|
NotificationsSentState stats = getNotificationsSentState(entry);
|
||||||
|
if (stats == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !stats.blocked;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NotificationsSentState contains how often an app sends notifications and how recently it sent
|
* NotificationsSentState contains how often an app sends notifications and how recently it sent
|
||||||
* one.
|
* one.
|
||||||
@@ -201,5 +260,8 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
|||||||
public int avgSentWeekly = 0;
|
public int avgSentWeekly = 0;
|
||||||
public long lastSent = 0;
|
public long lastSent = 0;
|
||||||
public int sentCount = 0;
|
public int sentCount = 0;
|
||||||
|
public boolean blockable;
|
||||||
|
public boolean blocked;
|
||||||
|
public boolean systemApp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.Switch;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
@@ -47,7 +48,10 @@ public class ApplicationViewHolder extends RecyclerView.ViewHolder {
|
|||||||
final TextView mSummary;
|
final TextView mSummary;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final TextView mDisabled;
|
final TextView mDisabled;
|
||||||
|
@VisibleForTesting
|
||||||
|
final ViewGroup mWidgetContainer;
|
||||||
|
@VisibleForTesting
|
||||||
|
final Switch mSwitch;
|
||||||
|
|
||||||
ApplicationViewHolder(View itemView, boolean keepStableHeight) {
|
ApplicationViewHolder(View itemView, boolean keepStableHeight) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
@@ -57,11 +61,30 @@ public class ApplicationViewHolder extends RecyclerView.ViewHolder {
|
|||||||
mSummary = itemView.findViewById(android.R.id.summary);
|
mSummary = itemView.findViewById(android.R.id.summary);
|
||||||
mDisabled = itemView.findViewById(R.id.appendix);
|
mDisabled = itemView.findViewById(R.id.appendix);
|
||||||
mKeepStableHeight = keepStableHeight;
|
mKeepStableHeight = keepStableHeight;
|
||||||
|
mSwitch = itemView.findViewById(R.id.switchWidget);
|
||||||
|
mWidgetContainer = itemView.findViewById(android.R.id.widget_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static View newView(ViewGroup parent) {
|
static View newView(ViewGroup parent) {
|
||||||
return LayoutInflater.from(parent.getContext())
|
return newView(parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static View newView(ViewGroup parent, boolean twoTarget) {
|
||||||
|
ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.preference_app, parent, false);
|
.inflate(R.layout.preference_app, parent, false);
|
||||||
|
if (twoTarget) {
|
||||||
|
final ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
|
||||||
|
if (widgetFrame != null) {
|
||||||
|
LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.preference_widget_master_switch, widgetFrame, true);
|
||||||
|
|
||||||
|
View divider = LayoutInflater.from(parent.getContext()).inflate(
|
||||||
|
R.layout.preference_two_target_divider, view, false);
|
||||||
|
// second to last, before widget frame
|
||||||
|
view.addView(divider, view.getChildCount() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSummary(CharSequence summary) {
|
void setSummary(CharSequence summary) {
|
||||||
@@ -141,4 +164,12 @@ public class ApplicationViewHolder extends RecyclerView.ViewHolder {
|
|||||||
setSummary(invalidSizeStr);
|
setSummary(invalidSizeStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateSwitch(View.OnClickListener listener, boolean enabled, boolean checked) {
|
||||||
|
if (mSwitch != null && mWidgetContainer != null) {
|
||||||
|
mWidgetContainer.setOnClickListener(listener);
|
||||||
|
mSwitch.setChecked(checked);
|
||||||
|
mSwitch.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -109,6 +109,7 @@ import com.android.settings.dashboard.SummaryLoader;
|
|||||||
import com.android.settings.fuelgauge.HighPowerDetail;
|
import com.android.settings.fuelgauge.HighPowerDetail;
|
||||||
import com.android.settings.notification.AppNotificationSettings;
|
import com.android.settings.notification.AppNotificationSettings;
|
||||||
import com.android.settings.notification.ConfigureNotificationSettings;
|
import com.android.settings.notification.ConfigureNotificationSettings;
|
||||||
|
import com.android.settings.notification.NotificationBackend;
|
||||||
import com.android.settings.widget.LoadingViewController;
|
import com.android.settings.widget.LoadingViewController;
|
||||||
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
|
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
|
||||||
import com.android.settings.wifi.ChangeWifiStateDetails;
|
import com.android.settings.wifi.ChangeWifiStateDetails;
|
||||||
@@ -223,6 +224,7 @@ public class ManageApplications extends InstrumentedFragment
|
|||||||
private Spinner mFilterSpinner;
|
private Spinner mFilterSpinner;
|
||||||
private FilterSpinnerAdapter mFilterAdapter;
|
private FilterSpinnerAdapter mFilterAdapter;
|
||||||
private UsageStatsManager mUsageStatsManager;
|
private UsageStatsManager mUsageStatsManager;
|
||||||
|
private NotificationBackend mNotificationBackend;
|
||||||
private ResetAppsHelper mResetAppsHelper;
|
private ResetAppsHelper mResetAppsHelper;
|
||||||
private String mVolumeUuid;
|
private String mVolumeUuid;
|
||||||
private int mStorageType;
|
private int mStorageType;
|
||||||
@@ -292,6 +294,7 @@ public class ManageApplications extends InstrumentedFragment
|
|||||||
mListType = LIST_TYPE_NOTIFICATION;
|
mListType = LIST_TYPE_NOTIFICATION;
|
||||||
mUsageStatsManager =
|
mUsageStatsManager =
|
||||||
(UsageStatsManager) getContext().getSystemService(Context.USAGE_STATS_SERVICE);
|
(UsageStatsManager) getContext().getSystemService(Context.USAGE_STATS_SERVICE);
|
||||||
|
mNotificationBackend = new NotificationBackend();
|
||||||
mSortOrder = R.id.sort_order_recent_notification;
|
mSortOrder = R.id.sort_order_recent_notification;
|
||||||
screenTitle = R.string.app_notifications_title;
|
screenTitle = R.string.app_notifications_title;
|
||||||
} else {
|
} else {
|
||||||
@@ -869,8 +872,9 @@ public class ManageApplications extends InstrumentedFragment
|
|||||||
mContext = manageApplications.getActivity();
|
mContext = manageApplications.getActivity();
|
||||||
mAppFilter = appFilter;
|
mAppFilter = appFilter;
|
||||||
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
||||||
mExtraInfoBridge = new AppStateNotificationBridge(mState, this,
|
mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
|
||||||
manageApplications.mUsageStatsManager);
|
manageApplications.mUsageStatsManager,
|
||||||
|
manageApplications.mNotificationBackend);
|
||||||
} else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
|
} else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
|
||||||
mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
|
mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
|
||||||
} else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
|
} else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
|
||||||
@@ -988,7 +992,12 @@ public class ManageApplications extends InstrumentedFragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
final View view = ApplicationViewHolder.newView(parent);
|
View view;
|
||||||
|
if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
|
||||||
|
view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
|
||||||
|
} else {
|
||||||
|
view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
|
||||||
|
}
|
||||||
return new ApplicationViewHolder(view,
|
return new ApplicationViewHolder(view,
|
||||||
shouldUseStableItemHeight(mManageApplications.mListType));
|
shouldUseStableItemHeight(mManageApplications.mListType));
|
||||||
}
|
}
|
||||||
@@ -1276,6 +1285,7 @@ public class ManageApplications extends InstrumentedFragment
|
|||||||
mState.ensureIcon(entry);
|
mState.ensureIcon(entry);
|
||||||
holder.setIcon(entry.icon);
|
holder.setIcon(entry.icon);
|
||||||
updateSummary(holder, entry);
|
updateSummary(holder, entry);
|
||||||
|
updateSwitch(holder, entry);
|
||||||
holder.updateDisableView(entry.info);
|
holder.updateDisableView(entry.info);
|
||||||
}
|
}
|
||||||
holder.setEnabled(isEnabled(position));
|
holder.setEnabled(isEnabled(position));
|
||||||
@@ -1328,6 +1338,24 @@ public class ManageApplications extends InstrumentedFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateSwitch(ApplicationViewHolder holder, AppEntry entry) {
|
||||||
|
switch (mManageApplications.mListType) {
|
||||||
|
case LIST_TYPE_NOTIFICATION:
|
||||||
|
holder.updateSwitch(((AppStateNotificationBridge) mExtraInfoBridge)
|
||||||
|
.getSwitchOnClickListener(entry),
|
||||||
|
AppStateNotificationBridge.enableSwitch(entry),
|
||||||
|
AppStateNotificationBridge.checkSwitch(entry));
|
||||||
|
if (entry.extraInfo != null) {
|
||||||
|
holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
|
||||||
|
(NotificationsSentState) entry.extraInfo,
|
||||||
|
(mLastSortMode == R.id.sort_order_recent_notification)));
|
||||||
|
} else {
|
||||||
|
holder.setSummary(null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasExtraView() {
|
private boolean hasExtraView() {
|
||||||
return mExtraViewController != null
|
return mExtraViewController != null
|
||||||
&& mExtraViewController.shouldShow();
|
&& mExtraViewController.shouldShow();
|
||||||
|
@@ -65,11 +65,15 @@ public class NotificationBackend {
|
|||||||
|
|
||||||
public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) {
|
public AppRow loadAppRow(Context context, PackageManager pm, PackageInfo app) {
|
||||||
final AppRow row = loadAppRow(context, pm, app.applicationInfo);
|
final AppRow row = loadAppRow(context, pm, app.applicationInfo);
|
||||||
|
recordCanBeBlocked(context, pm, app, row);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
void recordCanBeBlocked(Context context, PackageManager pm, PackageInfo app, AppRow row) {
|
||||||
row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app);
|
row.systemApp = Utils.isSystemPackage(context.getResources(), pm, app);
|
||||||
final String[] nonBlockablePkgs = context.getResources().getStringArray(
|
final String[] nonBlockablePkgs = context.getResources().getStringArray(
|
||||||
com.android.internal.R.array.config_nonBlockableNotificationPackages);
|
com.android.internal.R.array.config_nonBlockableNotificationPackages);
|
||||||
markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
|
markAppRowWithBlockables(nonBlockablePkgs, row, app.packageName);
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting static void markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row,
|
@VisibleForTesting static void markAppRowWithBlockables(String[] nonBlockablePkgs, AppRow row,
|
||||||
@@ -92,6 +96,19 @@ public class NotificationBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSystemApp(Context context, ApplicationInfo app) {
|
||||||
|
try {
|
||||||
|
PackageInfo info = context.getPackageManager().getPackageInfo(
|
||||||
|
app.packageName, PackageManager.GET_SIGNATURES);
|
||||||
|
final AppRow row = new AppRow();
|
||||||
|
recordCanBeBlocked(context, context.getPackageManager(), info, row);
|
||||||
|
return row.systemApp;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getNotificationsBanned(String pkg, int uid) {
|
public boolean getNotificationsBanned(String pkg, int uid) {
|
||||||
try {
|
try {
|
||||||
final boolean enabled = sINM.areNotificationsEnabledForPackage(pkg, uid);
|
final boolean enabled = sINM.areNotificationsEnabledForPackage(pkg, uid);
|
||||||
|
@@ -33,8 +33,11 @@ import static junit.framework.Assert.assertFalse;
|
|||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.usage.UsageEvents;
|
import android.app.usage.UsageEvents;
|
||||||
@@ -44,9 +47,12 @@ import android.content.Context;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Switch;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
|
import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
|
||||||
|
import com.android.settings.notification.NotificationBackend;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
@@ -74,6 +80,8 @@ public class AppStateNotificationBridgeTest {
|
|||||||
private ApplicationsState mState;
|
private ApplicationsState mState;
|
||||||
@Mock
|
@Mock
|
||||||
private UsageStatsManager mUsageStats;
|
private UsageStatsManager mUsageStats;
|
||||||
|
@Mock
|
||||||
|
private NotificationBackend mBackend;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private AppStateNotificationBridge mBridge;
|
private AppStateNotificationBridge mBridge;
|
||||||
|
|
||||||
@@ -82,10 +90,12 @@ public class AppStateNotificationBridgeTest {
|
|||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
when(mState.newSession(any())).thenReturn(mSession);
|
when(mState.newSession(any())).thenReturn(mSession);
|
||||||
when(mState.getBackgroundLooper()).thenReturn(mock(Looper.class));
|
when(mState.getBackgroundLooper()).thenReturn(mock(Looper.class));
|
||||||
|
when(mBackend.getNotificationsBanned(anyString(), anyInt())).thenReturn(true);
|
||||||
|
when(mBackend.isSystemApp(any(), any())).thenReturn(true);
|
||||||
mContext = RuntimeEnvironment.application.getApplicationContext();
|
mContext = RuntimeEnvironment.application.getApplicationContext();
|
||||||
|
|
||||||
mBridge = new AppStateNotificationBridge(mState,
|
mBridge = new AppStateNotificationBridge(mContext, mState,
|
||||||
mock(AppStateBaseBridge.Callback.class), mUsageStats);
|
mock(AppStateBaseBridge.Callback.class), mUsageStats, mBackend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AppEntry getMockAppEntry(String pkg) {
|
private AppEntry getMockAppEntry(String pkg) {
|
||||||
@@ -213,6 +223,9 @@ public class AppStateNotificationBridgeTest {
|
|||||||
assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(6);
|
assertThat(((NotificationsSentState) apps.get(0).extraInfo).lastSent).isEqualTo(6);
|
||||||
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1);
|
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentDaily).isEqualTo(1);
|
||||||
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0);
|
assertThat(((NotificationsSentState) apps.get(0).extraInfo).avgSentWeekly).isEqualTo(0);
|
||||||
|
assertThat(((NotificationsSentState) apps.get(0).extraInfo).blocked).isTrue();
|
||||||
|
assertThat(((NotificationsSentState) apps.get(0).extraInfo).systemApp).isTrue();
|
||||||
|
assertThat(((NotificationsSentState) apps.get(0).extraInfo).blockable).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -281,6 +294,9 @@ public class AppStateNotificationBridgeTest {
|
|||||||
assertThat(((NotificationsSentState) entry.extraInfo).lastSent).isEqualTo(12);
|
assertThat(((NotificationsSentState) entry.extraInfo).lastSent).isEqualTo(12);
|
||||||
assertThat(((NotificationsSentState) entry.extraInfo).avgSentDaily).isEqualTo(2);
|
assertThat(((NotificationsSentState) entry.extraInfo).avgSentDaily).isEqualTo(2);
|
||||||
assertThat(((NotificationsSentState) entry.extraInfo).avgSentWeekly).isEqualTo(0);
|
assertThat(((NotificationsSentState) entry.extraInfo).avgSentWeekly).isEqualTo(0);
|
||||||
|
assertThat(((NotificationsSentState) entry.extraInfo).blocked).isTrue();
|
||||||
|
assertThat(((NotificationsSentState) entry.extraInfo).systemApp).isTrue();
|
||||||
|
assertThat(((NotificationsSentState) entry.extraInfo).blockable).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -410,4 +426,33 @@ public class AppStateNotificationBridgeTest {
|
|||||||
assertThat(entries).containsExactly(veryFrequentDailyEntry, notFrequentDailyEntry,
|
assertThat(entries).containsExactly(veryFrequentDailyEntry, notFrequentDailyEntry,
|
||||||
veryFrequentWeeklyEntry, notFrequentWeeklyEntry);
|
veryFrequentWeeklyEntry, notFrequentWeeklyEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwitchOnClickListener() {
|
||||||
|
ViewGroup parent = mock(ViewGroup.class);
|
||||||
|
Switch toggle = mock(Switch.class);
|
||||||
|
when(toggle.isChecked()).thenReturn(true);
|
||||||
|
when(toggle.isEnabled()).thenReturn(true);
|
||||||
|
when(parent.findViewById(anyInt())).thenReturn(toggle);
|
||||||
|
|
||||||
|
AppEntry entry = mock(AppEntry.class);
|
||||||
|
entry.info = new ApplicationInfo();
|
||||||
|
entry.info.packageName = "pkg";
|
||||||
|
entry.info.uid = 1356;
|
||||||
|
entry.extraInfo = new NotificationsSentState();
|
||||||
|
|
||||||
|
ViewGroup.OnClickListener listener = mBridge.getSwitchOnClickListener(entry);
|
||||||
|
listener.onClick(parent);
|
||||||
|
|
||||||
|
verify(toggle).toggle();
|
||||||
|
verify(mBackend).setNotificationsEnabledForPackage(
|
||||||
|
entry.info.packageName, entry.info.uid, true);
|
||||||
|
assertThat(((NotificationsSentState) entry.extraInfo).blocked).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSwitchViews_nullDoesNotCrash() {
|
||||||
|
mBridge.enableSwitch(null);
|
||||||
|
mBridge.checkSwitch(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -91,4 +91,31 @@ public class ApplicationViewHolderTest {
|
|||||||
mHolder.updateSizeText(entry, invalidStr, ManageApplications.SIZE_EXTERNAL);
|
mHolder.updateSizeText(entry, invalidStr, ManageApplications.SIZE_EXTERNAL);
|
||||||
assertThat(mHolder.mSummary.getText()).isEqualTo(invalidStr);
|
assertThat(mHolder.mSummary.getText()).isEqualTo(invalidStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void oneTouchTarget() {
|
||||||
|
assertThat(mHolder.mSwitch).isNull();
|
||||||
|
assertThat(mHolder.mWidgetContainer.getChildCount()).isEqualTo(0);
|
||||||
|
// assert no exception
|
||||||
|
mHolder.updateSwitch(null, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twoTouchTarget() {
|
||||||
|
mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true);
|
||||||
|
mHolder = new ApplicationViewHolder(mView, false /* useStableHeight */);
|
||||||
|
assertThat(mHolder.mSwitch).isNotNull();
|
||||||
|
assertThat(mHolder.mWidgetContainer.getChildCount()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateSwitch() {
|
||||||
|
mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true);
|
||||||
|
mHolder = new ApplicationViewHolder(mView, false /* useStableHeight */);
|
||||||
|
mHolder.updateSwitch(v -> {}, true, true);
|
||||||
|
|
||||||
|
assertThat(mHolder.mSwitch.isChecked()).isTrue();
|
||||||
|
assertThat(mHolder.mSwitch.isEnabled()).isTrue();
|
||||||
|
assertThat(mHolder.mWidgetContainer.hasOnClickListeners()).isTrue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,8 @@ import static com.android.settings.applications.manageapplications.AppFilterRegi
|
|||||||
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MAIN;
|
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_MAIN;
|
||||||
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION;
|
import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
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.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
@@ -265,6 +267,42 @@ public class ManageApplicationsTest {
|
|||||||
verify(adapter).notifyDataSetChanged();
|
verify(adapter).notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void applicationsAdapter_onBindViewHolder_updateSwitch_notifications() {
|
||||||
|
ManageApplications manageApplications = mock(ManageApplications.class);
|
||||||
|
manageApplications.mListType = LIST_TYPE_NOTIFICATION;
|
||||||
|
ApplicationViewHolder holder = mock(ApplicationViewHolder.class);
|
||||||
|
ReflectionHelpers.setField(holder, "itemView", mock(View.class));
|
||||||
|
ManageApplications.ApplicationsAdapter adapter =
|
||||||
|
new ManageApplications.ApplicationsAdapter(mState,
|
||||||
|
manageApplications, mock(AppFilterItem.class),
|
||||||
|
mock(Bundle.class));
|
||||||
|
final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
|
||||||
|
appList.add(mock(ApplicationsState.AppEntry.class));
|
||||||
|
ReflectionHelpers.setField(adapter, "mEntries", appList);
|
||||||
|
|
||||||
|
adapter.onBindViewHolder(holder, 0);
|
||||||
|
verify(holder).updateSwitch(any(), anyBoolean(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void applicationsAdapter_onBindViewHolder_updateSwitch_notNotifications() {
|
||||||
|
ManageApplications manageApplications = mock(ManageApplications.class);
|
||||||
|
manageApplications.mListType = LIST_TYPE_MAIN;
|
||||||
|
ApplicationViewHolder holder = mock(ApplicationViewHolder.class);
|
||||||
|
ReflectionHelpers.setField(holder, "itemView", mock(View.class));
|
||||||
|
ManageApplications.ApplicationsAdapter adapter =
|
||||||
|
new ManageApplications.ApplicationsAdapter(mState,
|
||||||
|
manageApplications, mock(AppFilterItem.class),
|
||||||
|
mock(Bundle.class));
|
||||||
|
final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
|
||||||
|
appList.add(mock(ApplicationsState.AppEntry.class));
|
||||||
|
ReflectionHelpers.setField(adapter, "mEntries", appList);
|
||||||
|
|
||||||
|
adapter.onBindViewHolder(holder, 0);
|
||||||
|
verify(holder, never()).updateSwitch(any(), anyBoolean(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpOptionMenus() {
|
private void setUpOptionMenus() {
|
||||||
when(mMenu.findItem(anyInt())).thenAnswer(invocation -> {
|
when(mMenu.findItem(anyInt())).thenAnswer(invocation -> {
|
||||||
final Object[] args = invocation.getArguments();
|
final Object[] args = invocation.getArguments();
|
||||||
|
Reference in New Issue
Block a user