Restrict toggle/slider slice when the preference restricted

Bug: 289980550
Test: robotest & manual
Change-Id: Id87fbf12a2722344dd07886e810e7c61a9f401aa
This commit is contained in:
Edgar Wang
2023-07-05 17:10:34 +08:00
parent 1ac510e4b1
commit ab75ea8099
9 changed files with 125 additions and 15 deletions

View File

@@ -36,6 +36,7 @@
android:icon="@drawable/ic_media_stream" android:icon="@drawable/ic_media_stream"
android:title="@string/media_volume_option_title" android:title="@string/media_volume_option_title"
android:order="-180" android:order="-180"
settings:userRestriction="no_adjust_volume"
settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/> settings:controller="com.android.settings.notification.MediaVolumePreferenceController"/>
<!-- Media output switcher --> <!-- Media output switcher -->
@@ -53,6 +54,7 @@
android:icon="@drawable/ic_local_phone_24_lib" android:icon="@drawable/ic_local_phone_24_lib"
android:title="@string/call_volume_option_title" android:title="@string/call_volume_option_title"
android:order="-170" android:order="-170"
settings:userRestriction="no_adjust_volume"
settings:controller="com.android.settings.notification.CallVolumePreferenceController"/> settings:controller="com.android.settings.notification.CallVolumePreferenceController"/>
<!-- Hands free profile output switcher --> <!-- Hands free profile output switcher -->
@@ -70,6 +72,7 @@
android:icon="@drawable/ic_ring_volume" android:icon="@drawable/ic_ring_volume"
android:title="@string/separate_ring_volume_option_title" android:title="@string/separate_ring_volume_option_title"
android:order="-155" android:order="-155"
settings:userRestriction="no_adjust_volume"
settings:controller="com.android.settings.notification.SeparateRingVolumePreferenceController"/> settings:controller="com.android.settings.notification.SeparateRingVolumePreferenceController"/>
<!-- Notification volume --> <!-- Notification volume -->
@@ -78,6 +81,7 @@
android:icon="@drawable/ic_notifications" android:icon="@drawable/ic_notifications"
android:title="@string/notification_volume_option_title" android:title="@string/notification_volume_option_title"
android:order="-150" android:order="-150"
settings:userRestriction="no_adjust_volume"
settings:controller="com.android.settings.notification.NotificationVolumePreferenceController" settings:controller="com.android.settings.notification.NotificationVolumePreferenceController"
settings:unavailableSliceSubtitle="@string/notification_volume_disabled_summary"/> settings:unavailableSliceSubtitle="@string/notification_volume_disabled_summary"/>
@@ -87,6 +91,7 @@
android:icon="@*android:drawable/ic_audio_alarm" android:icon="@*android:drawable/ic_audio_alarm"
android:title="@string/alarm_volume_option_title" android:title="@string/alarm_volume_option_title"
android:order="-140" android:order="-140"
settings:userRestriction="no_adjust_volume"
settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/> settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
<!-- TODO(b/174964721): make this a PrimarySwitchPreference --> <!-- TODO(b/174964721): make this a PrimarySwitchPreference -->

View File

@@ -74,7 +74,8 @@ public class PreferenceXmlParserUtils {
MetadataFlag.FLAG_NEED_SEARCHABLE, MetadataFlag.FLAG_NEED_SEARCHABLE,
MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE, MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE,
MetadataFlag.FLAG_FOR_WORK, MetadataFlag.FLAG_FOR_WORK,
MetadataFlag.FLAG_NEED_HIGHLIGHTABLE_MENU_KEY}) MetadataFlag.FLAG_NEED_HIGHLIGHTABLE_MENU_KEY,
MetadataFlag.FLAG_NEED_USER_RESTRICTION})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface MetadataFlag { public @interface MetadataFlag {
@@ -91,6 +92,7 @@ public class PreferenceXmlParserUtils {
int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 11; int FLAG_UNAVAILABLE_SLICE_SUBTITLE = 1 << 11;
int FLAG_FOR_WORK = 1 << 12; int FLAG_FOR_WORK = 1 << 12;
int FLAG_NEED_HIGHLIGHTABLE_MENU_KEY = 1 << 13; int FLAG_NEED_HIGHLIGHTABLE_MENU_KEY = 1 << 13;
int FLAG_NEED_USER_RESTRICTION = 1 << 14;
} }
public static final String METADATA_PREF_TYPE = "type"; public static final String METADATA_PREF_TYPE = "type";
@@ -105,6 +107,7 @@ public class PreferenceXmlParserUtils {
public static final String METADATA_UNAVAILABLE_SLICE_SUBTITLE = "unavailable_slice_subtitle"; public static final String METADATA_UNAVAILABLE_SLICE_SUBTITLE = "unavailable_slice_subtitle";
public static final String METADATA_FOR_WORK = "for_work"; public static final String METADATA_FOR_WORK = "for_work";
public static final String METADATA_HIGHLIGHTABLE_MENU_KEY = "highlightable_menu_key"; public static final String METADATA_HIGHLIGHTABLE_MENU_KEY = "highlightable_menu_key";
public static final String METADATA_USER_RESTRICTION = "userRestriction";
private static final String ENTRIES_SEPARATOR = "|"; private static final String ENTRIES_SEPARATOR = "|";
@@ -257,9 +260,16 @@ public class PreferenceXmlParserUtils {
preferenceMetadata.putString(METADATA_HIGHLIGHTABLE_MENU_KEY, preferenceMetadata.putString(METADATA_HIGHLIGHTABLE_MENU_KEY,
getHighlightableMenuKey(preferenceAttributes)); getHighlightableMenuKey(preferenceAttributes));
} }
if (hasFlag(flags, MetadataFlag.FLAG_NEED_USER_RESTRICTION)) {
preferenceMetadata.putString(METADATA_USER_RESTRICTION,
getUserRestriction(context, attrs));
}
metadata.add(preferenceMetadata); metadata.add(preferenceMetadata);
preferenceAttributes.recycle(); preferenceAttributes.recycle();
if (preferenceScreenAttributes != null) {
preferenceScreenAttributes.recycle();
}
} while ((type = parser.next()) != XmlPullParser.END_DOCUMENT } while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)); && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
parser.close(); parser.close();
@@ -351,4 +361,13 @@ public class PreferenceXmlParserUtils {
return styledAttributes.getBoolean( return styledAttributes.getBoolean(
R.styleable.Preference_forWork, false); R.styleable.Preference_forWork, false);
} }
private static String getUserRestriction(Context context, AttributeSet attrs) {
TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
R.styleable.RestrictedPreference);
String userRestriction = preferenceAttributes.getString(
R.styleable.RestrictedPreference_userRestriction);
preferenceAttributes.recycle();
return userRestriction;
}
} }

View File

@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle;
import android.provider.SettingsSlicesContract; import android.provider.SettingsSlicesContract;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet; import android.util.ArraySet;
@@ -50,6 +51,8 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController; import com.android.settings.core.SliderPreferenceController;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Arrays; import java.util.Arrays;
@@ -86,6 +89,16 @@ public class SliceBuilderUtils {
return buildUnavailableSlice(context, sliceData); return buildUnavailableSlice(context, sliceData);
} }
String userRestriction = sliceData.getUserRestriction();
if (!TextUtils.isEmpty(userRestriction)) {
RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
userRestriction, UserHandle.myUserId());
if (admin != null) {
return buildIntentSlice(context, sliceData, controller);
}
}
switch (sliceData.getSliceType()) { switch (sliceData.getSliceType()) {
case SliceData.SliceType.INTENT: case SliceData.SliceType.INTENT:
return buildIntentSlice(context, sliceData, controller); return buildIntentSlice(context, sliceData, controller);

View File

@@ -73,6 +73,8 @@ public class SliceData {
private final int mHighlightMenuRes; private final int mHighlightMenuRes;
private final String mUserRestriction;
@SliceType @SliceType
private final int mSliceType; private final int mSliceType;
@@ -132,6 +134,10 @@ public class SliceData {
return mIsPublicSlice; return mIsPublicSlice;
} }
public String getUserRestriction() {
return mUserRestriction;
}
private SliceData(Builder builder) { private SliceData(Builder builder) {
mKey = builder.mKey; mKey = builder.mKey;
mTitle = builder.mTitle; mTitle = builder.mTitle;
@@ -146,6 +152,7 @@ public class SliceData {
mUnavailableSliceSubtitle = builder.mUnavailableSliceSubtitle; mUnavailableSliceSubtitle = builder.mUnavailableSliceSubtitle;
mIsPublicSlice = builder.mIsPublicSlice; mIsPublicSlice = builder.mIsPublicSlice;
mHighlightMenuRes = builder.mHighlightMenuRes; mHighlightMenuRes = builder.mHighlightMenuRes;
mUserRestriction = builder.mUserRestriction;
} }
@Override @Override
@@ -189,6 +196,8 @@ public class SliceData {
private boolean mIsPublicSlice; private boolean mIsPublicSlice;
private String mUserRestriction;
public Builder setKey(String key) { public Builder setKey(String key) {
mKey = key; mKey = key;
return this; return this;
@@ -255,6 +264,11 @@ public class SliceData {
return this; return this;
} }
public Builder setUserRestriction(String userRestriction) {
mUserRestriction = userRestriction;
return this;
}
public SliceData build() { public SliceData build() {
if (TextUtils.isEmpty(mKey)) { if (TextUtils.isEmpty(mKey)) {
throw new InvalidSliceDataException("Key cannot be empty"); throw new InvalidSliceDataException("Key cannot be empty");

View File

@@ -22,6 +22,7 @@ import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_UNAVAILABLE_SLICE_SUBTITLE; import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_UNAVAILABLE_SLICE_SUBTITLE;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_USER_RESTRICTION;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
@@ -189,7 +190,8 @@ class SliceDataConverter {
| MetadataFlag.FLAG_NEED_PREF_TITLE | MetadataFlag.FLAG_NEED_PREF_TITLE
| MetadataFlag.FLAG_NEED_PREF_ICON | MetadataFlag.FLAG_NEED_PREF_ICON
| MetadataFlag.FLAG_NEED_PREF_SUMMARY | MetadataFlag.FLAG_NEED_PREF_SUMMARY
| MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE); | MetadataFlag.FLAG_UNAVAILABLE_SLICE_SUBTITLE
| MetadataFlag.FLAG_NEED_USER_RESTRICTION);
for (Bundle bundle : metadata) { for (Bundle bundle : metadata) {
// TODO (b/67996923) Non-controller Slices should become intent-only slices. // TODO (b/67996923) Non-controller Slices should become intent-only slices.
@@ -218,6 +220,7 @@ class SliceDataConverter {
METADATA_UNAVAILABLE_SLICE_SUBTITLE); METADATA_UNAVAILABLE_SLICE_SUBTITLE);
final boolean isPublicSlice = controller.isPublicSlice(); final boolean isPublicSlice = controller.isPublicSlice();
final int highlightMenuRes = controller.getSliceHighlightMenuRes(); final int highlightMenuRes = controller.getSliceHighlightMenuRes();
final String userRestriction = bundle.getString(METADATA_USER_RESTRICTION);
final SliceData xmlSlice = new SliceData.Builder() final SliceData xmlSlice = new SliceData.Builder()
.setKey(key) .setKey(key)
@@ -232,6 +235,7 @@ class SliceDataConverter {
.setUnavailableSliceSubtitle(unavailableSliceSubtitle) .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
.setIsPublicSlice(isPublicSlice) .setIsPublicSlice(isPublicSlice)
.setHighlightMenuRes(highlightMenuRes) .setHighlightMenuRes(highlightMenuRes)
.setUserRestriction(userRestriction)
.build(); .build();
xmlSliceData.add(xmlSlice); xmlSliceData.add(xmlSlice);

View File

@@ -51,6 +51,7 @@ public class SlicesDatabaseAccessor {
IndexColumns.SLICE_TYPE, IndexColumns.SLICE_TYPE,
IndexColumns.UNAVAILABLE_SLICE_SUBTITLE, IndexColumns.UNAVAILABLE_SLICE_SUBTITLE,
IndexColumns.HIGHLIGHT_MENU_RESOURCE, IndexColumns.HIGHLIGHT_MENU_RESOURCE,
IndexColumns.USER_RESTRICTION,
}; };
private final Context mContext; private final Context mContext;
@@ -166,6 +167,8 @@ public class SlicesDatabaseAccessor {
cursor.getColumnIndex(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE)); cursor.getColumnIndex(IndexColumns.UNAVAILABLE_SLICE_SUBTITLE));
final int highlightMenuRes = cursor.getInt( final int highlightMenuRes = cursor.getInt(
cursor.getColumnIndex(IndexColumns.HIGHLIGHT_MENU_RESOURCE)); cursor.getColumnIndex(IndexColumns.HIGHLIGHT_MENU_RESOURCE));
final String userRestriction = cursor.getString(
cursor.getColumnIndex(IndexColumns.USER_RESTRICTION));
if (isIntentOnly) { if (isIntentOnly) {
sliceType = SliceData.SliceType.INTENT; sliceType = SliceData.SliceType.INTENT;
@@ -184,6 +187,7 @@ public class SlicesDatabaseAccessor {
.setSliceType(sliceType) .setSliceType(sliceType)
.setUnavailableSliceSubtitle(unavailableSliceSubtitle) .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
.setHighlightMenuRes(highlightMenuRes) .setHighlightMenuRes(highlightMenuRes)
.setUserRestriction(userRestriction)
.build(); .build();
} }

View File

@@ -36,7 +36,7 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "slices_index.db"; private static final String DATABASE_NAME = "slices_index.db";
private static final String SHARED_PREFS_TAG = "slices_shared_prefs"; private static final String SHARED_PREFS_TAG = "slices_shared_prefs";
private static final int DATABASE_VERSION = 9; private static final int DATABASE_VERSION = 10;
public interface Tables { public interface Tables {
String TABLE_SLICES_INDEX = "slices_index"; String TABLE_SLICES_INDEX = "slices_index";
@@ -108,6 +108,11 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper {
* Resource ID for the menu entry of the setting. * Resource ID for the menu entry of the setting.
*/ */
String HIGHLIGHT_MENU_RESOURCE = "highlight_menu"; String HIGHLIGHT_MENU_RESOURCE = "highlight_menu";
/**
* The name of user restriction for the setting.
*/
String USER_RESTRICTION = "user_restriction";
} }
private static final String CREATE_SLICES_TABLE = private static final String CREATE_SLICES_TABLE =
@@ -138,6 +143,8 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper {
+ IndexColumns.PUBLIC_SLICE + IndexColumns.PUBLIC_SLICE
+ ", " + ", "
+ IndexColumns.HIGHLIGHT_MENU_RESOURCE + IndexColumns.HIGHLIGHT_MENU_RESOURCE
+ ", "
+ IndexColumns.USER_RESTRICTION
+ " INTEGER DEFAULT 0 " + " INTEGER DEFAULT 0 "
+ ");"; + ");";

View File

@@ -117,6 +117,7 @@ class SlicesIndexer implements Runnable {
dataRow.getUnavailableSliceSubtitle()); dataRow.getUnavailableSliceSubtitle());
values.put(IndexColumns.PUBLIC_SLICE, dataRow.isPublicSlice()); values.put(IndexColumns.PUBLIC_SLICE, dataRow.isPublicSlice());
values.put(IndexColumns.HIGHLIGHT_MENU_RESOURCE, dataRow.getHighlightMenuRes()); values.put(IndexColumns.HIGHLIGHT_MENU_RESOURCE, dataRow.getHighlightMenuRes());
values.put(IndexColumns.USER_RESTRICTION, dataRow.getUserRestriction());
database.replaceOrThrow(Tables.TABLE_SLICES_INDEX, null /* nullColumnHack */, database.replaceOrThrow(Tables.TABLE_SLICES_INDEX, null /* nullColumnHack */,
values); values);

View File

@@ -42,28 +42,33 @@ import com.android.settings.testutils.FakeSliderController;
import com.android.settings.testutils.FakeToggleController; import com.android.settings.testutils.FakeToggleController;
import com.android.settings.testutils.FakeUnavailablePreferenceController; import com.android.settings.testutils.FakeUnavailablePreferenceController;
import com.android.settings.testutils.SliceTester; import com.android.settings.testutils.SliceTester;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
public class SliceBuilderUtilsTest { public class SliceBuilderUtilsTest {
private final String KEY = "KEY"; private static final String KEY = "KEY";
private final String TITLE = "title"; private static final String TITLE = "title";
private final String SUMMARY = "summary"; private static final String SUMMARY = "summary";
private final String SCREEN_TITLE = "screen title"; private static final String SCREEN_TITLE = "screen title";
private final String KEYWORDS = "a, b, c"; private static final String KEYWORDS = "a, b, c";
private final String FRAGMENT_NAME = "fragment name"; private static final String FRAGMENT_NAME = "fragment name";
private final int ICON = R.drawable.ic_settings_accent; private static final String RESTRICTION = "no_brightness";
private final Uri URI = Uri.parse("content://com.android.settings.slices/test"); private static final int ICON = R.drawable.ic_settings_accent;
private final Class TOGGLE_CONTROLLER = FakeToggleController.class; private static final Uri URI = Uri.parse("content://com.android.settings.slices/test");
private final Class SLIDER_CONTROLLER = FakeSliderController.class; private static final Class TOGGLE_CONTROLLER = FakeToggleController.class;
private final Class INVALID_SLIDER_CONTROLLER = FakeInvalidSliderController.class; private static final Class SLIDER_CONTROLLER = FakeSliderController.class;
private final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class; private static final Class INVALID_SLIDER_CONTROLLER = FakeInvalidSliderController.class;
private static final Class CONTEXT_CONTROLLER = FakeContextOnlyPreferenceController.class;
private Context mContext; private Context mContext;
@@ -74,6 +79,11 @@ public class SliceBuilderUtilsTest {
SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS); SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
} }
@After
public void tearDown() {
ShadowRestrictedLockUtilsInternal.reset();
}
@Test @Test
public void buildIntentSlice_returnsMatchingSlice() { public void buildIntentSlice_returnsMatchingSlice() {
final SliceData sliceData = getMockData(CONTEXT_CONTROLLER, SliceData.SliceType.INTENT); final SliceData sliceData = getMockData(CONTEXT_CONTROLLER, SliceData.SliceType.INTENT);
@@ -98,6 +108,27 @@ public class SliceBuilderUtilsTest {
SliceTester.testSettingsSliderSlice(mContext, slice, data); SliceTester.testSettingsSliderSlice(mContext, slice, data);
} }
@Test
public void buildToggleSlice_withUserRestriction_shouldReturnToggleSlice() {
final SliceData mockData = getMockData(TOGGLE_CONTROLLER, SliceData.SliceType.SWITCH,
RESTRICTION);
final Slice slice = SliceBuilderUtils.buildSlice(mContext, mockData);
SliceTester.testSettingsToggleSlice(mContext, slice, mockData);
}
@Test
public void buildToggleSlice_withUserRestrictionAndRestricted_shouldReturnIntentSlice() {
final SliceData mockData = getMockData(TOGGLE_CONTROLLER, SliceData.SliceType.SWITCH,
RESTRICTION);
ShadowRestrictedLockUtilsInternal.setRestricted(true);
final Slice slice = SliceBuilderUtils.buildSlice(mContext, mockData);
SliceTester.testSettingsIntentSlice(mContext, slice, mockData);
}
@Test @Test
public void testGetPreferenceController_buildsMatchingController() { public void testGetPreferenceController_buildsMatchingController() {
final BasePreferenceController controller = final BasePreferenceController controller =
@@ -425,8 +456,19 @@ public class SliceBuilderUtilsTest {
null /* unavailableSliceSubtitle */); null /* unavailableSliceSubtitle */);
} }
private SliceData getMockData(Class prefController, int sliceType, String userRestriction) {
return getMockData(prefController, SUMMARY, sliceType, SCREEN_TITLE, ICON,
null /* unavailableSliceSubtitle */, userRestriction);
}
private SliceData getMockData(Class prefController, String summary, int sliceType, private SliceData getMockData(Class prefController, String summary, int sliceType,
String screenTitle, int icon, String unavailableSliceSubtitle) { String screenTitle, int icon, String unavailableSliceSubtitle) {
return getMockData(prefController, summary, sliceType, screenTitle, icon,
unavailableSliceSubtitle, null /* userRestriction */);
}
private SliceData getMockData(Class prefController, String summary, int sliceType,
String screenTitle, int icon, String unavailableSliceSubtitle, String userRestriction) {
return new SliceData.Builder() return new SliceData.Builder()
.setKey(KEY) .setKey(KEY)
.setTitle(TITLE) .setTitle(TITLE)
@@ -439,6 +481,7 @@ public class SliceBuilderUtilsTest {
.setPreferenceControllerClassName(prefController.getName()) .setPreferenceControllerClassName(prefController.getName())
.setSliceType(sliceType) .setSliceType(sliceType)
.setUnavailableSliceSubtitle(unavailableSliceSubtitle) .setUnavailableSliceSubtitle(unavailableSliceSubtitle)
.setUserRestriction(userRestriction)
.build(); .build();
} }
} }