Merge changes from topic "Hide notification channel slice" into qt-dev

* changes:
  Log interacted package from ContextualNotificationChannelSlice
  Hide notification channel slice that is interacted
This commit is contained in:
Fan Zhang
2019-04-12 23:38:27 +00:00
committed by Android (Google) Code Review
10 changed files with 469 additions and 4 deletions

View File

@@ -0,0 +1,130 @@
/*
* Copyright (C) 2019 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.homepage.contextualcards;
import static android.content.Context.MODE_PRIVATE;
import static com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice.PREFS;
import static com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice.PREF_KEY_INTERACTED_PACKAGES;
import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI;
import static com.android.settings.slices.CustomSliceRegistry.FLASHLIGHT_SLICE_URI;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.util.ArraySet;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
import androidx.slice.builders.ListBuilder;
import androidx.slice.builders.SliceAction;
import androidx.slice.widget.SliceLiveData;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.applications.AppInfoBase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
public class ContextualCardFeatureProviderImplTest {
private Context mContext;
private ContextualCardFeatureProviderImpl mImpl;
private SharedPreferences mSharedPreferences;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mImpl = new ContextualCardFeatureProviderImpl(mContext);
mSharedPreferences = mContext.getSharedPreferences(PREFS, MODE_PRIVATE);
// Set-up specs for SliceMetadata.
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
}
@After
public void tearDown() {
removeInteractedPackageFromSharedPreference();
}
@Test
public void logNotificationPackage_isContextualNotificationChannel_shouldLogPackage() {
final String packageName = "com.android.test.app";
final Slice slice = buildSlice(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI, packageName);
mImpl.logNotificationPackage(slice);
final Set<String> interactedPackages = mSharedPreferences.getStringSet(
PREF_KEY_INTERACTED_PACKAGES, new ArraySet<>());
assertThat(interactedPackages.contains(packageName)).isTrue();
}
@Test
public void logNotificationPackage_isNotContextualNotificationChannel_shouldNotLogPackage() {
final String packageName = "com.android.test.app";
final Slice slice = buildSlice(FLASHLIGHT_SLICE_URI, packageName);
mImpl.logNotificationPackage(slice);
final Set<String> interactedPackages = mSharedPreferences.getStringSet(
PREF_KEY_INTERACTED_PACKAGES, new ArraySet<>());
assertThat(interactedPackages.contains(packageName)).isFalse();
}
private Slice buildSlice(Uri sliceUri, String packageName) {
final Bundle args = new Bundle();
args.putString(AppInfoBase.ARG_PACKAGE_NAME, packageName);
final Intent intent = new Intent("action");
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
final PendingIntent pendingIntent = spy(
PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */));
doReturn(intent).when(pendingIntent).getIntent();
final IconCompat icon = IconCompat.createWithResource(mContext, R.drawable.empty_icon);
final SliceAction action = SliceAction.createDeeplink(pendingIntent, icon,
ListBuilder.SMALL_IMAGE, "title");
return new ListBuilder(mContext, sliceUri, ListBuilder.INFINITY)
.addRow(new ListBuilder.RowBuilder()
.addEndItem(icon, ListBuilder.ICON_IMAGE)
.setTitle("title")
.setPrimaryAction(action))
.build();
}
private void removeInteractedPackageFromSharedPreference() {
if (mSharedPreferences.contains(PREF_KEY_INTERACTED_PACKAGES)) {
mSharedPreferences.edit().remove(PREF_KEY_INTERACTED_PACKAGES).apply();
}
}
}

View File

@@ -16,30 +16,49 @@
package com.android.settings.homepage.contextualcards.slices;
import static android.content.Context.MODE_PRIVATE;
import static com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice.PREFS;
import static com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice.PREF_KEY_INTERACTED_PACKAGES;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.Uri;
import android.util.ArraySet;
import com.android.settings.R;
import com.android.settings.slices.CustomSliceRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
public class ContextualNotificationChannelSliceTest {
private static final String PACKAGE_NAME = "package_name";
private Context mContext;
private ContextualNotificationChannelSlice mNotificationChannelSlice;
private SharedPreferences mSharedPreferences;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mNotificationChannelSlice = new ContextualNotificationChannelSlice(mContext);
mSharedPreferences = mContext.getSharedPreferences(PREFS, MODE_PRIVATE);
}
@After
public void tearDown() {
removeInteractedPackageFromSharedPreference();
}
@Test
@@ -55,4 +74,34 @@ public class ContextualNotificationChannelSliceTest {
assertThat(subTitle).isEqualTo(mContext.getText(R.string.recently_installed_app));
}
@Test
public void isUserInteracted_hasInteractedPackage_shouldBeTrue() {
addInteractedPackageToSharedPreference();
final boolean isInteracted = mNotificationChannelSlice.isUserInteracted(PACKAGE_NAME);
assertThat(isInteracted).isTrue();
}
@Test
public void isUserInteracted_noInteractedPackage_shouldBeFalse() {
final boolean isInteracted = mNotificationChannelSlice.isUserInteracted(PACKAGE_NAME);
assertThat(isInteracted).isFalse();
}
private void addInteractedPackageToSharedPreference() {
final Set<String> interactedPackages = new ArraySet<>();
interactedPackages.add(PACKAGE_NAME);
mSharedPreferences.edit().putStringSet(PREF_KEY_INTERACTED_PACKAGES,
interactedPackages).apply();
}
private void removeInteractedPackageFromSharedPreference() {
if (mSharedPreferences.contains(PREF_KEY_INTERACTED_PACKAGES)) {
mSharedPreferences.edit().remove(PREF_KEY_INTERACTED_PACKAGES).apply();
}
}
}

View File

@@ -26,7 +26,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.app.NotificationChannel;
@@ -299,6 +298,21 @@ public class NotificationChannelSliceTest {
assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.no_suggested_app));
}
@Test
@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
public void getSlice_isInteractedPackage_shouldHaveNoSuggestedAppTitle() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
false /* isChannelBlocked */);
doReturn(true).when(mNotificationChannelSlice).isUserInteracted(any(String.class));
final Slice slice = mNotificationChannelSlice.getSlice();
final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.no_suggested_app));
}
private void addMockPackageToPackageManager(boolean isRecentlyInstalled, int flags) {
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.name = APP_LABEL;

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2019 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.homepage.contextualcards.slices;
import static android.content.Context.MODE_PRIVATE;
import static com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice.PREFS;
import static com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice.PREF_KEY_INTERACTED_PACKAGES;
import static com.google.common.truth.Truth.assertThat;
import static org.robolectric.Shadows.shadowOf;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.util.ArraySet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowPackageManager;
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
public class NotificationChannelWorkerTest {
private static final Uri URI = Uri.parse("content://com.android.settings.slices/test");
private static final String PACKAGE_NAME = "com.test.notification.channel.slice";
private Context mContext;
private NotificationChannelWorker mNotificationChannelWorker;
private ShadowPackageManager mPackageManager;
private SharedPreferences mSharedPreferences;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mNotificationChannelWorker = new NotificationChannelWorker(mContext, URI);
// Shadow PackageManager to add mock package.
mPackageManager = shadowOf(mContext.getPackageManager());
mSharedPreferences = mContext.getSharedPreferences(PREFS, MODE_PRIVATE);
addInteractedPackageToSharedPreference();
}
@After
public void tearDown() {
mPackageManager.removePackage(PACKAGE_NAME);
removeInteractedPackageFromSharedPreference();
}
@Test
public void onSliceUnpinned_interactedPackageIsUninstalled_shouldRemovePackage() {
mNotificationChannelWorker.onSliceUnpinned();
final Set<String> interactedPackages = mSharedPreferences.getStringSet(
PREF_KEY_INTERACTED_PACKAGES, new ArraySet<>());
assertThat(interactedPackages.contains(PACKAGE_NAME)).isFalse();
}
@Test
public void onSliceUnpinned_interactedPackageIsInstalled_shouldKeepPackage() {
mockInteractedPackageAsInstalled();
mNotificationChannelWorker.onSliceUnpinned();
final Set<String> interactedPackages = mSharedPreferences.getStringSet(
PREF_KEY_INTERACTED_PACKAGES, new ArraySet<>());
assertThat(interactedPackages.contains(PACKAGE_NAME)).isTrue();
}
private void mockInteractedPackageAsInstalled() {
final PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = PACKAGE_NAME;
mPackageManager.addPackage(packageInfo);
}
private void addInteractedPackageToSharedPreference() {
final Set<String> interactedPackages = new ArraySet<>();
interactedPackages.add(PACKAGE_NAME);
mSharedPreferences.edit().putStringSet(PREF_KEY_INTERACTED_PACKAGES,
interactedPackages).apply();
}
private void removeInteractedPackageFromSharedPreference() {
if (mSharedPreferences.contains(PREF_KEY_INTERACTED_PACKAGES)) {
mSharedPreferences.edit().remove(PREF_KEY_INTERACTED_PACKAGES).apply();
}
}
}