Snap for 11992154 from 2345b63c68 to 24Q4-release
Change-Id: I4336f08b19bf2645d539a030f96fff6fce8d7e5c
This commit is contained in:
@@ -140,7 +140,7 @@
|
||||
<uses-permission android:name="android.permission.REMAP_MODIFIER_KEYS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_GPU_SERVICE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_GAME_MODE" />
|
||||
<uses-permission android:name="android.permission.RESTART_PHONE_PROCESS" />
|
||||
<uses-permission android:name="android.permission.RESTART_TELEPHONY_PROCESS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ENHANCED_CONFIRMATION_STATES" />
|
||||
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
|
||||
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
|
||||
|
||||
12
aconfig/settings_wifi_flag_declarations.aconfig
Normal file
12
aconfig/settings_wifi_flag_declarations.aconfig
Normal file
@@ -0,0 +1,12 @@
|
||||
package: "com.android.settings.flags"
|
||||
container: "system_ext"
|
||||
|
||||
# NOTE: Keep alphabetized to help limit merge conflicts from multiple simultaneous editors.
|
||||
|
||||
flag {
|
||||
name: "enable_wifi_sharing_runtime_fragment"
|
||||
namespace: "prism_qr"
|
||||
description: "Use WifiFeatureProvider to get the instance of WifiDppQrCodeGeneratorFragment."
|
||||
bug: "329012096"
|
||||
}
|
||||
|
||||
62
res/layout/zen_mode_type_item.xml
Normal file
62
res/layout/zen_mode_type_item.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2024 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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@id/title"
|
||||
android:layout_below="@id/title"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -7927,6 +7927,19 @@
|
||||
<!-- Zen Modes: Summary for the Do not Disturb option and associated settings page. [CHAR LIMIT=240]-->
|
||||
<string name="zen_mode_settings_summary">Only get notified by important people and apps</string>
|
||||
|
||||
<!-- Zen Modes: Option to add an automatic schedule for a mode. [CHAR_LIMIT=40] -->
|
||||
<string name="zen_mode_select_schedule">Select activation type</string>
|
||||
|
||||
<!-- Zen Modes: Option to choose a time-based schedule for a mode. [CHAR_LIMIT=40] -->
|
||||
<string name="zen_mode_select_schedule_time">Time</string>
|
||||
<!-- Zen Modes: Example text for the option to choose a time-based schedule for a mode. [CHAR_LIMIT=60] -->
|
||||
<string name="zen_mode_select_schedule_time_example">Ex. \"9:30 – 5:00 PM\"</string>
|
||||
|
||||
<!-- Zen Modes: Option to choose a calendar-events-based schedule for a mode. [CHAR_LIMIT=40] -->
|
||||
<string name="zen_mode_select_schedule_calendar">Calendar</string>
|
||||
<!-- Zen Modes: Example text for the option to choose a calendar-events-based schedule for a mode. [CHAR_LIMIT=60] -->
|
||||
<string name="zen_mode_select_schedule_calendar_example">Ex. \"Personal calendar\"</string>
|
||||
|
||||
<!-- Subtitle for the Do not Disturb slice. [CHAR LIMIT=50]-->
|
||||
<string name="zen_mode_slice_subtitle">Limit interruptions</string>
|
||||
|
||||
|
||||
@@ -271,12 +271,12 @@ public class ResetNetworkRequest {
|
||||
builder.resetIms(mSubscriptionIdToResetIms);
|
||||
}
|
||||
// Reset phone process and RILD may impact above components, keep them at the end
|
||||
if ((mResetOptions & RESET_PHONE_PROCESS) != 0) {
|
||||
builder.restartPhoneProcess();
|
||||
}
|
||||
if ((mResetOptions & RESET_RILD) != 0) {
|
||||
builder.restartRild();
|
||||
}
|
||||
if ((mResetOptions & RESET_PHONE_PROCESS) != 0) {
|
||||
builder.restartPhoneProcess();
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,10 @@ public class AudioStreamMediaService extends Service {
|
||||
public void onSourceLost(int broadcastId) {
|
||||
super.onSourceLost(broadcastId);
|
||||
if (broadcastId == mBroadcastId) {
|
||||
Log.d(TAG, "onSourceLost() : stopSelf");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
@@ -86,6 +90,10 @@ public class AudioStreamMediaService extends Service {
|
||||
&& mAudioStreamsHelper.getAllConnectedSources().stream()
|
||||
.map(BluetoothLeBroadcastReceiveState::getBroadcastId)
|
||||
.noneMatch(id -> id == mBroadcastId)) {
|
||||
Log.d(TAG, "onSourceRemoved() : stopSelf");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
@@ -96,6 +104,10 @@ public class AudioStreamMediaService extends Service {
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int bluetoothState) {
|
||||
if (BluetoothAdapter.STATE_OFF == bluetoothState) {
|
||||
Log.d(TAG, "onBluetoothStateChanged() : stopSelf");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
@@ -120,6 +132,10 @@ public class AudioStreamMediaService extends Service {
|
||||
});
|
||||
}
|
||||
if (mDevices == null || mDevices.isEmpty()) {
|
||||
Log.d(TAG, "onProfileConnectionStateChanged() : stopSelf");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
@@ -246,21 +262,27 @@ public class AudioStreamMediaService extends Service {
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
Log.d(TAG, "onDestroy()");
|
||||
super.onDestroy();
|
||||
|
||||
if (!AudioSharingUtils.isFeatureEnabled()) {
|
||||
Log.d(TAG, "onDestroy() : skip due to feature not enabled");
|
||||
return;
|
||||
}
|
||||
if (mLocalBtManager != null) {
|
||||
Log.d(TAG, "onDestroy() : unregister mBluetoothCallback");
|
||||
mLocalBtManager.getEventManager().unregisterCallback(mBluetoothCallback);
|
||||
}
|
||||
if (mLeBroadcastAssistant != null) {
|
||||
Log.d(TAG, "onDestroy() : unregister mBroadcastAssistantCallback");
|
||||
mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
|
||||
}
|
||||
if (mVolumeControl != null) {
|
||||
Log.d(TAG, "onDestroy() : unregister mVolumeControlCallback");
|
||||
mVolumeControl.unregisterCallback(mVolumeControlCallback);
|
||||
}
|
||||
if (mLocalSession != null) {
|
||||
Log.d(TAG, "onDestroy() : release mLocalSession");
|
||||
mLocalSession.release();
|
||||
mLocalSession = null;
|
||||
}
|
||||
@@ -273,6 +295,9 @@ public class AudioStreamMediaService extends Service {
|
||||
mBroadcastId = intent != null ? intent.getIntExtra(BROADCAST_ID, -1) : -1;
|
||||
if (mBroadcastId == -1) {
|
||||
Log.w(TAG, "Invalid broadcast ID. Service will not start.");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
@@ -282,6 +307,9 @@ public class AudioStreamMediaService extends Service {
|
||||
}
|
||||
if (mDevices == null || mDevices.isEmpty()) {
|
||||
Log.w(TAG, "No device. Service will not start.");
|
||||
if (mNotificationManager != null) {
|
||||
mNotificationManager.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ public final class BugReportContentProvider extends ContentProvider {
|
||||
LogUtils.dumpBatteryUsageSlotDatabaseHist(context, writer);
|
||||
LogUtils.dumpBatteryEventDatabaseHist(context, writer);
|
||||
LogUtils.dumpBatteryStateDatabaseHist(context, writer);
|
||||
LogUtils.dumpBatteryReattributeDatabaseHist(context, writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.settings.fuelgauge.batteryusage.bugreport;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils;
|
||||
import com.android.settings.fuelgauge.batteryusage.AppOptimizationModeEvent;
|
||||
@@ -29,6 +31,8 @@ import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventDao;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventDao;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryReattributeDao;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryReattributeEntity;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryState;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
|
||||
@@ -127,6 +131,24 @@ public final class LogUtils {
|
||||
dumpListItems(writer, entities, entity -> entity);
|
||||
}
|
||||
|
||||
static void dumpBatteryReattributeDatabaseHist(Context context, PrintWriter writer) {
|
||||
dumpBatteryReattributeDatabaseHist(
|
||||
BatteryStateDatabase.getInstance(context).batteryReattributeDao(),
|
||||
writer);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void dumpBatteryReattributeDatabaseHist(
|
||||
BatteryReattributeDao batteryReattributeDao, PrintWriter writer) {
|
||||
writer.println("\n\tBatteryReattribute DatabaseHistory:");
|
||||
final List<BatteryReattributeEntity> entities =
|
||||
batteryReattributeDao.getAllAfter(
|
||||
Clock.systemUTC().millis() - DUMP_TIME_OFFSET.toMillis());
|
||||
if (entities != null && !entities.isEmpty()) {
|
||||
dumpListItems(writer, entities, entity -> entity);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T, S> void dumpListItems(
|
||||
PrintWriter writer, List<T> itemList, Function<T, S> itemConverter) {
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
@@ -62,6 +62,7 @@ public class BatteryReattributeEntity {
|
||||
.append("\nBatteryReattributeEntity{")
|
||||
.append("\n\t" + utcToLocalTimeForLogging(timestampStart))
|
||||
.append("\n\t" + utcToLocalTimeForLogging(timestampEnd))
|
||||
.append("\n\t" + ConvertUtils.decodeBatteryReattribute(reattributeData))
|
||||
.append("\n}");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.network;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
@@ -28,11 +29,14 @@ import android.net.wifi.WifiManager;
|
||||
import android.net.wifi.p2p.WifiP2pManager;
|
||||
import android.os.Looper;
|
||||
import android.os.RecoverySystem;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.ResetNetworkRequest;
|
||||
@@ -257,15 +261,15 @@ public class ResetNetworkOperationBuilder {
|
||||
*/
|
||||
public ResetNetworkOperationBuilder restartPhoneProcess() {
|
||||
Runnable runnable = () -> {
|
||||
try {
|
||||
mContext.getContentResolver().call(
|
||||
getResetTelephonyContentProviderAuthority(),
|
||||
METHOD_RESTART_PHONE_PROCESS,
|
||||
/* arg= */ null,
|
||||
/* extras= */ null);
|
||||
Log.i(TAG, "Phone process was restarted.");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Log.w(TAG, "Fail to restart phone process: " + iae);
|
||||
// Unstable content provider can avoid us getting killed together with phone process
|
||||
try (ContentProviderClient client = getUnstableTelephonyContentProviderClient()) {
|
||||
if (client != null) {
|
||||
client.call(METHOD_RESTART_PHONE_PROCESS, /* arg= */ null, /* extra= */ null);
|
||||
Log.i(TAG, "Phone process was restarted.");
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
// It's normal to throw RE since phone process immediately dies
|
||||
Log.i(TAG, "Phone process has been restarted: " + re);
|
||||
}
|
||||
};
|
||||
mResetSequence.add(runnable);
|
||||
@@ -279,15 +283,13 @@ public class ResetNetworkOperationBuilder {
|
||||
*/
|
||||
public ResetNetworkOperationBuilder restartRild() {
|
||||
Runnable runnable = () -> {
|
||||
try {
|
||||
mContext.getContentResolver().call(
|
||||
getResetTelephonyContentProviderAuthority(),
|
||||
METHOD_RESTART_RILD,
|
||||
/* arg= */ null,
|
||||
/* extras= */ null);
|
||||
Log.i(TAG, "RILD was restarted.");
|
||||
} catch (IllegalArgumentException iae) {
|
||||
Log.w(TAG, "Fail to restart RILD: " + iae);
|
||||
try (ContentProviderClient client = getUnstableTelephonyContentProviderClient()) {
|
||||
if (client != null) {
|
||||
client.call(METHOD_RESTART_RILD, /* arg= */ null, /* extra= */ null);
|
||||
Log.i(TAG, "RILD was restarted.");
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Fail to restart RILD: " + re);
|
||||
}
|
||||
};
|
||||
mResetSequence.add(runnable);
|
||||
@@ -322,9 +324,18 @@ public class ResetNetworkOperationBuilder {
|
||||
* @return the authority of the telephony content provider that support methods
|
||||
* resetPhoneProcess and resetRild.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
String getResetTelephonyContentProviderAuthority() {
|
||||
private String getResetTelephonyContentProviderAuthority() {
|
||||
return mContext.getResources().getString(
|
||||
R.string.reset_telephony_stack_content_provider_authority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the unstable content provider to avoid us getting killed with phone process
|
||||
*/
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
public ContentProviderClient getUnstableTelephonyContentProviderClient() {
|
||||
return mContext.getContentResolver().acquireUnstableContentProviderClient(
|
||||
getResetTelephonyContentProviderAuthority());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.network.apn
|
||||
|
||||
import android.provider.Telephony
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.booleanResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.widget.preference.SwitchPreference
|
||||
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
|
||||
|
||||
@Composable
|
||||
fun ApnEditCarrierEnabled(apnData: ApnData, onCarrierEnabledChanged: (Boolean) -> Unit) {
|
||||
SwitchPreference(
|
||||
object : SwitchPreferenceModel {
|
||||
override val title = stringResource(R.string.carrier_enabled)
|
||||
val allowEdit = booleanResource(R.bool.config_allow_edit_carrier_enabled)
|
||||
override val changeable = {
|
||||
allowEdit && apnData.isFieldEnabled(Telephony.Carriers.CARRIER_ENABLED)
|
||||
}
|
||||
override val checked = { apnData.carrierEnabled }
|
||||
override val onCheckedChange = onCarrierEnabledChanged
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -235,19 +235,7 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
|
||||
enabled = apnData.isFieldEnabled(Telephony.Carriers.ROAMING_PROTOCOL),
|
||||
) { apnData = apnData.copy(apnRoaming = it) }
|
||||
ApnNetworkTypeCheckBox(apnData) { apnData = apnData.copy(networkType = it) }
|
||||
SwitchPreference(
|
||||
object : SwitchPreferenceModel {
|
||||
override val title = stringResource(R.string.carrier_enabled)
|
||||
override val changeable = {
|
||||
apnData.apnEnableEnabled &&
|
||||
apnData.isFieldEnabled(Telephony.Carriers.CARRIER_ENABLED)
|
||||
}
|
||||
override val checked = { apnData.apnEnable }
|
||||
override val onCheckedChange = { newChecked: Boolean ->
|
||||
apnData = apnData.copy(apnEnable = newChecked)
|
||||
}
|
||||
}
|
||||
)
|
||||
ApnEditCarrierEnabled(apnData) { apnData = apnData.copy(carrierEnabled = it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ fun getApnDataFromUri(uri: Uri, context: Context): ApnData {
|
||||
apnRoaming = context.convertProtocol2Options(
|
||||
cursor.getString(Telephony.Carriers.ROAMING_PROTOCOL)
|
||||
),
|
||||
apnEnable = cursor.getInt(Telephony.Carriers.CARRIER_ENABLED) == 1,
|
||||
carrierEnabled = cursor.getInt(Telephony.Carriers.CARRIER_ENABLED) == 1,
|
||||
networkType = cursor.getLong(Telephony.Carriers.NETWORK_TYPE_BITMASK),
|
||||
edited = cursor.getInt(Telephony.Carriers.EDITED_STATUS),
|
||||
userEditable = cursor.getInt(Telephony.Carriers.USER_EDITABLE),
|
||||
|
||||
@@ -44,11 +44,10 @@ data class ApnData(
|
||||
val apnType: String = "",
|
||||
val apnProtocol: Int = -1,
|
||||
val apnRoaming: Int = -1,
|
||||
val apnEnable: Boolean = true,
|
||||
val carrierEnabled: Boolean = true,
|
||||
val networkType: Long = 0,
|
||||
val edited: Int = Telephony.Carriers.USER_EDITED,
|
||||
val userEditable: Int = 1,
|
||||
val apnEnableEnabled: Boolean = true,
|
||||
val newApn: Boolean = false,
|
||||
val subId: Int = -1,
|
||||
val validEnabled: Boolean = false,
|
||||
@@ -72,7 +71,7 @@ data class ApnData(
|
||||
Telephony.Carriers.NETWORK_TYPE_BITMASK to networkType,
|
||||
// Copy network type into lingering network type.
|
||||
Telephony.Carriers.LINGERING_NETWORK_TYPE_BITMASK to networkType,
|
||||
Telephony.Carriers.CARRIER_ENABLED to apnEnable,
|
||||
Telephony.Carriers.CARRIER_ENABLED to carrierEnabled,
|
||||
Telephony.Carriers.EDITED_STATUS to Telephony.Carriers.USER_EDITED,
|
||||
)
|
||||
|
||||
@@ -134,10 +133,6 @@ fun getApnDataInit(arguments: Bundle, context: Context, uriInit: Uri, subId: Int
|
||||
)
|
||||
}
|
||||
|
||||
apnDataInit = apnDataInit.copy(
|
||||
apnEnableEnabled =
|
||||
context.resources.getBoolean(R.bool.config_allow_edit_carrier_enabled)
|
||||
)
|
||||
// TODO: mIsCarrierIdApn
|
||||
return disableInit(apnDataInit)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@ package com.android.settings.notification.modes;
|
||||
|
||||
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
|
||||
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
||||
import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent;
|
||||
import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleTime;
|
||||
import static android.service.notification.ZenModeConfig.tryParseEventConditionId;
|
||||
import static android.service.notification.ZenModeConfig.tryParseScheduleConditionId;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -26,7 +32,10 @@ import android.app.AutomaticZenRule;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenDeviceEffects;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.service.notification.ZenPolicy;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -204,6 +213,44 @@ class ZenMode {
|
||||
: new ZenDeviceEffects.Builder().build();
|
||||
}
|
||||
|
||||
public void setCustomModeConditionId(Context context, Uri conditionId) {
|
||||
checkState(SystemZenRules.PACKAGE_ANDROID.equals(mRule.getPackageName()),
|
||||
"Trying to change condition of non-system-owned rule %s (to %s)",
|
||||
mRule, conditionId);
|
||||
|
||||
Uri oldCondition = mRule.getConditionId();
|
||||
mRule.setConditionId(conditionId);
|
||||
|
||||
ZenModeConfig.ScheduleInfo scheduleInfo = tryParseScheduleConditionId(conditionId);
|
||||
if (scheduleInfo != null) {
|
||||
mRule.setType(AutomaticZenRule.TYPE_SCHEDULE_TIME);
|
||||
mRule.setOwner(ZenModeConfig.getScheduleConditionProvider());
|
||||
mRule.setTriggerDescription(
|
||||
getTriggerDescriptionForScheduleTime(context, scheduleInfo));
|
||||
return;
|
||||
}
|
||||
|
||||
ZenModeConfig.EventInfo eventInfo = tryParseEventConditionId(conditionId);
|
||||
if (eventInfo != null) {
|
||||
mRule.setType(AutomaticZenRule.TYPE_SCHEDULE_CALENDAR);
|
||||
mRule.setOwner(ZenModeConfig.getEventConditionProvider());
|
||||
mRule.setTriggerDescription(getTriggerDescriptionForScheduleEvent(context, eventInfo));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ZenModeConfig.isValidCustomManualConditionId(conditionId)) {
|
||||
mRule.setType(AutomaticZenRule.TYPE_OTHER);
|
||||
mRule.setOwner(ZenModeConfig.getCustomManualConditionProvider());
|
||||
mRule.setTriggerDescription("");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.wtf(TAG, String.format(
|
||||
"Changed condition of rule %s (%s -> %s) but cannot recognize which kind of "
|
||||
+ "condition it was!",
|
||||
mRule, oldCondition, conditionId));
|
||||
}
|
||||
|
||||
public boolean canEditName() {
|
||||
return !isManualDnd();
|
||||
}
|
||||
@@ -224,6 +271,15 @@ class ZenMode {
|
||||
return mIsActive;
|
||||
}
|
||||
|
||||
public boolean isSystemOwned() {
|
||||
return SystemZenRules.PACKAGE_ANDROID.equals(mRule.getPackageName());
|
||||
}
|
||||
|
||||
@AutomaticZenRule.Type
|
||||
public int getType() {
|
||||
return mRule.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
return obj instanceof ZenMode other
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ZenModeFragment extends ZenModeFragmentBase {
|
||||
prefControllers.add(new ZenModeDisplayLinkPreferenceController(
|
||||
context, "mode_display_settings", mBackend, mHelperBackend));
|
||||
prefControllers.add(new ZenModeSetTriggerLinkPreferenceController(context,
|
||||
"zen_automatic_trigger_category", mBackend));
|
||||
"zen_automatic_trigger_category", this, mBackend));
|
||||
return prefControllers;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.modes;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class ZenModeScheduleChooserDialog extends InstrumentedDialogFragment {
|
||||
|
||||
private static final String TAG = "ZenModeScheduleChooserDialog";
|
||||
|
||||
static final int OPTION_TIME = 0;
|
||||
static final int OPTION_CALENDAR = 1;
|
||||
|
||||
private record ScheduleOption(@StringRes int nameResId, @StringRes int exampleResId,
|
||||
@DrawableRes int iconResId) {}
|
||||
|
||||
private static final ImmutableList<ScheduleOption> SCHEDULE_OPTIONS = ImmutableList.of(
|
||||
new ScheduleOption(R.string.zen_mode_select_schedule_time,
|
||||
R.string.zen_mode_select_schedule_time_example,
|
||||
com.android.internal.R.drawable.ic_zen_mode_type_schedule_time),
|
||||
new ScheduleOption(R.string.zen_mode_select_schedule_calendar,
|
||||
R.string.zen_mode_select_schedule_calendar_example,
|
||||
com.android.internal.R.drawable.ic_zen_mode_type_schedule_calendar));
|
||||
|
||||
private OnScheduleOptionListener mOptionListener;
|
||||
|
||||
interface OnScheduleOptionListener {
|
||||
void onScheduleSelected(Uri conditionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
// TODO: b/332937635 - Update metrics category
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show(DashboardFragment parent, OnScheduleOptionListener optionListener) {
|
||||
ZenModeScheduleChooserDialog dialog = new ZenModeScheduleChooserDialog();
|
||||
dialog.mOptionListener = optionListener;
|
||||
dialog.setTargetFragment(parent, 0);
|
||||
dialog.show(parent.getParentFragmentManager(), TAG);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
checkState(getContext() != null);
|
||||
return new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.zen_mode_choose_rule_type)
|
||||
.setAdapter(new OptionsAdapter(getContext()),
|
||||
(dialog, which) -> onScheduleTypeSelected(which))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create();
|
||||
}
|
||||
|
||||
private static class OptionsAdapter extends ArrayAdapter<ScheduleOption> {
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
OptionsAdapter(@NonNull Context context) {
|
||||
super(context, R.layout.zen_mode_type_item, SCHEDULE_OPTIONS);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.zen_mode_type_item, parent, false);
|
||||
}
|
||||
// No need for holder pattern since we have only 2 items.
|
||||
ImageView imageView = checkNotNull(convertView.findViewById(R.id.icon));
|
||||
TextView title = checkNotNull(convertView.findViewById(R.id.title));
|
||||
TextView subtitle = checkNotNull(convertView.findViewById(R.id.subtitle));
|
||||
|
||||
ScheduleOption option = checkNotNull(getItem(position));
|
||||
imageView.setImageResource(option.iconResId());
|
||||
title.setText(option.nameResId());
|
||||
subtitle.setText(option.exampleResId());
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private void onScheduleTypeSelected(int whichOption) {
|
||||
Uri conditionId = switch (whichOption) {
|
||||
case OPTION_TIME -> getDefaultScheduleTimeCondition();
|
||||
case OPTION_CALENDAR -> getDefaultScheduleCalendarCondition();
|
||||
default -> ZenModeConfig.toCustomManualConditionId();
|
||||
};
|
||||
|
||||
mOptionListener.onScheduleSelected(conditionId);
|
||||
}
|
||||
|
||||
private static Uri getDefaultScheduleTimeCondition() {
|
||||
ZenModeConfig.ScheduleInfo schedule = new ZenModeConfig.ScheduleInfo();
|
||||
schedule.days = ZenModeConfig.ALL_DAYS;
|
||||
schedule.startHour = 9;
|
||||
schedule.startMinute = 30;
|
||||
schedule.endHour = 17;
|
||||
return ZenModeConfig.toScheduleConditionId(schedule);
|
||||
}
|
||||
|
||||
private static Uri getDefaultScheduleCalendarCondition() {
|
||||
ZenModeConfig.EventInfo eventInfo = new ZenModeConfig.EventInfo();
|
||||
eventInfo.calendarId = null; // All calendars of the current user.
|
||||
eventInfo.reply = ZenModeConfig.EventInfo.REPLY_ANY_EXCEPT_NO;
|
||||
return ZenModeConfig.toEventConditionId(eventInfo);
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package com.android.settings.notification.modes;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.CalendarContract;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -42,7 +40,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ZenModeSetCalendarPreferenceController extends AbstractZenModePreferenceController {
|
||||
class ZenModeSetCalendarPreferenceController extends AbstractZenModePreferenceController {
|
||||
@VisibleForTesting
|
||||
protected static final String KEY_CALENDAR = "calendar";
|
||||
@VisibleForTesting
|
||||
@@ -122,11 +120,7 @@ public class ZenModeSetCalendarPreferenceController extends AbstractZenModePrefe
|
||||
@VisibleForTesting
|
||||
protected Function<ZenMode, ZenMode> updateEventMode(ZenModeConfig.EventInfo event) {
|
||||
return (zenMode) -> {
|
||||
zenMode.getRule().setConditionId(ZenModeConfig.toEventConditionId(event));
|
||||
if (Flags.modesApi() && Flags.modesUi()) {
|
||||
zenMode.getRule().setTriggerDescription(
|
||||
SystemZenRules.getTriggerDescriptionForScheduleEvent(mContext, event));
|
||||
}
|
||||
zenMode.setCustomModeConditionId(mContext, ZenModeConfig.toEventConditionId(event));
|
||||
return zenMode;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
package com.android.settings.notification.modes;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.content.Context;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.ArraySet;
|
||||
@@ -116,16 +114,13 @@ class ZenModeSetSchedulePreferenceController extends AbstractZenModePreferenceCo
|
||||
@VisibleForTesting
|
||||
protected Function<ZenMode, ZenMode> updateScheduleMode(ZenModeConfig.ScheduleInfo schedule) {
|
||||
return (zenMode) -> {
|
||||
zenMode.getRule().setConditionId(ZenModeConfig.toScheduleConditionId(schedule));
|
||||
if (Flags.modesApi() && Flags.modesUi()) {
|
||||
zenMode.getRule().setTriggerDescription(
|
||||
SystemZenRules.getTriggerDescriptionForScheduleTime(mContext, schedule));
|
||||
}
|
||||
zenMode.setCustomModeConditionId(mContext,
|
||||
ZenModeConfig.toScheduleConditionId(schedule));
|
||||
return zenMode;
|
||||
};
|
||||
}
|
||||
|
||||
private ZenModeTimePickerFragment.TimeSetter mStartSetter = (hour, minute) -> {
|
||||
private final ZenModeTimePickerFragment.TimeSetter mStartSetter = (hour, minute) -> {
|
||||
if (!isValidTime(hour, minute)) {
|
||||
return;
|
||||
}
|
||||
@@ -137,7 +132,7 @@ class ZenModeSetSchedulePreferenceController extends AbstractZenModePreferenceCo
|
||||
saveMode(updateScheduleMode(mSchedule));
|
||||
};
|
||||
|
||||
private ZenModeTimePickerFragment.TimeSetter mEndSetter = (hour, minute) -> {
|
||||
private final ZenModeTimePickerFragment.TimeSetter mEndSetter = (hour, minute) -> {
|
||||
if (!isValidTime(hour, minute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,15 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.notification.modes;
|
||||
|
||||
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
|
||||
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
|
||||
|
||||
import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -29,7 +27,7 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.PrimarySwitchPreference;
|
||||
|
||||
/**
|
||||
@@ -39,9 +37,13 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
|
||||
@VisibleForTesting
|
||||
protected static final String AUTOMATIC_TRIGGER_PREF_KEY = "zen_automatic_trigger_settings";
|
||||
|
||||
private final DashboardFragment mFragment;
|
||||
|
||||
ZenModeSetTriggerLinkPreferenceController(Context context, String key,
|
||||
DashboardFragment fragment,
|
||||
ZenModesBackend backend) {
|
||||
super(context, key, backend);
|
||||
mFragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,46 +56,52 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
|
||||
// This controller is expected to govern a preference category so that it controls the
|
||||
// availability of the entire preference category if the mode doesn't have a way to
|
||||
// automatically trigger (such as manual DND).
|
||||
Preference switchPref = ((PreferenceCategory) preference).findPreference(
|
||||
PrimarySwitchPreference switchPref = ((PreferenceCategory) preference).findPreference(
|
||||
AUTOMATIC_TRIGGER_PREF_KEY);
|
||||
if (switchPref == null) {
|
||||
return;
|
||||
}
|
||||
((PrimarySwitchPreference) switchPref).setChecked(zenMode.getRule().isEnabled());
|
||||
switchPref.setChecked(zenMode.getRule().isEnabled());
|
||||
switchPref.setOnPreferenceChangeListener(mSwitchChangeListener);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(MODE_ID, zenMode.getId());
|
||||
switchPref.setSummary(zenMode.getRule().getTriggerDescription());
|
||||
switchPref.setIcon(null);
|
||||
switchPref.setOnPreferenceClickListener(null);
|
||||
switchPref.setIntent(null);
|
||||
|
||||
// TODO: b/341961712 - direct preference to app-owned intent if available
|
||||
switch (zenMode.getRule().getType()) {
|
||||
case TYPE_SCHEDULE_TIME:
|
||||
switchPref.setTitle(R.string.zen_mode_set_schedule_link);
|
||||
switchPref.setSummary(zenMode.getRule().getTriggerDescription());
|
||||
switchPref.setIntent(new SubSettingLauncher(mContext)
|
||||
.setDestination(ZenModeSetScheduleFragment.class.getName())
|
||||
// TODO: b/332937635 - set correct metrics category
|
||||
.setSourceMetricsCategory(0)
|
||||
.setArguments(bundle)
|
||||
.toIntent());
|
||||
break;
|
||||
case TYPE_SCHEDULE_CALENDAR:
|
||||
switchPref.setTitle(R.string.zen_mode_set_calendar_link);
|
||||
switchPref.setSummary(zenMode.getRule().getTriggerDescription());
|
||||
switchPref.setIntent(new SubSettingLauncher(mContext)
|
||||
.setDestination(ZenModeSetCalendarFragment.class.getName())
|
||||
// TODO: b/332937635 - set correct metrics category
|
||||
.setSourceMetricsCategory(0)
|
||||
.setArguments(bundle)
|
||||
.toIntent());
|
||||
break;
|
||||
default:
|
||||
// TODO: b/342156843 - change this to allow adding a trigger condition for system
|
||||
// rules that don't yet have a type selected
|
||||
switchPref.setTitle("not implemented");
|
||||
if (zenMode.isSystemOwned() && zenMode.getType() == TYPE_SCHEDULE_TIME) {
|
||||
switchPref.setTitle(R.string.zen_mode_set_schedule_link);
|
||||
// TODO: b/332937635 - set correct metrics category
|
||||
switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext,
|
||||
ZenModeSetScheduleFragment.class, zenMode.getId(), 0).toIntent());
|
||||
} else if (zenMode.isSystemOwned() && zenMode.getType() == TYPE_SCHEDULE_CALENDAR) {
|
||||
switchPref.setTitle(R.string.zen_mode_set_calendar_link);
|
||||
switchPref.setIcon(null);
|
||||
// TODO: b/332937635 - set correct metrics category
|
||||
switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext,
|
||||
ZenModeSetCalendarFragment.class, zenMode.getId(), 0).toIntent());
|
||||
} else if (zenMode.isSystemOwned()) {
|
||||
switchPref.setTitle(R.string.zen_mode_select_schedule);
|
||||
switchPref.setIcon(R.drawable.ic_add_24dp);
|
||||
switchPref.setSummary("");
|
||||
// TODO: b/342156843 - Hide the switch (needs support in SettingsLib).
|
||||
switchPref.setOnPreferenceClickListener(clickedPreference -> {
|
||||
ZenModeScheduleChooserDialog.show(mFragment, mOnScheduleOptionListener);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
// TODO: b/341961712 - direct preference to app-owned intent if available
|
||||
switchPref.setTitle("not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
final ZenModeScheduleChooserDialog.OnScheduleOptionListener mOnScheduleOptionListener =
|
||||
conditionId -> saveMode(mode -> {
|
||||
mode.setCustomModeConditionId(mContext, conditionId);
|
||||
return mode;
|
||||
});
|
||||
|
||||
@VisibleForTesting
|
||||
protected Preference.OnPreferenceChangeListener mSwitchChangeListener = (p, newValue) -> {
|
||||
final boolean newEnabled = (Boolean) newValue;
|
||||
@@ -103,5 +111,6 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
|
||||
}
|
||||
return zenMode;
|
||||
});
|
||||
// TODO: b/342156843 - Do we want to jump to the corresponding schedule editing screen?
|
||||
};
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.Condition;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -194,19 +193,11 @@ class ZenModesBackend {
|
||||
*/
|
||||
@Nullable
|
||||
ZenMode addCustomMode(String name) {
|
||||
ZenModeConfig.ScheduleInfo schedule = new ZenModeConfig.ScheduleInfo();
|
||||
schedule.days = ZenModeConfig.ALL_DAYS;
|
||||
schedule.startHour = 22;
|
||||
schedule.endHour = 7;
|
||||
|
||||
// TODO: b/326442408 - Create as "manual" (i.e. no trigger) instead of schedule-time.
|
||||
AutomaticZenRule rule = new AutomaticZenRule.Builder(name,
|
||||
ZenModeConfig.toScheduleConditionId(schedule))
|
||||
.setPackage(ZenModeConfig.getScheduleConditionProvider().getPackageName())
|
||||
.setType(AutomaticZenRule.TYPE_SCHEDULE_CALENDAR)
|
||||
.setOwner(ZenModeConfig.getScheduleConditionProvider())
|
||||
.setTriggerDescription(SystemZenRules.getTriggerDescriptionForScheduleTime(
|
||||
mContext, schedule))
|
||||
ZenModeConfig.toCustomManualConditionId())
|
||||
.setPackage(ZenModeConfig.getCustomManualConditionProvider().getPackageName())
|
||||
.setType(AutomaticZenRule.TYPE_OTHER)
|
||||
.setOwner(ZenModeConfig.getCustomManualConditionProvider())
|
||||
.setManualInvocationAllowed(true)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class ZenSubSettingLauncher {
|
||||
SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION);
|
||||
}
|
||||
|
||||
private static SubSettingLauncher forModeFragment(Context context,
|
||||
static SubSettingLauncher forModeFragment(Context context,
|
||||
Class<? extends ZenModeFragmentBase> fragmentClass, String modeId,
|
||||
int sourceMetricsCategory) {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
@@ -17,16 +17,32 @@
|
||||
package com.android.settings.print
|
||||
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Add
|
||||
import androidx.compose.material.icons.outlined.Print
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.android.settings.R
|
||||
@@ -36,13 +52,18 @@ import com.android.settings.print.PrintSettingsFragment.EXTRA_CHECKED
|
||||
import com.android.settings.print.PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME
|
||||
import com.android.settings.print.PrintSettingsFragment.EXTRA_TITLE
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.compose.rememberContext
|
||||
import com.android.settingslib.spa.framework.compose.rememberDrawablePainter
|
||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||
import com.android.settingslib.spa.framework.theme.SettingsOpacity
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
||||
import com.android.settingslib.spa.widget.ui.Category
|
||||
import com.android.settingslib.spa.widget.ui.SettingsIcon
|
||||
import com.android.settingslib.spaprivileged.settingsprovider.settingsSecureStringFlow
|
||||
import com.android.settingslib.spaprivileged.template.common.UserProfilePager
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
object PrintSettingsPageProvider : SettingsPageProvider {
|
||||
override val name = "PrintSettings"
|
||||
@@ -52,51 +73,101 @@ object PrintSettingsPageProvider : SettingsPageProvider {
|
||||
RegularScaffold(title = stringResource(R.string.print_settings)) {
|
||||
val context = LocalContext.current
|
||||
val printRepository = remember(context) { PrintRepository(context) }
|
||||
UserProfilePager {
|
||||
PrintServices(printRepository)
|
||||
}
|
||||
UserProfilePager { PrintServices(printRepository) }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PrintServices(printRepository: PrintRepository) {
|
||||
val printServiceDisplayInfos by remember {
|
||||
printRepository.printServiceDisplayInfosFlow()
|
||||
}.collectAsStateWithLifecycle(initialValue = emptyList())
|
||||
Category(title = stringResource(R.string.print_settings_title)) {
|
||||
for (printServiceDisplayInfo in printServiceDisplayInfos) {
|
||||
PrintService(printServiceDisplayInfo)
|
||||
val printServiceDisplayInfos by
|
||||
remember { printRepository.printServiceDisplayInfosFlow() }
|
||||
.collectAsStateWithLifecycle(initialValue = emptyList())
|
||||
if (printServiceDisplayInfos.isEmpty()) {
|
||||
NoServicesInstalled()
|
||||
} else {
|
||||
Category(title = stringResource(R.string.print_settings_title)) {
|
||||
for (printServiceDisplayInfo in printServiceDisplayInfos) {
|
||||
PrintService(printServiceDisplayInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
AddPrintService()
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun NoServicesInstalled() {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize().padding(SettingsDimension.itemPaddingAround),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Print,
|
||||
contentDescription = null,
|
||||
modifier =
|
||||
Modifier.size(110.dp)
|
||||
.padding(SettingsDimension.itemPaddingAround)
|
||||
.alpha(SettingsOpacity.SurfaceTone),
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.print_no_services_installed),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@Composable
|
||||
fun PrintService(displayInfo: PrintServiceDisplayInfo) {
|
||||
val context = LocalContext.current
|
||||
Preference(model = object : PreferenceModel {
|
||||
override val title = displayInfo.title
|
||||
override val summary = { displayInfo.summary }
|
||||
override val icon: @Composable () -> Unit = {
|
||||
Image(
|
||||
painter = rememberDrawablePainter(displayInfo.icon),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(SettingsDimension.appIconItemSize),
|
||||
)
|
||||
}
|
||||
override val onClick = {
|
||||
SubSettingLauncher(context).apply {
|
||||
setDestination(PrintServiceSettingsFragment::class.qualifiedName)
|
||||
setArguments(
|
||||
bundleOf(
|
||||
EXTRA_CHECKED to displayInfo.isEnabled,
|
||||
EXTRA_TITLE to displayInfo.title,
|
||||
EXTRA_SERVICE_COMPONENT_NAME to displayInfo.componentName
|
||||
)
|
||||
Preference(
|
||||
object : PreferenceModel {
|
||||
override val title = displayInfo.title
|
||||
override val summary = { displayInfo.summary }
|
||||
override val icon: @Composable () -> Unit = {
|
||||
Image(
|
||||
painter = rememberDrawablePainter(displayInfo.icon),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(SettingsDimension.appIconItemSize),
|
||||
)
|
||||
setSourceMetricsCategory(SettingsEnums.PRINT_SETTINGS)
|
||||
}.launch()
|
||||
}
|
||||
override val onClick = { launchPrintServiceSettings(context, displayInfo) }
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
private fun launchPrintServiceSettings(context: Context, displayInfo: PrintServiceDisplayInfo) {
|
||||
SubSettingLauncher(context)
|
||||
.apply {
|
||||
setDestination(PrintServiceSettingsFragment::class.qualifiedName)
|
||||
setArguments(
|
||||
bundleOf(
|
||||
EXTRA_CHECKED to displayInfo.isEnabled,
|
||||
EXTRA_TITLE to displayInfo.title,
|
||||
EXTRA_SERVICE_COMPONENT_NAME to displayInfo.componentName
|
||||
)
|
||||
)
|
||||
setSourceMetricsCategory(SettingsEnums.PRINT_SETTINGS)
|
||||
}
|
||||
.launch()
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AddPrintService(
|
||||
searchUriFlow: Flow<String> = rememberContext { context ->
|
||||
context.settingsSecureStringFlow(Settings.Secure.PRINT_SERVICE_SEARCH_URI)
|
||||
},
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val searchUri by searchUriFlow.collectAsStateWithLifecycle("")
|
||||
if (searchUri.isEmpty()) return
|
||||
Preference(
|
||||
object : PreferenceModel {
|
||||
override val title = stringResource(R.string.print_menu_item_add_service)
|
||||
override val icon = @Composable { SettingsIcon(imageVector = Icons.Outlined.Add) }
|
||||
override val onClick = {
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(searchUri)))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -236,7 +238,12 @@ public class WifiDppConfiguratorActivity extends WifiDppBaseActivity implements
|
||||
WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
|
||||
|
||||
if (fragment == null) {
|
||||
fragment = new WifiDppQrCodeGeneratorFragment();
|
||||
if (Flags.enableWifiSharingRuntimeFragment()) {
|
||||
fragment = FeatureFactory.getFeatureFactory().getWifiFeatureProvider()
|
||||
.getWifiDppQrCodeGeneratorFragment();
|
||||
} else {
|
||||
fragment = new WifiDppQrCodeGeneratorFragment();
|
||||
}
|
||||
} else {
|
||||
if (fragment.isVisible()) {
|
||||
return;
|
||||
|
||||
@@ -56,7 +56,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
|
||||
private static final String TAG = "WifiDppQrCodeGeneratorFragment";
|
||||
|
||||
private ImageView mQrCodeView;
|
||||
private String mQrCode;
|
||||
protected String mQrCode;
|
||||
|
||||
private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
|
||||
private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon";
|
||||
@@ -258,7 +258,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
|
||||
return button;
|
||||
}
|
||||
|
||||
private void setQrCode() {
|
||||
protected void setQrCode() {
|
||||
try {
|
||||
final int qrcodeSize = getContext().getResources().getDimensionPixelSize(
|
||||
R.dimen.qrcode_size);
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.lifecycle.ViewModelStoreOwner;
|
||||
|
||||
import com.android.settings.wifi.details.WifiNetworkDetailsViewModel;
|
||||
import com.android.settings.wifi.dpp.WifiDppQrCodeGeneratorFragment;
|
||||
import com.android.settings.wifi.repository.SharedConnectivityRepository;
|
||||
import com.android.settings.wifi.repository.WifiHotspotRepository;
|
||||
import com.android.settings.wifi.tether.WifiHotspotSecurityViewModel;
|
||||
@@ -146,6 +147,15 @@ public class WifiFeatureProvider {
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instance of WifiDppQrCodeGeneratorFragment
|
||||
*/
|
||||
public WifiDppQrCodeGeneratorFragment getWifiDppQrCodeGeneratorFragment() {
|
||||
WifiDppQrCodeGeneratorFragment fragment = new WifiDppQrCodeGeneratorFragment();
|
||||
verboseLog(TAG, "getWifiDppQrCodeGeneratorFragment():" + fragment);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a {@link Log#VERBOSE} log message.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.fuelgauge.batteryusage.bugreport;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.fuelgauge.batteryusage.BatteryReattribute;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryReattributeDao;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryReattributeEntity;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
|
||||
import com.android.settings.testutils.BatteryTestUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public final class LogUtilsTest {
|
||||
|
||||
private StringWriter mTestStringWriter;
|
||||
private PrintWriter mTestPrintWriter;
|
||||
private Context mContext;
|
||||
private BatteryStateDatabase mDatabase;
|
||||
private BatteryReattributeDao mBatteryReattributeDao;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mTestStringWriter = new StringWriter();
|
||||
mTestPrintWriter = new PrintWriter(mTestStringWriter);
|
||||
mDatabase = BatteryTestUtils.setUpBatteryStateDatabase(mContext);
|
||||
mBatteryReattributeDao = mDatabase.batteryReattributeDao();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mBatteryReattributeDao.clearAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dumpBatteryReattributeDatabaseHist_noData_printExpectedResult() {
|
||||
LogUtils.dumpBatteryReattributeDatabaseHist(mBatteryReattributeDao, mTestPrintWriter);
|
||||
|
||||
assertThat(mTestStringWriter.toString())
|
||||
.contains("BatteryReattribute DatabaseHistory:");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dumpBatteryReattributeDatabaseHist_printExpectedResult() {
|
||||
final long currentTimeMillis = System.currentTimeMillis();
|
||||
// Insert the first testing data.
|
||||
final BatteryReattribute batteryReattribute1 =
|
||||
BatteryReattribute.newBuilder()
|
||||
.setTimestampStart(currentTimeMillis - 20000)
|
||||
.setTimestampEnd(currentTimeMillis - 10000)
|
||||
.putReattributeData(1001, 0.1f)
|
||||
.putReattributeData(1002, 0.99f)
|
||||
.build();
|
||||
mBatteryReattributeDao.insert(new BatteryReattributeEntity(batteryReattribute1));
|
||||
// Insert the second testing data.
|
||||
final BatteryReattribute batteryReattribute2 =
|
||||
BatteryReattribute.newBuilder()
|
||||
.setTimestampStart(currentTimeMillis - 40000)
|
||||
.setTimestampEnd(currentTimeMillis - 20000)
|
||||
.putReattributeData(1003, 1f)
|
||||
.build();
|
||||
mBatteryReattributeDao.insert(new BatteryReattributeEntity(batteryReattribute2));
|
||||
|
||||
LogUtils.dumpBatteryReattributeDatabaseHist(mBatteryReattributeDao, mTestPrintWriter);
|
||||
|
||||
final String result = mTestStringWriter.toString();
|
||||
assertThat(result).contains("BatteryReattribute DatabaseHistory:");
|
||||
assertThat(result).contains(batteryReattribute1.toString());
|
||||
assertThat(result).contains(batteryReattribute2.toString());
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
|
||||
import androidx.preference.DropDownPreference;
|
||||
@@ -85,7 +86,9 @@ public class ZenModeSetCalendarPreferenceControllerTest {
|
||||
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
|
||||
public void updateEventMode_updatesConditionAndTriggerDescription() {
|
||||
ZenMode mode = new ZenMode("id",
|
||||
new AutomaticZenRule.Builder("name", Uri.parse("condition")).build(),
|
||||
new AutomaticZenRule.Builder("name", Uri.parse("condition"))
|
||||
.setPackage(SystemZenRules.PACKAGE_ANDROID)
|
||||
.build(),
|
||||
true); // is active
|
||||
|
||||
// Explicitly update preference controller with mode info first, which will also call
|
||||
@@ -99,6 +102,7 @@ public class ZenModeSetCalendarPreferenceControllerTest {
|
||||
// apply event mode updater to existing mode
|
||||
ZenMode out = mPrefController.updateEventMode(eventInfo).apply(mode);
|
||||
|
||||
assertThat(out.getRule().getOwner()).isEqualTo(ZenModeConfig.getEventConditionProvider());
|
||||
assertThat(out.getRule().getConditionId()).isEqualTo(
|
||||
ZenModeConfig.toEventConditionId(eventInfo));
|
||||
assertThat(out.getRule().getTriggerDescription()).isEqualTo("My events");
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ToggleButton;
|
||||
@@ -81,7 +82,9 @@ public class ZenModeSetSchedulePreferenceControllerTest {
|
||||
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
|
||||
public void updateScheduleRule_updatesConditionAndTriggerDescription() {
|
||||
ZenMode mode = new ZenMode("id",
|
||||
new AutomaticZenRule.Builder("name", Uri.parse("condition")).build(),
|
||||
new AutomaticZenRule.Builder("name", Uri.parse("condition"))
|
||||
.setPackage(SystemZenRules.PACKAGE_ANDROID)
|
||||
.build(),
|
||||
true); // is active
|
||||
|
||||
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
|
||||
@@ -93,6 +96,8 @@ public class ZenModeSetSchedulePreferenceControllerTest {
|
||||
assertThat(out.getRule().getConditionId())
|
||||
.isEqualTo(ZenModeConfig.toScheduleConditionId(scheduleInfo));
|
||||
assertThat(out.getRule().getTriggerDescription()).isNotEmpty();
|
||||
assertThat(out.getRule().getOwner()).isEqualTo(
|
||||
ZenModeConfig.getScheduleConditionProvider());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.notification.modes;
|
||||
|
||||
import static android.app.AutomaticZenRule.TYPE_OTHER;
|
||||
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
|
||||
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
|
||||
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
|
||||
@@ -31,10 +32,10 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.AutomaticZenRule;
|
||||
import android.app.Flags;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.service.notification.SystemZenRules;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.service.notification.ZenPolicy;
|
||||
|
||||
@@ -43,6 +44,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.PrimarySwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -57,6 +59,7 @@ import org.robolectric.RobolectricTestRunner;
|
||||
import java.util.Calendar;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||
public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
|
||||
@@ -65,10 +68,13 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
private ZenModesBackend mBackend;
|
||||
private Context mContext;
|
||||
|
||||
private PrimarySwitchPreference mPreference;
|
||||
|
||||
@Mock
|
||||
private PreferenceCategory mPrefCategory;
|
||||
@Mock
|
||||
private PrimarySwitchPreference mPreference;
|
||||
private DashboardFragment mFragment;
|
||||
|
||||
private ZenModeSetTriggerLinkPreferenceController mPrefController;
|
||||
|
||||
@Before
|
||||
@@ -77,12 +83,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
|
||||
mPrefController = new ZenModeSetTriggerLinkPreferenceController(mContext,
|
||||
"zen_automatic_trigger_category", mBackend);
|
||||
"zen_automatic_trigger_category", mFragment, mBackend);
|
||||
mPreference = new PrimarySwitchPreference(mContext);
|
||||
when(mPrefCategory.findPreference(AUTOMATIC_TRIGGER_PREF_KEY)).thenReturn(mPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||
public void testIsAvailable() {
|
||||
// should not be available for manual DND
|
||||
ZenMode manualMode = ZenMode.manualDndMode(new AutomaticZenRule.Builder("Do Not Disturb",
|
||||
@@ -117,12 +123,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
|
||||
// Update preference controller with a zen mode that is not enabled
|
||||
mPrefController.updateZenMode(mPrefCategory, zenMode);
|
||||
verify(mPreference).setChecked(false);
|
||||
assertThat(mPreference.getCheckedState()).isFalse();
|
||||
|
||||
// Now with the rule enabled
|
||||
zenMode.getRule().setEnabled(true);
|
||||
mPrefController.updateZenMode(mPrefCategory, zenMode);
|
||||
verify(mPreference).setChecked(true);
|
||||
assertThat(mPreference.getCheckedState()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,21 +160,24 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
eventInfo.calName = "My events";
|
||||
ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
|
||||
ZenModeConfig.toEventConditionId(eventInfo))
|
||||
.setPackage(SystemZenRules.PACKAGE_ANDROID)
|
||||
.setType(TYPE_SCHEDULE_CALENDAR)
|
||||
.setTriggerDescription("My events")
|
||||
.build(),
|
||||
true); // is active
|
||||
mPrefController.updateZenMode(mPrefCategory, mode);
|
||||
|
||||
verify(mPreference).setTitle(R.string.zen_mode_set_calendar_link);
|
||||
verify(mPreference).setSummary(mode.getRule().getTriggerDescription());
|
||||
assertThat(mPreference.getTitle()).isNotNull();
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.zen_mode_set_calendar_link));
|
||||
assertThat(mPreference.getSummary()).isNotNull();
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(
|
||||
mode.getRule().getTriggerDescription());
|
||||
assertThat(mPreference.getIcon()).isNull();
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mPreference).setIntent(captor.capture());
|
||||
// Destination as written into the intent by SubSettingLauncher
|
||||
assertThat(
|
||||
captor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
|
||||
ZenModeSetCalendarFragment.class.getName());
|
||||
assertThat(mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(ZenModeSetCalendarFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -179,20 +188,75 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
scheduleInfo.endHour = 15;
|
||||
ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
|
||||
ZenModeConfig.toScheduleConditionId(scheduleInfo))
|
||||
.setPackage(SystemZenRules.PACKAGE_ANDROID)
|
||||
.setType(TYPE_SCHEDULE_TIME)
|
||||
.setTriggerDescription("some schedule")
|
||||
.build(),
|
||||
true); // is active
|
||||
mPrefController.updateZenMode(mPrefCategory, mode);
|
||||
|
||||
verify(mPreference).setTitle(R.string.zen_mode_set_schedule_link);
|
||||
verify(mPreference).setSummary(mode.getRule().getTriggerDescription());
|
||||
assertThat(mPreference.getTitle()).isNotNull();
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.zen_mode_set_schedule_link));
|
||||
assertThat(mPreference.getSummary()).isNotNull();
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo(
|
||||
mode.getRule().getTriggerDescription());
|
||||
assertThat(mPreference.getIcon()).isNull();
|
||||
|
||||
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mPreference).setIntent(captor.capture());
|
||||
// Destination as written into the intent by SubSettingLauncher
|
||||
assertThat(
|
||||
captor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
|
||||
ZenModeSetScheduleFragment.class.getName());
|
||||
assertThat(mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
|
||||
.isEqualTo(ZenModeSetScheduleFragment.class.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRuleLink_manual() {
|
||||
ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
|
||||
ZenModeConfig.toCustomManualConditionId())
|
||||
.setPackage(SystemZenRules.PACKAGE_ANDROID)
|
||||
.setType(TYPE_OTHER)
|
||||
.setTriggerDescription("Will not be shown")
|
||||
.build(),
|
||||
true); // is active
|
||||
mPrefController.updateZenMode(mPrefCategory, mode);
|
||||
|
||||
assertThat(mPreference.getTitle()).isNotNull();
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.zen_mode_select_schedule));
|
||||
assertThat(mPreference.getIcon()).isNotNull();
|
||||
assertThat(mPreference.getSummary()).isNotNull();
|
||||
assertThat(mPreference.getSummary().toString()).isEqualTo("");
|
||||
|
||||
// Set up a click listener to open the dialog.
|
||||
assertThat(mPreference.getOnPreferenceClickListener()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onScheduleChosen_updatesMode() {
|
||||
ZenMode originalMode = new ZenMode("id",
|
||||
new AutomaticZenRule.Builder("name", ZenModeConfig.toCustomManualConditionId())
|
||||
.setPackage(SystemZenRules.PACKAGE_ANDROID)
|
||||
.setType(TYPE_OTHER)
|
||||
.setTriggerDescription("")
|
||||
.build(),
|
||||
false);
|
||||
mPrefController.updateZenMode(mPrefCategory, originalMode);
|
||||
|
||||
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
|
||||
scheduleInfo.days = new int[] { Calendar.MONDAY };
|
||||
scheduleInfo.startHour = 12;
|
||||
scheduleInfo.endHour = 15;
|
||||
Uri scheduleUri = ZenModeConfig.toScheduleConditionId(scheduleInfo);
|
||||
|
||||
mPrefController.mOnScheduleOptionListener.onScheduleSelected(scheduleUri);
|
||||
|
||||
// verify the backend got asked to update the mode to be schedule-based.
|
||||
ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
|
||||
verify(mBackend).updateMode(captor.capture());
|
||||
ZenMode updatedMode = captor.getValue();
|
||||
assertThat(updatedMode.getType()).isEqualTo(TYPE_SCHEDULE_TIME);
|
||||
assertThat(updatedMode.getRule().getConditionId()).isEqualTo(scheduleUri);
|
||||
assertThat(updatedMode.getRule().getTriggerDescription()).isNotEmpty();
|
||||
assertThat(updatedMode.getRule().getOwner()).isEqualTo(
|
||||
ZenModeConfig.getScheduleConditionProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.network.apn
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.assertIsOff
|
||||
import androidx.compose.ui.test.assertIsOn
|
||||
import androidx.compose.ui.test.junit4.ComposeTestRule
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.stub
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ApnEditCarrierEnabledTest {
|
||||
|
||||
@get:Rule val composeTestRule = createComposeRule()
|
||||
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {}
|
||||
|
||||
private val resources = spy(context.resources) {}
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
context.stub { on { resources } doReturn resources }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun carrierEnabled_displayed() {
|
||||
composeTestRule.setContent { ApnEditCarrierEnabled(ApnData()) {} }
|
||||
|
||||
composeTestRule.onCarrierEnabled().assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun carrierEnabled_isChecked() {
|
||||
val apnData = ApnData(carrierEnabled = true)
|
||||
|
||||
composeTestRule.setContent { ApnEditCarrierEnabled(apnData) {} }
|
||||
|
||||
composeTestRule.onCarrierEnabled().assertIsOn()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun carrierEnabled_allowEdit_checkChanged() {
|
||||
resources.stub { on { getBoolean(R.bool.config_allow_edit_carrier_enabled) } doReturn true }
|
||||
var apnData by mutableStateOf(ApnData(carrierEnabled = true))
|
||||
composeTestRule.setContent {
|
||||
CompositionLocalProvider(LocalContext provides context) {
|
||||
ApnEditCarrierEnabled(apnData) { apnData = apnData.copy(carrierEnabled = it) }
|
||||
}
|
||||
}
|
||||
|
||||
composeTestRule.onCarrierEnabled().performClick()
|
||||
|
||||
composeTestRule.onCarrierEnabled().assertIsEnabled().assertIsOff()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun carrierEnabled_notAllowEdit_checkNotChanged() {
|
||||
resources.stub {
|
||||
on { getBoolean(R.bool.config_allow_edit_carrier_enabled) } doReturn false
|
||||
}
|
||||
var apnData by mutableStateOf(ApnData(carrierEnabled = true))
|
||||
composeTestRule.setContent {
|
||||
CompositionLocalProvider(LocalContext provides context) {
|
||||
ApnEditCarrierEnabled(apnData) { apnData = apnData.copy(carrierEnabled = it) }
|
||||
}
|
||||
}
|
||||
|
||||
composeTestRule.onCarrierEnabled().performClick()
|
||||
|
||||
composeTestRule.onCarrierEnabled().assertIsNotEnabled().assertIsOn()
|
||||
}
|
||||
|
||||
private fun ComposeTestRule.onCarrierEnabled() =
|
||||
onNodeWithText(context.getString(R.string.carrier_enabled))
|
||||
}
|
||||
@@ -21,24 +21,17 @@ import android.net.Uri
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertIsOff
|
||||
import androidx.compose.ui.test.assertIsOn
|
||||
import androidx.compose.ui.test.hasText
|
||||
import androidx.compose.ui.test.isFocused
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onAllNodesWithText
|
||||
import androidx.compose.ui.test.onChild
|
||||
import androidx.compose.ui.test.onChildAt
|
||||
import androidx.compose.ui.test.onLast
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.onRoot
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollToNode
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.google.common.truth.Truth
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -55,7 +48,6 @@ class ApnEditPageProviderTest {
|
||||
private val port = "port"
|
||||
private val apnType = context.resources.getString(R.string.apn_type)
|
||||
private val apnRoaming = "IPv4"
|
||||
private val apnEnable = context.resources.getString(R.string.carrier_enabled)
|
||||
private val apnProtocolOptions =
|
||||
context.resources.getStringArray(R.array.apn_protocol_entries).toList()
|
||||
private val passwordTitle = context.resources.getString(R.string.apn_password)
|
||||
@@ -65,7 +57,6 @@ class ApnEditPageProviderTest {
|
||||
port = port,
|
||||
apnType = apnType,
|
||||
apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
|
||||
apnEnable = true
|
||||
)
|
||||
private val apnData = mutableStateOf(
|
||||
apnInit
|
||||
@@ -133,39 +124,6 @@ class ApnEditPageProviderTest {
|
||||
composeTestRule.onNodeWithText(apnRoaming, true).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Ignore("b/342374681")
|
||||
@Test
|
||||
fun carrier_enabled_displayed() {
|
||||
composeTestRule.setContent {
|
||||
ApnPage(apnInit, remember { apnData }, uri)
|
||||
}
|
||||
composeTestRule.onRoot().onChild().onChildAt(0)
|
||||
.performScrollToNode(hasText(apnEnable, true))
|
||||
composeTestRule.onNodeWithText(apnEnable, true).assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun carrier_enabled_isChecked() {
|
||||
composeTestRule.setContent {
|
||||
ApnPage(apnInit, remember { apnData }, uri)
|
||||
}
|
||||
composeTestRule.onRoot().onChild().onChildAt(0)
|
||||
.performScrollToNode(hasText(apnEnable, true))
|
||||
composeTestRule.onNodeWithText(apnEnable, true).assertIsOn()
|
||||
}
|
||||
|
||||
@Ignore("b/342374681")
|
||||
@Test
|
||||
fun carrier_enabled_checkChanged() {
|
||||
composeTestRule.setContent {
|
||||
ApnPage(apnInit, remember { apnData }, uri)
|
||||
}
|
||||
composeTestRule.onRoot().onChild().onChildAt(0)
|
||||
.performScrollToNode(hasText(apnEnable, true))
|
||||
composeTestRule.onNodeWithText(apnEnable, true).performClick()
|
||||
composeTestRule.onNodeWithText(apnEnable, true).assertIsOff()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun password_displayed() {
|
||||
composeTestRule.setContent {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.print
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.test.isDisplayed
|
||||
@@ -31,7 +32,9 @@ import com.android.settings.print.PrintRepository.PrintServiceDisplayInfo
|
||||
import com.android.settings.print.PrintSettingsFragment.EXTRA_CHECKED
|
||||
import com.android.settings.print.PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME
|
||||
import com.android.settings.print.PrintSettingsFragment.EXTRA_TITLE
|
||||
import com.android.settings.print.PrintSettingsPageProvider.AddPrintService
|
||||
import com.android.settings.print.PrintSettingsPageProvider.PrintService
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -44,35 +47,32 @@ import org.mockito.kotlin.whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class PrintSettingsPageProviderTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
@get:Rule val composeTestRule = createComposeRule()
|
||||
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||
doNothing().whenever(mock).startActivity(any())
|
||||
}
|
||||
private val context: Context =
|
||||
spy(ApplicationProvider.getApplicationContext()) {
|
||||
doNothing().whenever(mock).startActivity(any())
|
||||
}
|
||||
|
||||
private val displayInfo = PrintServiceDisplayInfo(
|
||||
title = TITLE,
|
||||
isEnabled = true,
|
||||
summary = SUMMARY,
|
||||
icon = context.getDrawable(R.drawable.ic_settings_print)!!,
|
||||
componentName = "ComponentName",
|
||||
)
|
||||
private val displayInfo =
|
||||
PrintServiceDisplayInfo(
|
||||
title = TITLE,
|
||||
isEnabled = true,
|
||||
summary = SUMMARY,
|
||||
icon = context.getDrawable(R.drawable.ic_settings_print)!!,
|
||||
componentName = "ComponentName",
|
||||
)
|
||||
|
||||
@Test
|
||||
fun printService_titleDisplayed() {
|
||||
composeTestRule.setContent {
|
||||
PrintService(displayInfo)
|
||||
}
|
||||
composeTestRule.setContent { PrintService(displayInfo) }
|
||||
|
||||
composeTestRule.onNodeWithText(TITLE).isDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun printService_summaryDisplayed() {
|
||||
composeTestRule.setContent {
|
||||
PrintService(displayInfo)
|
||||
}
|
||||
composeTestRule.setContent { PrintService(displayInfo) }
|
||||
|
||||
composeTestRule.onNodeWithText(SUMMARY).isDisplayed()
|
||||
}
|
||||
@@ -80,25 +80,43 @@ class PrintSettingsPageProviderTest {
|
||||
@Test
|
||||
fun printService_onClick() {
|
||||
composeTestRule.setContent {
|
||||
CompositionLocalProvider(LocalContext provides context) {
|
||||
PrintService(displayInfo)
|
||||
}
|
||||
CompositionLocalProvider(LocalContext provides context) { PrintService(displayInfo) }
|
||||
}
|
||||
|
||||
composeTestRule.onNodeWithText(TITLE).performClick()
|
||||
|
||||
verify(context).startActivity(argThat {
|
||||
val fragment = getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)
|
||||
val arguments = getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!!
|
||||
fragment == PrintServiceSettingsFragment::class.qualifiedName &&
|
||||
arguments.getBoolean(EXTRA_CHECKED) == displayInfo.isEnabled &&
|
||||
arguments.getString(EXTRA_TITLE) == displayInfo.title &&
|
||||
arguments.getString(EXTRA_SERVICE_COMPONENT_NAME) == displayInfo.componentName
|
||||
})
|
||||
verify(context)
|
||||
.startActivity(
|
||||
argThat {
|
||||
val fragment = getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)
|
||||
val arguments = getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!!
|
||||
fragment == PrintServiceSettingsFragment::class.qualifiedName &&
|
||||
arguments.getBoolean(EXTRA_CHECKED) == displayInfo.isEnabled &&
|
||||
arguments.getString(EXTRA_TITLE) == displayInfo.title &&
|
||||
arguments.getString(EXTRA_SERVICE_COMPONENT_NAME) ==
|
||||
displayInfo.componentName
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addPrintService_onClick() {
|
||||
composeTestRule.setContent {
|
||||
CompositionLocalProvider(LocalContext provides context) {
|
||||
AddPrintService(flowOf(SEARCH_URI))
|
||||
}
|
||||
}
|
||||
|
||||
composeTestRule
|
||||
.onNodeWithText(context.getString(R.string.print_menu_item_add_service))
|
||||
.performClick()
|
||||
|
||||
verify(context).startActivity(argThat { data == Uri.parse(SEARCH_URI) })
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TITLE = "Title"
|
||||
const val SUMMARY = "Summary"
|
||||
const val SEARCH_URI = "search.uri"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,16 @@
|
||||
|
||||
package com.android.settings.network;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkPolicyManager;
|
||||
@@ -67,7 +63,7 @@ public class ResetNetworkOperationBuilderTest {
|
||||
@Mock
|
||||
private NetworkPolicyManager mNetworkPolicyManager;
|
||||
@Mock
|
||||
private ContentProvider mContentProvider;;
|
||||
private ContentProviderClient mContentProviderClient;
|
||||
|
||||
|
||||
private Context mContext;
|
||||
@@ -77,9 +73,8 @@ public class ResetNetworkOperationBuilderTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||
doReturn(ContentResolver.wrap(mContentProvider)).when(mContext).getContentResolver();
|
||||
|
||||
mBuilder = spy(new ResetNetworkOperationBuilder(mContext));
|
||||
doReturn(mContentProviderClient).when(mBuilder).getUnstableTelephonyContentProviderClient();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -184,38 +179,38 @@ public class ResetNetworkOperationBuilderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash() {
|
||||
doThrow(new IllegalArgumentException()).when(mContentProvider).call(
|
||||
anyString(), anyString(), anyString(), any());
|
||||
public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash()
|
||||
throws Exception {
|
||||
doReturn(null).when(mBuilder).getUnstableTelephonyContentProviderClient();
|
||||
|
||||
mBuilder.restartPhoneProcess().build().run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restartRild_withoutTelephonyContentProvider_shouldNotCrash() {
|
||||
doThrow(new IllegalArgumentException()).when(mContentProvider).call(
|
||||
anyString(), anyString(), anyString(), any());
|
||||
public void restartRild_withoutTelephonyContentProvider_shouldNotCrash()
|
||||
throws Exception {
|
||||
doReturn(null).when(mBuilder).getUnstableTelephonyContentProviderClient();
|
||||
|
||||
mBuilder.restartRild().build().run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess() {
|
||||
public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess()
|
||||
throws Exception {
|
||||
mBuilder.restartPhoneProcess().build().run();
|
||||
|
||||
verify(mContentProvider).call(
|
||||
eq(mBuilder.getResetTelephonyContentProviderAuthority()),
|
||||
verify(mContentProviderClient).call(
|
||||
eq(ResetNetworkOperationBuilder.METHOD_RESTART_PHONE_PROCESS),
|
||||
isNull(),
|
||||
isNull());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void restartRild_withTelephonyContentProvider_shouldCallRestartRild() {
|
||||
public void restartRild_withTelephonyContentProvider_shouldCallRestartRild()
|
||||
throws Exception {
|
||||
mBuilder.restartRild().build().run();
|
||||
|
||||
verify(mContentProvider).call(
|
||||
eq(mBuilder.getResetTelephonyContentProviderAuthority()),
|
||||
verify(mContentProviderClient).call(
|
||||
eq(ResetNetworkOperationBuilder.METHOD_RESTART_RILD),
|
||||
isNull(),
|
||||
isNull());
|
||||
|
||||
Reference in New Issue
Block a user