diff options
author | 2020-02-19 21:30:59 +0800 | |
---|---|---|
committer | 2020-02-24 23:07:01 +0800 | |
commit | dd4d763019a84c2e8412f45251b0885956941f5c (patch) | |
tree | 4e457b3ef53768f630f5bbfc59bbd0ef53a97a43 | |
parent | b629d69db047c40f2b110f2d73ad8ceb1b32ea68 (diff) |
Refine the SchedulesProvider
Bug: 148995400
Test: make RunSettingsLibRoboTests -j56
Change-Id: I84dfa571eefffa74f49ed861fba7a49d1b50c659
5 files changed, 327 insertions, 43 deletions
diff --git a/packages/SettingsLib/SchedulesProvider/res/values/config.xml b/packages/SettingsLib/SchedulesProvider/res/values/config.xml new file mode 100644 index 000000000000..48f3e3ef4542 --- /dev/null +++ b/packages/SettingsLib/SchedulesProvider/res/values/config.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 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. +--> +<resources> + <!-- Package name for the caller of the Schedules provider. --> + <string name="config_schedules_provider_caller_package" translatable="false">com.android.settings</string> +</resources>
\ No newline at end of file diff --git a/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/ScheduleInfo.java b/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/ScheduleInfo.java index 7d2b8e2878d6..26bcd54930b6 100644 --- a/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/ScheduleInfo.java +++ b/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/ScheduleInfo.java @@ -24,9 +24,9 @@ import android.text.TextUtils; import androidx.annotation.NonNull; /** - * This is a schedule data item. It contains the schedule title text, the summary text which - * displays on the summary of the Settings preference and an {@link Intent}. Intent is able to - * launch the editing page of the schedule data when user clicks this item (preference). + * Schedule data item containing the schedule title text, the summary text which is displayed on the + * summary of the Settings preference and an {@link Intent} which Settings will launch when the + * user clicks on the preference. */ public class ScheduleInfo implements Parcelable { private static final String TAG = "ScheduleInfo"; @@ -40,7 +40,7 @@ public class ScheduleInfo implements Parcelable { mIntent = builder.mIntent; } - protected ScheduleInfo(Parcel in) { + private ScheduleInfo(Parcel in) { mTitle = in.readString(); mSummary = in.readString(); mIntent = in.readParcelable(Intent.class.getClassLoader()); @@ -48,8 +48,6 @@ public class ScheduleInfo implements Parcelable { /** * Returns the title text. - * - * @return The title. */ public String getTitle() { return mTitle; @@ -57,15 +55,14 @@ public class ScheduleInfo implements Parcelable { /** * Returns the summary text. - * - * @return The summary. */ public String getSummary() { return mSummary; } /** - * Returns an {@link Intent}. + * Returns an {@link Intent} which Settings will launch when the user clicks on a schedule + * preference. */ public Intent getIntent() { return mIntent; @@ -107,19 +104,15 @@ public class ScheduleInfo implements Parcelable { @NonNull @Override public String toString() { - return "title : " + mTitle + " summary : " + mSummary + (mIntent == null - ? " and intent is null." : "."); + return "title: " + mTitle + ", summary: " + mSummary + ", intent: " + mIntent; } /** * A simple builder for {@link ScheduleInfo}. */ public static class Builder { - @NonNull private String mTitle; - @NonNull private String mSummary; - @NonNull private Intent mIntent; /** diff --git a/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/SchedulesProvider.java b/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/SchedulesProvider.java index a423e475d357..28d5f07cc51c 100644 --- a/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/SchedulesProvider.java +++ b/packages/SettingsLib/SchedulesProvider/src/com/android/settingslib/schedulesprovider/SchedulesProvider.java @@ -21,19 +21,18 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.ArrayList; -import java.util.List; import java.util.stream.Collectors; /** - * This provider is a bridge for client apps to provide the schedule data. - * Client provider needs to implement their {@link #getScheduleInfoList()} and returns a list of - * {@link ScheduleInfo}. + * A bridge for client apps to provide the schedule data. Client provider needs to implement + * {@link #getScheduleInfoList()} returning a list of {@link ScheduleInfo}. */ public abstract class SchedulesProvider extends ContentProvider { public static final String METHOD_GENERATE_SCHEDULE_INFO_LIST = "generateScheduleInfoList"; @@ -46,9 +45,8 @@ public abstract class SchedulesProvider extends ContentProvider { } @Override - public final Cursor query( - Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { + public final Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { throw new UnsupportedOperationException("Query operation is not supported currently."); } @@ -74,18 +72,24 @@ public abstract class SchedulesProvider extends ContentProvider { } /** - * Return the list of the schedule information. - * - * @return a list of the {@link ScheduleInfo}. + * Returns the list of the schedule information. */ public abstract ArrayList<ScheduleInfo> getScheduleInfoList(); /** - * Returns a bundle which contains a list of {@link ScheduleInfo} and data types: - * scheduleInfoList : ArrayList<ScheduleInfo> + * Returns a bundle which contains a list of {@link ScheduleInfo}s: + * + * <ul> + * <li>scheduleInfoList: ArrayList<ScheduleInfo> + * </ul> */ @Override public Bundle call(@NonNull String method, @Nullable String arg, @Nullable Bundle extras) { + if (!TextUtils.equals(getCallingPackage(), + getContext().getText(R.string.config_schedules_provider_caller_package))) { + return null; + } + final Bundle bundle = new Bundle(); if (METHOD_GENERATE_SCHEDULE_INFO_LIST.equals(method)) { final ArrayList<ScheduleInfo> scheduleInfoList = filterInvalidData( @@ -98,36 +102,40 @@ public abstract class SchedulesProvider extends ContentProvider { } /** - * To filter the invalid schedule info. + * Filters our invalid schedule infos from {@code schedulesInfoList}. * - * @param scheduleInfoList The list of the {@link ScheduleInfo}. - * @return The valid list of the {@link ScheduleInfo}. + * @return valid {@link SchedulesInfo}s if {@code schedulesInfoList} is not null. Otherwise, + * null. */ - private ArrayList<ScheduleInfo> filterInvalidData(ArrayList<ScheduleInfo> scheduleInfoList) { + @Nullable + private ArrayList<ScheduleInfo> filterInvalidData( + @Nullable ArrayList<ScheduleInfo> scheduleInfoList) { if (scheduleInfoList == null) { Log.d(TAG, "package : " + getContext().getPackageName() + " has no scheduling data."); return null; } // Dump invalid data in debug mode. if (SystemProperties.getInt("ro.debuggable", 0) == 1) { - new Thread(() -> { - dumpInvalidData(scheduleInfoList); - }).start(); + dumpInvalidData(scheduleInfoList); } - final List<ScheduleInfo> filteredList = scheduleInfoList + return scheduleInfoList .stream() - .filter(scheduleInfo -> scheduleInfo.isValid()) - .collect(Collectors.toList()); - - return new ArrayList<>(filteredList); + .filter(ScheduleInfo::isValid) + .collect(Collectors.toCollection(ArrayList::new)); } private void dumpInvalidData(ArrayList<ScheduleInfo> scheduleInfoList) { - Log.d(TAG, "package : " + getContext().getPackageName() - + " provided some scheduling data are invalid."); - scheduleInfoList + final boolean hasInvalidData = scheduleInfoList .stream() - .filter(scheduleInfo -> !scheduleInfo.isValid()) - .forEach(scheduleInfo -> Log.d(TAG, scheduleInfo.toString())); + .anyMatch(scheduleInfo -> !scheduleInfo.isValid()); + + if (hasInvalidData) { + Log.w(TAG, "package : " + getContext().getPackageName() + + " provided some scheduling data that are invalid."); + scheduleInfoList + .stream() + .filter(scheduleInfo -> !scheduleInfo.isValid()) + .forEach(scheduleInfo -> Log.w(TAG, scheduleInfo.toString())); + } } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/schedulesprovider/ScheduleInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/schedulesprovider/ScheduleInfoTest.java new file mode 100644 index 000000000000..5ec89eddda6e --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/schedulesprovider/ScheduleInfoTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2020 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.settingslib.schedulesprovider; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Intent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class ScheduleInfoTest { + private static final String TEST_TITLE = "Night Light"; + private static final String TEST_SUMMARY = "Night Light summary"; + private static final String TEST_EMPTY_SUMMARY = ""; + + @Test + public void builder_usedValidArguments_isValid() { + final Intent intent = createTestIntent(); + final ScheduleInfo info = createTestScheduleInfo(TEST_TITLE, TEST_SUMMARY, intent); + + assertThat(info).isNotNull(); + assertThat(info.isValid()).isTrue(); + } + + @Test + public void builder_useEmptySummary_isInvalid() { + final Intent intent = createTestIntent(); + final ScheduleInfo info = createTestScheduleInfo(TEST_TITLE, TEST_EMPTY_SUMMARY, intent); + + assertThat(info).isNotNull(); + assertThat(info.isValid()).isFalse(); + } + + @Test + public void builder_intentIsNull_isInvalid() { + final ScheduleInfo info = new ScheduleInfo.Builder() + .setTitle(TEST_TITLE) + .setSummary(TEST_SUMMARY) + .build(); + + assertThat(info).isNotNull(); + assertThat(info.isValid()).isFalse(); + } + + @Test + public void getTitle_setValidTitle_shouldReturnSameCorrectTitle() { + final Intent intent = createTestIntent(); + final ScheduleInfo info = createTestScheduleInfo(TEST_TITLE, TEST_SUMMARY, intent); + + assertThat(info.getTitle()).isEqualTo(TEST_TITLE); + } + + @Test + public void getSummary_setValidSummary_shouldReturnSameCorrectSummary() { + final Intent intent = createTestIntent(); + final ScheduleInfo info = createTestScheduleInfo(TEST_TITLE, TEST_SUMMARY, intent); + + assertThat(info.getSummary()).isEqualTo(TEST_SUMMARY); + } + + @Test + public void getIntent_setValidIntent_shouldReturnSameCorrectIntent() { + final Intent intent = createTestIntent(); + final ScheduleInfo info = createTestScheduleInfo(TEST_TITLE, TEST_SUMMARY, intent); + + assertThat(info.getIntent()).isEqualTo(intent); + } + + private static Intent createTestIntent() { + return new Intent("android.settings.NIGHT_DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + } + + private static ScheduleInfo createTestScheduleInfo(String title, String summary, + Intent intent) { + return new ScheduleInfo.Builder() + .setTitle(title) + .setSummary(summary) + .setIntent(intent) + .build(); + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/schedulesprovider/SchedulesProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/schedulesprovider/SchedulesProviderTest.java new file mode 100644 index 000000000000..eb2e8e055378 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/schedulesprovider/SchedulesProviderTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2020 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.settingslib.schedulesprovider; + +import static com.google.common.truth.Truth.assertThat; + +import static org.robolectric.Shadows.shadowOf; + +import android.content.Intent; +import android.os.Bundle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; + +import java.util.ArrayList; + +@RunWith(RobolectricTestRunner.class) +public class SchedulesProviderTest { + private static final String INVALID_PACKAGE = "com.android.sunny"; + private static final String VALID_PACKAGE = "com.android.settings"; + private static final String INVALID_METHOD = "queryTestData"; + private TestSchedulesProvider mProvider; + + @Before + public void setUp() { + mProvider = Robolectric.setupContentProvider(TestSchedulesProvider.class); + shadowOf(mProvider).setCallingPackage(VALID_PACKAGE); + mProvider.setScheduleInfos(TestSchedulesProvider.createOneValidScheduleInfo()); + } + + @Test + public void call_invalidCallingPkg_returnNull() { + shadowOf(mProvider).setCallingPackage(INVALID_PACKAGE); + + final Bundle bundle = mProvider.call(SchedulesProvider.METHOD_GENERATE_SCHEDULE_INFO_LIST, + null /* arg */, null /* extras */); + + assertThat(bundle).isNull(); + } + + @Test + public void call_invalidMethod_returnBundleWithoutScheduleInfoData() { + final Bundle bundle = mProvider.call(INVALID_METHOD, null /* arg */, null /* extras */); + + assertThat(bundle).isNotNull(); + assertThat(bundle.containsKey(SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST)).isFalse(); + } + + @Test + public void call_validMethod_returnScheduleInfoData() { + final Bundle bundle = mProvider.call(SchedulesProvider.METHOD_GENERATE_SCHEDULE_INFO_LIST, + null /* arg */, null /* extras */); + + assertThat(bundle).isNotNull(); + assertThat(bundle.containsKey(SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST)).isTrue(); + final ArrayList<ScheduleInfo> infos = bundle.getParcelableArrayList( + SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST); + assertThat(infos).hasSize(1); + } + + @Test + public void call_addTwoValidData_returnScheduleInfoData() { + mProvider.setScheduleInfos(TestSchedulesProvider.createTwoValidScheduleInfos()); + final Bundle bundle = mProvider.call(SchedulesProvider.METHOD_GENERATE_SCHEDULE_INFO_LIST, + null /* arg */, null /* extras */); + + assertThat(bundle).isNotNull(); + assertThat(bundle.containsKey(SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST)).isTrue(); + final ArrayList<ScheduleInfo> infos = bundle.getParcelableArrayList( + SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST); + assertThat(infos).hasSize(2); + } + + @Test + public void call_addTwoValidDataAndOneInvalidData_returnTwoScheduleInfoData() { + mProvider.setScheduleInfos(TestSchedulesProvider.createTwoValidAndOneInvalidScheduleInfo()); + final Bundle bundle = mProvider.call(SchedulesProvider.METHOD_GENERATE_SCHEDULE_INFO_LIST, + null /* arg */, null /* extras */); + + assertThat(bundle).isNotNull(); + assertThat(bundle.containsKey(SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST)).isTrue(); + final ArrayList<ScheduleInfo> infos = bundle.getParcelableArrayList( + SchedulesProvider.BUNDLE_SCHEDULE_INFO_LIST); + assertThat(infos).hasSize(2); + } + + private static class TestSchedulesProvider extends SchedulesProvider { + private ArrayList<ScheduleInfo> mScheduleInfos = new ArrayList<>(); + + @Override + public ArrayList<ScheduleInfo> getScheduleInfoList() { + return mScheduleInfos; + } + + void setScheduleInfos(ArrayList<ScheduleInfo> scheduleInfos) { + mScheduleInfos = scheduleInfos; + } + + private static ArrayList<ScheduleInfo> createOneValidScheduleInfo() { + final ArrayList<ScheduleInfo> scheduleInfos = new ArrayList<>(); + final Intent intent = new Intent("android.settings.NIGHT_DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + final ScheduleInfo info = new ScheduleInfo.Builder().setTitle( + "Night Light").setSummary("This a sunny test").setIntent(intent).build(); + scheduleInfos.add(info); + + return scheduleInfos; + } + + private static ArrayList<ScheduleInfo> createTwoValidScheduleInfos() { + final ArrayList<ScheduleInfo> scheduleInfos = new ArrayList<>(); + Intent intent = new Intent("android.settings.NIGHT_DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + ScheduleInfo info = new ScheduleInfo.Builder().setTitle( + "Night Light").setSummary("This a sunny test").setIntent(intent).build(); + scheduleInfos.add(info); + + intent = new Intent("android.settings.DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + info = new ScheduleInfo.Builder().setTitle("Display").setSummary( + "Display summary").setIntent(intent).build(); + scheduleInfos.add(info); + + return scheduleInfos; + } + + private static ArrayList<ScheduleInfo> createTwoValidAndOneInvalidScheduleInfo() { + final ArrayList<ScheduleInfo> scheduleInfos = new ArrayList<>(); + Intent intent = new Intent("android.settings.NIGHT_DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + ScheduleInfo info = new ScheduleInfo.Builder().setTitle( + "Night Light").setSummary("This a sunny test").setIntent(intent).build(); + scheduleInfos.add(info); + + intent = new Intent("android.settings.DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + info = new ScheduleInfo.Builder().setTitle("Display").setSummary( + "Display summary").setIntent(intent).build(); + scheduleInfos.add(info); + + intent = new Intent("android.settings.DISPLAY_SETTINGS").addCategory( + Intent.CATEGORY_DEFAULT); + info = new ScheduleInfo.Builder().setTitle("").setSummary("Display summary").setIntent( + intent).build(); + scheduleInfos.add(info); + + return scheduleInfos; + } + } +} |