Snap for 5339364 from db6e6629b4 to qt-release

Change-Id: Ia39e14a4ba497b852eeb9213716e921a279dacaf
This commit is contained in:
android-build-team Robot
2019-02-27 04:14:45 +00:00
85 changed files with 1239 additions and 2142 deletions

View File

@@ -3009,6 +3009,7 @@
android:theme="@style/Theme.BottomDialog" android:theme="@style/Theme.BottomDialog"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:launchMode="singleTop" android:launchMode="singleTop"
android:taskAffinity=".panel.SettingsPanelActivity"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.settings.panel.action.INTERNET_CONNECTIVITY" /> <action android:name="android.settings.panel.action.INTERNET_CONNECTIVITY" />

View File

@@ -20,7 +20,7 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/title" android:id="@+id/panel_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"

View File

@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 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.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<TextView
style="@style/device_info_dialog_label"
android:id="@+id/model_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/model_info" />
<TextView
style="@style/device_info_dialog_value"
android:id="@+id/model_value"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
style="@style/device_info_dialog_label"
android:id="@+id/serial_number_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/status_serial_number" />
<TextView
style="@style/device_info_dialog_value"
android:id="@+id/serial_number_value"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
style="@style/device_info_dialog_label"
android:id="@+id/hardware_rev_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hardware_revision" />
<TextView
style="@style/device_info_dialog_value"
android:id="@+id/hardware_rev_value"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>

View File

@@ -16,4 +16,5 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_content" android:id="@+id/main_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="match_parent"/> android:layout_width="match_parent"
android:animateLayoutChanges="true"/>

View File

@@ -2153,6 +2153,10 @@
<string name="wifi_dpp_could_not_add_device">Couldn\u2019t add device</string> <string name="wifi_dpp_could_not_add_device">Couldn\u2019t add device</string>
<!-- Title for the fragment to show that device found but naming known [CHAR LIMIT=50] --> <!-- Title for the fragment to show that device found but naming known [CHAR LIMIT=50] -->
<string name="wifi_dpp_device_found">Device found</string> <string name="wifi_dpp_device_found">Device found</string>
<!-- Hint for Wi-Fi DPP handshake running [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_sharing_wifi_with_this_device">Sharing Wi\u2011Fi with this device\u2026</string>
<!-- Hint for Wi-Fi DPP handshake running [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_connecting">Connecting\u2026</string>
<!-- Label for the try again button [CHAR LIMIT=20]--> <!-- Label for the try again button [CHAR LIMIT=20]-->
<string name="retry">Retry</string> <string name="retry">Retry</string>
<!-- Label for the check box to share a network with other users on the same device --> <!-- Label for the check box to share a network with other users on the same device -->
@@ -3623,7 +3627,7 @@
<string name="master_clear_final_button_text">Erase everything</string> <string name="master_clear_final_button_text">Erase everything</string>
<!-- Master clear failed message --> <!-- Master clear failed message -->
<string name="master_clear_failed">No reset was performed because the System Clear service isn\u2019t available.</string> <string name="master_clear_failed">No reset was performed because the System Clear service isn\u2019t available.</string>
<!-- Master clear confirmation screen title [CHAR LIMIT=30] --> <!-- Master clear confirmation screen title [CHAR LIMIT=33] -->
<string name="master_clear_confirm_title">Erase all data?</string> <string name="master_clear_confirm_title">Erase all data?</string>
<!-- Error message for users that aren't allowed to factory reset [CHAR LIMIT=none] --> <!-- Error message for users that aren't allowed to factory reset [CHAR LIMIT=none] -->
<string name="master_clear_not_available">Factory reset is not available for this user</string> <string name="master_clear_not_available">Factory reset is not available for this user</string>

52
res/xml/hardware_info.xml Normal file
View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="hardware_info_screen"
android:title="@string/hardware_info"
settings:keywords="@string/keywords_model_and_hardware">
<!-- Model -->
<Preference
android:key="hardware_info_device_model"
android:title="@string/model_info"
android:summary="@string/summary_placeholder"
settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.deviceinfo.hardwareinfo.DeviceModelPreferenceController"
settings:enableCopying="true"/>
<!-- SerialNumber -->
<Preference
android:key="hardware_info_device_serial"
android:title="@string/status_serial_number"
android:summary="@string/summary_placeholder"
settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.deviceinfo.hardwareinfo.SerialNumberPreferenceController"
settings:enableCopying="true"/>
<!-- Hardware revision -->
<Preference
android:key="hardware_info_device_revision"
android:title="@string/hardware_revision"
android:summary="@string/summary_placeholder"
settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.deviceinfo.hardwareinfo.HardwareRevisionPreferenceController"
settings:enableCopying="true"/>
</PreferenceScreen>

View File

@@ -105,7 +105,8 @@
settings:keywords="@string/keywords_model_and_hardware" settings:keywords="@string/keywords_model_and_hardware"
android:summary="@string/summary_placeholder" android:summary="@string/summary_placeholder"
settings:allowDynamicSummaryInSlice="true" settings:allowDynamicSummaryInSlice="true"
settings:controller="com.android.settings.deviceinfo.DeviceModelPreferenceController"/> android:fragment="com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFragment"
settings:controller="com.android.settings.deviceinfo.HardwareInfoPreferenceController"/>
<!-- IMEI --> <!-- IMEI -->
<Preference <Preference

View File

@@ -82,6 +82,8 @@ public class RecentAppsPreferenceController extends BasePreferenceController
Preference mAllAppPref; Preference mAllAppPref;
@VisibleForTesting @VisibleForTesting
Preference mDivider; Preference mDivider;
@VisibleForTesting
boolean mIsFirstLaunch;
private final PackageManager mPm; private final PackageManager mPm;
private final UsageStatsManager mUsageStatsManager; private final UsageStatsManager mUsageStatsManager;
@@ -93,6 +95,7 @@ public class RecentAppsPreferenceController extends BasePreferenceController
private Fragment mHost; private Fragment mHost;
private Calendar mCal; private Calendar mCal;
private List<UsageStats> mStats; private List<UsageStats> mStats;
private List<UsageStats> mRecentApps;
private boolean mHasRecentApps; private boolean mHasRecentApps;
static { static {
@@ -115,6 +118,9 @@ public class RecentAppsPreferenceController extends BasePreferenceController
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext); mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
mPowerManager = mContext.getSystemService(PowerManager.class); mPowerManager = mContext.getSystemService(PowerManager.class);
mUsageStatsManager = mContext.getSystemService(UsageStatsManager.class); mUsageStatsManager = mContext.getSystemService(UsageStatsManager.class);
mRecentApps = new ArrayList<>();
mIsFirstLaunch = true;
reloadData();
} }
public void setFragment(Fragment fragment) { public void setFragment(Fragment fragment) {
@@ -123,8 +129,7 @@ public class RecentAppsPreferenceController extends BasePreferenceController
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
reloadData(); return mRecentApps.isEmpty() ? AVAILABLE_UNSEARCHABLE : AVAILABLE;
return getDisplayableRecentAppList().isEmpty() ? AVAILABLE_UNSEARCHABLE : AVAILABLE;
} }
@Override @Override
@@ -152,7 +157,11 @@ public class RecentAppsPreferenceController extends BasePreferenceController
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference) {
super.updateState(preference); super.updateState(preference);
// In order to improve launch time, we don't load data again at first launch.
if (!mIsFirstLaunch) {
reloadData();
refreshUi(); refreshUi();
}
// Show total number of installed apps as See all's summary. // Show total number of installed apps as See all's summary.
new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON, new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
mContext.getPackageManager()) { mContext.getPackageManager()) {
@@ -167,6 +176,7 @@ public class RecentAppsPreferenceController extends BasePreferenceController
} }
} }
}.execute(); }.execute();
mIsFirstLaunch = false;
} }
@Override @Override
@@ -177,11 +187,9 @@ public class RecentAppsPreferenceController extends BasePreferenceController
@VisibleForTesting @VisibleForTesting
void refreshUi() { void refreshUi() {
reloadData(); if (mRecentApps != null && !mRecentApps.isEmpty()) {
final List<UsageStats> recentApps = getDisplayableRecentAppList();
if (recentApps != null && !recentApps.isEmpty()) {
mHasRecentApps = true; mHasRecentApps = true;
displayRecentApps(recentApps); displayRecentApps();
} else { } else {
mHasRecentApps = false; mHasRecentApps = false;
displayOnlyAppInfo(); displayOnlyAppInfo();
@@ -197,6 +205,8 @@ public class RecentAppsPreferenceController extends BasePreferenceController
: mUsageStatsManager.queryUsageStats( : mUsageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_BEST, mCal.getTimeInMillis(), UsageStatsManager.INTERVAL_BEST, mCal.getTimeInMillis(),
System.currentTimeMillis()); System.currentTimeMillis());
updateDisplayableRecentAppList();
} }
private void displayOnlyAppInfo() { private void displayOnlyAppInfo() {
@@ -206,10 +216,10 @@ public class RecentAppsPreferenceController extends BasePreferenceController
mRecentAppsPreference.setVisible(false); mRecentAppsPreference.setVisible(false);
} }
private void displayRecentApps(List<UsageStats> recentApps) { private void displayRecentApps() {
int showAppsCount = 0; int showAppsCount = 0;
for (UsageStats stat : recentApps) { for (UsageStats stat : mRecentApps) {
final AppEntityInfo appEntityInfoInfo = createAppEntity(stat); final AppEntityInfo appEntityInfoInfo = createAppEntity(stat);
if (appEntityInfoInfo != null) { if (appEntityInfoInfo != null) {
mAppEntitiesController.setAppEntity(showAppsCount++, appEntityInfoInfo); mAppEntitiesController.setAppEntity(showAppsCount++, appEntityInfoInfo);
@@ -246,8 +256,8 @@ public class RecentAppsPreferenceController extends BasePreferenceController
.build(); .build();
} }
private List<UsageStats> getDisplayableRecentAppList() { private void updateDisplayableRecentAppList() {
final List<UsageStats> recentApps = new ArrayList<>(); mRecentApps.clear();
final Map<String, UsageStats> map = new ArrayMap<>(); final Map<String, UsageStats> map = new ArrayMap<>();
final int statCount = mStats.size(); final int statCount = mStats.size();
for (int i = 0; i < statCount; i++) { for (int i = 0; i < statCount; i++) {
@@ -273,13 +283,12 @@ public class RecentAppsPreferenceController extends BasePreferenceController
if (appEntry == null) { if (appEntry == null) {
continue; continue;
} }
recentApps.add(stat); mRecentApps.add(stat);
count++; count++;
if (count >= AppEntitiesHeaderController.MAXIMUM_APPS) { if (count >= AppEntitiesHeaderController.MAXIMUM_APPS) {
break; break;
} }
} }
return recentApps;
} }

View File

@@ -30,6 +30,7 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
private static final String TAG = "DeviceAdminListItem"; private static final String TAG = "DeviceAdminListItem";
private final UserHandle mUserHandle;
private final String mKey; private final String mKey;
private final DeviceAdminInfo mInfo; private final DeviceAdminInfo mInfo;
private final CharSequence mName; private final CharSequence mName;
@@ -39,7 +40,8 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
public DeviceAdminListItem(Context context, DeviceAdminInfo info) { public DeviceAdminListItem(Context context, DeviceAdminInfo info) {
mInfo = info; mInfo = info;
mKey = mInfo.getComponent().flattenToString(); mUserHandle = new UserHandle(getUserIdFromDeviceAdminInfo(mInfo));
mKey = mUserHandle.getIdentifier() + "@" + mInfo.getComponent().flattenToString();
mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
final PackageManager pm = context.getPackageManager(); final PackageManager pm = context.getPackageManager();
mName = mInfo.loadLabel(pm); mName = mInfo.loadLabel(pm);
@@ -48,8 +50,7 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
} catch (Resources.NotFoundException exception) { } catch (Resources.NotFoundException exception) {
Log.w(TAG, "Setting description to null because can't find resource: " + mKey); Log.w(TAG, "Setting description to null because can't find resource: " + mKey);
} }
mIcon = pm.getUserBadgedIcon(mInfo.loadIcon(pm), mIcon = pm.getUserBadgedIcon(mInfo.loadIcon(pm), mUserHandle);
new UserHandle(DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo)));
} }
@Override @Override
@@ -70,8 +71,7 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
} }
public boolean isActive() { public boolean isActive() {
return mDPM.isAdminActiveAsUser(mInfo.getComponent(), return mDPM.isAdminActiveAsUser(mInfo.getComponent(), getUserIdFromDeviceAdminInfo(mInfo));
DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo));
} }
public Drawable getIcon() { public Drawable getIcon() {
@@ -79,16 +79,25 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
} }
public boolean isEnabled() { public boolean isEnabled() {
return !mDPM.isRemovingAdmin(mInfo.getComponent(), return !mDPM.isRemovingAdmin(mInfo.getComponent(), getUserIdFromDeviceAdminInfo(mInfo));
DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo));
} }
public UserHandle getUser() { public UserHandle getUser() {
return new UserHandle(DeviceAdminUtils.getUserIdFromDeviceAdminInfo(mInfo)); return new UserHandle(getUserIdFromDeviceAdminInfo(mInfo));
} }
public Intent getLaunchIntent(Context context) { public Intent getLaunchIntent(Context context) {
return new Intent(context, DeviceAdminAdd.class) return new Intent(context, DeviceAdminAdd.class)
.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mInfo.getComponent()); .putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mInfo.getComponent());
} }
/**
* Extracts the user id from a device admin info object.
*
* @param adminInfo the device administrator info.
* @return identifier of the user associated with the device admin.
*/
private static int getUserIdFromDeviceAdminInfo(DeviceAdminInfo adminInfo) {
return UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid);
}
} }

View File

@@ -53,6 +53,9 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.FooterPreferenceMixinCompat; import com.android.settingslib.widget.FooterPreferenceMixinCompat;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -249,8 +252,7 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
Log.w(TAG, "Unable to load component: " + activeAdmin); Log.w(TAG, "Unable to load component: " + activeAdmin);
continue; continue;
} }
final DeviceAdminInfo deviceAdminInfo = DeviceAdminUtils.createDeviceAdminInfo( final DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(mContext, ai);
mContext, ai);
if (deviceAdminInfo == null) { if (deviceAdminInfo == null) {
continue; continue;
} }
@@ -286,7 +288,7 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
&& alreadyAddedComponents.contains(riComponentName)) { && alreadyAddedComponents.contains(riComponentName)) {
continue; continue;
} }
DeviceAdminInfo deviceAdminInfo = DeviceAdminUtils.createDeviceAdminInfo( DeviceAdminInfo deviceAdminInfo = createDeviceAdminInfo(
mContext, resolveInfo.activityInfo); mContext, resolveInfo.activityInfo);
// add only visible ones (note: active admins are added regardless of visibility) // add only visible ones (note: active admins are added regardless of visibility)
if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) { if (deviceAdminInfo != null && deviceAdminInfo.isVisible()) {
@@ -297,4 +299,20 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
} }
} }
} }
/**
* Creates a device admin info object for the resolved intent that points to the component of
* the device admin.
*
* @param ai ActivityInfo for the admin component.
* @return new {@link DeviceAdminInfo} object or null if there was an error.
*/
private static DeviceAdminInfo createDeviceAdminInfo(Context context, ActivityInfo ai) {
try {
return new DeviceAdminInfo(context, ai);
} catch (XmlPullParserException | IOException e) {
Log.w(TAG, "Skipping " + ai, e);
}
return null;
}
} }

View File

@@ -1,58 +0,0 @@
/*
* 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.applications.specialaccess.deviceadmin;
import android.app.admin.DeviceAdminInfo;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.os.UserHandle;
import android.util.Log;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
public class DeviceAdminUtils {
private static final String TAG = "DeviceAdminUtils";
/**
* Creates a device admin info object for the resolved intent that points to the component of
* the device admin.
*
* @param ai ActivityInfo for the admin component.
* @return new {@link DeviceAdminInfo} object or null if there was an error.
*/
public static DeviceAdminInfo createDeviceAdminInfo(Context context, ActivityInfo ai) {
try {
return new DeviceAdminInfo(context, ai);
} catch (XmlPullParserException | IOException e) {
Log.w(TAG, "Skipping " + ai, e);
}
return null;
}
/**
* Extracts the user id from a device admin info object.
*
* @param adminInfo the device administrator info.
* @return identifier of the user associated with the device admin.
*/
public static int getUserIdFromDeviceAdminInfo(DeviceAdminInfo adminInfo) {
return UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid);
}
}

View File

@@ -42,7 +42,6 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.slices.Copyable;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -50,7 +49,7 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.development.DevelopmentSettingsEnabler; import com.android.settingslib.development.DevelopmentSettingsEnabler;
public class BuildNumberPreferenceController extends BasePreferenceController implements Copyable, public class BuildNumberPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart { LifecycleObserver, OnStart {
static final int TAPS_TO_BE_A_DEVELOPER = 7; static final int TAPS_TO_BE_A_DEVELOPER = 7;
@@ -108,6 +107,11 @@ public class BuildNumberPreferenceController extends BasePreferenceController im
return true; return true;
} }
@Override
public boolean isCopyableSlice() {
return true;
}
@Override @Override
public void copy() { public void copy() {
final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService( final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(

View File

@@ -1,91 +0,0 @@
/*
* Copyright (C) 2017 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.deviceinfo;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class HardwareInfoDialogFragment extends InstrumentedDialogFragment {
public static final String TAG = "HardwareInfo";
@Override
public int getMetricsCategory() {
return SettingsEnums.DIALOG_SETTINGS_HARDWARE_INFO;
}
public static HardwareInfoDialogFragment newInstance() {
final HardwareInfoDialogFragment fragment = new HardwareInfoDialogFragment();
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle(R.string.hardware_info)
.setPositiveButton(android.R.string.ok, null);
final View content = LayoutInflater.from(builder.getContext())
.inflate(R.layout.dialog_hardware_info, null /* parent */);
// Model
setText(content, R.id.model_label, R.id.model_value,
DeviceModelPreferenceController.getDeviceModel());
// Serial number
setText(content, R.id.serial_number_label, R.id.serial_number_value, getSerialNumber());
// Hardware rev
setText(content, R.id.hardware_rev_label, R.id.hardware_rev_value,
SystemProperties.get("ro.boot.hardware.revision"));
return builder.setView(content).create();
}
@VisibleForTesting
void setText(View content, int labelViewId, int valueViewId, String value) {
if (content == null) {
return;
}
final View labelView = content.findViewById(labelViewId);
final TextView valueView = content.findViewById(valueViewId);
if (!TextUtils.isEmpty(value)) {
labelView.setVisibility(View.VISIBLE);
valueView.setVisibility(View.VISIBLE);
valueView.setText(value);
} else {
labelView.setVisibility(View.GONE);
valueView.setVisibility(View.GONE);
}
}
@VisibleForTesting
String getSerialNumber() {
return Build.getSerial();
}
}

View File

@@ -17,11 +17,8 @@ package com.android.settings.deviceinfo;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
@@ -31,21 +28,14 @@ import com.android.settingslib.DeviceInfoUtils;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask; import java.util.concurrent.FutureTask;
public class DeviceModelPreferenceController extends BasePreferenceController { public class HardwareInfoPreferenceController extends BasePreferenceController {
private static final String TAG = "DeviceModelPrefCtrl"; private static final String TAG = "DeviceModelPrefCtrl";
private Fragment mHost; public HardwareInfoPreferenceController(Context context, String key) {
public DeviceModelPreferenceController(Context context, String key) {
super(context, key); super(context, key);
} }
public void setHost(Fragment fragment) {
mHost = fragment;
}
@Override @Override
public void displayPreference(PreferenceScreen screen) { public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen); super.displayPreference(screen);
@@ -54,7 +44,7 @@ public class DeviceModelPreferenceController extends BasePreferenceController {
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_device_model) return mContext.getResources().getBoolean(R.bool.config_show_device_model)
? AVAILABLE : UNSUPPORTED_ON_DEVICE; ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
} }
@Override @Override
@@ -62,21 +52,6 @@ public class DeviceModelPreferenceController extends BasePreferenceController {
return mContext.getResources().getString(R.string.model_summary, getDeviceModel()); return mContext.getResources().getString(R.string.model_summary, getDeviceModel());
} }
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
final HardwareInfoDialogFragment fragment = HardwareInfoDialogFragment.newInstance();
fragment.show(mHost.getFragmentManager(), HardwareInfoDialogFragment.TAG);
return true;
}
@Override
public boolean isSliceable() {
return true;
}
public static String getDeviceModel() { public static String getDeviceModel() {
FutureTask<String> msvSuffixTask = new FutureTask<>(() -> DeviceInfoUtils.getMsvSuffix()); FutureTask<String> msvSuffixTask = new FutureTask<>(() -> DeviceInfoUtils.getMsvSuffix());

View File

@@ -35,14 +35,12 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.slices.Copyable;
import com.android.settingslib.DeviceInfoUtils; import com.android.settingslib.DeviceInfoUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class PhoneNumberPreferenceController extends BasePreferenceController implements public class PhoneNumberPreferenceController extends BasePreferenceController {
Copyable {
private final static String KEY_PHONE_NUMBER = "phone_number"; private final static String KEY_PHONE_NUMBER = "phone_number";
@@ -98,6 +96,11 @@ public class PhoneNumberPreferenceController extends BasePreferenceController im
return true; return true;
} }
@Override
public boolean isCopyableSlice() {
return true;
}
@Override @Override
public void copy() { public void copy() {
final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService( final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(

View File

@@ -31,7 +31,6 @@ import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.BluetoothAddressPreferenceController; import com.android.settings.deviceinfo.BluetoothAddressPreferenceController;
import com.android.settings.deviceinfo.BuildNumberPreferenceController; import com.android.settings.deviceinfo.BuildNumberPreferenceController;
import com.android.settings.deviceinfo.DeviceModelPreferenceController;
import com.android.settings.deviceinfo.DeviceNamePreferenceController; import com.android.settings.deviceinfo.DeviceNamePreferenceController;
import com.android.settings.deviceinfo.FccEquipmentIdPreferenceController; import com.android.settings.deviceinfo.FccEquipmentIdPreferenceController;
import com.android.settings.deviceinfo.FeedbackPreferenceController; import com.android.settings.deviceinfo.FeedbackPreferenceController;
@@ -41,7 +40,6 @@ import com.android.settings.deviceinfo.RegulatoryInfoPreferenceController;
import com.android.settings.deviceinfo.SafetyInfoPreferenceController; import com.android.settings.deviceinfo.SafetyInfoPreferenceController;
import com.android.settings.deviceinfo.UptimePreferenceController; import com.android.settings.deviceinfo.UptimePreferenceController;
import com.android.settings.deviceinfo.WifiMacAddressPreferenceController; import com.android.settings.deviceinfo.WifiMacAddressPreferenceController;
import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceController;
import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController; import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController;
import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceController; import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
@@ -77,7 +75,6 @@ public class MyDeviceInfoFragment extends DashboardFragment
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
use(DeviceModelPreferenceController.class).setHost(this /* parent */);
use(ImeiInfoPreferenceController.class).setHost(this /* parent */); use(ImeiInfoPreferenceController.class).setHost(this /* parent */);
use(DeviceNamePreferenceController.class).setHost(this /* parent */); use(DeviceNamePreferenceController.class).setHost(this /* parent */);
mBuildNumberPreferenceController = use(BuildNumberPreferenceController.class); mBuildNumberPreferenceController = use(BuildNumberPreferenceController.class);

View File

@@ -31,12 +31,11 @@ import androidx.preference.Preference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.slices.Copyable; import com.android.settings.slices.Sliceable;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
public class FirmwareVersionDetailPreferenceController extends BasePreferenceController implements public class FirmwareVersionDetailPreferenceController extends BasePreferenceController {
Copyable {
private static final String TAG = "firmwareDialogCtrl"; private static final String TAG = "firmwareDialogCtrl";
private static final int DELAY_TIMER_MILLIS = 500; private static final int DELAY_TIMER_MILLIS = 500;
@@ -119,7 +118,7 @@ public class FirmwareVersionDetailPreferenceController extends BasePreferenceCon
@Override @Override
public void copy() { public void copy() {
Copyable.setCopyContent(mContext, getSummary(), Sliceable.setCopyContent(mContext, getSummary(),
mContext.getText(R.string.firmware_version)); mContext.getText(R.string.firmware_version));
} }
} }

View File

@@ -0,0 +1,42 @@
/*
* 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.deviceinfo.hardwareinfo;
import android.content.Context;
import com.android.settings.deviceinfo.HardwareInfoPreferenceController;
public class DeviceModelPreferenceController extends HardwareInfoPreferenceController {
public DeviceModelPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
final int availability = super.getAvailabilityStatus();
if (availability == AVAILABLE_UNSEARCHABLE) {
return AVAILABLE;
}
return availability;
}
@Override
public boolean isSliceable() {
return true;
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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.deviceinfo.hardwareinfo;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
@SearchIndexable
public class HardwareInfoFragment extends DashboardFragment {
public static final String TAG = "HardwareInfo";
@Override
public int getMetricsCategory() {
return SettingsEnums.DIALOG_SETTINGS_HARDWARE_INFO;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.hardware_info;
}
@Override
protected String getLogTag() {
return TAG;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.hardware_info;
result.add(sir);
return result;
}
@Override
protected boolean isPageSearchEnabled(Context context) {
return context.getResources().getBoolean(R.bool.config_show_device_model);
}
};
}

View File

@@ -0,0 +1,46 @@
/*
* 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.deviceinfo.hardwareinfo;
import android.content.Context;
import android.os.SystemProperties;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class HardwareRevisionPreferenceController extends BasePreferenceController {
public HardwareRevisionPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_device_model)
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isSliceable() {
return true;
}
@Override
public CharSequence getSummary() {
return SystemProperties.get("ro.boot.hardware.revision");
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.deviceinfo.hardwareinfo;
import android.content.Context;
import android.os.Build;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.slices.Sliceable;
public class SerialNumberPreferenceController extends BasePreferenceController {
public SerialNumberPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_device_model)
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isSliceable() {
return true;
}
@Override
public boolean isCopyableSlice() {
return true;
}
@Override
public void copy() {
Sliceable.setCopyContent(mContext, getSummary(),
mContext.getText(R.string.status_serial_number));
}
@Override
public CharSequence getSummary() {
return Build.getSerial();
}
}

View File

@@ -29,7 +29,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.slices.Copyable; import com.android.settings.slices.Sliceable;
import com.android.settingslib.Utils; import com.android.settingslib.Utils;
import java.util.ArrayList; import java.util.ArrayList;
@@ -38,7 +38,7 @@ import java.util.List;
/** /**
* Controller that manages preference for single and multi sim devices. * Controller that manages preference for single and multi sim devices.
*/ */
public class ImeiInfoPreferenceController extends BasePreferenceController implements Copyable { public class ImeiInfoPreferenceController extends BasePreferenceController {
private final boolean mIsMultiSim; private final boolean mIsMultiSim;
private final TelephonyManager mTelephonyManager; private final TelephonyManager mTelephonyManager;
@@ -105,9 +105,14 @@ public class ImeiInfoPreferenceController extends BasePreferenceController imple
return true; return true;
} }
@Override
public boolean isCopyableSlice() {
return true;
}
@Override @Override
public void copy() { public void copy() {
Copyable.setCopyContent(mContext, getSummary(), mContext.getText(R.string.status_imei)); Sliceable.setCopyContent(mContext, getSummary(), mContext.getText(R.string.status_imei));
} }
private void updatePreference(Preference preference, int simSlot) { private void updatePreference(Preference preference, int simSlot) {

View File

@@ -65,6 +65,11 @@ public class StatsManagerConfig {
AnomalyType.EXCESSIVE_CRASH_RATE, AnomalyType.EXCESSIVE_CRASH_RATE,
AnomalyType.EXCESSIVE_CRASH_LOOPING, AnomalyType.EXCESSIVE_CRASH_LOOPING,
AnomalyType.NUMBER_OF_OPEN_FILES, AnomalyType.NUMBER_OF_OPEN_FILES,
AnomalyType.EXCESSIVE_CAMERA_USAGE_IN_BACKGROUND,
AnomalyType.EXCESSIVE_CONTACT_ACCESS,
AnomalyType.EXCESSIVE_AUDIO_IN_BACKGROUND,
AnomalyType.EXCESSIVE_CRASH_ANR_IN_BACKGROUND,
AnomalyType.BATTERY_DRAIN_FROM_UNUSED_APP,
}) })
public @interface AnomalyType { public @interface AnomalyType {
/** /**
@@ -218,6 +223,42 @@ public class StatsManagerConfig {
* The application crashed because no more file descriptors were available. * The application crashed because no more file descriptors were available.
*/ */
int NUMBER_OF_OPEN_FILES = 26; int NUMBER_OF_OPEN_FILES = 26;
/**
* The application used an excessive amount of CPU while in a
* background process state.
*/
int EXCESSIVE_CPU_USAGE_IN_BACKGROUND = 27;
/**
* The application kept the camera open for an excessive amount
* of time while in a bckground process state.
*/
int EXCESSIVE_CAMERA_USAGE_IN_BACKGROUND = 28;
/**
* The application has accessed the contacts content provider an
* excessive amount.
*/
int EXCESSIVE_CONTACT_ACCESS = 29;
/**
* The application has played too much audio while in a background
* process state.
*/
int EXCESSIVE_AUDIO_IN_BACKGROUND = 30;
/**
* The application has crashed or ANRed too many times while in a
* background process state.
*/
int EXCESSIVE_CRASH_ANR_IN_BACKGROUND = 31;
/**
* An application which has not been used by the user recently
* was detected to cause an excessive amount of battery drain.
*/
int BATTERY_DRAIN_FROM_UNUSED_APP = 32;
} }
} }

View File

@@ -61,6 +61,17 @@ public class PreventRingingSwitchPreferenceController extends AbstractPreference
LayoutPreference pref = screen.findPreference(getPreferenceKey()); LayoutPreference pref = screen.findPreference(getPreferenceKey());
if (pref != null) { if (pref != null) {
mSettingObserver = new SettingObserver(pref); mSettingObserver = new SettingObserver(pref);
pref.setOnPreferenceClickListener(preference -> {
int preventRinging = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.VOLUME_HUSH_GESTURE,
Settings.Secure.VOLUME_HUSH_VIBRATE);
boolean isChecked = preventRinging != Settings.Secure.VOLUME_HUSH_OFF;
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.VOLUME_HUSH_GESTURE, isChecked
? Settings.Secure.VOLUME_HUSH_OFF
: Settings.Secure.VOLUME_HUSH_VIBRATE);
return true;
});
mSwitch = pref.findViewById(R.id.switch_bar); mSwitch = pref.findViewById(R.id.switch_bar);
if (mSwitch != null) { if (mSwitch != null) {
mSwitch.addOnSwitchChangeListener(this); mSwitch.addOnSwitchChangeListener(this);

View File

@@ -23,6 +23,7 @@ import static com.android.settings.slices.CustomSliceRegistry.NOTIFICATION_CHANN
import android.content.Context; import android.content.Context;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.format.DateUtils; import android.text.format.DateUtils;

View File

@@ -36,7 +36,7 @@ import androidx.slice.builders.SliceAction;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SubSettings; import com.android.settings.SubSettings;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.deviceinfo.DeviceModelPreferenceController; import com.android.settings.deviceinfo.HardwareInfoPreferenceController;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment; import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.slices.CustomSliceRegistry; import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable; import com.android.settings.slices.CustomSliceable;
@@ -107,7 +107,7 @@ public class DeviceInfoSlice implements CustomSliceable {
} }
private CharSequence getDeviceModel() { private CharSequence getDeviceModel() {
return DeviceModelPreferenceController.getDeviceModel(); return HardwareInfoPreferenceController.getDeviceModel();
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -15,20 +15,26 @@
*/ */
package com.android.settings.nfc; package com.android.settings.nfc;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.Uri;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnResume;
import java.io.IOException;
public class NfcPreferenceController extends TogglePreferenceController public class NfcPreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnResume, OnPause { implements LifecycleObserver, OnResume, OnPause {
@@ -51,8 +57,7 @@ public class NfcPreferenceController extends TogglePreferenceController
return; return;
} }
final SwitchPreference switchPreference = final SwitchPreference switchPreference = screen.findPreference(getPreferenceKey());
(SwitchPreference) screen.findPreference(getPreferenceKey());
mNfcEnabler = new NfcEnabler(mContext, switchPreference); mNfcEnabler = new NfcEnabler(mContext, switchPreference);
@@ -86,14 +91,6 @@ public class NfcPreferenceController extends TogglePreferenceController
: UNSUPPORTED_ON_DEVICE; : UNSUPPORTED_ON_DEVICE;
} }
@Override
public IntentFilter getIntentFilter() {
final IntentFilter filter = new IntentFilter();
filter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
filter.addAction(NfcAdapter.EXTRA_ADAPTER_STATE);
return filter;
}
@Override @Override
public boolean hasAsyncUpdate() { public boolean hasAsyncUpdate() {
return true; return true;
@@ -104,6 +101,11 @@ public class NfcPreferenceController extends TogglePreferenceController
return true; return true;
} }
@Override
public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
return NfcSliceWorker.class;
}
@Override @Override
public void onResume() { public void onResume() {
if (mAirplaneModeObserver != null) { if (mAirplaneModeObserver != null) {
@@ -135,4 +137,77 @@ public class NfcPreferenceController extends TogglePreferenceController
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS); Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC); return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
} }
/**
* Listener for background changes to NFC.
*
* <p>
* Listen to broadcasts from {@link NfcAdapter}. The worker will call notify changed on the
* NFC Slice only when the following extras are present in the broadcast:
* <ul>
* <li>{@link NfcAdapter#STATE_ON}</li>
* <li>{@link NfcAdapter#STATE_OFF}</li>
* </ul>
*/
public static class NfcSliceWorker extends SliceBackgroundWorker<Void> {
private static final String TAG = "NfcSliceWorker";
private static final IntentFilter NFC_FILTER =
new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
private NfcUpdateReceiver mUpdateObserver;
public NfcSliceWorker(Context context, Uri uri) {
super(context, uri);
mUpdateObserver = new NfcUpdateReceiver(this);
}
@Override
protected void onSlicePinned() {
getContext().registerReceiver(mUpdateObserver, NFC_FILTER);
}
@Override
protected void onSliceUnpinned() {
getContext().unregisterReceiver(mUpdateObserver);
}
@Override
public void close() throws IOException {
mUpdateObserver = null;
}
public void updateSlice() {
notifySliceChange();
}
public class NfcUpdateReceiver extends BroadcastReceiver {
private final int NO_EXTRA = -1;
private final NfcSliceWorker mSliceBackgroundWorker;
public NfcUpdateReceiver(NfcSliceWorker sliceWorker) {
mSliceBackgroundWorker = sliceWorker;
}
@Override
public void onReceive(Context context, Intent intent) {
final int nfcStateExtra = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
NO_EXTRA);
// Do nothing if state change is empty, or an intermediate step.
if ( (nfcStateExtra == NO_EXTRA)
|| (nfcStateExtra == NfcAdapter.STATE_TURNING_ON)
|| (nfcStateExtra == NfcAdapter.STATE_TURNING_OFF)) {
Log.d(TAG, "Transitional update, dropping broadcast");
return;
}
Log.d(TAG, "Nfc broadcast received, updating Slice.");
mSliceBackgroundWorker.updateSlice();
}
}
}
} }

View File

@@ -16,18 +16,46 @@
package com.android.settings.notification; package com.android.settings.notification;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.widget.CandidateInfo;
import com.google.common.annotations.VisibleForTesting;
public class NotificationAssistantPreferenceController extends BasePreferenceController { public class NotificationAssistantPreferenceController extends BasePreferenceController {
@VisibleForTesting
protected NotificationBackend mNotificationBackend;
private PackageManager mPackageManager;
public NotificationAssistantPreferenceController(Context context, String preferenceKey) { public NotificationAssistantPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
mNotificationBackend = new NotificationBackend();
mPackageManager = mContext.getPackageManager();
} }
@Override @Override
public int getAvailabilityStatus() { public int getAvailabilityStatus() {
return BasePreferenceController.AVAILABLE; return BasePreferenceController.AVAILABLE;
} }
@Override
public CharSequence getSummary() {
CandidateInfo appSelected = new NotificationAssistantPicker.CandidateNone(mContext);
ComponentName assistant = mNotificationBackend.getAllowedNotificationAssistant();
if (assistant != null) {
appSelected = createCandidateInfo(assistant);
}
return appSelected.loadLabel();
}
@VisibleForTesting
protected CandidateInfo createCandidateInfo(ComponentName cn) {
return new DefaultAppInfo(mContext, mPackageManager, UserHandle.myUserId(), cn);
}
} }

View File

@@ -50,13 +50,18 @@ public abstract class RingtonePreferenceControllerBase extends AbstractPreferenc
} }
private void updateSummary(Preference preference) { private void updateSummary(Preference preference) {
Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(mContext, getRingtoneType()); final Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(
final CharSequence summary = Ringtone.getTitle( mContext, getRingtoneType());
final CharSequence summary;
if (ringtoneUri == null) {
summary = null;
} else {
summary = Ringtone.getTitle(
mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */); mContext, ringtoneUri, false /* followSettingsUri */, true /* allowRemote */);
}
if (summary != null) { if (summary != null) {
ThreadUtils.postOnMainThread(() -> { ThreadUtils.postOnMainThread(() -> preference.setSummary(summary));
preference.setSummary(summary);
});
} }
} }

View File

@@ -1,51 +0,0 @@
/*
* 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.slices;
import static android.content.Context.CLIPBOARD_SERVICE;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.widget.Toast;
import com.android.settings.R;
/**
* Provide the copy ability for preference controller to copy the data to the clipboard.
*/
public interface Copyable {
/**
* Copy the key slice information to the clipboard.
* It is highly recommended to show the toast to notify users when implemented this function.
*/
void copy();
/**
* Set the copy content to the clipboard and show the toast.
*/
static void setCopyContent(Context context, CharSequence copyContent,
CharSequence messageTitle) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(
CLIPBOARD_SERVICE);
final ClipData clip = ClipData.newPlainText("text", copyContent);
clipboard.setPrimaryClip(clip);
final String toast = context.getString(R.string.copyable_slice_toast, messageTitle);
Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
}
}

View File

@@ -83,18 +83,6 @@ public interface CustomSliceable extends Sliceable {
*/ */
Intent getIntent(); Intent getIntent();
/**
* Settings Slices which require background work, such as updating lists should implement a
* {@link SliceBackgroundWorker} and return it here. An example of background work is updating
* a list of Wifi networks available in the area.
*
* @return a {@link Class<? extends SliceBackgroundWorker>} to perform background work for the
* slice.
*/
default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
return null;
}
/** /**
* Standardize the intents returned to indicate actions by the Slice. * Standardize the intents returned to indicate actions by the Slice.
* <p> * <p>

View File

@@ -153,7 +153,7 @@ public class SettingsSliceProvider extends SliceProvider {
if (filter != null) { if (filter != null) {
registerIntentToUri(filter, sliceUri); registerIntentToUri(filter, sliceUri);
} }
ThreadUtils.postOnMainThread(() -> startBackgroundWorker(sliceable)); ThreadUtils.postOnMainThread(() -> startBackgroundWorker(sliceable, sliceUri));
return; return;
} }
@@ -326,20 +326,19 @@ public class SettingsSliceProvider extends SliceProvider {
} }
} }
private void startBackgroundWorker(CustomSliceable sliceable) { private void startBackgroundWorker(Sliceable sliceable, Uri uri) {
final Class workerClass = sliceable.getBackgroundWorkerClass(); final Class workerClass = sliceable.getBackgroundWorkerClass();
if (workerClass == null) { if (workerClass == null) {
return; return;
} }
final Uri uri = sliceable.getUri();
if (mPinnedWorkers.containsKey(uri)) { if (mPinnedWorkers.containsKey(uri)) {
return; return;
} }
Log.d(TAG, "Starting background worker for: " + uri); Log.d(TAG, "Starting background worker for: " + uri);
final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance( final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(
getContext(), sliceable); getContext(), sliceable, uri);
mPinnedWorkers.put(uri, worker); mPinnedWorkers.put(uri, worker);
worker.onSlicePinned(); worker.onSlicePinned();
} }
@@ -397,6 +396,8 @@ public class SettingsSliceProvider extends SliceProvider {
registerIntentToUri(filter, uri); registerIntentToUri(filter, uri);
} }
ThreadUtils.postOnMainThread(() -> startBackgroundWorker(controller, uri));
final List<Uri> pinnedSlices = getContext().getSystemService( final List<Uri> pinnedSlices = getContext().getSystemService(
SliceManager.class).getPinnedSlices(); SliceManager.class).getPinnedSlices();
if (pinnedSlices.contains(uri)) { if (pinnedSlices.contains(uri)) {

View File

@@ -80,13 +80,12 @@ public abstract class SliceBackgroundWorker<E> implements Closeable {
* Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link
* CustomSliceable} * CustomSliceable}
*/ */
static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) { static SliceBackgroundWorker getInstance(Context context, Sliceable sliceable, Uri uri) {
final Uri uri = sliceable.getUri();
SliceBackgroundWorker worker = getInstance(uri); SliceBackgroundWorker worker = getInstance(uri);
if (worker == null) { if (worker == null) {
final Class<? extends SliceBackgroundWorker> workerClass = final Class<? extends SliceBackgroundWorker> workerClass =
sliceable.getBackgroundWorkerClass(); sliceable.getBackgroundWorkerClass();
worker = createInstance(context, uri, workerClass); worker = createInstance(context.getApplicationContext(), uri, workerClass);
LIVE_WORKERS.put(uri, worker); LIVE_WORKERS.put(uri, worker);
} }
return worker; return worker;

View File

@@ -184,7 +184,7 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
final BasePreferenceController controller = getPreferenceController(context, key); final BasePreferenceController controller = getPreferenceController(context, key);
if (!(controller instanceof Copyable)) { if (!(controller instanceof Sliceable)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Copyable action passed for a non-copyable key:" + key); "Copyable action passed for a non-copyable key:" + key);
} }
@@ -197,7 +197,7 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
return; return;
} }
((Copyable) controller).copy(); controller.copy();
} }
/** /**

View File

@@ -93,7 +93,7 @@ public class SliceBuilderUtils {
return buildUnavailableSlice(context, sliceData); return buildUnavailableSlice(context, sliceData);
} }
if (controller instanceof Copyable) { if (controller.isCopyableSlice()) {
return buildCopyableSlice(context, sliceData, controller); return buildCopyableSlice(context, sliceData, controller);
} }

View File

@@ -16,7 +16,15 @@
package com.android.settings.slices; package com.android.settings.slices;
import static android.content.Context.CLIPBOARD_SERVICE;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.widget.Toast;
import com.android.settings.R;
/** /**
* A collection of API making a PreferenceController "sliceable" * A collection of API making a PreferenceController "sliceable"
@@ -55,4 +63,44 @@ public interface Sliceable {
default boolean hasAsyncUpdate() { default boolean hasAsyncUpdate() {
return false; return false;
} }
/**
* Copy the key slice information to the clipboard.
* It is highly recommended to show the toast to notify users when implemented this function.
*/
default void copy() {
}
/**
* Whether or not it's a copyable slice.
*/
default boolean isCopyableSlice() {
return false;
}
/**
* Set the copy content to the clipboard and show the toast.
*/
static void setCopyContent(Context context, CharSequence copyContent,
CharSequence messageTitle) {
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(
CLIPBOARD_SERVICE);
final ClipData clip = ClipData.newPlainText("text", copyContent);
clipboard.setPrimaryClip(clip);
final String toast = context.getString(R.string.copyable_slice_toast, messageTitle);
Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
}
/**
* Settings Slices which require background work, such as updating lists should implement a
* {@link SliceBackgroundWorker} and return it here. An example of background work is updating
* a list of Wifi networks available in the area.
*
* @return a {@link Class<? extends SliceBackgroundWorker>} to perform background work for the
* slice.
*/
default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
return null;
}
} }

View File

@@ -71,7 +71,7 @@ class SlicesIndexer implements Runnable {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
database.beginTransaction(); database.beginTransaction();
try { try {
mHelper.reconstruct(mHelper.getWritableDatabase()); mHelper.reconstruct(database);
List<SliceData> indexData = getSliceData(); List<SliceData> indexData = getSliceData();
insertSliceData(database, indexData); insertSliceData(database, indexData);

View File

@@ -19,12 +19,14 @@ package com.android.settings.wifi;
import android.app.Activity; import android.app.Activity;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Intent; import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -40,7 +42,10 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
final static int SUBMIT_BUTTON_ID = android.R.id.button1; final static int SUBMIT_BUTTON_ID = android.R.id.button1;
@VisibleForTesting @VisibleForTesting
final static int CANCEL_BUTTON_ID = android.R.id.button2; final static int CANCEL_BUTTON_ID = android.R.id.button2;
final static int SCANNER_BUTTON_ID = R.id.ssid_scanner_button; final static int SSID_SCANNER_BUTTON_ID = R.id.ssid_scanner_button;
final static int PASSWORD_SCANNER_BUTTON_ID = R.id.password_scanner_button;
private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0;
private WifiConfigController mUIController; private WifiConfigController mUIController;
private Button mSubmitBtn; private Button mSubmitBtn;
@@ -68,10 +73,12 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
mSubmitBtn = rootView.findViewById(SUBMIT_BUTTON_ID); mSubmitBtn = rootView.findViewById(SUBMIT_BUTTON_ID);
mCancelBtn = rootView.findViewById(CANCEL_BUTTON_ID); mCancelBtn = rootView.findViewById(CANCEL_BUTTON_ID);
final ImageButton scannerButton = rootView.findViewById(SCANNER_BUTTON_ID); final ImageButton ssidScannerButton = rootView.findViewById(SSID_SCANNER_BUTTON_ID);
final ImageButton passwordScannerButton = rootView.findViewById(PASSWORD_SCANNER_BUTTON_ID);
mSubmitBtn.setOnClickListener(this); mSubmitBtn.setOnClickListener(this);
mCancelBtn.setOnClickListener(this); mCancelBtn.setOnClickListener(this);
scannerButton.setOnClickListener(this); ssidScannerButton.setOnClickListener(this);
passwordScannerButton.setOnClickListener(this);
mUIController = new WifiConfigController(this, rootView, null, getMode()); mUIController = new WifiConfigController(this, rootView, null, getMode());
return rootView; return rootView;
@@ -85,6 +92,8 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
@Override @Override
public void onClick(View view) { public void onClick(View view) {
String ssid = null;
switch (view.getId()) { switch (view.getId()) {
case SUBMIT_BUTTON_ID: case SUBMIT_BUTTON_ID:
handleSubmitAction(); handleSubmitAction();
@@ -92,14 +101,33 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
case CANCEL_BUTTON_ID: case CANCEL_BUTTON_ID:
handleCancelAction(); handleCancelAction();
break; break;
case SCANNER_BUTTON_ID: case SSID_SCANNER_BUTTON_ID:
final TextView ssidEditText = getView().findViewById(R.id.ssid);
ssid = ssidEditText.getText().toString();
// No break and flows to case PASSWORD_SCANNER_BUTTON_ID
case PASSWORD_SCANNER_BUTTON_ID:
// Launch QR code scanner to join a network. // Launch QR code scanner to join a network.
getContext().startActivity( startActivityForResult(WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid),
WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null)); REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER);
break; break;
} }
} }
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) {
if (resultCode != Activity.RESULT_OK) {
return;
}
final WifiConfiguration config = data.getParcelableExtra(
WifiDialogActivity.KEY_WIFI_CONFIGURATION);
successfullyFinish(config);
}
}
@Override @Override
public int getMode() { public int getMode() {
return WifiConfigUiBase.MODE_CONNECT; return WifiConfigUiBase.MODE_CONNECT;
@@ -158,9 +186,13 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
@VisibleForTesting @VisibleForTesting
void handleSubmitAction() { void handleSubmitAction() {
successfullyFinish(mUIController.getConfig());
}
private void successfullyFinish(WifiConfiguration config) {
final Intent intent = new Intent(); final Intent intent = new Intent();
final Activity activity = getActivity(); final Activity activity = getActivity();
intent.putExtra(WIFI_CONFIG_KEY, mUIController.getConfig()); intent.putExtra(WIFI_CONFIG_KEY, config);
activity.setResult(Activity.RESULT_OK, intent); activity.setResult(Activity.RESULT_OK, intent);
activity.finish(); activity.finish();
} }

View File

@@ -18,15 +18,16 @@ package com.android.settings.wifi;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
@@ -40,6 +41,9 @@ public class WifiDialog extends AlertDialog implements WifiConfigUiBase,
default void onSubmit(WifiDialog dialog) { default void onSubmit(WifiDialog dialog) {
} }
default void onScan(WifiDialog dialog, String ssid) {
}
} }
private static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE; private static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE;
@@ -80,18 +84,6 @@ public class WifiDialog extends AlertDialog implements WifiConfigUiBase,
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
mView = getLayoutInflater().inflate(R.layout.wifi_dialog, /* root */ null); mView = getLayoutInflater().inflate(R.layout.wifi_dialog, /* root */ null);
final ImageButton scannerButton = mView.findViewById(R.id.password_scanner_button);
if (scannerButton != null) {
scannerButton.setOnClickListener((View v) -> {
String ssid = null;
if (mAccessPoint != null) {
ssid = mAccessPoint.getSsidStr();
}
// Launch QR code scanner to join a network.
getContext().startActivity(
WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid));
});
}
setView(mView); setView(mView);
mController = new WifiConfigController(this, mView, mAccessPoint, mMode); mController = new WifiConfigController(this, mView, mAccessPoint, mMode);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -109,6 +101,35 @@ public class WifiDialog extends AlertDialog implements WifiConfigUiBase,
} }
} }
@Override
protected void onStart() {
View.OnClickListener onClickScannerButtonListener = v -> {
if (mListener == null) {
return;
}
String ssid = null;
if (mAccessPoint == null) {
final TextView ssidEditText = findViewById(R.id.ssid);
ssid = ssidEditText.getText().toString();
} else {
ssid = mAccessPoint.getSsidStr();
}
mListener.onScan(/* WifiDialog */ this, ssid);
};
final ImageButton ssidScannerButton = findViewById(R.id.ssid_scanner_button);
ssidScannerButton.setOnClickListener(onClickScannerButtonListener);
final ImageButton passwordScannerButton = findViewById(R.id.password_scanner_button);
passwordScannerButton.setOnClickListener(onClickScannerButtonListener);
if (mHideSubmitButton) {
ssidScannerButton.setVisibility(View.GONE);
passwordScannerButton.setVisibility(View.GONE);
}
}
public void onRestoreInstanceState(Bundle savedInstanceState) { public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState); super.onRestoreInstanceState(savedInstanceState);
mController.updatePassword(); mController.updatePassword();

View File

@@ -29,6 +29,7 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.settings.SetupWizardUtils; import com.android.settings.SetupWizardUtils;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -49,10 +50,13 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
@VisibleForTesting @VisibleForTesting
static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller"; static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller";
private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration"; public static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
private static final int RESULT_CONNECTED = RESULT_FIRST_USER; private static final int RESULT_CONNECTED = RESULT_FIRST_USER;
private static final int RESULT_FORGET = RESULT_FIRST_USER + 1; private static final int RESULT_FORGET = RESULT_FIRST_USER + 1;
private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0;
private WifiDialog mDialog; private WifiDialog mDialog;
@Override @Override
@@ -162,4 +166,25 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
mDialog = null; mDialog = null;
finish(); finish();
} }
@Override
public void onScan(WifiDialog dialog, String ssid) {
// Launch QR code scanner to join a network.
startActivityForResult(WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid),
REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) {
if (resultCode != RESULT_OK) {
return;
}
setResult(RESULT_CONNECTED, data);
finish();
}
}
} }

View File

@@ -117,6 +117,8 @@ public class WifiSettings extends RestrictedSettingsFragment
private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks"; private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks";
private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message"; private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message";
private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0;
private static boolean isVerboseLoggingEnabled() { private static boolean isVerboseLoggingEnabled() {
return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE); return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
} }
@@ -427,10 +429,17 @@ public class WifiSettings extends RestrictedSettingsFragment
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);
// Only handle request comes from AddNetworkFragment
if (requestCode == ADD_NETWORK_REQUEST) { if (requestCode == ADD_NETWORK_REQUEST) {
handleAddNetworkRequest(resultCode, data); handleAddNetworkRequest(resultCode, data);
return; return;
} else if (requestCode == REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER) {
if (resultCode == Activity.RESULT_OK) {
if (mDialog != null) {
mDialog.dismiss();
}
mWifiTracker.resumeScanning();
}
return;
} }
final boolean formerlyRestricted = mIsRestricted; final boolean formerlyRestricted = mIsRestricted;
@@ -1065,6 +1074,13 @@ public class WifiSettings extends RestrictedSettingsFragment
} }
} }
@Override
public void onScan(WifiDialog dialog, String ssid) {
// Launch QR code scanner to join a network.
startActivityForResult(WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid),
REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER);
}
/* package */ void submit(WifiConfigController configController) { /* package */ void submit(WifiConfigController configController) {
final WifiConfiguration config = configController.getConfig(); final WifiConfiguration config = configController.getConfig();

View File

@@ -172,6 +172,9 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mLatestStatusCode = code; mLatestStatusCode = code;
} }
if (isGoingInitiator()) {
mSummary.setText(R.string.wifi_dpp_sharing_wifi_with_this_device);
}
mProgressBar.setVisibility(isGoingInitiator() ? View.VISIBLE : View.INVISIBLE); mProgressBar.setVisibility(isGoingInitiator() ? View.VISIBLE : View.INVISIBLE);
mButtonRight.setVisibility(isGoingInitiator() ? View.INVISIBLE : View.VISIBLE); mButtonRight.setVisibility(isGoingInitiator() ? View.INVISIBLE : View.VISIBLE);
} }
@@ -255,7 +258,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mTitle.setText(information); mTitle.setText(information);
} }
mSummary.setText(getString(R.string.wifi_dpp_add_device_to_wifi, getSsid())); updateSummary();
mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view); mWifiApPictureView = view.findViewById(R.id.wifi_ap_picture_view);
mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network); mChooseDifferentNetwork = view.findViewById(R.id.choose_different_network);
@@ -273,6 +276,7 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
mProgressBar.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.VISIBLE);
mButtonRight.setVisibility(View.INVISIBLE); mButtonRight.setVisibility(View.INVISIBLE);
startWifiDppConfiguratorInitiator(); startWifiDppConfiguratorInitiator();
updateSummary();
}); });
if (savedInstanceState != null) { if (savedInstanceState != null) {
@@ -342,4 +346,12 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment {
return model.isGoingInitiator(); return model.isGoingInitiator();
} }
private void updateSummary() {
if (isGoingInitiator()) {
mSummary.setText(R.string.wifi_dpp_sharing_wifi_with_this_device);
} else {
mSummary.setText(getString(R.string.wifi_dpp_add_device_to_wifi, getSsid()));
}
}
} }

View File

@@ -31,7 +31,6 @@ import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.Size; import android.util.Size;
@@ -48,6 +47,7 @@ import android.widget.TextView;
import androidx.lifecycle.ViewModelProviders; import androidx.lifecycle.ViewModelProviders;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.wifi.WifiDialogActivity;
import com.android.settings.wifi.qrcode.QrCamera; import com.android.settings.wifi.qrcode.QrCamera;
import com.android.settings.wifi.qrcode.QrDecorateView; import com.android.settings.wifi.qrcode.QrDecorateView;
@@ -77,6 +77,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
// Key for Bundle usage // Key for Bundle usage
private static final String KEY_IS_CONFIGURATOR_MODE = "key_is_configurator_mode"; private static final String KEY_IS_CONFIGURATOR_MODE = "key_is_configurator_mode";
private static final String KEY_LATEST_ERROR_CODE = "key_latest_error_code"; private static final String KEY_LATEST_ERROR_CODE = "key_latest_error_code";
private static final String KEY_WIFI_CONFIGURATION = "key_wifi_configuration";
private ProgressBar mProgressBar; private ProgressBar mProgressBar;
private QrCamera mCamera; private QrCamera mCamera;
@@ -93,6 +94,9 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
/** QR code data scanned by camera */ /** QR code data scanned by camera */
private WifiQrCode mWifiQrCode; private WifiQrCode mWifiQrCode;
/** The WifiConfiguration connecting for enrollee usage */
private WifiConfiguration mWifiConfiguration;
private int mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE; private int mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE;
@Override @Override
@@ -102,6 +106,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
if (savedInstanceState != null) { if (savedInstanceState != null) {
mIsConfiguratorMode = savedInstanceState.getBoolean(KEY_IS_CONFIGURATOR_MODE); mIsConfiguratorMode = savedInstanceState.getBoolean(KEY_IS_CONFIGURATOR_MODE);
mLatestStatusCode = savedInstanceState.getInt(KEY_LATEST_ERROR_CODE); mLatestStatusCode = savedInstanceState.getInt(KEY_LATEST_ERROR_CODE);
mWifiConfiguration = savedInstanceState.getParcelable(KEY_WIFI_CONFIGURATION);
} }
final WifiDppInitiatorViewModel model = final WifiDppInitiatorViewModel model =
@@ -224,13 +229,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
} else { } else {
mTitle.setText(R.string.wifi_dpp_scan_qr_code); mTitle.setText(R.string.wifi_dpp_scan_qr_code);
String description; updateEnrolleeSummary();
if (TextUtils.isEmpty(mSsid)) {
description = getString(R.string.wifi_dpp_scan_qr_code_join_unknown_network, mSsid);
} else {
description = getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid);
}
mSummary.setText(description);
} }
mErrorMessage = view.findViewById(R.id.error_message); mErrorMessage = view.findViewById(R.id.error_message);
@@ -410,6 +409,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
if (!mIsConfiguratorMode) { if (!mIsConfiguratorMode) {
mProgressBar.setVisibility(View.VISIBLE); mProgressBar.setVisibility(View.VISIBLE);
startWifiDppEnrolleeInitiator((WifiQrCode)msg.obj); startWifiDppEnrolleeInitiator((WifiQrCode)msg.obj);
updateEnrolleeSummary();
} }
break; break;
@@ -417,6 +417,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
mErrorMessage.setVisibility(View.INVISIBLE); mErrorMessage.setVisibility(View.INVISIBLE);
final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj; final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj;
mWifiConfiguration = wifiNetworkConfig.getWifiConfigurationOrNull();
wifiNetworkConfig.connect(getContext(), wifiNetworkConfig.connect(getContext(),
/* listener */ WifiDppQrCodeScannerFragment.this); /* listener */ WifiDppQrCodeScannerFragment.this);
break; break;
@@ -431,6 +432,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(KEY_IS_CONFIGURATOR_MODE, mIsConfiguratorMode); outState.putBoolean(KEY_IS_CONFIGURATOR_MODE, mIsConfiguratorMode);
outState.putInt(KEY_LATEST_ERROR_CODE, mLatestStatusCode); outState.putInt(KEY_LATEST_ERROR_CODE, mLatestStatusCode);
outState.putParcelable(KEY_WIFI_CONFIGURATION, mWifiConfiguration);
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }
@@ -446,6 +448,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
for (WifiConfiguration wifiConfig : wifiConfigs) { for (WifiConfiguration wifiConfig : wifiConfigs) {
if (wifiConfig.networkId == newNetworkId) { if (wifiConfig.networkId == newNetworkId) {
mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS; mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_SUCCESS;
mWifiConfiguration = wifiConfig;
wifiManager.connect(wifiConfig, WifiDppQrCodeScannerFragment.this); wifiManager.connect(wifiConfig, WifiDppQrCodeScannerFragment.this);
return; return;
} }
@@ -453,6 +456,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
Log.e(TAG, "Invalid networkId " + newNetworkId); Log.e(TAG, "Invalid networkId " + newNetworkId);
mLatestStatusCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; mLatestStatusCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC;
updateEnrolleeSummary();
mProgressBar.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.INVISIBLE);
showErrorMessage(getString(R.string.wifi_dpp_check_connection_try_again)); showErrorMessage(getString(R.string.wifi_dpp_check_connection_try_again));
restartCamera(); restartCamera();
@@ -520,6 +524,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
} }
mLatestStatusCode = code; mLatestStatusCode = code;
updateEnrolleeSummary();
mProgressBar.setVisibility(View.INVISIBLE); mProgressBar.setVisibility(View.INVISIBLE);
restartCamera(); restartCamera();
} }
@@ -539,9 +544,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
@Override @Override
public void onSuccess() { public void onSuccess() {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); final Intent resultIntent = new Intent();
resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION, mWifiConfiguration);
final Activity hostActivity = getActivity(); final Activity hostActivity = getActivity();
hostActivity.setResult(Activity.RESULT_OK); hostActivity.setResult(Activity.RESULT_OK, resultIntent);
hostActivity.finish(); hostActivity.finish();
} }
@@ -578,4 +585,18 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
mCamera.start(surfaceTexture); mCamera.start(surfaceTexture);
} }
private void updateEnrolleeSummary() {
if (isGoingInitiator()) {
mSummary.setText(R.string.wifi_dpp_connecting);
} else {
String description;
if (TextUtils.isEmpty(mSsid)) {
description = getString(R.string.wifi_dpp_scan_qr_code_join_unknown_network, mSsid);
} else {
description = getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid);
}
mSummary.setText(description);
}
}
} }

View File

@@ -95,6 +95,11 @@ public class WifiDppUtils {
/** /**
* Returns an intent to launch QR code scanner for Wi-Fi DPP enrollee. * Returns an intent to launch QR code scanner for Wi-Fi DPP enrollee.
* *
* After enrollee success, the callee activity will return connecting WifiConfiguration by
* putExtra {@code WifiDialogActivity.KEY_WIFI_CONFIGURATION} for
* {@code Activity#setResult(int resultCode, Intent data)}. The calling object should check
* if it's available before using it.
*
* @param ssid The data corresponding to {@code WifiConfiguration} SSID * @param ssid The data corresponding to {@code WifiConfiguration} SSID
* @return Intent for launching QR code scanner * @return Intent for launching QR code scanner
*/ */

View File

@@ -228,7 +228,7 @@ public class WifiNetworkConfig {
/** /**
* This is a simplified method from {@code WifiConfigController.getConfig()} * This is a simplified method from {@code WifiConfigController.getConfig()}
*/ */
private WifiConfiguration getWifiConfigurationOrNull() { WifiConfiguration getWifiConfigurationOrNull() {
if (!isValidConfig(this)) { if (!isValidConfig(this)) {
return null; return null;
} }

View File

@@ -25,9 +25,9 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -146,6 +146,7 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats); .thenReturn(stats);
mAppEntry.info = mApplicationInfo; mAppEntry.info = mApplicationInfo;
mController.reloadData();
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@@ -157,13 +158,17 @@ public class RecentAppsPreferenceControllerTest {
} }
@Test @Test
public void displayPreferenceAndUpdateState_shouldRefreshUi() { public void displayPreference_shouldNotReloadData() {
doNothing().when(mController).refreshUi();
mController.displayPreference(mScreen); mController.displayPreference(mScreen);
mController.updateState(mScreen);
verify(mController, times(2)).refreshUi(); verify(mController, never()).reloadData();
}
@Test
public void displayPreference_shouldRefreshUi() {
mController.displayPreference(mScreen);
verify(mController).refreshUi();
} }
@Test @Test
@@ -173,6 +178,25 @@ public class RecentAppsPreferenceControllerTest {
assertThat(mController.mAppEntitiesController).isNotNull(); assertThat(mController.mAppEntitiesController).isNotNull();
} }
@Test
public void updateState_firstLaunch_shouldNotReloadData() {
mController.mIsFirstLaunch = true;
mController.updateState(mRecentAppsPreference);
verify(mController, never()).reloadData();
}
@Test
public void updateState_afterFirstLaunch_shouldReloadDataAndRefreshUi() {
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference);
verify(mController).reloadData();
verify(mController).refreshUi();
}
@Test @Test
public void updateState_threeValidRecentOpenAppsSet_setAppEntityThreeTime() { public void updateState_threeValidRecentOpenAppsSet_setAppEntityThreeTime() {
final List<UsageStats> stats = new ArrayList<>(); final List<UsageStats> stats = new ArrayList<>();
@@ -203,6 +227,7 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats); .thenReturn(stats);
mAppEntry.info = mApplicationInfo; mAppEntry.info = mApplicationInfo;
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference); mController.updateState(mRecentAppsPreference);
@@ -243,6 +268,7 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats); .thenReturn(stats);
mAppEntry.info = mApplicationInfo; mAppEntry.info = mApplicationInfo;
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference); mController.updateState(mRecentAppsPreference);
@@ -274,6 +300,7 @@ public class RecentAppsPreferenceControllerTest {
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats); .thenReturn(stats);
mAppEntry.info = mApplicationInfo; mAppEntry.info = mApplicationInfo;
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference); mController.updateState(mRecentAppsPreference);
@@ -314,6 +341,7 @@ public class RecentAppsPreferenceControllerTest {
// Make sure stat2 is considered an instant app. // Make sure stat2 is considered an instant app.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (ApplicationInfo info) -> info == stat2Entry.info); (InstantAppDataProvider) (ApplicationInfo info) -> info == stat2Entry.info);
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference); mController.updateState(mRecentAppsPreference);
@@ -389,6 +417,7 @@ public class RecentAppsPreferenceControllerTest {
.thenReturn(new ResolveInfo()); .thenReturn(new ResolveInfo());
when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong())) when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
.thenReturn(stats); .thenReturn(stats);
mController.mIsFirstLaunch = false;
mController.updateState(mRecentAppsPreference); mController.updateState(mRecentAppsPreference);

View File

@@ -67,7 +67,7 @@ public class DeviceAdminListItemTest {
DeviceAdminListItem item = new DeviceAdminListItem(mContext, mDeviceAdminInfo); DeviceAdminListItem item = new DeviceAdminListItem(mContext, mDeviceAdminInfo);
assertThat(item.getKey()).isEqualTo(cn.flattenToShortString()); assertThat(item.getKey()).isEqualTo("0@" + cn.flattenToShortString());
assertThat(item.getName()).isEqualTo(label); assertThat(item.getName()).isEqualTo(label);
assertThat(item.getDescription()).isEqualTo(description); assertThat(item.getDescription()).isEqualTo(description);
} }

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2017 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.deviceinfo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.os.SystemProperties;
import android.view.View;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class HardwareInfoDialogFragmentTest {
private FragmentActivity mActivity;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
}
@Test
public void display_shouldShowHardwareRevision() {
final String TEST_HARDWARE_REV = "123";
SystemProperties.set("ro.boot.hardware.revision", TEST_HARDWARE_REV);
final HardwareInfoDialogFragment fragment = spy(HardwareInfoDialogFragment.newInstance());
doReturn("").when(fragment).getSerialNumber();
fragment.show(mActivity.getSupportFragmentManager(), HardwareInfoDialogFragment.TAG);
verify(fragment).setText(
any(View.class), eq(R.id.model_label), eq(R.id.model_value),
anyString());
verify(fragment).setText(
any(View.class), eq(R.id.hardware_rev_label), eq(R.id.hardware_rev_value),
anyString());
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.deviceinfo.hardwareinfo;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
public class DeviceModelPreferenceControllerTest {
private Context mContext;
private DeviceModelPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new DeviceModelPreferenceController(mContext, "test_key");
}
@Test
public void getAvailabilityStatus_configAllowed_available() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
@Config(qualifiers = "mcc999")
public void getAvailabilityStatus_configDisallowed_unavailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.UNSUPPORTED_ON_DEVICE);
}
@Test
public void isAlwaysSliceable() {
assertThat(mController.isSliceable()).isTrue();
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 The Android Open Source Project * Copyright (C) 2019 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -13,56 +13,44 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.deviceinfo; package com.android.settings.deviceinfo.hardwareinfo;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.deviceinfo.HardwareInfoPreferenceController;
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.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class DeviceModelPreferenceControllerTest { public class HardwareInfoPreferenceControllerTest {
private final String KEY = "device_model"; private final String KEY = "device_model";
@Mock
private Fragment mFragment;
private Preference mPreference; private Preference mPreference;
private PreferenceScreen mPreferenceScreen; private PreferenceScreen mPreferenceScreen;
private Context mContext; private Context mContext;
private DeviceModelPreferenceController mController; private HardwareInfoPreferenceController mController;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
mController = new DeviceModelPreferenceController(mContext, KEY); mController = new HardwareInfoPreferenceController(mContext, KEY);
mController.setHost(mFragment);
mPreference = new Preference(mContext); mPreference = new Preference(mContext);
mPreference.setKey(KEY); mPreference.setKey(KEY);
final PreferenceManager preferenceManager = new PreferenceManager(mContext); final PreferenceManager preferenceManager = new PreferenceManager(mContext);
@@ -73,7 +61,7 @@ public class DeviceModelPreferenceControllerTest {
@Test @Test
public void isAvailable_returnTrueIfVisible() { public void isAvailable_returnTrueIfVisible() {
assertThat(mController.getAvailabilityStatus()).isEqualTo( assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE); BasePreferenceController.AVAILABLE_UNSEARCHABLE);
} }
@Test @Test
@@ -90,22 +78,6 @@ public class DeviceModelPreferenceControllerTest {
assertThat(containBuildModel(mPreference.getSummary())).isTrue(); assertThat(containBuildModel(mPreference.getSummary())).isTrue();
} }
@Test
public void clickPreference_shouldLaunchHardwareInfoDialog() {
FragmentManager fragmentManager = mock(FragmentManager.class);
when(mFragment.getFragmentManager()).thenReturn(fragmentManager);
when(fragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
verify(fragmentManager.beginTransaction())
.add(any(HardwareInfoDialogFragment.class), eq(HardwareInfoDialogFragment.TAG));
}
@Test
public void isSliceable_shouldBeTrue() {
assertThat(mController.isSliceable()).isTrue();
}
private boolean containBuildModel(CharSequence result) { private boolean containBuildModel(CharSequence result) {
final String oracle = mContext.getResources().getString(R.string.model_summary, final String oracle = mContext.getResources().getString(R.string.model_summary,
Build.MODEL); Build.MODEL);

View File

@@ -0,0 +1,60 @@
/*
* 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.deviceinfo.hardwareinfo;
import static com.google.common.truth.Truth.assertThat;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class SerialNumberPreferenceControllerTest {
private Context mContext;
private SerialNumberPreferenceController mController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mController = new SerialNumberPreferenceController(mContext, "test");
}
@Test
public void isCopyableSlice() {
assertThat(mController.isSliceable()).isTrue();
assertThat(mController.isCopyableSlice()).isTrue();
}
@Test
public void copy_shouldPutSerialNumberToClipBoard() {
mController.copy();
final ClipboardManager clipboardManager = mContext.getSystemService(ClipboardManager.class);
final ClipData data = clipboardManager.getPrimaryClip();
assertThat(data.getItemAt(0).getText().toString()).contains(Build.getSerial());
}
}

View File

@@ -18,6 +18,7 @@ package com.android.settings.gestures;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@@ -29,8 +30,10 @@ import android.content.res.Resources;
import android.provider.Settings; import android.provider.Settings;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBar;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -95,4 +98,16 @@ public class PreventRingingSwitchPreferenceControllerTest {
mController.updateState(mPreference); mController.updateState(mPreference);
verify(mController.mSwitch, times(1)).setChecked(true); verify(mController.mSwitch, times(1)).setChecked(true);
} }
@Test
public void testPreferenceClickListenerAttached() {
PreferenceScreen preferenceScreen = mock(PreferenceScreen.class);
LayoutPreference mLayoutPreference = mock(LayoutPreference.class);
when(preferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
mLayoutPreference);
mController.displayPreference(preferenceScreen);
verify(mLayoutPreference, times(1))
.setOnPreferenceClickListener(any());
}
} }

View File

@@ -19,10 +19,13 @@ package com.android.settings.nfc;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.nfc.NfcManager; import android.nfc.NfcManager;
import android.os.UserManager; import android.os.UserManager;
@@ -31,6 +34,10 @@ import android.provider.Settings;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import com.android.settings.nfc.NfcPreferenceController.NfcSliceWorker;
import com.android.settings.nfc.NfcPreferenceController.NfcSliceWorker.NfcUpdateReceiver;
import com.android.settings.slices.SliceBuilderUtils;
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;
@@ -246,4 +253,67 @@ public class NfcPreferenceControllerTest {
assertThat(mNfcController.mAirplaneModeObserver).isNull(); assertThat(mNfcController.mAirplaneModeObserver).isNull();
} }
@Test
public void ncfSliceWorker_nfcBroadcast_noExtra_sliceDoesntUpdate() {
final NfcSliceWorker worker = spy(new NfcSliceWorker(mContext, getDummyUri()));
final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker);
final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
receiver.onReceive(mContext, triggerIntent);
verify(worker, times(0)).updateSlice();
}
@Test
public void ncfSliceWorker_nfcBroadcast_turningOn_sliceDoesntUpdate() {
final NfcSliceWorker worker = spy(new NfcSliceWorker(mContext, getDummyUri()));
final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker);
final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_TURNING_ON);
receiver.onReceive(mContext, triggerIntent);
verify(worker, times(0)).updateSlice();
}
@Test
public void ncfSliceWorker_nfcBroadcast_turningOff_sliceDoesntUpdate() {
final NfcSliceWorker worker = spy(new NfcSliceWorker(mContext, getDummyUri()));
final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker);
final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_TURNING_OFF);
receiver.onReceive(mContext, triggerIntent);
verify(worker, times(0)).updateSlice();
}
@Test
public void ncfSliceWorker_nfcBroadcast_nfcOn_sliceUpdates() {
final NfcSliceWorker worker = spy(new NfcSliceWorker(mContext, getDummyUri()));
final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker);
final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_ON);
receiver.onReceive(mContext, triggerIntent);
verify(worker).updateSlice();
}
@Test
public void ncfSliceWorker_nfcBroadcast_nfcOff_sliceUpdates() {
final NfcSliceWorker worker = spy(new NfcSliceWorker(mContext, getDummyUri()));
final NfcUpdateReceiver receiver = worker.new NfcUpdateReceiver(worker);
final Intent triggerIntent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
triggerIntent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF);
receiver.onReceive(mContext, triggerIntent);
verify(worker).updateSlice();
}
private Uri getDummyUri() {
return SliceBuilderUtils.getUri("action/nfc", false);
}
} }

View File

@@ -0,0 +1,100 @@
/*
* 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.notification;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Debug;
import com.android.settingslib.widget.CandidateInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class NotificationAssistantPreferenceControllerTest {
private static final String KEY = "TEST_KEY";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
private NotificationBackend mBackend;
private NotificationAssistantPreferenceController mPreferenceController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreferenceController = new TestPreferenceController(mContext, mBackend);
}
@Test
public void testGetSummary_noAssistant() {
when(mBackend.getAllowedNotificationAssistant()).thenReturn(null);
CharSequence noneLabel = new NotificationAssistantPicker.CandidateNone(mContext)
.loadLabel();
assertEquals(noneLabel, mPreferenceController.getSummary());
}
@Test
public void testGetSummary_TestAssistant() {
String testName = "test_pkg/test_cls";
when(mBackend.getAllowedNotificationAssistant()).thenReturn(
ComponentName.unflattenFromString(testName));
assertEquals(testName, mPreferenceController.getSummary());
}
private final class TestPreferenceController extends NotificationAssistantPreferenceController {
private TestPreferenceController(Context context, NotificationBackend backend) {
super(context, KEY);
mNotificationBackend = backend;
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
protected CandidateInfo createCandidateInfo(ComponentName cn) {
return new CandidateInfo(true) {
@Override
public CharSequence loadLabel() { return cn.flattenToString(); }
@Override
public Drawable loadIcon() { return null; }
@Override
public String getKey() { return null; }
};
}
}
}

View File

@@ -20,31 +20,31 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.content.Context; import android.content.Context;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.provider.Settings;
import androidx.preference.Preference; import androidx.preference.Preference;
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.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public class RingtonePreferenceControllerBaseTest { public class RingtonePreferenceControllerBaseTest {
@Mock
private Context mContext; private Context mContext;
private RingtonePreferenceControllerBase mController; private RingtonePreferenceControllerBase mController;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application;
mController = new RingtonePreferenceControllerBaseTestable(mContext); mController = new RingtonePreferenceControllerBaseTestable(mContext);
} }
@@ -56,12 +56,24 @@ public class RingtonePreferenceControllerBaseTest {
@Test @Test
public void updateState_shouldSetSummary() { public void updateState_shouldSetSummary() {
Preference preference = mock(Preference.class); Preference preference = mock(Preference.class);
Settings.System.putString(mContext.getContentResolver(), Settings.System.RINGTONE,
"content://test/ringtone");
mController.updateState(preference); mController.updateState(preference);
verify(preference).setSummary(anyString()); verify(preference).setSummary(anyString());
} }
@Test
public void updateState_nullRingtone_shouldNotGetTitle() {
Preference preference = mock(Preference.class);
Settings.System.putString(mContext.getContentResolver(), Settings.System.RINGTONE, null);
mController.updateState(preference);
verify(preference, never()).setSummary(anyString());
}
private class RingtonePreferenceControllerBaseTestable private class RingtonePreferenceControllerBaseTestable
extends RingtonePreferenceControllerBase { extends RingtonePreferenceControllerBase {
RingtonePreferenceControllerBaseTestable(Context context) { RingtonePreferenceControllerBaseTestable(Context context) {

View File

@@ -64,6 +64,7 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@@ -183,6 +184,20 @@ public class SettingsSliceProviderTest {
verify(mProvider).registerIntentToUri(eq(FakeToggleController.INTENT_FILTER), eq(uri)); verify(mProvider).registerIntentToUri(eq(FakeToggleController.INTENT_FILTER), eq(uri));
} }
@Test
public void loadSlice_registersBackgroundListener() {
insertSpecialCase(KEY);
final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
mProvider.loadSlice(uri);
Robolectric.flushForegroundThreadScheduler();
Robolectric.flushBackgroundThreadScheduler();
assertThat(mProvider.mPinnedWorkers.get(uri).getClass())
.isEqualTo(FakeToggleController.TestWorker.class);
}
@Test @Test
public void testLoadSlice_doesNotCacheWithoutPin() { public void testLoadSlice_doesNotCacheWithoutPin() {
insertSpecialCase(KEY); insertSpecialCase(KEY);

View File

@@ -19,9 +19,8 @@ package com.android.settings.testutils;
import android.content.Context; import android.content.Context;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.slices.Copyable;
public class FakeCopyableController extends BasePreferenceController implements Copyable { public class FakeCopyableController extends BasePreferenceController {
public FakeCopyableController(Context context, String preferenceKey) { public FakeCopyableController(Context context, String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
@@ -38,6 +37,7 @@ public class FakeCopyableController extends BasePreferenceController implements
} }
@Override @Override
public void copy() { public boolean isCopyableSlice() {
return true;
} }
} }

View File

@@ -19,10 +19,14 @@ package com.android.settings.testutils;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.Uri;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.provider.Settings; import android.provider.Settings;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
import com.android.settings.slices.SliceBackgroundWorker;
import java.io.IOException;
public class FakeToggleController extends TogglePreferenceController { public class FakeToggleController extends TogglePreferenceController {
@@ -70,6 +74,11 @@ public class FakeToggleController extends TogglePreferenceController {
return true; return true;
} }
@Override
public Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
return TestWorker.class;
}
@Override @Override
public boolean hasAsyncUpdate() { public boolean hasAsyncUpdate() {
return mIsAsyncUpdate; return mIsAsyncUpdate;
@@ -78,4 +87,23 @@ public class FakeToggleController extends TogglePreferenceController {
public void setAsyncUpdate(boolean isAsyncUpdate) { public void setAsyncUpdate(boolean isAsyncUpdate) {
mIsAsyncUpdate = isAsyncUpdate; mIsAsyncUpdate = isAsyncUpdate;
} }
public static class TestWorker extends SliceBackgroundWorker<Void> {
public TestWorker(Context context, Uri uri) {
super(context, uri);
}
@Override
protected void onSlicePinned() {
}
@Override
protected void onSliceUnpinned() {
}
@Override
public void close() throws IOException {
}
}
} }

View File

@@ -1,59 +0,0 @@
/*
* Copyright (C) 2017 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;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.support.test.uiautomator.UiDevice;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DisplaySettingsTest {
private Instrumentation mInstrumentation;
private Context mContext;
private UiDevice mDevice;
@Before
public void setUp() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getTargetContext();
mDevice = UiDevice.getInstance(mInstrumentation);
}
@Test
public void launchBrightnessLevel_shouldNotCrash() {
mInstrumentation.startActivitySync(
new Intent(mContext, DisplaySettings.class));
onView(withText(mContext.getString(R.string.brightness))).perform(click());
// should not crash
mDevice.pressBack(); // dismiss the brightness dialog
}
}

View File

@@ -1,110 +0,0 @@
/*
* Copyright (C) 2017 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;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.app.Instrumentation.ActivityResult;
import android.content.Context;
import android.content.Intent;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.google.android.setupcompat.PartnerCustomizationLayout;
import com.google.android.setupcompat.template.FooterBarMixin;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class EncryptionInterstitialTest {
private Instrumentation mInstrumentation;
private Context mContext;
private TestActivityMonitor mActivityMonitor;
@Before
public void setUp() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getTargetContext();
mActivityMonitor = new TestActivityMonitor();
mInstrumentation.addMonitor(mActivityMonitor);
}
@After
public void tearDown() {
mInstrumentation.removeMonitor(mActivityMonitor);
}
@Test
public void clickYes_shouldRequirePassword() {
final Activity activity = mInstrumentation.startActivitySync(
new Intent(mContext, EncryptionInterstitial.class)
.putExtra("extra_unlock_method_intent", new Intent("test.unlock.intent")));
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
layout.getMixin(FooterBarMixin.class).getPrimaryButtonView().performClick();
mActivityMonitor.waitForActivityWithTimeout(1000);
assertEquals(1, mActivityMonitor.getHits());
assertTrue(mActivityMonitor.mMatchedIntent.getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, false));
}
@Test
public void clickNo_shouldNotRequirePassword() {
final Activity activity = mInstrumentation.startActivitySync(
new Intent(mContext, EncryptionInterstitial.class)
.putExtra("extra_unlock_method_intent", new Intent("test.unlock.intent")));
final PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
layout.getMixin(FooterBarMixin.class).getSecondaryButtonView().performClick();
mActivityMonitor.waitForActivityWithTimeout(1000);
assertEquals(1, mActivityMonitor.getHits());
assertFalse(mActivityMonitor.mMatchedIntent.getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true));
}
private static class TestActivityMonitor extends ActivityMonitor {
Intent mMatchedIntent = null;
@Override
public ActivityResult onStartActivity(Intent intent) {
if ("test.unlock.intent".equals(intent.getAction())) {
mMatchedIntent = intent;
return new ActivityResult(Activity.RESULT_OK, null);
}
return null;
}
}
}

View File

@@ -1,126 +0,0 @@
/*
* Copyright (C) 2017 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;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ManagedAccessSettingsLowRamTest {
private Instrumentation mInstrumentation;
private Context mTargetContext;
@Before
public void setUp() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTargetContext = mInstrumentation.getTargetContext();
}
@Test
public void testManagedAccessOptionsVisibility() throws Exception {
mInstrumentation.startActivitySync(new Intent(mTargetContext,
com.android.settings.Settings.AppAndNotificationDashboardActivity.class));
onView(withText(mTargetContext.getString(R.string.expand_button_title))).perform(click());
onView(withText(mTargetContext.getString(R.string.special_access))).perform(click());
String[] managedServiceLabels = new String[] {"Do Not Disturb access",
"VR helper services", "Notification access", "Picture-in-picture"};
for (String label : managedServiceLabels) {
if (ActivityManager.isLowRamDeviceStatic()) {
onView(withText(label)).check(doesNotExist());
} else {
onView(withText(label)).check(matches(isDisplayed()));
}
}
}
@Test
public void launchNotificationSetting_onlyWorksIfNotLowRam() {
final Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
mInstrumentation.startActivitySync(intent);
final String label = "This feature is not available on this device";
if (ActivityManager.isLowRamDeviceStatic()) {
onView(withText(label)).check(matches(isDisplayed()));
} else {
onView(withText(label)).check(doesNotExist());
}
}
@Test
public void launchDndSetting_onlyWorksIfNotLowRam() {
final Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
mInstrumentation.startActivitySync(intent);
final String label = "This feature is not available on this device";
if (ActivityManager.isLowRamDeviceStatic()) {
onView(withText(label)).check(matches(isDisplayed()));
} else {
onView(withText(label)).check(doesNotExist());
}
}
@Test
public void launchVrSetting_onlyWorksIfNotLowRam() {
final Intent intent = new Intent(Settings.ACTION_VR_LISTENER_SETTINGS);
mInstrumentation.startActivitySync(intent);
final String label = "This feature is not available on this device";
if (ActivityManager.isLowRamDeviceStatic()) {
onView(withText(label)).check(matches(isDisplayed()));
} else {
onView(withText(label)).check(doesNotExist());
}
}
@Test
public void launchPictureInPictureSetting_onlyWorksIfNotLowRam() {
final Intent intent = new Intent(Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS);
mInstrumentation.startActivitySync(intent);
final String label = "This feature is not available on this device";
if (ActivityManager.isLowRamDeviceStatic()) {
onView(withText(label)).check(matches(isDisplayed()));
} else {
onView(withText(label)).check(doesNotExist());
}
}
}

View File

@@ -16,12 +16,6 @@
package com.android.settings; package com.android.settings;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.RootMatchers.isDialog;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static junit.framework.Assert.fail; import static junit.framework.Assert.fail;
import android.app.Instrumentation; import android.app.Instrumentation;
@@ -29,8 +23,6 @@ import android.app.UiAutomation;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.util.Log;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -40,10 +32,6 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class RegulatoryInfoDisplayActivityTest { public class RegulatoryInfoDisplayActivityTest {
@@ -82,73 +70,4 @@ public class RegulatoryInfoDisplayActivityTest {
return; return;
} }
} }
@Test
public void launchRegulatoryInfo_shouldNotCrash() {
final Context context = mInstrumentation.getTargetContext();
final boolean hasRegulatoryInfo = context.getResources()
.getBoolean(R.bool.config_show_regulatory_info);
if (!hasRegulatoryInfo) {
return;
}
// Launch intent
mInstrumentation.startActivitySync(mRegulatoryInfoIntent);
onView(withId(R.id.regulatoryInfo))
.inRoot(isDialog())
.check(matches(isDisplayed()));
}
@Test
public void launchRegulatoryInfo_withInfoImage_shouldDisplay() throws IOException {
// TODO: Remove "setenforce 0" when selinux rules is updated to give read permission for
// regulatory info.
mUiAutomation.executeShellCommand("setenforce 0");
final boolean tempFileCreated = ensureRegulatoryInfoImageExists();
try {
final Context context = mInstrumentation.getTargetContext();
final boolean hasRegulatoryInfo = context.getResources()
.getBoolean(R.bool.config_show_regulatory_info);
if (!hasRegulatoryInfo) {
return;
}
// Launch intent
mInstrumentation.startActivitySync(mRegulatoryInfoIntent);
onView(withId(R.id.regulatoryInfo))
.inRoot(isDialog())
.check(matches(isDisplayed()));
} finally {
if (tempFileCreated) {
final String filename =
RegulatoryInfoDisplayActivity.getRegulatoryInfoImageFileName();
new File(filename).delete();
Log.d(TAG, "Deleting temp file " + filename);
}
}
}
/**
* Ensures regulatory label image exists on disk.
*
* @return true if a test image is created.
*/
private boolean ensureRegulatoryInfoImageExists() throws IOException {
final String filename = RegulatoryInfoDisplayActivity.getRegulatoryInfoImageFileName();
if (new File(filename).exists()) {
return false;
}
Log.d(TAG, "Creating temp file " + filename);
final Bitmap bitmap = Bitmap.createBitmap(400 /* width */, 400 /* height */,
Bitmap.Config.ARGB_8888);
final FileOutputStream out = new FileOutputStream(filename);
bitmap.compress(Bitmap.CompressFormat.PNG, 100 /* quality */, out);
out.close();
return true;
}
} }

View File

@@ -1,130 +0,0 @@
/*
* Copyright (C) 2010 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;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.test.ActivityInstrumentationTestCase2;
import java.util.List;
/**
* Tests for the Settings operator/manufacturer hook.
*
* Running all tests:
*
* make SettingsTests
* adb push SettingsTests.apk /system/app/SettingsTests.apk
* adb shell am instrument \
* -w com.android.settings.tests/android.test.InstrumentationTestRunner
*/
public class SettingsHookTests extends ActivityInstrumentationTestCase2<Settings> {
private static final String PACKAGE_NAME = "com.android.settings.tests.unit";
private static final String KEY_SETTINGS_ROOT = "parent";
private static final String KEY_SETTINGS_OPERATOR = "operator_settings";
private static final String KEY_SETTINGS_MANUFACTURER = "manufacturer_settings";
private static final String INTENT_OPERATOR_HOOK = "com.android.settings.OPERATOR_APPLICATION_SETTING";
private static final String INTENT_MANUFACTURER_HOOK = "com.android.settings.MANUFACTURER_APPLICATION_SETTING";
private Settings mSettings;
public SettingsHookTests() {
super("com.android.settings", Settings.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mSettings = getActivity();
}
/**
* Test that the operator/manufacturer settings hook test application is
* available and that it's installed in the device's system image.
*/
public void testSettingsHookTestAppAvailable() throws Exception {
Context context = mSettings.getApplicationContext();
PackageManager pm = context.getPackageManager();
ApplicationInfo applicationInfo = pm.getApplicationInfo(PACKAGE_NAME, 0);
assertTrue((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
}
/**
* Test that the operator test activity has registered an intent-filter for
* an action named 'android.settings.OPERATOR_APPLICATION_SETTING'.
*/
public void testOperatorIntentFilter() {
boolean result = false;
Context context = mSettings.getApplicationContext();
PackageManager pm = context.getPackageManager();
Intent intent = new Intent(INTENT_OPERATOR_HOOK);
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : list) {
if (resolveInfo.activityInfo.packageName.equals(PACKAGE_NAME)) {
result = true;
}
}
assertTrue("Intent-filter not found", result);
}
/**
* Test that the manufacturer test activity has registered an intent-filter
* for an action named 'android.settings.MANUFACTURER_APPLICATION_SETTING'.
*/
public void testManufacturerIntentFilter() {
boolean result = false;
Context context = mSettings.getApplicationContext();
PackageManager pm = context.getPackageManager();
Intent intent = new Intent(INTENT_MANUFACTURER_HOOK);
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : list) {
if (resolveInfo.activityInfo.packageName.equals(PACKAGE_NAME)) {
result = true;
}
}
assertTrue("Intent-filter not found", result);
}
/**
* Test that the operator preference is available in the Settings
* application.
*/
public void testOperatorPreferenceAvailable() {
// TODO: fix this test case to work with fragments
// PreferenceGroup root = (PreferenceGroup)mSettings.findPreference(KEY_SETTINGS_ROOT);
// Preference operatorPreference = root.findPreference(KEY_SETTINGS_OPERATOR);
// assertNotNull(operatorPreference);
}
/**
* Test that the manufacturer preference is available in the Settings
* application.
*/
public void testManufacturerPreferenceAvailable() {
// TODO: fix this test case to work with fragments
// PreferenceGroup root = (PreferenceGroup)mSettings.findPreference(KEY_SETTINGS_ROOT);
// Preference manufacturerHook = root.findPreference(KEY_SETTINGS_MANUFACTURER);
// assertNotNull(manufacturerHook);
}
}

View File

@@ -30,6 +30,7 @@ import static org.hamcrest.Matchers.allOf;
import android.app.Instrumentation; import android.app.Instrumentation;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.widget.CompoundButton; import android.widget.CompoundButton;
@@ -63,14 +64,6 @@ public class AccessibilityShortcutPreferenceFragmentTest {
mActivity = mActivityRule.getActivity(); mActivity = mActivityRule.getActivity();
} }
@Test
public void lockScreenPreference_defaultBeforeDialogShown_isOff() {
setDialogShown(false);
setOnLockscreen(null);
startFragment();
assertLockscreenSwitchIsCheckedIs(false);
}
@Test @Test
public void lockScreenPreference_setOnBeforeDialogShown_isOn() { public void lockScreenPreference_setOnBeforeDialogShown_isOn() {
setDialogShown(false); setDialogShown(false);
@@ -87,14 +80,6 @@ public class AccessibilityShortcutPreferenceFragmentTest {
assertLockscreenSwitchIsCheckedIs(true); assertLockscreenSwitchIsCheckedIs(true);
} }
@Test
public void lockScreenPreference_setOffAfterDialogShown_isOn() {
setDialogShown(true);
setOnLockscreen(false);
startFragment();
assertLockscreenSwitchIsCheckedIs(false);
}
private void startFragment() { private void startFragment() {
mInstrumentation.runOnMainSync(() -> { mInstrumentation.runOnMainSync(() -> {
new SubSettingLauncher(mActivity) new SubSettingLauncher(mActivity)

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C) 2017 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.applications;
import android.content.Context;
import android.content.Intent;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
import android.widget.TextView;
import androidx.test.filters.SmallTest;
import com.android.settings.R;
import org.junit.Test;
/**
* Test for Advanced App preferences.
*/
@SmallTest
public class DefaultAppSettingsTest extends InstrumentationTestCase {
private UiDevice mDevice;
private Context mTargetContext;
private String mTargetPackage;
@Override
protected void setUp() throws Exception {
super.setUp();
mDevice = UiDevice.getInstance(getInstrumentation());
mTargetContext = getInstrumentation().getTargetContext();
mTargetPackage = mTargetContext.getPackageName();
}
@Test
public void testSelectDefaultHome_shouldLaunchHomePicker() throws Exception {
launchDefaultApps();
final String titleHomeApp = mTargetContext.getResources().getString(R.string.home_app);
mDevice.findObject(new UiSelector().text(titleHomeApp)).click();
final UiObject actionBar = mDevice.findObject(new UiSelector().resourceId(
"com.android.settings:id/action_bar"));
final UiObject title = actionBar.getChild(
new UiSelector().className(TextView.class.getName()));
assertEquals(titleHomeApp, title.getText());
}
private void launchDefaultApps() throws Exception {
final Intent settingsIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(mTargetPackage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getInstrumentation().getContext().startActivity(settingsIntent);
final String titleApps = mTargetContext.getResources().getString(
R.string.app_and_notification_dashboard_title);
mDevice.findObject(new UiSelector().text(titleApps)).click();
final String titleAdvance = mTargetContext.getResources().getString(
R.string.advanced_section_header);
mDevice.findObject(new UiSelector().text(titleAdvance)).click();
final String titleDefaultApps = mTargetContext.getResources().getString(
R.string.app_default_dashboard_title);
mDevice.findObject(new UiSelector().text(titleDefaultApps)).click();
}
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright (C) 2017 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.applications;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import android.app.Instrumentation;
import android.content.Intent;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ManageApplicationsLaunchTest {
private Instrumentation mInstrumentation;
@Before
public void setUp() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
}
@Test
public void launchAppsSettings_shouldShowAppList() throws Exception {
final Intent appsSettingsIntent = new
Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
mInstrumentation.startActivitySync(appsSettingsIntent);
onView(allOf(withText("Calculator"))).check(matches(isDisplayed()));
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2017 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.applications;
import android.content.Context;
import android.content.Intent;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.test.InstrumentationTestCase;
import android.widget.TextView;
import androidx.test.filters.SmallTest;
import com.android.settings.R;
import org.junit.Test;
/**
* Test for Special App Access preferences.
*/
@SmallTest
public class SpecialAppAccessSettingsTest extends InstrumentationTestCase {
private UiDevice mDevice;
private Context mTargetContext;
private String mTargetPackage;
@Override
protected void setUp() throws Exception {
super.setUp();
mDevice = UiDevice.getInstance(getInstrumentation());
mTargetContext = getInstrumentation().getTargetContext();
mTargetPackage = mTargetContext.getPackageName();
}
@Test
public void testSelectPictureInPicture_shouldNotCrash() throws Exception {
launchSpecialApps();
final String titlePictureInPictureApp =
mTargetContext.getResources().getString(R.string.picture_in_picture_title);
// select Picture-in-Picture
mDevice.findObject(new UiSelector().text(titlePictureInPictureApp)).click();
// Picture-in-picture settings page should launch and no crash
final UiObject actionBar = mDevice.findObject(new UiSelector().resourceId(
"com.android.settings:id/action_bar"));
final UiObject title = actionBar.getChild(
new UiSelector().className(TextView.class.getName()));
assertEquals(titlePictureInPictureApp, title.getText());
}
private void launchSpecialApps() throws Exception {
final Intent settingsIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(mTargetPackage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getInstrumentation().getContext().startActivity(settingsIntent);
final String titleApps = mTargetContext.getResources().getString(
R.string.app_and_notification_dashboard_title);
mDevice.findObject(new UiSelector().text(titleApps)).click();
final String titleAdvance = mTargetContext.getResources().getString(
R.string.advanced_section_header);
mDevice.findObject(new UiSelector().text(titleAdvance)).click();
final String titleSpecialApps = mTargetContext.getResources().getString(
R.string.special_access);
try {
// scollbar may or may not be present, depending on how many recents app are there. If
// the page is scrollable, scroll to the bottom to show the special app access settings.
final UiScrollable settings = new UiScrollable(
new UiSelector().packageName(mTargetContext.getPackageName()).scrollable(true));
settings.scrollTextIntoView(titleSpecialApps);
} catch (UiObjectNotFoundException e) {
// ignore
}
mDevice.findObject(new UiSelector().text(titleSpecialApps)).click();
}
}

View File

@@ -39,7 +39,7 @@ import java.util.List;
public class BackupIntentTest { public class BackupIntentTest {
private static final String INTENT_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; private static final String INTENT_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
private static final String BACKUP_SETTINGS_ACTIVITY = private static final String BACKUP_SETTINGS_ACTIVITY =
"com.android.settings.backup.UserBackupSettingsActivity"; "com.android.settings.Settings$PrivacyDashboardActivity";
private Context mContext; private Context mContext;

View File

@@ -1,106 +0,0 @@
/*
* Copyright (C) 2017 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.bluetooth;
import static org.mockito.Mockito.when;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.support.test.uiautomator.UiDevice;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.SettingsActivity;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.instrumentation.Instrumentable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class BluetoothDeviceDetailsRotationTest {
private Context mContext;
private UiDevice mUiDevice;
private Instrumentation mInstrumentation;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private CachedBluetoothDevice mCachedDevice;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private LocalBluetoothManager mBluetoothManager;
private String mDeviceAddress;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getTargetContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mDeviceAddress = "AA:BB:CC:DD:EE:FF";
when(mCachedDevice.getAddress()).thenReturn(mDeviceAddress);
when(mCachedDevice.getName()).thenReturn("Mock Device");
BluetoothDeviceDetailsFragment.sTestDataFactory =
new BluetoothDeviceDetailsFragment.TestDataFactory() {
@Override
public CachedBluetoothDevice getDevice(String deviceAddress) {
return mCachedDevice;
}
@Override
public LocalBluetoothManager getManager(Context context) {
return mBluetoothManager;
}
};
}
@Test
public void rotation() {
Intent intent = new Intent("android.settings.BLUETOOTH_SETTINGS");
SettingsActivity activity = (SettingsActivity) mInstrumentation.startActivitySync(intent);
Bundle args = new Bundle(1);
args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS, mDeviceAddress);
new SubSettingLauncher(activity)
.setDestination(BluetoothDeviceDetailsFragment.class.getName())
.setTitleText("test")
.setArguments(args)
.setSourceMetricsCategory(Instrumentable.METRICS_CATEGORY_UNKNOWN)
.launch();
try {
mUiDevice.setOrientationLeft();
mUiDevice.setOrientationNatural();
mUiDevice.setOrientationRight();
mUiDevice.setOrientationNatural();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2017 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.bluetooth;
import android.app.Instrumentation;
import android.content.Intent;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DevicePickerActivityTest {
private Instrumentation mInstrumentation;
@Before
public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
}
@Test
public void startActivityNoCrash() {
mInstrumentation.startActivitySync(
new Intent("android.bluetooth.devicepicker.action.LAUNCH"));
// No crash
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C) 2017 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.connecteddevice;
import static com.google.common.truth.Truth.assertThat;
import android.app.Instrumentation;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class ConnectedDeviceActivityTest {
private static final String INTENT_ACTION = "android.intent.action.MAIN";
private static final String CONNECTED_DEVICE_TITLE = "Connected devices";
private Instrumentation mInstrumentation;
@Before
public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
}
@Test
public void queryConnectedDeviceActivity_onlyOneResponse() {
final PackageManager packageManager = mInstrumentation.getContext().getPackageManager();
final Intent intent = new Intent(INTENT_ACTION);
int count = 0;
final List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent,
PackageManager.GET_META_DATA);
for (ResolveInfo info : resolveInfoList) {
if (TextUtils.equals(info.activityInfo.loadLabel(packageManager).toString(),
CONNECTED_DEVICE_TITLE)) {
count++;
}
}
assertThat(count).isEqualTo(1);
}
}

View File

@@ -18,13 +18,9 @@ package com.android.settings.dashboard;
import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; import static androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static com.android.settings.dashboard.FirstIdViewMatcher.withFirstId;
import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.allOf;
import android.app.Instrumentation; import android.app.Instrumentation;
@@ -57,12 +53,6 @@ public class PreferenceThemeTest {
mTargetPackage = mTargetContext.getPackageName(); mTargetPackage = mTargetContext.getPackageName();
} }
@Test
public void startPhoneStatus_preferenceIconSpaceReserved() throws InterruptedException {
launchPhoneStatus();
onView(withFirstId(R.id.icon_frame)).check(matches(isDisplayed()));
}
@Test @Test
public void startSetupWizardLockScreen_preferenceIconSpaceNotReserved() { public void startSetupWizardLockScreen_preferenceIconSpaceNotReserved() {
launchSetupWizardLockScreen(); launchSetupWizardLockScreen();
@@ -72,14 +62,6 @@ public class PreferenceThemeTest {
onView(withId(R.id.icon_container)).check(doesNotExist()); onView(withId(R.id.icon_container)).check(doesNotExist());
} }
private void launchPhoneStatus() {
final Intent settingsIntent = new Intent("android.settings.DEVICE_INFO_SETTINGS")
.addCategory(Intent.CATEGORY_DEFAULT)
.setPackage(mTargetPackage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
InstrumentationRegistry.getInstrumentation().startActivitySync(settingsIntent);
}
private void launchSetupWizardLockScreen() { private void launchSetupWizardLockScreen() {
final Intent settingsIntent = new Intent("com.android.settings.SETUP_LOCK_SCREEN") final Intent settingsIntent = new Intent("com.android.settings.SETUP_LOCK_SCREEN")
.addCategory(Intent.CATEGORY_DEFAULT) .addCategory(Intent.CATEGORY_DEFAULT)

View File

@@ -1,64 +0,0 @@
/*
* Copyright (C) 2017 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;
import static junit.framework.Assert.assertEquals;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.NetworkTemplate;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MobileDataUsageActivityTest {
private static final String TAG = "MobileDataUsageTest";
@Test
public void test_mobileDataUsageIntent() {
final Context context = InstrumentationRegistry.getTargetContext();
final PackageManager packageManager = context.getPackageManager();
final int subId = SubscriptionManager.getDefaultSubscriptionId();
final NetworkTemplate template = getNetworkTemplate(context, subId);
Intent intent = new Intent(android.provider.Settings.ACTION_MOBILE_DATA_USAGE);
intent.putExtra(android.provider.Settings.EXTRA_NETWORK_TEMPLATE, template);
intent.putExtra(android.provider.Settings.EXTRA_SUB_ID, subId);
assertEquals(packageManager.queryIntentActivities(intent, 0).size(), 1);
context.startActivity(intent);
// Should exit gracefully without crashing.
}
private NetworkTemplate getNetworkTemplate(Context context, int subId) {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
tm.getSubscriberId(subId));
return NetworkTemplate.normalize(mobileAll,
tm.getMergedSubscriberIds());
}
}

View File

@@ -56,9 +56,6 @@ public class TimeZoneDataTest {
*/ */
assertThat(mTimeZoneData.lookupCountryCodesForZoneId("Europe/Simferopol").isEmpty()) assertThat(mTimeZoneData.lookupCountryCodesForZoneId("Europe/Simferopol").isEmpty())
.isTrue(); .isTrue();
// Metlakatla has the same time as Anchorage after 2015
assertThat(mTimeZoneData.lookupCountryCodesForZoneId("America/Metlakatla").isEmpty())
.isTrue();
assertThat(mTimeZoneData.lookupCountryCodesForZoneId("Europe/London").isEmpty()) assertThat(mTimeZoneData.lookupCountryCodesForZoneId("Europe/London").isEmpty())
.isFalse(); .isFalse();
assertThat(mTimeZoneData.lookupCountryCodesForZoneId("America/Los_Angeles").isEmpty()) assertThat(mTimeZoneData.lookupCountryCodesForZoneId("America/Los_Angeles").isEmpty())

View File

@@ -1,41 +0,0 @@
package com.android.settings.deviceinfo;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.intent.Intents.intended;
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import androidx.test.espresso.intent.rule.IntentsTestRule;
import androidx.test.filters.SmallTest;
import com.android.settings.R;
import com.android.settings.Settings.StorageDashboardActivity;
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import org.junit.Rule;
import org.junit.Test;
@SmallTest
public class StorageDashboardFragmentTest {
public static final String EXTRA_KEY = ":settings:show_fragment";
@Rule
public IntentsTestRule<StorageDashboardActivity> mActivityRule =
new IntentsTestRule<>(StorageDashboardActivity.class, true, true);
@Test
public void testStorageManagePreference_canClickTextView() throws InterruptedException {
// Click on the actual textbox instead of just somewhere in the preference
onView(withText(R.string.automatic_storage_manager_preference_title)).perform(click());
// Check that it worked by seeing if we switched screens
intended(hasExtra(equalTo(EXTRA_KEY),
containsString(AutomaticStorageManagerSettings.class.getName())));
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) 2017 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.dream;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DreamSettingsLaunchTest {
@Test
public void launchFromIntent_doesNotCrash() {
final Context context = InstrumentationRegistry.getTargetContext();
Intent intent = new Intent(Settings.ACTION_DREAM_SETTINGS);
context.startActivity(intent);
}
}

View File

@@ -41,6 +41,7 @@ import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.provider.Settings; import android.provider.Settings;
import android.support.test.uiautomator.UiDevice;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.espresso.intent.Intents; import androidx.test.espresso.intent.Intents;
@@ -55,7 +56,9 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class AppNotificationSettingsTest { public class AppNotificationSettingsTest {
private static final String WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard";
private UiDevice mUiDevice;
private Context mTargetContext; private Context mTargetContext;
private Instrumentation mInstrumentation; private Instrumentation mInstrumentation;
@@ -68,9 +71,14 @@ public class AppNotificationSettingsTest {
private NotificationChannel mUngroupedChannel; private NotificationChannel mUngroupedChannel;
@Before @Before
public void setUp() { public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation(); mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTargetContext = mInstrumentation.getTargetContext(); mTargetContext = mInstrumentation.getTargetContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mUiDevice.wakeUp();
mUiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND);
mNm = (NotificationManager) mTargetContext.getSystemService(Context.NOTIFICATION_SERVICE); mNm = (NotificationManager) mTargetContext.getSystemService(Context.NOTIFICATION_SERVICE);
mGroup1 = new NotificationChannelGroup(this.getClass().getName() + "1", "group1"); mGroup1 = new NotificationChannelGroup(this.getClass().getName() + "1", "group1");
@@ -87,7 +95,8 @@ public class AppNotificationSettingsTest {
@Test @Test
public void launchNotificationSetting_shouldNotHaveAppInfoLink() { public void launchNotificationSetting_shouldNotHaveAppInfoLink() {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName()); .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mInstrumentation.startActivitySync(intent); mInstrumentation.startActivitySync(intent);
@@ -99,60 +108,38 @@ public class AppNotificationSettingsTest {
@Test @Test
public void launchNotificationSetting_showGroupsWithMultipleChannels() { public void launchNotificationSetting_showGroupsWithMultipleChannels() {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName()); .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mInstrumentation.startActivitySync(intent); mInstrumentation.startActivitySync(intent);
onView(allOf(withText(mGroup1.getName().toString()))).check( onView(allOf(withText(mGroup1.getName().toString()))).check(
matches(isDisplayed())); matches(isDisplayed()));
try { onView(allOf(withText(mGroup1Channel1.getName().toString()))).check(
onView(allOf(withText(mGroup1Channel1.getName().toString()))) matches(isDisplayed()));
.check(matches(isDisplayed())); onView(allOf(withText(mGroup1Channel2.getName().toString()))).check(
fail("Channel erroneously appearing"); matches(isDisplayed()));
} catch (Exception e) {
// expected
}
// links to group page
Intents.init();
onView(allOf(withText(mGroup1.getName().toString()))).perform(click());
intended(allOf(hasExtra(EXTRA_SHOW_FRAGMENT,
ChannelGroupNotificationSettings.class.getName())));
Intents.release();
} }
@Test @Test
public void launchNotificationSetting_showUngroupedChannels() { public void launchNotificationSetting_showUngroupedChannels() {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName()); .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mInstrumentation.startActivitySync(intent); mInstrumentation.startActivitySync(intent);
onView(allOf(withText(mUngroupedChannel.getName().toString()))) onView(allOf(withText(mUngroupedChannel.getName().toString())))
.check(matches(isDisplayed())); .check(matches(isDisplayed()));
// links directly to channel page
Intents.init();
onView(allOf(withText(mUngroupedChannel.getName().toString()))).perform(click());
intended(allOf(hasExtra(EXTRA_SHOW_FRAGMENT, ChannelNotificationSettings.class.getName())));
Intents.release();
} }
@Test @Test
public void launchNotificationSetting_showGroupsWithOneChannel() { public void launchNotificationSetting_showGroupsWithOneChannel() {
final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName()); .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mInstrumentation.startActivitySync(intent); mInstrumentation.startActivitySync(intent);
onView(allOf(withText(mGroup2.getName().toString())))
.check(matches(isDisplayed()));
onView(allOf(withText(mGroup2Channel1.getName().toString()))) onView(allOf(withText(mGroup2Channel1.getName().toString())))
.check(matches(isDisplayed())); .check(matches(isDisplayed()));
try {
onView(allOf(withText(mGroup2.getName().toString()))).check(
matches(isDisplayed()));
fail("Group erroneously appearing");
} catch (Exception e) {
// expected
}
// links directly to channel page
Intents.init();
onView(allOf(withText(mGroup2Channel1.getName().toString()))).perform(click());
intended(allOf(hasExtra(EXTRA_SHOW_FRAGMENT, ChannelNotificationSettings.class.getName())));
Intents.release();
} }
private NotificationChannel createChannel(NotificationChannelGroup group, private NotificationChannel createChannel(NotificationChannelGroup group,

View File

@@ -36,6 +36,7 @@ import android.content.Intent;
import android.os.Process; import android.os.Process;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.provider.Settings; import android.provider.Settings;
import android.support.test.uiautomator.UiDevice;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -48,17 +49,23 @@ import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class ChannelNotificationSettingsTest { public class ChannelNotificationSettingsTest {
private static final String WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard";
private UiDevice mUiDevice;
private Context mTargetContext; private Context mTargetContext;
private Instrumentation mInstrumentation; private Instrumentation mInstrumentation;
private NotificationChannel mNotificationChannel; private NotificationChannel mNotificationChannel;
private NotificationManager mNm; private NotificationManager mNm;
@Before @Before
public void setUp() { public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation(); mInstrumentation = InstrumentationRegistry.getInstrumentation();
mTargetContext = mInstrumentation.getTargetContext(); mTargetContext = mInstrumentation.getTargetContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mUiDevice.wakeUp();
mUiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND);
mNm = (NotificationManager) mTargetContext.getSystemService(Context.NOTIFICATION_SERVICE); mNm = (NotificationManager) mTargetContext.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationChannel = new NotificationChannel(this.getClass().getName(), mNotificationChannel = new NotificationChannel(this.getClass().getName(),
this.getClass().getName(), IMPORTANCE_MIN); this.getClass().getName(), IMPORTANCE_MIN);
@@ -69,7 +76,8 @@ public class ChannelNotificationSettingsTest {
public void launchNotificationSetting_shouldNotCrash() { public void launchNotificationSetting_shouldNotCrash() {
final Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) final Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName()) .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_ID, mNotificationChannel.getId()); .putExtra(Settings.EXTRA_CHANNEL_ID, mNotificationChannel.getId())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mInstrumentation.startActivitySync(intent); mInstrumentation.startActivitySync(intent);
onView(allOf(withText(mNotificationChannel.getName().toString()))).check( onView(allOf(withText(mNotificationChannel.getName().toString()))).check(
@@ -90,12 +98,12 @@ public class ChannelNotificationSettingsTest {
final Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) final Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName()) .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
.putExtra(Settings.EXTRA_CHANNEL_ID, blocked.getId()); .putExtra(Settings.EXTRA_CHANNEL_ID, blocked.getId())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mInstrumentation.startActivitySync(intent); mInstrumentation.startActivitySync(intent);
onView(allOf(withText("Off"), isDisplayed())).check(matches(isDisplayed())); onView(allOf(withText("At your request, Android is blocking this category of notifications"
onView(allOf(withText("Android is blocking this category of notifications from" + " from appearing on this device"))).check(matches(isDisplayed()));
+ " appearing on this device"))).check(matches(isDisplayed()));
try { try {
onView(allOf(withText("On the lock screen"))).check(matches(isDisplayed())); onView(allOf(withText("On the lock screen"))).check(matches(isDisplayed()));

View File

@@ -37,27 +37,29 @@ public class ZenModeSettingsIntegrationTest {
@Test @Test
public void testZenModeSettingsPreferences() { public void testZenModeSettingsPreferences() {
launchZenSettings(); launchZenSettings();
onView(withText("Behavior")).check(matches(isDisplayed())); onView(withText("Calls")).check(matches(isDisplayed()));
onView(withText("Turn on automatically")).check(matches(isDisplayed())); onView(withText("SMS, MMS, and messaging apps")).check(matches(isDisplayed()));
onView(withText("Restrict notifications")).check(matches(isDisplayed()));
onView(withText("Duration")).check(matches(isDisplayed()));
onView(withText("Schedules")).check(matches(isDisplayed()));
} }
@Test @Test
public void testZenModeBehaviorPreferences() { public void testZenModeBehaviorPreferences() {
launchZenBehaviorSettings(); launchZenBehaviorSettings();
onView(withText("Alarms")).check(matches(isDisplayed()));
onView(withText("Media and system feedback")).check(matches(isDisplayed()));
onView(withText("Reminders")).check(matches(isDisplayed()));
onView(withText("Events")).check(matches(isDisplayed()));
onView(withText("Messages")).check(matches(isDisplayed()));
onView(withText("Calls")).check(matches(isDisplayed())); onView(withText("Calls")).check(matches(isDisplayed()));
onView(withText("Repeat callers")).check(matches(isDisplayed())); onView(withText("SMS, MMS, and messaging apps")).check(matches(isDisplayed()));
onView(withText("Restrict notifications")).check(matches(isDisplayed()));
onView(withText("Duration")).check(matches(isDisplayed()));
onView(withText("Schedules")).check(matches(isDisplayed()));
} }
@Test @Test
public void testZenModeAutomationPreferences() { public void testZenModeAutomationPreferences() {
launchZenAutomationSettings(); launchZenAutomationSettings();
onView(withText("Weekend")).check(matches(isDisplayed())); onView(withText("Sleeping")).check(matches(isDisplayed()));
onView(withText("Add rule")).check(matches(isDisplayed())); onView(withText("Event")).check(matches(isDisplayed()));
onView(withText("Add more")).check(matches(isDisplayed()));
} }
private void launchZenSettings() { private void launchZenSettings() {

View File

@@ -1,77 +0,0 @@
/*
* 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.
*/
package com.android.settings.tests;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.core.IsNot.not;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DrawOverlayDetailsTest {
private final static String PACKAGE_SYSTEM_UI = "com.android.systemui";
@Test
public void testSystemUiDrawOverlayDetails_Disabled() throws Exception{
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(android.provider.Settings
.ACTION_MANAGE_OVERLAY_PERMISSION));
final Context targetContext = instrumentation.getTargetContext();
final PackageManager packageManager = targetContext.getPackageManager();
final String appName = (String) packageManager.getApplicationLabel(packageManager
.getApplicationInfo(PACKAGE_SYSTEM_UI, PackageManager.GET_META_DATA));
final UiDevice device = UiDevice.getInstance(instrumentation);
device.waitForIdle();
openActionBarOverflowOrOptionsMenu(targetContext);
onView(withText(targetContext.getString(R.string.menu_show_system))).perform(click());
device.waitForIdle();
final UiScrollable settings = new UiScrollable(
new UiSelector().packageName(targetContext.getPackageName()).scrollable(true));
settings.scrollTextIntoView(appName);
onView(withText(appName)).perform(click());
onView(withText(targetContext.getString(R.string.permit_draw_overlay))).check(matches
(not(isEnabled())));
}
}

View File

@@ -1,72 +0,0 @@
/*
* 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.
*/
package com.android.settings.tests;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static junit.framework.Assert.assertEquals;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class KeepOnScreenTest {
private static int EXPECTED_FLAG = BatteryManager.BATTERY_PLUGGED_AC
| BatteryManager.BATTERY_PLUGGED_USB | BatteryManager.BATTERY_PLUGGED_WIRELESS;
@Test
public void testStayAwake_turnOn_StayAwakeWhileWirelessCharging() throws Exception{
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(android.provider.Settings
.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
final Context targetContext = instrumentation.getTargetContext();
final int prevFlag = Settings.Global.getInt(targetContext.getContentResolver(), Settings
.Global.STAY_ON_WHILE_PLUGGED_IN);
// Turn on "Stay Awake" if needed
if (prevFlag == 0) {
onView(withText(R.string.keep_screen_on)).perform(click());
}
final int currentFlag = Settings.Global.getInt(targetContext.getContentResolver(), Settings
.Global.STAY_ON_WHILE_PLUGGED_IN);
assertEquals(EXPECTED_FLAG, currentFlag);
// Since this app doesn't have permission(and shouldn't have) to change global setting, we
// can only tearDown in this way
if (prevFlag != currentFlag) {
onView(withText(R.string.keep_screen_on)).perform(click());
}
}
}

View File

@@ -1,42 +0,0 @@
/*
* 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.
*/
package com.android.settings.tests;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import android.app.Instrumentation;
import android.content.Intent;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class PrivateVolumeSettingsTest {
@Test
public void test_ManageStorageNotShown() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(
new Intent(android.provider.Settings.ACTION_INTERNAL_STORAGE_SETTINGS));
onView(withText(com.android.settings.R.string.storage_menu_manage)).check(doesNotExist());
}
}

View File

@@ -1,84 +0,0 @@
/*
* 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.
*/
package com.android.settings.tests;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class SettingsRestoreAfterCloseTest {
private static final String PACKAGE_SETTINGS = "com.android.settings";
private static final int TIME_OUT = 2000;
private boolean mAlwaysFinish;
@Before
public void setUp() throws Exception {
// To make sure when we press home button, the activity will be destroyed by OS
Context context = InstrumentationRegistry.getContext();
mAlwaysFinish = Settings.Global.getInt(
context.getContentResolver(), Settings.Global
.ALWAYS_FINISH_ACTIVITIES, 0)
!= 0;
ActivityManager.getService().setAlwaysFinish(true);
}
@After
public void tearDown() throws Exception {
ActivityManager.getService().setAlwaysFinish(mAlwaysFinish);
}
@Test
public void testRtlStability_AppCloseAndReOpen_shouldNotCrash() throws Exception {
final UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation
());
uiDevice.pressHome();
// Open the settings app
startSettingsMainActivity(uiDevice);
// Press home button
uiDevice.pressHome();
final String launcherPackage = uiDevice.getLauncherPackageName();
uiDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), TIME_OUT);
// Open the settings again
startSettingsMainActivity(uiDevice);
}
private void startSettingsMainActivity(UiDevice uiDevice) {
Context context = InstrumentationRegistry.getContext();
context.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
uiDevice.wait(Until.hasObject(By.pkg(PACKAGE_SETTINGS).depth(0)), TIME_OUT);
}
}

View File

@@ -1,140 +0,0 @@
/*
* 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.
*/
package com.android.settings.users;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.Intent;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class UserSettingsTest {
private static final String SYSTEM = "System";
private static final String ADVANCED = "Advanced";
private static final String USERS = "Multiple users";
private static final String EMERGNENCY_INFO = "Emergency information";
private static final String ADD_USERS_WHEN_LOCKED = "Add users";
private static final String SWITCH_USER_BUTTON = "com.android.systemui:id/multi_user_switch";
private static final String SETTINGS_BUTTON = "com.android.systemui:id/settings_button";
private static final String PRIMARY_USER = "Owner";
private static final String GUEST_USER = "Guest";
private static final String ADD_GUEST = "Add guest";
private static final String CONTINUE = "Yes, continue";
private UiDevice mDevice;
private Context mContext;
private String mTargetPackage;
@Before
public void setUp() {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mContext = InstrumentationRegistry.getTargetContext();
mTargetPackage = mContext.getPackageName();
}
@Test
public void testEmergencyInfoNotExists() throws Exception {
launchUserSettings();
UiObject emergencyInfoPreference =
mDevice.findObject(new UiSelector().text(EMERGNENCY_INFO));
assertThat(emergencyInfoPreference.exists()).isFalse();
}
@Test
public void testAddUsersWhenLockedNotExists() throws Exception {
launchUserSettings();
UiObject addUsersPreference =
mDevice.findObject(new UiSelector().text(ADD_USERS_WHEN_LOCKED));
assertThat(addUsersPreference.exists()).isFalse();
}
@Test
public void testUsersExistsOnSecondaryUser() throws Exception {
// switch to guest user
switchToOrCreateGuest();
// launch settings (launch from intent doesn't work, hence launch from quick settings)
mDevice.openQuickSettings();
mDevice.findObject(new UiSelector().resourceId(SETTINGS_BUTTON)).click();
// launch system settings and expand whole screen
final UiScrollable settings = new UiScrollable(
new UiSelector().packageName(mTargetPackage).scrollable(true));
final String titleSystem = SYSTEM;
settings.scrollTextIntoView(titleSystem);
mDevice.findObject(new UiSelector().text(titleSystem)).click();
mDevice.findObject(new UiSelector().text(ADVANCED)).click();
final boolean hasUsersSettings = mDevice.findObject(new UiSelector().text(USERS)).exists();
// switch back to primary user
mDevice.openQuickSettings();
mDevice.findObject(new UiSelector().resourceId(SWITCH_USER_BUTTON)).click();
mDevice.findObject(new UiSelector().text(PRIMARY_USER)).click();
assertThat(hasUsersSettings).isTrue();
}
private void launchSettings() {
Intent settingsIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setPackage(mTargetPackage)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(settingsIntent);
}
private void launchUserSettings() throws Exception {
launchSettings();
final UiScrollable settings = new UiScrollable(
new UiSelector().packageName(mTargetPackage).scrollable(true));
final String titleSystem = SYSTEM;
settings.scrollTextIntoView(titleSystem);
mDevice.findObject(new UiSelector().text(titleSystem)).click();
mDevice.findObject(new UiSelector().text(ADVANCED)).click();
mDevice.findObject(new UiSelector().text(USERS)).click();
}
private void switchToOrCreateGuest() throws UiObjectNotFoundException {
mDevice.openQuickSettings();
mDevice.findObject(new UiSelector().resourceId(SWITCH_USER_BUTTON)).click();
// if no existing guest user, select "Add guest", otherwise select "Guest"
final UiObject addGuest = mDevice.findObject(new UiSelector().text(ADD_GUEST));
if (addGuest.exists()) {
addGuest.click();
mDevice.waitForIdle();
mDevice.pressBack();
} else {
mDevice.findObject(new UiSelector().text(GUEST_USER)).click();
mDevice.waitForIdle();
mDevice.findObject(new UiSelector().text(CONTINUE)).click();
mDevice.waitForIdle();
}
}
}

View File

@@ -56,7 +56,8 @@ public class WifiTetherSettingsTest {
mTetherActivityIntent = new Intent() mTetherActivityIntent = new Intent()
.setClassName(mInstrumentation.getTargetContext().getPackageName(), .setClassName(mInstrumentation.getTargetContext().getPackageName(),
Settings.TetherSettingsActivity.class.getName()) Settings.TetherSettingsActivity.class.getName())
.setPackage(mInstrumentation.getTargetContext().getPackageName()); .setPackage(mInstrumentation.getTargetContext().getPackageName())
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} }
@After @After
@@ -69,7 +70,6 @@ public class WifiTetherSettingsTest {
launchWifiTetherActivity(); launchWifiTetherActivity();
onView(withText("Hotspot name")).check(matches(isDisplayed())); onView(withText("Hotspot name")).check(matches(isDisplayed()));
onView(withText("Hotspot password")).check(matches(isDisplayed())); onView(withText("Hotspot password")).check(matches(isDisplayed()));
onView(withText("AP Band")).check(matches(isDisplayed()));
} }
private void launchWifiTetherActivity() { private void launchWifiTetherActivity() {