Snap for 8535289 from 6408e8391b to tm-qpr1-release
Change-Id: I684550d1a1f7c500e07975fc8fd3cde4935c6c0b
This commit is contained in:
@@ -4124,7 +4124,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.bluetooth.BluetoothBroadcastsDialog" />
|
||||
android:value="com.android.settings.bluetooth.BluetoothBroadcastDialog" />
|
||||
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
|
||||
android:value="true" />
|
||||
</activity>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 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.
|
||||
-->
|
||||
|
||||
<ripple
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/settingslib_ripple_color">
|
||||
|
||||
<item android:id="@android:id/background">
|
||||
<layer-list android:paddingMode="stack"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="48dp"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingRight="0dp">
|
||||
<item>
|
||||
<shape>
|
||||
<corners android:radius="28dp"/>
|
||||
<solid android:color="@android:color/system_accent1_100"/>
|
||||
<size android:height="@dimen/settingslib_spinner_height"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:gravity="center|end"
|
||||
android:width="18dp"
|
||||
android:height="18dp"
|
||||
android:end="12dp"
|
||||
android:drawable="@drawable/settingslib_arrow_drop_down"/>
|
||||
</layer-list>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -39,7 +39,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:entries="@array/bytes_picker_sizes"
|
||||
style="@style/DataByteEditorSpinner"/>
|
||||
android:entries="@array/bytes_picker_sizes" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -14137,6 +14137,8 @@
|
||||
<!-- BT LE Audio Device: Media Broadcast -->
|
||||
<!-- The title of the Media Broadcast Dialog [CHAR LIMIT=none] -->
|
||||
<string name="bluetooth_broadcast_dialog_title">Broadcast</string>
|
||||
<!-- [CHAR LIMIT=NONE] Le audio broadcast dialog, switch to others app. -->
|
||||
<string name="bluetooth_broadcast_dialog_broadcast_app">Broadcast <xliff:g id="currentApp" example="App Name 2">%1$s</xliff:g></string>
|
||||
<!-- The message of the Media Broadcast Dialog for finding broadcast [CHAR LIMIT=none] -->
|
||||
<string name="bluetooth_broadcast_dialog_find_message">Listen to broadcasts that are playing near you</string>
|
||||
<!-- The message of the Media Broadcast Dialog for broadcast [CHAR LIMIT=none] -->
|
||||
|
||||
@@ -952,11 +952,6 @@
|
||||
<item name="contentPadding">@dimen/dream_item_content_padding</item>
|
||||
</style>
|
||||
|
||||
<style name="DataByteEditorSpinner" parent="@style/Spinner.SettingsLib">
|
||||
<item name="android:background">@drawable/data_bytes_editor_spinner_background</item>
|
||||
<item name="android:dropDownVerticalOffset">36dp</item>
|
||||
</style>
|
||||
|
||||
<style name="BroadcastActionButton" parent="@android:style/Widget.Material.Button">
|
||||
<item name="android:background">@drawable/broadcast_button_outline</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
|
||||
@@ -649,6 +649,11 @@
|
||||
android:title="@string/enable_non_resizable_multi_window"
|
||||
android:summary="@string/enable_non_resizable_multi_window_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="back_navigation_animation"
|
||||
android:title="@string/back_navigation_animation"
|
||||
android:summary="@string/back_navigation_animation_summary" />
|
||||
|
||||
<Preference
|
||||
android:key="reset_shortcut_manager_throttling"
|
||||
android:title="@string/reset_shortcut_manager_throttling" />
|
||||
|
||||
@@ -19,27 +19,30 @@ package com.android.settings.applications.managedomainurls;
|
||||
import android.content.Context;
|
||||
import android.content.pm.verify.domain.DomainVerificationManager;
|
||||
import android.content.pm.verify.domain.DomainVerificationUserState;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.intentpicker.IntentPickerUtils;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.settingslib.widget.AppPreference;
|
||||
|
||||
public class DomainAppPreference extends AppPreference {
|
||||
|
||||
private Drawable mCacheIcon;
|
||||
|
||||
private final AppEntry mEntry;
|
||||
private final DomainVerificationManager mDomainVerificationManager;
|
||||
private final IconDrawableFactory mIconDrawableFactory;
|
||||
|
||||
public DomainAppPreference(final Context context, IconDrawableFactory iconFactory,
|
||||
AppEntry entry) {
|
||||
public DomainAppPreference(final Context context, AppEntry entry) {
|
||||
super(context);
|
||||
mIconDrawableFactory = iconFactory;
|
||||
mDomainVerificationManager = context.getSystemService(DomainVerificationManager.class);
|
||||
mEntry = entry;
|
||||
mEntry.ensureLabel(getContext());
|
||||
|
||||
mCacheIcon = AppUtils.getIconFromCache(mEntry);
|
||||
setState();
|
||||
}
|
||||
|
||||
@@ -54,7 +57,12 @@ public class DomainAppPreference extends AppPreference {
|
||||
|
||||
private void setState() {
|
||||
setTitle(mEntry.label);
|
||||
setIcon(mIconDrawableFactory.getBadgedIcon(mEntry.info));
|
||||
|
||||
if (mCacheIcon != null) {
|
||||
setIcon(mCacheIcon);
|
||||
} else {
|
||||
setIcon(R.drawable.empty_icon);
|
||||
}
|
||||
setSummary(getDomainsSummary(mEntry.info.packageName));
|
||||
}
|
||||
|
||||
@@ -69,4 +77,18 @@ public class DomainAppPreference extends AppPreference {
|
||||
packageName);
|
||||
return userState == null ? false : userState.isLinkHandlingAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
if (mCacheIcon == null) {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
final Drawable icon = AppUtils.getIcon(getContext(), mEntry);
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
setIcon(icon);
|
||||
mCacheIcon = icon;
|
||||
});
|
||||
});
|
||||
}
|
||||
super.onBindViewHolder(view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IconDrawableFactory;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
@@ -30,6 +29,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.intentpicker.AppLaunchSettings;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||
|
||||
@@ -98,6 +98,10 @@ public class DomainAppPreferenceController extends BasePreferenceController impl
|
||||
if (mContext == null) {
|
||||
return;
|
||||
}
|
||||
// Preload top visible icons of app list.
|
||||
AppUtils.preloadTopIcons(mContext, apps,
|
||||
mContext.getResources().getInteger(R.integer.config_num_visible_app_icons));
|
||||
|
||||
rebuildAppList(mDomainAppList, apps);
|
||||
}
|
||||
|
||||
@@ -157,13 +161,12 @@ public class DomainAppPreferenceController extends BasePreferenceController impl
|
||||
cacheAllPrefs(group);
|
||||
final int size = apps.size();
|
||||
final Context context = group.getContext();
|
||||
final IconDrawableFactory iconDrawableFactory = IconDrawableFactory.newInstance(context);
|
||||
for (int i = 0; i < size; i++) {
|
||||
final AppEntry entry = apps.get(i);
|
||||
final String key = entry.info.packageName + "|" + entry.info.uid;
|
||||
DomainAppPreference preference = (DomainAppPreference) getCachedPreference(key);
|
||||
if (preference == null) {
|
||||
preference = new DomainAppPreference(context, iconDrawableFactory, entry);
|
||||
preference = new DomainAppPreference(context, entry);
|
||||
preference.setKey(key);
|
||||
group.addPreference(preference);
|
||||
} else {
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Context;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.applications.AppIconCacheManager;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
/**
|
||||
@@ -58,4 +59,10 @@ public class ManageDomainUrls extends DashboardFragment {
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.manage_domain_url_settings);
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
AppIconCacheManager.getInstance().release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,105 +19,93 @@ package com.android.settings.bluetooth;
|
||||
import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.media.MediaOutputConstants;
|
||||
|
||||
/**
|
||||
* This Dialog allowed users to do some actions for broadcast media or find the
|
||||
* nearby broadcast sources.
|
||||
*/
|
||||
public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
|
||||
public static final String KEY_APP_LABEL = "app_label";
|
||||
public static final String KEY_DEVICE_ADDRESS =
|
||||
BluetoothFindBroadcastsFragment.KEY_DEVICE_ADDRESS;
|
||||
|
||||
private static final String TAG = "BTBroadcastsDialog";
|
||||
|
||||
private static final CharSequence UNKNOWN_APP_LABEL = "unknown";
|
||||
private Context mContext;
|
||||
private CharSequence mCurrentAppLabel = UNKNOWN_APP_LABEL;
|
||||
private String mDeviceAddress;
|
||||
private LocalBluetoothManager mLocalBluetoothManager;
|
||||
private AlertDialog mAlertDialog;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mContext = getActivity();
|
||||
mCurrentAppLabel = getActivity().getIntent().getCharSequenceExtra(KEY_APP_LABEL);
|
||||
mDeviceAddress = getActivity().getIntent().getStringExtra(KEY_DEVICE_ADDRESS);
|
||||
mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
|
||||
setShowsDialog(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
final Context context = getActivity();
|
||||
final boolean isMediaPlaying = isMediaPlaying();
|
||||
View layout = View.inflate(mContext,
|
||||
com.android.settingslib.R.layout.broadcast_dialog, null);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(isMediaPlaying ? R.string.bluetooth_find_broadcast
|
||||
: R.string.bluetooth_broadcast_dialog_title);
|
||||
builder.setMessage(isMediaPlaying ? R.string.bluetooth_broadcast_dialog_find_message
|
||||
: R.string.bluetooth_broadcast_dialog_broadcast_message);
|
||||
TextView title = layout.findViewById(com.android.settingslib.R.id.dialog_title);
|
||||
TextView subTitle = layout.findViewById(com.android.settingslib.R.id.dialog_subtitle);
|
||||
title.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
|
||||
subTitle.setText(
|
||||
mContext.getString(R.string.bluetooth_broadcast_dialog_broadcast_message));
|
||||
|
||||
ArrayList<String> optionList = new ArrayList<String>();
|
||||
if (!isMediaPlaying) {
|
||||
optionList.add(context.getString(R.string.bluetooth_broadcast_dialog_title));
|
||||
}
|
||||
optionList.add(context.getString(R.string.bluetooth_find_broadcast));
|
||||
optionList.add(context.getString(android.R.string.cancel));
|
||||
|
||||
View content = LayoutInflater.from(context).inflate(
|
||||
R.layout.sim_confirm_dialog_multiple_enabled_profiles_supported, null);
|
||||
|
||||
if (content != null) {
|
||||
Log.i(TAG, "list =" + optionList.toString());
|
||||
|
||||
final ArrayAdapter<String> arrayAdapterItems = new ArrayAdapter<String>(
|
||||
context,
|
||||
R.layout.sim_confirm_dialog_item_multiple_enabled_profiles_supported,
|
||||
optionList);
|
||||
final ListView lvItems = content.findViewById(R.id.carrier_list);
|
||||
if (lvItems != null) {
|
||||
lvItems.setVisibility(View.VISIBLE);
|
||||
lvItems.setAdapter(arrayAdapterItems);
|
||||
lvItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
Log.i(TAG, "list onClick =" + position);
|
||||
Log.i(TAG, "list item =" + optionList.get(position));
|
||||
|
||||
if (position == optionList.size() - 1) {
|
||||
// The last position in the options is the Cancel button. So when
|
||||
// the user clicks the button, we do nothing but dismiss the dialog.
|
||||
dismiss();
|
||||
} else {
|
||||
if (optionList.get(position).equals(
|
||||
context.getString(R.string.bluetooth_find_broadcast))) {
|
||||
launchFindBroadcastsActivity();
|
||||
} else {
|
||||
launchMediaOutputBroadcastDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
builder.setView(content);
|
||||
Button broadcastBtn = layout.findViewById(com.android.settingslib.R.id.positive_btn);
|
||||
if (TextUtils.isEmpty(mCurrentAppLabel)) {
|
||||
broadcastBtn.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
|
||||
} else {
|
||||
Log.i(TAG, "optionList is empty");
|
||||
broadcastBtn.setText(mContext.getString(
|
||||
R.string.bluetooth_broadcast_dialog_broadcast_app,
|
||||
String.valueOf(mCurrentAppLabel)));
|
||||
}
|
||||
broadcastBtn.setOnClickListener((view) -> {
|
||||
launchMediaOutputBroadcastDialog();
|
||||
});
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
return dialog;
|
||||
Button findBroadcastBtn = layout.findViewById(com.android.settingslib.R.id.negative_btn);
|
||||
findBroadcastBtn.setText(mContext.getString(R.string.bluetooth_find_broadcast));
|
||||
findBroadcastBtn.setOnClickListener((view) -> {
|
||||
launchFindBroadcastsActivity();
|
||||
});
|
||||
|
||||
Button cancelBtn = layout.findViewById(com.android.settingslib.R.id.neutral_btn);
|
||||
cancelBtn.setOnClickListener((view) -> {
|
||||
dismiss();
|
||||
getActivity().finish();
|
||||
});
|
||||
|
||||
mAlertDialog = new AlertDialog.Builder(mContext,
|
||||
com.android.settingslib.R.style.Theme_AlertDialog_SettingsLib)
|
||||
.setView(layout)
|
||||
.create();
|
||||
|
||||
return mAlertDialog;
|
||||
}
|
||||
|
||||
private boolean isMediaPlaying() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
@@ -130,10 +118,55 @@ public class BluetoothBroadcastDialog extends InstrumentedDialogFragment {
|
||||
}
|
||||
|
||||
private void launchFindBroadcastsActivity() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(KEY_DEVICE_ADDRESS, mDeviceAddress);
|
||||
|
||||
new SubSettingLauncher(mContext)
|
||||
.setTitleRes(R.string.bluetooth_find_broadcast_title)
|
||||
.setDestination(BluetoothFindBroadcastsFragment.class.getName())
|
||||
.setArguments(bundle)
|
||||
.setSourceMetricsCategory(SettingsEnums.PAGE_UNKNOWN)
|
||||
.launch();
|
||||
dismissVolumePanel();
|
||||
}
|
||||
|
||||
private void launchMediaOutputBroadcastDialog() {
|
||||
if (startBroadcast()) {
|
||||
mContext.sendBroadcast(new Intent()
|
||||
.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME)
|
||||
.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG)
|
||||
.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME,
|
||||
getActivity().getPackageName()));
|
||||
dismissVolumePanel();
|
||||
}
|
||||
}
|
||||
|
||||
private LocalBluetoothLeBroadcast getLEAudioBroadcastProfile() {
|
||||
if (mLocalBluetoothManager != null && mLocalBluetoothManager.getProfileManager() != null) {
|
||||
LocalBluetoothLeBroadcast bluetoothLeBroadcast =
|
||||
mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
|
||||
if (bluetoothLeBroadcast != null) {
|
||||
return bluetoothLeBroadcast;
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "Can not get LE Audio Broadcast Profile");
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean startBroadcast() {
|
||||
LocalBluetoothLeBroadcast btLeBroadcast = getLEAudioBroadcastProfile();
|
||||
if (btLeBroadcast != null) {
|
||||
btLeBroadcast.startBroadcast(String.valueOf(mCurrentAppLabel), null);
|
||||
return true;
|
||||
}
|
||||
Log.d(TAG, "Can not broadcast successfully");
|
||||
return false;
|
||||
}
|
||||
|
||||
private void dismissVolumePanel() {
|
||||
// Dismiss volume panel
|
||||
mContext.sendBroadcast(new Intent()
|
||||
.setPackage(MediaOutputConstants.SETTINGS_PACKAGE_NAME)
|
||||
.setAction(MediaOutputConstants.ACTION_CLOSE_PANEL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* PreferenceController for enabling/disabling animation related to back button and back gestures.
|
||||
*/
|
||||
public class BackAnimationPreferenceController extends DeveloperOptionsPreferenceController
|
||||
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
|
||||
|
||||
private static final String BACK_NAVIGATION_ANIMATION_KEY =
|
||||
"back_navigation_animation";
|
||||
|
||||
private static final int SETTING_VALUE_OFF = 0;
|
||||
private static final int SETTING_VALUE_ON = 1;
|
||||
private final DevelopmentSettingsDashboardFragment mFragment;
|
||||
|
||||
@VisibleForTesting
|
||||
BackAnimationPreferenceController(Context context) {
|
||||
super(context);
|
||||
mFragment = null;
|
||||
}
|
||||
|
||||
|
||||
public BackAnimationPreferenceController(Context context,
|
||||
DevelopmentSettingsDashboardFragment fragment) {
|
||||
super(context);
|
||||
Objects.requireNonNull(fragment);
|
||||
mFragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return BACK_NAVIGATION_ANIMATION_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean isEnabled = (Boolean) newValue;
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION,
|
||||
isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
|
||||
if (mFragment != null && isEnabled) {
|
||||
BackAnimationPreferenceDialog.show(mFragment);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF);
|
||||
((SwitchPreference) mPreference).setChecked(mode != SETTING_VALUE_OFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
super.onDeveloperOptionsSwitchDisabled();
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF);
|
||||
((SwitchPreference) mPreference).setChecked(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.development;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
/**
|
||||
* Information dialog shown when enabling back animations
|
||||
*/
|
||||
public class BackAnimationPreferenceDialog extends InstrumentedDialogFragment
|
||||
implements DialogInterface.OnClickListener {
|
||||
|
||||
public static final String TAG = "BackAnimationDlg";
|
||||
|
||||
private BackAnimationPreferenceDialog() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Show this dialog.
|
||||
*/
|
||||
public static void show(@NonNull Fragment host) {
|
||||
FragmentActivity activity = host.getActivity();
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
FragmentManager manager = activity.getSupportFragmentManager();
|
||||
if (manager.findFragmentByTag(TAG) == null) {
|
||||
BackAnimationPreferenceDialog dialog = new BackAnimationPreferenceDialog();
|
||||
dialog.setTargetFragment(host, 0 /* requestCode */);
|
||||
dialog.show(manager, TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.DIALOG_BACK_ANIMATIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.back_navigation_animation)
|
||||
.setMessage(R.string.back_navigation_animation_dialog)
|
||||
.setPositiveButton(android.R.string.ok, this /* onClickListener */)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@@ -607,6 +607,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
controllers.add(new OverlaySettingsPreferenceController(context));
|
||||
controllers.add(new StylusHandwritingPreferenceController(context));
|
||||
controllers.add(new IngressRateLimitPreferenceController((context)));
|
||||
controllers.add(new BackAnimationPreferenceController(context, fragment));
|
||||
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements
|
||||
return mLocalMediaManager.getCurrentConnectedDevice();
|
||||
}
|
||||
|
||||
String getPackageName() {
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.settings.network;
|
||||
|
||||
import static android.provider.SettingsSlicesContract.KEY_AIRPLANE_MODE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -54,7 +55,6 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
|
||||
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
|
||||
.appendPath(SettingsSlicesContract.KEY_AIRPLANE_MODE)
|
||||
.build();
|
||||
private static final String EXIT_ECM_RESULT = "exit_ecm_result";
|
||||
|
||||
private Fragment mFragment;
|
||||
private AirplaneModeEnabler mAirplaneModeEnabler;
|
||||
@@ -147,7 +147,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CODE_EXIT_ECM) {
|
||||
final boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false);
|
||||
final boolean isChoiceYes = (resultCode == Activity.RESULT_OK);
|
||||
// Set Airplane mode based on the return value and checkbox state
|
||||
mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes,
|
||||
mAirplaneModePreference.isChecked());
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.android.settings.network.MobilePlanPreferenceController.MANAGE
|
||||
import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.util.Log;
|
||||
@@ -29,6 +30,7 @@ import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.OnActivityResultListener;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.network.MobilePlanPreferenceController.MobilePlanPreferenceHost;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
@@ -44,7 +46,7 @@ import java.util.List;
|
||||
|
||||
@SearchIndexable
|
||||
public class NetworkDashboardFragment extends DashboardFragment implements
|
||||
MobilePlanPreferenceHost {
|
||||
MobilePlanPreferenceHost, OnActivityResultListener {
|
||||
|
||||
private static final String TAG = "NetworkDashboardFrag";
|
||||
|
||||
@@ -152,6 +154,17 @@ public class NetworkDashboardFragment extends DashboardFragment implements
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
switch (requestCode) {
|
||||
case AirplaneModePreferenceController.REQUEST_CODE_EXIT_ECM:
|
||||
use(AirplaneModePreferenceController.class)
|
||||
.onActivityResult(requestCode, resultCode, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.network_provider_internet) {
|
||||
@Override
|
||||
|
||||
@@ -467,6 +467,9 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
}
|
||||
|
||||
private boolean restoreDefaultApn() {
|
||||
// Callback of data connection change could be some noise during the stage of restore.
|
||||
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
|
||||
showDialog(DIALOG_RESTORE_DEFAULTAPN);
|
||||
mRestoreDefaultApnMode = true;
|
||||
|
||||
@@ -517,6 +520,7 @@ public class ApnSettings extends RestrictedSettingsFragment
|
||||
getResources().getString(
|
||||
R.string.restore_default_apn_completed),
|
||||
Toast.LENGTH_LONG).show();
|
||||
restartPhoneStateListener(mSubId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,9 +80,6 @@ public class EnabledNetworkModePreferenceController extends
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
boolean visible;
|
||||
if (!isCallStateIdle()) {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
|
||||
final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
|
||||
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||
@@ -97,6 +94,8 @@ public class EnabledNetworkModePreferenceController extends
|
||||
visible = false;
|
||||
} else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
|
||||
visible = false;
|
||||
} else if (!isCallStateIdle()) {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
} else {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
@@ -31,9 +31,12 @@ import androidx.slice.builders.SliceAction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.bluetooth.BluetoothBroadcastDialog;
|
||||
import com.android.settings.media.MediaOutputIndicatorWorker;
|
||||
import com.android.settings.slices.CustomSliceRegistry;
|
||||
import com.android.settings.slices.SliceBackgroundWorker;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.media.BluetoothMediaDevice;
|
||||
import com.android.settingslib.media.MediaDevice;
|
||||
import com.android.settingslib.media.MediaOutputConstants;
|
||||
|
||||
@@ -42,6 +45,9 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
||||
private static final String KEY_MEDIA_VOLUME = "media_volume";
|
||||
|
||||
private MediaOutputIndicatorWorker mWorker;
|
||||
private MediaDevice mMediaDevice;
|
||||
private static final String ACTION_LAUNCH_BROADCAST_DIALOG =
|
||||
"android.settings.MEDIA_BROADCAST_DIALOG";
|
||||
|
||||
public MediaVolumePreferenceController(Context context) {
|
||||
super(context, KEY_MEDIA_VOLUME);
|
||||
@@ -91,9 +97,9 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
||||
}
|
||||
|
||||
private boolean isConnectedBLEDevice() {
|
||||
final MediaDevice device = getWorker().getCurrentConnectedMediaDevice();
|
||||
if (device != null) {
|
||||
return device.isBLEDevice();
|
||||
mMediaDevice = getWorker().getCurrentConnectedMediaDevice();
|
||||
if (mMediaDevice != null) {
|
||||
return mMediaDevice.isBLEDevice();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -106,17 +112,32 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
||||
}
|
||||
|
||||
final Intent intent = new Intent();
|
||||
PendingIntent pi = null;
|
||||
if (getWorker().isDeviceBroadcasting()) {
|
||||
intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
|
||||
intent.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
|
||||
intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME,
|
||||
getWorker().getActiveLocalMediaController().getPackageName());
|
||||
|
||||
pi = PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
|
||||
} else {
|
||||
// TODO(b/229577518) : Get the intent action of the Bluetooth Broadcast Dialog
|
||||
// for user to choose the action
|
||||
final CachedBluetoothDevice bluetoothDevice =
|
||||
((BluetoothMediaDevice) mMediaDevice).getCachedDevice();
|
||||
if (bluetoothDevice == null) {
|
||||
Log.d(TAG, "The bluetooth device is null");
|
||||
return null;
|
||||
}
|
||||
intent.setAction(ACTION_LAUNCH_BROADCAST_DIALOG);
|
||||
intent.putExtra(BluetoothBroadcastDialog.KEY_APP_LABEL,
|
||||
Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
|
||||
intent.putExtra(BluetoothBroadcastDialog.KEY_DEVICE_ADDRESS,
|
||||
bluetoothDevice.getAddress());
|
||||
|
||||
pi = PendingIntent.getActivity(context, 0 /* requestCode */, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
|
||||
}
|
||||
final PendingIntent pi = PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
|
||||
|
||||
final IconCompat icon = getBroadcastIcon(context);
|
||||
|
||||
return SliceAction.createDeeplink(pi, icon, ListBuilder.ICON_IMAGE, getPreferenceKey());
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.os.UserManager;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -41,6 +42,7 @@ import com.android.settings.widget.SettingsMainSwitchBar;
|
||||
import com.android.settingslib.TetherUtil;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -56,6 +58,8 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
@VisibleForTesting
|
||||
static final String KEY_WIFI_TETHER_NETWORK_NAME = "wifi_tether_network_name";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WIFI_TETHER_SECURITY = "wifi_tether_security";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WIFI_TETHER_NETWORK_PASSWORD = "wifi_tether_network_password";
|
||||
@VisibleForTesting
|
||||
static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off";
|
||||
@@ -72,7 +76,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
private WifiManager mWifiManager;
|
||||
private boolean mRestartWifiApAfterConfigChange;
|
||||
private boolean mUnavailable;
|
||||
|
||||
private WifiRestriction mWifiRestriction;
|
||||
@VisibleForTesting
|
||||
TetherChangeReceiver mTetherChangeReceiver;
|
||||
|
||||
@@ -82,6 +86,12 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
|
||||
public WifiTetherSettings() {
|
||||
super(UserManager.DISALLOW_CONFIG_TETHERING);
|
||||
mWifiRestriction = new WifiRestriction();
|
||||
}
|
||||
|
||||
public WifiTetherSettings(WifiRestriction wifiRestriction) {
|
||||
super(UserManager.DISALLOW_CONFIG_TETHERING);
|
||||
mWifiRestriction = wifiRestriction;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,9 +108,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setIfOnlyAvailableForAdmins(true);
|
||||
if (isUiRestricted()) {
|
||||
mUnavailable = true;
|
||||
}
|
||||
mUnavailable = isUiRestricted() || !mWifiRestriction.isHotspotAvailable(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,6 +143,11 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (!mWifiRestriction.isHotspotAvailable(getContext())) {
|
||||
getEmptyTextView().setText(R.string.not_allowed_by_ent);
|
||||
getPreferenceScreen().removeAll();
|
||||
return;
|
||||
}
|
||||
if (mUnavailable) {
|
||||
if (!isUiRestrictedByOnlyAdmin()) {
|
||||
getEmptyTextView().setText(R.string.tethering_settings_not_available);
|
||||
@@ -228,36 +241,67 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
use(WifiTetherMaximizeCompatibilityPreferenceController.class).updateDisplay();
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.wifi_tether_settings) {
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new SearchIndexProvider(R.xml.wifi_tether_settings);
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
final List<String> keys = super.getNonIndexableKeys(context);
|
||||
@VisibleForTesting
|
||||
static class SearchIndexProvider extends BaseSearchIndexProvider {
|
||||
|
||||
if (!TetherUtil.isTetherAvailable(context)) {
|
||||
keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
keys.add(KEY_WIFI_TETHER_AUTO_OFF);
|
||||
keys.add(KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
private final WifiRestriction mWifiRestriction;
|
||||
|
||||
// Remove duplicate
|
||||
keys.add(KEY_WIFI_TETHER_SCREEN);
|
||||
return keys;
|
||||
}
|
||||
SearchIndexProvider(int xmlRes) {
|
||||
super(xmlRes);
|
||||
mWifiRestriction = new WifiRestriction();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return !FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
|
||||
}
|
||||
@VisibleForTesting
|
||||
SearchIndexProvider(int xmlRes, WifiRestriction wifiRestriction) {
|
||||
super(xmlRes);
|
||||
mWifiRestriction = wifiRestriction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null /* listener */);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
final List<String> keys = super.getNonIndexableKeys(context);
|
||||
|
||||
if (!mWifiRestriction.isTetherAvailable(context)
|
||||
|| !mWifiRestriction.isHotspotAvailable(context)) {
|
||||
keys.add(KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
keys.add(KEY_WIFI_TETHER_SECURITY);
|
||||
keys.add(KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
keys.add(KEY_WIFI_TETHER_AUTO_OFF);
|
||||
keys.add(KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
// Remove duplicate
|
||||
keys.add(KEY_WIFI_TETHER_SCREEN);
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
return !FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null /* listener */);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class WifiRestriction {
|
||||
public boolean isTetherAvailable(@Nullable Context context) {
|
||||
if (context == null) return true;
|
||||
return TetherUtil.isTetherAvailable(context);
|
||||
}
|
||||
|
||||
public boolean isHotspotAvailable(@Nullable Context context) {
|
||||
if (context == null) return true;
|
||||
return WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class TetherChangeReceiver extends BroadcastReceiver {
|
||||
|
||||
@@ -29,7 +29,6 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.verify.domain.DomainVerificationManager;
|
||||
import android.content.pm.verify.domain.DomainVerificationUserState;
|
||||
import android.util.IconDrawableFactory;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
@@ -49,18 +48,14 @@ public class DomainAppPreferenceControllerTest {
|
||||
|
||||
private ApplicationsState.AppEntry mAppEntry;
|
||||
private Context mContext;
|
||||
private IconDrawableFactory mIconDrawableFactory;
|
||||
|
||||
@Mock
|
||||
private DomainVerificationManager mDomainVerificationManager;
|
||||
@Mock
|
||||
private DomainVerificationUserState mDomainVerificationUserState;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
|
||||
mAppEntry = new ApplicationsState.AppEntry(
|
||||
mContext, createApplicationInfo(mContext.getPackageName()), 0);
|
||||
when(mContext.getSystemService(DomainVerificationManager.class)).thenReturn(
|
||||
@@ -75,8 +70,7 @@ public class DomainAppPreferenceControllerTest {
|
||||
doReturn(domainVerificationUserState).when(
|
||||
mDomainVerificationManager).getDomainVerificationUserState(anyString());
|
||||
doReturn(true).when(domainVerificationUserState).isLinkHandlingAllowed();
|
||||
final DomainAppPreference pref = new DomainAppPreference(
|
||||
mContext, mIconDrawableFactory, mAppEntry);
|
||||
final DomainAppPreference pref = new DomainAppPreference(mContext, mAppEntry);
|
||||
|
||||
assertThat(pref.getLayoutResource()).isEqualTo(R.layout.preference_app);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.wifi.tether;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -33,38 +34,41 @@ import android.net.ConnectivityManager;
|
||||
import android.net.TetheringManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class WifiTetherSettingsTest {
|
||||
|
||||
private static final int XML_RES = R.xml.wifi_tether_settings;
|
||||
private static final String[] WIFI_REGEXS = {"wifi_regexs"};
|
||||
|
||||
private Context mContext;
|
||||
private WifiTetherSettings mWifiTetherSettings;
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Spy
|
||||
Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
private WifiManager mWifiManager;
|
||||
@Mock
|
||||
@@ -73,81 +77,55 @@ public class WifiTetherSettingsTest {
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private TetheringManager mTetheringManager;
|
||||
@Mock
|
||||
private WifiTetherSettings.WifiRestriction mWifiRestriction;
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@Mock
|
||||
private TextView mEmptyTextView;
|
||||
|
||||
private WifiTetherSettings mWifiTetherSettings;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
|
||||
MockitoAnnotations.initMocks(this);
|
||||
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
|
||||
doReturn(mConnectivityManager)
|
||||
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
doReturn(mTetheringManager).when(mContext).getSystemService(Context.TETHERING_SERVICE);
|
||||
doReturn(WIFI_REGEXS).when(mTetheringManager).getTetherableWifiRegexs();
|
||||
doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
|
||||
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
|
||||
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
|
||||
|
||||
mWifiTetherSettings = new WifiTetherSettings();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wifiTetherNonIndexableKeys_tetherAvailable_keysNotReturned() {
|
||||
FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false);
|
||||
// To let TetherUtil.isTetherAvailable return true, select one of the combinations
|
||||
setupIsTetherAvailable(true);
|
||||
|
||||
final List<String> niks =
|
||||
WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
|
||||
|
||||
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
|
||||
assertThat(niks).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wifiTetherNonIndexableKeys_tetherNotAvailable_keysReturned() {
|
||||
// To let TetherUtil.isTetherAvailable return false, select one of the combinations
|
||||
setupIsTetherAvailable(false);
|
||||
|
||||
final List<String> niks =
|
||||
WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
|
||||
|
||||
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
|
||||
assertThat(niks).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createPreferenceControllers_notEmpty() {
|
||||
assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getPreferenceControllers(mContext))
|
||||
.isNotEmpty();
|
||||
mWifiTetherSettings = new WifiTetherSettings(mWifiRestriction);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowFragment.class)
|
||||
public void startFragment_notAdminUser_shouldRemoveAllPreferences() {
|
||||
final WifiTetherSettings settings = spy(new WifiTetherSettings());
|
||||
final FragmentActivity activity = mock(FragmentActivity.class);
|
||||
when(settings.getActivity()).thenReturn(activity);
|
||||
when(settings.getContext()).thenReturn(mContext);
|
||||
final Resources.Theme theme = mContext.getTheme();
|
||||
when(activity.getTheme()).thenReturn(theme);
|
||||
when(activity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
doNothing().when(settings)
|
||||
.onCreatePreferences(any(Bundle.class), nullable(String.class));
|
||||
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
ReflectionHelpers.setField(settings, "mDashboardFeatureProvider",
|
||||
fakeFeatureFactory.dashboardFeatureProvider);
|
||||
final TextView emptyTextView = mock(TextView.class);
|
||||
ReflectionHelpers.setField(settings, "mEmptyTextView", emptyTextView);
|
||||
final PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||
doReturn(screen).when(settings).getPreferenceScreen();
|
||||
settings.onCreate(Bundle.EMPTY);
|
||||
public void onStart_uiIsRestricted_removeAllPreferences() {
|
||||
spyWifiTetherSettings();
|
||||
|
||||
settings.onStart();
|
||||
mWifiTetherSettings.onStart();
|
||||
|
||||
verify(screen).removeAll();
|
||||
verify(mPreferenceScreen).removeAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = ShadowFragment.class)
|
||||
public void onStart_hotspotNotAvailable_removeAllPreferences() {
|
||||
spyWifiTetherSettings();
|
||||
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
|
||||
|
||||
mWifiTetherSettings.onStart();
|
||||
|
||||
verify(mPreferenceScreen).removeAll();
|
||||
verify(mEmptyTextView).setText(anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createPreferenceControllers_getPreferenceControllersNotEmpty() {
|
||||
assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getPreferenceControllers(mContext))
|
||||
.isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,19 +137,86 @@ public class WifiTetherSettingsTest {
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
private void setupIsTetherAvailable(boolean returnValue) {
|
||||
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
|
||||
@Test
|
||||
public void getNonIndexableKeys_tetherAvailable_keysNotReturned() {
|
||||
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
|
||||
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
|
||||
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
|
||||
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
|
||||
|
||||
// For RestrictedLockUtils.checkIfRestrictionEnforced
|
||||
final int userId = UserHandle.myUserId();
|
||||
List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
|
||||
when(mUserManager.getUserRestrictionSources(
|
||||
UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId)))
|
||||
.thenReturn(enforcingUsers);
|
||||
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
|
||||
|
||||
// For RestrictedLockUtils.hasBaseUserRestriction
|
||||
when(mUserManager.hasBaseUserRestriction(
|
||||
UserManager.DISALLOW_CONFIG_TETHERING, UserHandle.of(userId)))
|
||||
.thenReturn(!returnValue);
|
||||
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
|
||||
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
|
||||
assertThat(keys).doesNotContain(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNonIndexableKeys_tetherNotAvailable_keysReturned() {
|
||||
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(false);
|
||||
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
|
||||
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
|
||||
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
|
||||
|
||||
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
|
||||
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNonIndexableKeys_hotspotNotAvailable_keysReturned() {
|
||||
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
|
||||
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
|
||||
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
|
||||
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
|
||||
|
||||
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
|
||||
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNonIndexableKeys_tetherAndHotspotNotAvailable_keysReturned() {
|
||||
when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(false);
|
||||
when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(false);
|
||||
WifiTetherSettings.SearchIndexProvider searchIndexProvider =
|
||||
new WifiTetherSettings.SearchIndexProvider(XML_RES, mWifiRestriction);
|
||||
|
||||
final List<String> keys = searchIndexProvider.getNonIndexableKeys(mContext);
|
||||
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_NAME);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_SECURITY);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_NETWORK_PASSWORD);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_AUTO_OFF);
|
||||
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
private void spyWifiTetherSettings() {
|
||||
mWifiTetherSettings = spy(new WifiTetherSettings(mWifiRestriction));
|
||||
final FragmentActivity activity = mock(FragmentActivity.class);
|
||||
when(mWifiTetherSettings.getActivity()).thenReturn(activity);
|
||||
when(mWifiTetherSettings.getContext()).thenReturn(mContext);
|
||||
final Resources.Theme theme = mContext.getTheme();
|
||||
when(activity.getTheme()).thenReturn(theme);
|
||||
when(activity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
doNothing().when(mWifiTetherSettings)
|
||||
.onCreatePreferences(any(Bundle.class), nullable(String.class));
|
||||
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
ReflectionHelpers.setField(mWifiTetherSettings, "mDashboardFeatureProvider",
|
||||
fakeFeatureFactory.dashboardFeatureProvider);
|
||||
ReflectionHelpers.setField(mWifiTetherSettings, "mEmptyTextView", mEmptyTextView);
|
||||
doReturn(mPreferenceScreen).when(mWifiTetherSettings).getPreferenceScreen();
|
||||
|
||||
mWifiTetherSettings.onCreate(Bundle.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.development;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BackAnimationPreferenceControllerTest {
|
||||
|
||||
private static final int SETTING_VALUE_OFF = 0;
|
||||
private static final int SETTING_VALUE_ON = 1;
|
||||
|
||||
private SwitchPreference mPreference;
|
||||
|
||||
private Context mContext;
|
||||
private BackAnimationPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
mContext = instrumentation.getTargetContext();
|
||||
mController = new BackAnimationPreferenceController(mContext);
|
||||
mPreference = new SwitchPreference(mContext);
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, -1);
|
||||
|
||||
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
|
||||
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
screen.addPreference(mPreference);
|
||||
mController.displayPreference(screen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_switchEnabled_shouldEnableBackAnimations() {
|
||||
mController.onPreferenceChange(mPreference, true /* new value */);
|
||||
|
||||
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */);
|
||||
assertThat(mode).isEqualTo(SETTING_VALUE_ON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_switchDisabled_shouldDisableBackAnimations() {
|
||||
mController.onPreferenceChange(mPreference, false /* new value */);
|
||||
|
||||
final int mode = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */);
|
||||
assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_settingEnabled_preferenceShouldBeChecked() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_ON);
|
||||
mController.updateState(mPreference);
|
||||
assertTrue(mPreference.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_settingDisabled_preferenceShouldNotBeChecked() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
assertFalse(mPreference.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference()
|
||||
throws InterruptedException {
|
||||
ContentResolver contentResolver = mContext.getContentResolver();
|
||||
int mode = doAndWaitForSettingChange(() -> mController.onDeveloperOptionsSwitchDisabled(),
|
||||
contentResolver);
|
||||
assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
|
||||
assertFalse(mPreference.isEnabled());
|
||||
assertFalse(mPreference.isChecked());
|
||||
}
|
||||
|
||||
private int doAndWaitForSettingChange(Runnable runnable, ContentResolver contentResolver) {
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
ContentObserver settingsObserver =
|
||||
new ContentObserver(new Handler(Looper.myLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
};
|
||||
contentResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.ENABLE_BACK_ANIMATION),
|
||||
false, settingsObserver, UserHandle.USER_SYSTEM
|
||||
);
|
||||
runnable.run();
|
||||
try {
|
||||
countDownLatch.await(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
return Settings.Global.getInt(contentResolver,
|
||||
Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user