Merge "Wake screen gesture"
diff --git a/res/drawable/ic_search_24dp.xml b/res/drawable/ic_search_24dp.xml
deleted file mode 100644
index d63711a..0000000
--- a/res/drawable/ic_search_24dp.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 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.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:fillColor="#FF000000"
- android:pathData="M20.49,19l-5.73,-5.73C15.53,12.2 16,10.91 16,9.5C16,5.91 13.09,3 9.5,3S3,5.91 3,9.5C3,13.09 5.91,16 9.5,16c1.41,0 2.7,-0.47 3.77,-1.24L19,20.49L20.49,19zM5,9.5C5,7.01 7.01,5 9.5,5S14,7.01 14,9.5S11.99,14 9.5,14S5,11.99 5,9.5z"/>
-</vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e5aea08..119e1fb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6903,8 +6903,6 @@
<!-- Search strings -->
<!-- Text to describe the search results fragment title [CHAR LIMIT=16] -->
<string name="search_results_title">Settings</string>
- <!-- Text used as a search hint into the search box -->
- <string name="search_menu">Search settings</string>
<!-- Search breadcrumb connector symbol -->
<string name="search_breadcrumb_connector" translatable="false">
<xliff:g name="first_item">%1$s</xliff:g> > <xliff:g name="second_item">%2$s</xliff:g>
@@ -9946,6 +9944,13 @@
<!-- UI debug setting: preference summary - describes the behavior of showing a dialog every time an app crashes [CHAR LIMIT=NONE] -->
<string name="show_first_crash_dialog_summary">Show dialog every time an app crashes</string>
+ <!-- UI debug setting: select current app to use ANGLE [CHAR LIMIT=100] -->
+ <string name="angle_enabled_app">Select ANGLE enabled app</string>
+ <!-- UI debug setting: no ANGLE enabled app has been set [CHAR LIMIT=100] -->
+ <string name="angle_enabled_app_not_set">No ANGLE enabled application set</string>
+ <!-- UI debug setting: ANGLE enabled app has been set [CHAR LIMIT=NONE] -->
+ <string name="angle_enabled_app_set">ANGLE enabled application: <xliff:g id="app_name" example="com.company.app">%1$s</xliff:g></string>
+
<!-- Title for Directory Access settings -->
<string name="directory_access">Directory access</string>
<!-- Keywords for Directory Access settings -->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 5b6d215..5a36463 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -424,6 +424,9 @@
android:summary="%s"
android:title="@string/simulate_color_space" />
+ <Preference android:key="angle_enabled_app"
+ android:title="@string/angle_enabled_app" />
+
</PreferenceCategory>
<PreferenceCategory
diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java
index 321cf74..a0cef3a 100644
--- a/src/com/android/settings/datausage/ChartDataUsagePreference.java
+++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java
@@ -24,7 +24,6 @@
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.FeatureFlagUtils;
-import android.util.Pair;
import android.util.SparseIntArray;
import androidx.annotation.VisibleForTesting;
@@ -35,6 +34,7 @@
import com.android.settings.Utils;
import com.android.settings.core.FeatureFlags;
import com.android.settings.widget.UsageView;
+import com.android.settingslib.net.NetworkCycleChartData;
import com.android.settingslib.net.NetworkCycleData;
import java.util.List;
@@ -53,7 +53,7 @@
private long mEnd;
@Deprecated
private NetworkStatsHistory mNetwork;
- private NetworkCycleData mNetworkCycleData;
+ private NetworkCycleChartData mNetworkCycleChartData;
private int mSecondaryColor;
private int mSeriesColor;
@@ -70,7 +70,7 @@
super.onBindViewHolder(holder);
final UsageView chart = (UsageView) holder.findViewById(R.id.data_usage);
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- if (mNetworkCycleData == null) {
+ if (mNetworkCycleChartData == null) {
return;
}
} else {
@@ -83,7 +83,7 @@
chart.clearPaths();
chart.configureGraph(toInt(mEnd - mStart), top);
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- calcPoints(chart, mNetworkCycleData.usageBuckets);
+ calcPoints(chart, mNetworkCycleChartData.getUsageBuckets());
} else {
calcPoints(chart);
}
@@ -98,7 +98,7 @@
public int getTop() {
long totalData = 0;
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_V2)) {
- totalData = mNetworkCycleData.totalUsage;
+ totalData = mNetworkCycleChartData.getTotalUsage();
} else {
NetworkStatsHistory.Entry entry = null;
final int start = mNetwork.getIndexBefore(mStart);
@@ -158,14 +158,14 @@
long totalData = 0;
for (NetworkCycleData data : usageSummary) {
- final long startTime = data.startTime;
- final long endTime = data.endTime;
+ final long startTime = data.getStartTime();
+ final long endTime = data.getEndTime();
// increment by current bucket total
- totalData += data.totalUsage;
+ totalData += data.getTotalUsage();
if (points.size() == 1) {
- points.put(toInt(data.startTime - mStart) - 1, -1);
+ points.put(toInt(startTime - mStart) - 1, -1);
}
points.put(toInt(startTime - mStart + 1), (int) (totalData / RESOLUTION));
points.put(toInt(endTime - mStart), (int) (totalData / RESOLUTION));
@@ -241,10 +241,10 @@
notifyChanged();
}
- public void setNetworkCycleData(NetworkCycleData data) {
- mNetworkCycleData = data;
- mStart = data.startTime;
- mEnd = data.endTime;
+ public void setNetworkCycleData(NetworkCycleChartData data) {
+ mNetworkCycleChartData = data;
+ mStart = data.getStartTime();
+ mEnd = data.getEndTime();
notifyChanged();
}
diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java
index bc4f649..9378dea 100644
--- a/src/com/android/settings/datausage/CycleAdapter.java
+++ b/src/com/android/settings/datausage/CycleAdapter.java
@@ -156,7 +156,7 @@
* Rebuild list based on network data. Always selects the newest item,
* updating the inspection range on chartData.
*/
- public boolean updateCycleList(List<NetworkCycleData> cycleData) {
+ public boolean updateCycleList(List<? extends NetworkCycleData> cycleData) {
// stash away currently selected cycle to try restoring below
final CycleAdapter.CycleItem previousItem = (CycleAdapter.CycleItem)
mSpinner.getSelectedItem();
@@ -164,7 +164,7 @@
final Context context = getContext();
for (NetworkCycleData data : cycleData) {
- add(new CycleAdapter.CycleItem(context, data.startTime, data.endTime));
+ add(new CycleAdapter.CycleItem(context, data.getStartTime(), data.getEndTime()));
}
// force pick the current cycle (first item)
diff --git a/src/com/android/settings/datausage/DataUsageListV2.java b/src/com/android/settings/datausage/DataUsageListV2.java
index 301eb44..ea652b3 100644
--- a/src/com/android/settings/datausage/DataUsageListV2.java
+++ b/src/com/android/settings/datausage/DataUsageListV2.java
@@ -61,8 +61,8 @@
import com.android.settings.widget.LoadingViewController;
import com.android.settingslib.AppItem;
import com.android.settingslib.net.ChartDataLoaderCompat;
-import com.android.settingslib.net.NetworkCycleDataLoader;
-import com.android.settingslib.net.NetworkCycleData;
+import com.android.settingslib.net.NetworkCycleChartDataLoader;
+import com.android.settingslib.net.NetworkCycleChartData;
import com.android.settingslib.net.NetworkStatsSummaryLoader;
import com.android.settingslib.net.UidDetailProvider;
@@ -107,7 +107,7 @@
int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@VisibleForTesting
int mNetworkType;
- private List<NetworkCycleData> mCycleData;
+ private List<NetworkCycleChartData> mCycleData;
private LoadingViewController mLoadingViewController;
private UidDetailProvider mUidDetailProvider;
@@ -322,7 +322,7 @@
mNetworkStatsDetailCallbacks);
final long totalBytes = mCycleData != null
- ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).totalUsage : 0;
+ ? mCycleData.get(mCycleSpinner.getSelectedItemPosition()).getTotalUsage() : 0;
final CharSequence totalPhrase = DataUsageUtils.formatDataUsage(getActivity(), totalBytes);
mUsageAmount.setTitle(getString(R.string.data_used_template, totalPhrase));
}
@@ -485,11 +485,11 @@
}
};
- private final LoaderCallbacks<List<NetworkCycleData>> mNetworkCycleDataCallbacks =
- new LoaderCallbacks<List<NetworkCycleData>>() {
+ private final LoaderCallbacks<List<NetworkCycleChartData>> mNetworkCycleDataCallbacks =
+ new LoaderCallbacks<List<NetworkCycleChartData>>() {
@Override
- public Loader<List<NetworkCycleData>> onCreateLoader(int id, Bundle args) {
- return new NetworkCycleDataLoader.Builder(getContext())
+ public Loader<List<NetworkCycleChartData>> onCreateLoader(int id, Bundle args) {
+ return NetworkCycleChartDataLoader.builder(getContext())
.setNetworkPolicy(services.mPolicyEditor.getPolicy(mTemplate))
.setNetworkType(mNetworkType)
.setNetworkTemplate(mTemplate)
@@ -498,8 +498,8 @@
}
@Override
- public void onLoadFinished(Loader<List<NetworkCycleData>> loader,
- List<NetworkCycleData> data) {
+ public void onLoadFinished(Loader<List<NetworkCycleChartData>> loader,
+ List<NetworkCycleChartData> data) {
mLoadingViewController.showContent(false /* animate */);
mCycleData = data;
// calculate policy cycles based on available data
@@ -507,7 +507,7 @@
}
@Override
- public void onLoaderReset(Loader<List<NetworkCycleData>> loader) {
+ public void onLoaderReset(Loader<List<NetworkCycleChartData>> loader) {
mCycleData = null;
}
};
diff --git a/src/com/android/settings/development/AngleEnabledAppPreferenceController.java b/src/com/android/settings/development/AngleEnabledAppPreferenceController.java
new file mode 100644
index 0000000..3a7f6bf
--- /dev/null
+++ b/src/com/android/settings/development/AngleEnabledAppPreferenceController.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 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.development;
+
+import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
+ .REQUEST_CODE_ANGLE_ENABLED_APP;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class AngleEnabledAppPreferenceController extends DeveloperOptionsPreferenceController
+ implements PreferenceControllerMixin, OnActivityResultListener {
+
+ private static final String ANGLE_ENABLED_APP_KEY = "angle_enabled_app";
+
+ private final DevelopmentSettingsDashboardFragment mFragment;
+ private final PackageManager mPackageManager;
+
+ public AngleEnabledAppPreferenceController(Context context,
+ DevelopmentSettingsDashboardFragment fragment) {
+ super(context);
+ mFragment = fragment;
+ mPackageManager = mContext.getPackageManager();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return ANGLE_ENABLED_APP_KEY;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (ANGLE_ENABLED_APP_KEY.equals(preference.getKey())) {
+ // pass it on to settings
+ final Intent intent = getActivityStartIntent();
+ mFragment.startActivityForResult(intent, REQUEST_CODE_ANGLE_ENABLED_APP);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ updatePreferenceSummary();
+ }
+
+ @Override
+ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode != REQUEST_CODE_ANGLE_ENABLED_APP || resultCode != Activity.RESULT_OK) {
+ return false;
+ }
+ Settings.Global.putString(mContext.getContentResolver(), Settings.Global.ANGLE_ENABLED_APP,
+ data.getAction());
+ updatePreferenceSummary();
+ return true;
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ mPreference.setSummary(mContext.getResources().getString(
+ R.string.angle_enabled_app_not_set));
+ }
+
+ @VisibleForTesting
+ Intent getActivityStartIntent() {
+ Intent intent = new Intent(mContext, AppPicker.class);
+ intent.putExtra(AppPicker.EXTRA_NON_SYSTEM, true /* value */);
+ return intent;
+ }
+
+ private void updatePreferenceSummary() {
+ final String angleEnabledApp = Settings.Global.getString(
+ mContext.getContentResolver(), Settings.Global.ANGLE_ENABLED_APP);
+ if (angleEnabledApp != null && angleEnabledApp.length() > 0) {
+ mPreference.setSummary(mContext.getResources().getString(
+ R.string.angle_enabled_app_set,
+ getAppLabel(angleEnabledApp)));
+ } else {
+ mPreference.setSummary(mContext.getResources().getString(
+ R.string.angle_enabled_app_not_set));
+ }
+ }
+
+ private String getAppLabel(String angleEnabledApp) {
+ try {
+ final ApplicationInfo ai = mPackageManager.getApplicationInfo(angleEnabledApp,
+ PackageManager.GET_DISABLED_COMPONENTS);
+ final CharSequence lab = mPackageManager.getApplicationLabel(ai);
+ return lab != null ? lab.toString() : angleEnabledApp;
+ } catch (PackageManager.NameNotFoundException e) {
+ return angleEnabledApp;
+ }
+ }
+}
diff --git a/src/com/android/settings/development/AppPicker.java b/src/com/android/settings/development/AppPicker.java
index 433f31a..04f318f 100644
--- a/src/com/android/settings/development/AppPicker.java
+++ b/src/com/android/settings/development/AppPicker.java
@@ -45,9 +45,11 @@
public static final String EXTRA_REQUESTIING_PERMISSION
= "com.android.settings.extra.REQUESTIING_PERMISSION";
public static final String EXTRA_DEBUGGABLE = "com.android.settings.extra.DEBUGGABLE";
+ public static final String EXTRA_NON_SYSTEM = "com.android.settings.extra.NON_SYSTEM";
private String mPermissionName;
private boolean mDebuggableOnly;
+ private boolean mNonSystemOnly;
@Override
protected void onCreate(Bundle icicle) {
@@ -55,6 +57,7 @@
mPermissionName = getIntent().getStringExtra(EXTRA_REQUESTIING_PERMISSION);
mDebuggableOnly = getIntent().getBooleanExtra(EXTRA_DEBUGGABLE, false);
+ mNonSystemOnly = getIntent().getBooleanExtra(EXTRA_NON_SYSTEM, false);
mAdapter = new AppListAdapter(this);
if (mAdapter.getCount() <= 0) {
@@ -113,6 +116,11 @@
}
}
+ // Filter out apps that are system apps if requested
+ if (mNonSystemOnly && ai.isSystemApp()) {
+ continue;
+ }
+
// Filter out apps that do not request the permission if required.
if (mPermissionName != null) {
boolean requestsPermission = false;
diff --git a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
index b7b2759..6e3ec93 100644
--- a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
+++ b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java
@@ -25,4 +25,6 @@
int REQUEST_CODE_DEBUG_APP = 1;
int REQUEST_MOCK_LOCATION_APP = 2;
+
+ int REQUEST_CODE_ANGLE_ENABLED_APP = 3;
}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 873cec4..cc8bd2e 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -405,6 +405,7 @@
controllers.add(new SelectDebugAppPreferenceController(context, fragment));
controllers.add(new WaitForDebuggerPreferenceController(context));
controllers.add(new EnableGpuDebugLayersPreferenceController(context));
+ controllers.add(new AngleEnabledAppPreferenceController(context, fragment));
controllers.add(new VerifyAppsOverUsbPreferenceController(context));
controllers.add(new LogdSizePreferenceController(context));
controllers.add(new LogPersistPreferenceController(context, fragment, lifecycle));
diff --git a/src/com/android/settings/homepage/CardContentLoader.java b/src/com/android/settings/homepage/CardContentLoader.java
index 9805ae3..5b81a23 100644
--- a/src/com/android/settings/homepage/CardContentLoader.java
+++ b/src/com/android/settings/homepage/CardContentLoader.java
@@ -17,16 +17,21 @@
package com.android.settings.homepage;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.Cursor;
+import android.util.Log;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import com.android.settings.homepage.deviceinfo.DataUsageSlice;
import com.android.settingslib.utils.AsyncLoaderCompat;
import java.util.ArrayList;
import java.util.List;
public class CardContentLoader extends AsyncLoaderCompat<List<ContextualCard>> {
+ private static final String TAG = "CardContentLoader";
static final int CARD_CONTENT_LOADER_ID = 1;
private Context mContext;
@@ -49,9 +54,9 @@
@Override
public List<ContextualCard> loadInBackground() {
final List<ContextualCard> result = new ArrayList<>();
- try (Cursor cursor = CardDatabaseHelper.getInstance(mContext).getContextualCards()) {
+ try (Cursor cursor = getContextualCardsFromProvider()) {
if (cursor.getCount() == 0) {
- //TODO(b/113372471): Load Default static cards and return 3 static cards
+ result.addAll(createStaticCards());
return result;
}
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
@@ -65,4 +70,58 @@
}
return result;
}
+
+ @VisibleForTesting
+ Cursor getContextualCardsFromProvider() {
+ return CardDatabaseHelper.getInstance(mContext).getContextualCards();
+ }
+
+ @VisibleForTesting
+ List<ContextualCard> createStaticCards() {
+ final long appVersionCode = getAppVersionCode();
+ final String packageName = mContext.getPackageName();
+ final double rankingScore = 0.0;
+ final List<ContextualCard> result = new ArrayList() {{
+ add(new ContextualCard.Builder()
+ .setSliceUri(DataUsageSlice.DATA_USAGE_CARD_URI.toString())
+ .setName(packageName + "/" + DataUsageSlice.PATH_DATA_USAGE_CARD)
+ .setPackageName(packageName)
+ .setRankingScore(rankingScore)
+ .setAppVersion(appVersionCode)
+ .setCardType(ContextualCard.CardType.SLICE)
+ .setIsHalfWidth(true)
+ .build());
+ //TODO(b/115971399): Will change following values of SliceUri and Name
+ // after landing these slice cards.
+ add(new ContextualCard.Builder()
+ .setSliceUri("content://com.android.settings.slices/intent/battery_card")
+ .setName(packageName + "/" + "battery_card")
+ .setPackageName(packageName)
+ .setRankingScore(rankingScore)
+ .setAppVersion(appVersionCode)
+ .setCardType(ContextualCard.CardType.SLICE)
+ .setIsHalfWidth(true)
+ .build());
+ add(new ContextualCard.Builder()
+ .setSliceUri("content://com.android.settings.slices/intent/device_info_card")
+ .setName(packageName + "/" + "device_info_card")
+ .setPackageName(packageName)
+ .setRankingScore(rankingScore)
+ .setAppVersion(appVersionCode)
+ .setCardType(ContextualCard.CardType.SLICE)
+ .setIsHalfWidth(true)
+ .build());
+ }};
+ return result;
+ }
+
+ private long getAppVersionCode() {
+ try {
+ return mContext.getPackageManager().getPackageInfo(mContext.getPackageName(),
+ 0 /* flags */).getLongVersionCode();
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Invalid package name for context", e);
+ }
+ return -1L;
+ }
}
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index c19ccef..ed26931 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -52,6 +52,7 @@
return "com.android.settings.intelligence";
}
+
/**
* Initializes the search toolbar.
*/
diff --git a/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java
new file mode 100644
index 0000000..03837c2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/AngleEnabledAppPreferenceControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2018 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.development;
+
+import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_CODE_ANGLE_ENABLED_APP;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AngleEnabledAppPreferenceControllerTest {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private DevelopmentSettingsDashboardFragment mFragment;
+ @Mock
+ private PackageManager mPackageManager;
+
+ private Context mContext;
+ private AngleEnabledAppPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new AngleEnabledAppPreferenceController(mContext, mFragment));
+ ReflectionHelpers
+ .setField(mController, "mPackageManager" /* field name */, mPackageManager);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_preferenceClicked_launchActivity() {
+ final Intent activityStartIntent = new Intent(mContext, AppPicker.class);
+ final String preferenceKey = mController.getPreferenceKey();
+ doReturn(activityStartIntent).when(mController).getActivityStartIntent();
+ when(mPreference.getKey()).thenReturn(preferenceKey);
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mFragment).startActivityForResult(activityStartIntent,
+ REQUEST_CODE_ANGLE_ENABLED_APP);
+ }
+
+ @Test
+ public void updateState_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledAppLabel() {
+ final String angleEnabledApp = "foobar";
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP,
+ angleEnabledApp);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setSummary(
+ mContext.getString(R.string.angle_enabled_app_set, angleEnabledApp));
+ }
+
+ @Test
+ public void updateState_noAppSelected_shouldUpdateSummaryWithNoAppSelected() {
+ final String angleEnabledApp = null;
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Global.putString(contentResolver, Settings.Global.ANGLE_ENABLED_APP,
+ angleEnabledApp);
+ mController.updateState(mPreference);
+
+ verify(mPreference).setSummary(
+ mContext.getString(R.string.angle_enabled_app_not_set));
+ }
+
+ @Test
+ public void onActivityResult_foobarAppSelected_shouldUpdateSummaryWithAngleEnabledLabel() {
+ Intent activityResultIntent = new Intent(mContext, AppPicker.class);
+ final String appLabel = "foobar";
+ activityResultIntent.setAction(appLabel);
+ final boolean result = mController
+ .onActivityResult(REQUEST_CODE_ANGLE_ENABLED_APP, Activity.RESULT_OK,
+ activityResultIntent);
+
+ assertThat(result).isTrue();
+ verify(mPreference).setSummary(
+ mContext.getString(R.string.angle_enabled_app_set, appLabel));
+ }
+
+ @Test
+ public void onActivityResult_badRequestCode_shouldReturnFalse() {
+ assertThat(mController.onActivityResult(
+ -1 /* requestCode */, -1 /* resultCode */, null /* intent */)).isFalse();
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ assertThat(mPreference.isEnabled()).isFalse();
+ verify(mPreference).setSummary(
+ mContext.getString(R.string.angle_enabled_app_not_set));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java
new file mode 100644
index 0000000..20ad067
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/CardContentLoaderTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CardContentLoaderTest {
+ private static final String[] QUERY_PROJECTION = {
+ CardDatabaseHelper.CardColumns.NAME,
+ CardDatabaseHelper.CardColumns.TYPE,
+ CardDatabaseHelper.CardColumns.SCORE,
+ CardDatabaseHelper.CardColumns.SLICE_URI,
+ CardDatabaseHelper.CardColumns.CATEGORY,
+ CardDatabaseHelper.CardColumns.LOCALIZED_TO_LOCALE,
+ CardDatabaseHelper.CardColumns.PACKAGE_NAME,
+ CardDatabaseHelper.CardColumns.APP_VERSION,
+ CardDatabaseHelper.CardColumns.TITLE_RES_NAME,
+ CardDatabaseHelper.CardColumns.TITLE_TEXT,
+ CardDatabaseHelper.CardColumns.SUMMARY_RES_NAME,
+ CardDatabaseHelper.CardColumns.SUMMARY_TEXT,
+ CardDatabaseHelper.CardColumns.ICON_RES_NAME,
+ CardDatabaseHelper.CardColumns.ICON_RES_ID,
+ CardDatabaseHelper.CardColumns.CARD_ACTION,
+ CardDatabaseHelper.CardColumns.EXPIRE_TIME_MS,
+ CardDatabaseHelper.CardColumns.SUPPORT_HALF_WIDTH
+ };
+
+ private Context mContext;
+ private CardContentLoader mCardContentLoader;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mCardContentLoader = spy(new CardContentLoader(mContext));
+ }
+
+ @Test
+ public void loadInBackground_hasDataInDb_shouldReturnData() {
+ final Cursor cursor = generateTwoRowContextualCards();
+ doReturn(cursor).when(mCardContentLoader).getContextualCardsFromProvider();
+
+ final List<ContextualCard> contextualCards = mCardContentLoader.loadInBackground();
+
+ assertThat(contextualCards.size()).isEqualTo(cursor.getCount());
+ }
+
+ @Test
+ public void loadInBackground_hasNoData_shouldReturnThreeDefaultData() {
+ final Cursor cursor = generateEmptyContextualCards();
+ doReturn(cursor).when(mCardContentLoader).getContextualCardsFromProvider();
+
+ final List<ContextualCard> contextualCards = mCardContentLoader.loadInBackground();
+
+ assertThat(contextualCards.size()).isEqualTo(mCardContentLoader.createStaticCards().size());
+ }
+
+ private MatrixCursor generateEmptyContextualCards() {
+ final MatrixCursor result = new MatrixCursor(QUERY_PROJECTION);
+ return result;
+ }
+
+ private MatrixCursor generateTwoRowContextualCards() {
+ final MatrixCursor result = generateEmptyContextualCards();
+ result.addRow(generateFirstFakeData());
+ result.addRow(generateSecondFakeData());
+ return result;
+ }
+
+ private Object[] generateFirstFakeData() {
+ final Object[] ref = new Object[]{
+ "auto_rotate", /* NAME */
+ ContextualCard.CardType.SLICE, /* TYPE */
+ 0.5, /* SCORE */
+ "content://com.android.settings.slices/action/auto_rotate", /* SLICE_URI */
+ 2, /* CATEGORY */
+ "", /* LOCALIZED_TO_LOCALE */
+ "com.android.settings", /* PACKAGE_NAME */
+ 1l, /* APP_VERSION */
+ "", /* TITLE_RES_NAME */
+ "", /* TITLE_TEXT */
+ "", /* SUMMARY_RES_NAME */
+ "", /* SUMMARY_TEXT */
+ "", /* ICON_RES_NAME */
+ 0, /* ICON_RES_ID */
+ 0, /* CARD_ACTION */
+ -1, /* EXPIRE_TIME_MS */
+ 0 /* SUPPORT_HALF_WIDTH */
+ };
+ return ref;
+ }
+
+ private Object[] generateSecondFakeData() {
+ final Object[] ref = new Object[]{
+ "toggle_airplane", /* NAME */
+ ContextualCard.CardType.SLICE, /* TYPE */
+ 0.5, /* SCORE */
+ "content://com.android.settings.slices/action/toggle_airplane", /* SLICE_URI */
+ 2, /* CATEGORY */
+ "", /* LOCALIZED_TO_LOCALE */
+ "com.android.settings", /* PACKAGE_NAME */
+ 1l, /* APP_VERSION */
+ "", /* TITLE_RES_NAME */
+ "", /* TITLE_TEXT */
+ "", /* SUMMARY_RES_NAME */
+ "", /* SUMMARY_TEXT */
+ "", /* ICON_RES_NAME */
+ 0, /* ICON_RES_ID */
+ 0, /* CARD_ACTION */
+ -1, /* EXPIRE_TIME_MS */
+ 0 /* SUPPORT_HALF_WIDTH */
+ };
+ return ref;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index 008d7f7..9507f4e 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -82,6 +82,8 @@
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/RestrictedLockUtils/res/")), null));
paths.add(new ResourcePath(null,
+ Fs.fromURL(new URL("file:frameworks/base/packages/SettingsLib/SearchWidget/res/")), null));
+ paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/base/core/res/res")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:frameworks/opt/setupwizard/library/main/res")), null));
diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/unit/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
similarity index 68%
rename from tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
rename to tests/unit/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
index 4b237a0..89ec476 100644
--- a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
+++ b/tests/unit/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
@@ -16,25 +16,28 @@
package com.android.settings.homepage;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static com.android.settings.homepage.SettingsHomepageActivity.PERSONAL_SETTINGS_TAG;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
import android.util.FeatureFlagUtils;
import androidx.fragment.app.Fragment;
import com.android.settings.core.FeatureFlags;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsRobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
public class SettingsHomepageActivityTest {
private Context mContext;
@@ -42,16 +45,27 @@
@Before
public void setUp() {
- mContext = RuntimeEnvironment.application;
+ mContext = InstrumentationRegistry.getTargetContext();
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, true);
}
+ @After
+ public void tearDown() {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlags.DYNAMIC_HOMEPAGE, false);
+ }
+
@Test
public void launchHomepage_shouldOpenPersonalSettings() {
- mActivity = Robolectric.setupActivity(SettingsHomepageActivity.class);
+ final Intent intent = new Intent().setClass(mContext, SettingsHomepageActivity.class)
+ .addFlags(FLAG_ACTIVITY_NEW_TASK);
+
+ mActivity = (SettingsHomepageActivity) InstrumentationRegistry.getInstrumentation()
+ .startActivitySync(intent);
+
final Fragment fragment = mActivity.getSupportFragmentManager()
.findFragmentByTag(PERSONAL_SETTINGS_TAG);
assertThat(fragment).isInstanceOf(PersonalSettingsFragment.class);
}
+
}