Snap for 11992154 from 2345b63c68 to 24Q4-release

Change-Id: I4336f08b19bf2645d539a030f96fff6fce8d7e5c
This commit is contained in:
Android Build Coastguard Worker
2024-06-19 23:22:23 +00:00
34 changed files with 968 additions and 258 deletions

View File

@@ -140,7 +140,7 @@
<uses-permission android:name="android.permission.REMAP_MODIFIER_KEYS" /> <uses-permission android:name="android.permission.REMAP_MODIFIER_KEYS" />
<uses-permission android:name="android.permission.ACCESS_GPU_SERVICE" /> <uses-permission android:name="android.permission.ACCESS_GPU_SERVICE" />
<uses-permission android:name="android.permission.MANAGE_GAME_MODE" /> <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.MANAGE_ENHANCED_CONFIRMATION_STATES" />
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" /> <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />

View 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"
}

View 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>

View File

@@ -7927,6 +7927,19 @@
<!-- Zen Modes: Summary for the Do not Disturb option and associated settings page. [CHAR LIMIT=240]--> <!-- 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> <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]--> <!-- Subtitle for the Do not Disturb slice. [CHAR LIMIT=50]-->
<string name="zen_mode_slice_subtitle">Limit interruptions</string> <string name="zen_mode_slice_subtitle">Limit interruptions</string>

View File

@@ -271,12 +271,12 @@ public class ResetNetworkRequest {
builder.resetIms(mSubscriptionIdToResetIms); builder.resetIms(mSubscriptionIdToResetIms);
} }
// Reset phone process and RILD may impact above components, keep them at the end // 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) { if ((mResetOptions & RESET_RILD) != 0) {
builder.restartRild(); builder.restartRild();
} }
if ((mResetOptions & RESET_PHONE_PROCESS) != 0) {
builder.restartPhoneProcess();
}
return builder; return builder;
} }
} }

View File

@@ -75,6 +75,10 @@ public class AudioStreamMediaService extends Service {
public void onSourceLost(int broadcastId) { public void onSourceLost(int broadcastId) {
super.onSourceLost(broadcastId); super.onSourceLost(broadcastId);
if (broadcastId == mBroadcastId) { if (broadcastId == mBroadcastId) {
Log.d(TAG, "onSourceLost() : stopSelf");
if (mNotificationManager != null) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
stopSelf(); stopSelf();
} }
} }
@@ -86,6 +90,10 @@ public class AudioStreamMediaService extends Service {
&& mAudioStreamsHelper.getAllConnectedSources().stream() && mAudioStreamsHelper.getAllConnectedSources().stream()
.map(BluetoothLeBroadcastReceiveState::getBroadcastId) .map(BluetoothLeBroadcastReceiveState::getBroadcastId)
.noneMatch(id -> id == mBroadcastId)) { .noneMatch(id -> id == mBroadcastId)) {
Log.d(TAG, "onSourceRemoved() : stopSelf");
if (mNotificationManager != null) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
stopSelf(); stopSelf();
} }
} }
@@ -96,6 +104,10 @@ public class AudioStreamMediaService extends Service {
@Override @Override
public void onBluetoothStateChanged(int bluetoothState) { public void onBluetoothStateChanged(int bluetoothState) {
if (BluetoothAdapter.STATE_OFF == bluetoothState) { if (BluetoothAdapter.STATE_OFF == bluetoothState) {
Log.d(TAG, "onBluetoothStateChanged() : stopSelf");
if (mNotificationManager != null) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
stopSelf(); stopSelf();
} }
} }
@@ -120,6 +132,10 @@ public class AudioStreamMediaService extends Service {
}); });
} }
if (mDevices == null || mDevices.isEmpty()) { if (mDevices == null || mDevices.isEmpty()) {
Log.d(TAG, "onProfileConnectionStateChanged() : stopSelf");
if (mNotificationManager != null) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
stopSelf(); stopSelf();
} }
} }
@@ -246,21 +262,27 @@ public class AudioStreamMediaService extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
Log.d(TAG, "onDestroy()");
super.onDestroy(); super.onDestroy();
if (!AudioSharingUtils.isFeatureEnabled()) { if (!AudioSharingUtils.isFeatureEnabled()) {
Log.d(TAG, "onDestroy() : skip due to feature not enabled");
return; return;
} }
if (mLocalBtManager != null) { if (mLocalBtManager != null) {
Log.d(TAG, "onDestroy() : unregister mBluetoothCallback");
mLocalBtManager.getEventManager().unregisterCallback(mBluetoothCallback); mLocalBtManager.getEventManager().unregisterCallback(mBluetoothCallback);
} }
if (mLeBroadcastAssistant != null) { if (mLeBroadcastAssistant != null) {
Log.d(TAG, "onDestroy() : unregister mBroadcastAssistantCallback");
mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback); mLeBroadcastAssistant.unregisterServiceCallBack(mBroadcastAssistantCallback);
} }
if (mVolumeControl != null) { if (mVolumeControl != null) {
Log.d(TAG, "onDestroy() : unregister mVolumeControlCallback");
mVolumeControl.unregisterCallback(mVolumeControlCallback); mVolumeControl.unregisterCallback(mVolumeControlCallback);
} }
if (mLocalSession != null) { if (mLocalSession != null) {
Log.d(TAG, "onDestroy() : release mLocalSession");
mLocalSession.release(); mLocalSession.release();
mLocalSession = null; mLocalSession = null;
} }
@@ -273,6 +295,9 @@ public class AudioStreamMediaService extends Service {
mBroadcastId = intent != null ? intent.getIntExtra(BROADCAST_ID, -1) : -1; mBroadcastId = intent != null ? intent.getIntExtra(BROADCAST_ID, -1) : -1;
if (mBroadcastId == -1) { if (mBroadcastId == -1) {
Log.w(TAG, "Invalid broadcast ID. Service will not start."); Log.w(TAG, "Invalid broadcast ID. Service will not start.");
if (mNotificationManager != null) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
stopSelf(); stopSelf();
return START_NOT_STICKY; return START_NOT_STICKY;
} }
@@ -282,6 +307,9 @@ public class AudioStreamMediaService extends Service {
} }
if (mDevices == null || mDevices.isEmpty()) { if (mDevices == null || mDevices.isEmpty()) {
Log.w(TAG, "No device. Service will not start."); Log.w(TAG, "No device. Service will not start.");
if (mNotificationManager != null) {
mNotificationManager.cancel(NOTIFICATION_ID);
}
stopSelf(); stopSelf();
return START_NOT_STICKY; return START_NOT_STICKY;
} }

View File

@@ -60,6 +60,7 @@ public final class BugReportContentProvider extends ContentProvider {
LogUtils.dumpBatteryUsageSlotDatabaseHist(context, writer); LogUtils.dumpBatteryUsageSlotDatabaseHist(context, writer);
LogUtils.dumpBatteryEventDatabaseHist(context, writer); LogUtils.dumpBatteryEventDatabaseHist(context, writer);
LogUtils.dumpBatteryStateDatabaseHist(context, writer); LogUtils.dumpBatteryStateDatabaseHist(context, writer);
LogUtils.dumpBatteryReattributeDatabaseHist(context, writer);
} }
@Override @Override

View File

@@ -19,6 +19,8 @@ package com.android.settings.fuelgauge.batteryusage.bugreport;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.fuelgauge.BatteryUtils; import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils; import com.android.settings.fuelgauge.batteryusage.AppOptModeSharedPreferencesUtils;
import com.android.settings.fuelgauge.batteryusage.AppOptimizationModeEvent; 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.AppUsageEventEntity;
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventDao; import com.android.settings.fuelgauge.batteryusage.db.BatteryEventDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity; 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.BatteryState;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao; import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase; import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
@@ -127,6 +131,24 @@ public final class LogUtils {
dumpListItems(writer, entities, entity -> entity); 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( private static <T, S> void dumpListItems(
PrintWriter writer, List<T> itemList, Function<T, S> itemConverter) { PrintWriter writer, List<T> itemList, Function<T, S> itemConverter) {
final AtomicInteger counter = new AtomicInteger(0); final AtomicInteger counter = new AtomicInteger(0);

View File

@@ -62,6 +62,7 @@ public class BatteryReattributeEntity {
.append("\nBatteryReattributeEntity{") .append("\nBatteryReattributeEntity{")
.append("\n\t" + utcToLocalTimeForLogging(timestampStart)) .append("\n\t" + utcToLocalTimeForLogging(timestampStart))
.append("\n\t" + utcToLocalTimeForLogging(timestampEnd)) .append("\n\t" + utcToLocalTimeForLogging(timestampEnd))
.append("\n\t" + ConvertUtils.decodeBatteryReattribute(reattributeData))
.append("\n}"); .append("\n}");
return builder.toString(); return builder.toString();
} }

View File

@@ -18,6 +18,7 @@ package com.android.settings.network;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothManager;
import android.content.ContentProviderClient;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
@@ -28,11 +29,14 @@ import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pManager; import android.net.wifi.p2p.WifiP2pManager;
import android.os.Looper; import android.os.Looper;
import android.os.RecoverySystem; import android.os.RecoverySystem;
import android.os.RemoteException;
import android.os.SystemClock; import android.os.SystemClock;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.ResetNetworkRequest; import com.android.settings.ResetNetworkRequest;
@@ -257,15 +261,15 @@ public class ResetNetworkOperationBuilder {
*/ */
public ResetNetworkOperationBuilder restartPhoneProcess() { public ResetNetworkOperationBuilder restartPhoneProcess() {
Runnable runnable = () -> { Runnable runnable = () -> {
try { // Unstable content provider can avoid us getting killed together with phone process
mContext.getContentResolver().call( try (ContentProviderClient client = getUnstableTelephonyContentProviderClient()) {
getResetTelephonyContentProviderAuthority(), if (client != null) {
METHOD_RESTART_PHONE_PROCESS, client.call(METHOD_RESTART_PHONE_PROCESS, /* arg= */ null, /* extra= */ null);
/* arg= */ null,
/* extras= */ null);
Log.i(TAG, "Phone process was restarted."); Log.i(TAG, "Phone process was restarted.");
} catch (IllegalArgumentException iae) { }
Log.w(TAG, "Fail to restart phone process: " + iae); } 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); mResetSequence.add(runnable);
@@ -279,15 +283,13 @@ public class ResetNetworkOperationBuilder {
*/ */
public ResetNetworkOperationBuilder restartRild() { public ResetNetworkOperationBuilder restartRild() {
Runnable runnable = () -> { Runnable runnable = () -> {
try { try (ContentProviderClient client = getUnstableTelephonyContentProviderClient()) {
mContext.getContentResolver().call( if (client != null) {
getResetTelephonyContentProviderAuthority(), client.call(METHOD_RESTART_RILD, /* arg= */ null, /* extra= */ null);
METHOD_RESTART_RILD,
/* arg= */ null,
/* extras= */ null);
Log.i(TAG, "RILD was restarted."); Log.i(TAG, "RILD was restarted.");
} catch (IllegalArgumentException iae) { }
Log.w(TAG, "Fail to restart RILD: " + iae); } catch (RemoteException re) {
Log.w(TAG, "Fail to restart RILD: " + re);
} }
}; };
mResetSequence.add(runnable); mResetSequence.add(runnable);
@@ -322,9 +324,18 @@ public class ResetNetworkOperationBuilder {
* @return the authority of the telephony content provider that support methods * @return the authority of the telephony content provider that support methods
* resetPhoneProcess and resetRild. * resetPhoneProcess and resetRild.
*/ */
@VisibleForTesting private String getResetTelephonyContentProviderAuthority() {
String getResetTelephonyContentProviderAuthority() {
return mContext.getResources().getString( return mContext.getResources().getString(
R.string.reset_telephony_stack_content_provider_authority); 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());
}
} }

View File

@@ -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
}
)
}

View File

@@ -235,19 +235,7 @@ fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Ur
enabled = apnData.isFieldEnabled(Telephony.Carriers.ROAMING_PROTOCOL), enabled = apnData.isFieldEnabled(Telephony.Carriers.ROAMING_PROTOCOL),
) { apnData = apnData.copy(apnRoaming = it) } ) { apnData = apnData.copy(apnRoaming = it) }
ApnNetworkTypeCheckBox(apnData) { apnData = apnData.copy(networkType = it) } ApnNetworkTypeCheckBox(apnData) { apnData = apnData.copy(networkType = it) }
SwitchPreference( ApnEditCarrierEnabled(apnData) { apnData = apnData.copy(carrierEnabled = it) }
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)
}
}
)
} }
} }
} }

View File

@@ -90,7 +90,7 @@ fun getApnDataFromUri(uri: Uri, context: Context): ApnData {
apnRoaming = context.convertProtocol2Options( apnRoaming = context.convertProtocol2Options(
cursor.getString(Telephony.Carriers.ROAMING_PROTOCOL) 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), networkType = cursor.getLong(Telephony.Carriers.NETWORK_TYPE_BITMASK),
edited = cursor.getInt(Telephony.Carriers.EDITED_STATUS), edited = cursor.getInt(Telephony.Carriers.EDITED_STATUS),
userEditable = cursor.getInt(Telephony.Carriers.USER_EDITABLE), userEditable = cursor.getInt(Telephony.Carriers.USER_EDITABLE),

View File

@@ -44,11 +44,10 @@ data class ApnData(
val apnType: String = "", val apnType: String = "",
val apnProtocol: Int = -1, val apnProtocol: Int = -1,
val apnRoaming: Int = -1, val apnRoaming: Int = -1,
val apnEnable: Boolean = true, val carrierEnabled: Boolean = true,
val networkType: Long = 0, val networkType: Long = 0,
val edited: Int = Telephony.Carriers.USER_EDITED, val edited: Int = Telephony.Carriers.USER_EDITED,
val userEditable: Int = 1, val userEditable: Int = 1,
val apnEnableEnabled: Boolean = true,
val newApn: Boolean = false, val newApn: Boolean = false,
val subId: Int = -1, val subId: Int = -1,
val validEnabled: Boolean = false, val validEnabled: Boolean = false,
@@ -72,7 +71,7 @@ data class ApnData(
Telephony.Carriers.NETWORK_TYPE_BITMASK to networkType, Telephony.Carriers.NETWORK_TYPE_BITMASK to networkType,
// Copy network type into lingering network type. // Copy network type into lingering network type.
Telephony.Carriers.LINGERING_NETWORK_TYPE_BITMASK to networkType, 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, 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 // TODO: mIsCarrierIdApn
return disableInit(apnDataInit) return disableInit(apnDataInit)
} }

View File

@@ -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_ALL;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; 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; import static java.util.Objects.requireNonNull;
@@ -26,7 +32,10 @@ import android.app.AutomaticZenRule;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
import android.util.Log; import android.util.Log;
@@ -204,6 +213,44 @@ class ZenMode {
: new ZenDeviceEffects.Builder().build(); : 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() { public boolean canEditName() {
return !isManualDnd(); return !isManualDnd();
} }
@@ -224,6 +271,15 @@ class ZenMode {
return mIsActive; return mIsActive;
} }
public boolean isSystemOwned() {
return SystemZenRules.PACKAGE_ANDROID.equals(mRule.getPackageName());
}
@AutomaticZenRule.Type
public int getType() {
return mRule.getType();
}
@Override @Override
public boolean equals(@Nullable Object obj) { public boolean equals(@Nullable Object obj) {
return obj instanceof ZenMode other return obj instanceof ZenMode other

View File

@@ -52,7 +52,7 @@ public class ZenModeFragment extends ZenModeFragmentBase {
prefControllers.add(new ZenModeDisplayLinkPreferenceController( prefControllers.add(new ZenModeDisplayLinkPreferenceController(
context, "mode_display_settings", mBackend, mHelperBackend)); context, "mode_display_settings", mBackend, mHelperBackend));
prefControllers.add(new ZenModeSetTriggerLinkPreferenceController(context, prefControllers.add(new ZenModeSetTriggerLinkPreferenceController(context,
"zen_automatic_trigger_category", mBackend)); "zen_automatic_trigger_category", this, mBackend));
return prefControllers; return prefControllers;
} }

View File

@@ -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);
}
}

View File

@@ -16,14 +16,12 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.CalendarContract; import android.provider.CalendarContract;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -42,7 +40,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
public class ZenModeSetCalendarPreferenceController extends AbstractZenModePreferenceController { class ZenModeSetCalendarPreferenceController extends AbstractZenModePreferenceController {
@VisibleForTesting @VisibleForTesting
protected static final String KEY_CALENDAR = "calendar"; protected static final String KEY_CALENDAR = "calendar";
@VisibleForTesting @VisibleForTesting
@@ -122,11 +120,7 @@ public class ZenModeSetCalendarPreferenceController extends AbstractZenModePrefe
@VisibleForTesting @VisibleForTesting
protected Function<ZenMode, ZenMode> updateEventMode(ZenModeConfig.EventInfo event) { protected Function<ZenMode, ZenMode> updateEventMode(ZenModeConfig.EventInfo event) {
return (zenMode) -> { return (zenMode) -> {
zenMode.getRule().setConditionId(ZenModeConfig.toEventConditionId(event)); zenMode.setCustomModeConditionId(mContext, ZenModeConfig.toEventConditionId(event));
if (Flags.modesApi() && Flags.modesUi()) {
zenMode.getRule().setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleEvent(mContext, event));
}
return zenMode; return zenMode;
}; };
} }

View File

@@ -16,9 +16,7 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.ArraySet; import android.util.ArraySet;
@@ -116,16 +114,13 @@ class ZenModeSetSchedulePreferenceController extends AbstractZenModePreferenceCo
@VisibleForTesting @VisibleForTesting
protected Function<ZenMode, ZenMode> updateScheduleMode(ZenModeConfig.ScheduleInfo schedule) { protected Function<ZenMode, ZenMode> updateScheduleMode(ZenModeConfig.ScheduleInfo schedule) {
return (zenMode) -> { return (zenMode) -> {
zenMode.getRule().setConditionId(ZenModeConfig.toScheduleConditionId(schedule)); zenMode.setCustomModeConditionId(mContext,
if (Flags.modesApi() && Flags.modesUi()) { ZenModeConfig.toScheduleConditionId(schedule));
zenMode.getRule().setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleTime(mContext, schedule));
}
return zenMode; return zenMode;
}; };
} }
private ZenModeTimePickerFragment.TimeSetter mStartSetter = (hour, minute) -> { private final ZenModeTimePickerFragment.TimeSetter mStartSetter = (hour, minute) -> {
if (!isValidTime(hour, minute)) { if (!isValidTime(hour, minute)) {
return; return;
} }
@@ -137,7 +132,7 @@ class ZenModeSetSchedulePreferenceController extends AbstractZenModePreferenceCo
saveMode(updateScheduleMode(mSchedule)); saveMode(updateScheduleMode(mSchedule));
}; };
private ZenModeTimePickerFragment.TimeSetter mEndSetter = (hour, minute) -> { private final ZenModeTimePickerFragment.TimeSetter mEndSetter = (hour, minute) -> {
if (!isValidTime(hour, minute)) { if (!isValidTime(hour, minute)) {
return; return;
} }

View File

@@ -13,15 +13,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID;
import android.content.Context; import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -29,7 +27,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.PrimarySwitchPreference;
/** /**
@@ -39,9 +37,13 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
@VisibleForTesting @VisibleForTesting
protected static final String AUTOMATIC_TRIGGER_PREF_KEY = "zen_automatic_trigger_settings"; protected static final String AUTOMATIC_TRIGGER_PREF_KEY = "zen_automatic_trigger_settings";
private final DashboardFragment mFragment;
ZenModeSetTriggerLinkPreferenceController(Context context, String key, ZenModeSetTriggerLinkPreferenceController(Context context, String key,
DashboardFragment fragment,
ZenModesBackend backend) { ZenModesBackend backend) {
super(context, key, backend); super(context, key, backend);
mFragment = fragment;
} }
@Override @Override
@@ -54,46 +56,52 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
// This controller is expected to govern a preference category so that it controls the // 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 // availability of the entire preference category if the mode doesn't have a way to
// automatically trigger (such as manual DND). // automatically trigger (such as manual DND).
Preference switchPref = ((PreferenceCategory) preference).findPreference( PrimarySwitchPreference switchPref = ((PreferenceCategory) preference).findPreference(
AUTOMATIC_TRIGGER_PREF_KEY); AUTOMATIC_TRIGGER_PREF_KEY);
if (switchPref == null) { if (switchPref == null) {
return; return;
} }
((PrimarySwitchPreference) switchPref).setChecked(zenMode.getRule().isEnabled()); switchPref.setChecked(zenMode.getRule().isEnabled());
switchPref.setOnPreferenceChangeListener(mSwitchChangeListener); switchPref.setOnPreferenceChangeListener(mSwitchChangeListener);
Bundle bundle = new Bundle(); switchPref.setSummary(zenMode.getRule().getTriggerDescription());
bundle.putString(MODE_ID, zenMode.getId()); switchPref.setIcon(null);
switchPref.setOnPreferenceClickListener(null);
switchPref.setIntent(null);
// TODO: b/341961712 - direct preference to app-owned intent if available if (zenMode.isSystemOwned() && zenMode.getType() == TYPE_SCHEDULE_TIME) {
switch (zenMode.getRule().getType()) {
case TYPE_SCHEDULE_TIME:
switchPref.setTitle(R.string.zen_mode_set_schedule_link); 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 // TODO: b/332937635 - set correct metrics category
.setSourceMetricsCategory(0) switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext,
.setArguments(bundle) ZenModeSetScheduleFragment.class, zenMode.getId(), 0).toIntent());
.toIntent()); } else if (zenMode.isSystemOwned() && zenMode.getType() == TYPE_SCHEDULE_CALENDAR) {
break;
case TYPE_SCHEDULE_CALENDAR:
switchPref.setTitle(R.string.zen_mode_set_calendar_link); switchPref.setTitle(R.string.zen_mode_set_calendar_link);
switchPref.setSummary(zenMode.getRule().getTriggerDescription()); switchPref.setIcon(null);
switchPref.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModeSetCalendarFragment.class.getName())
// TODO: b/332937635 - set correct metrics category // TODO: b/332937635 - set correct metrics category
.setSourceMetricsCategory(0) switchPref.setIntent(ZenSubSettingLauncher.forModeFragment(mContext,
.setArguments(bundle) ZenModeSetCalendarFragment.class, zenMode.getId(), 0).toIntent());
.toIntent()); } else if (zenMode.isSystemOwned()) {
break; switchPref.setTitle(R.string.zen_mode_select_schedule);
default: switchPref.setIcon(R.drawable.ic_add_24dp);
// TODO: b/342156843 - change this to allow adding a trigger condition for system switchPref.setSummary("");
// rules that don't yet have a type selected // 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"); switchPref.setTitle("not implemented");
} }
} }
@VisibleForTesting
final ZenModeScheduleChooserDialog.OnScheduleOptionListener mOnScheduleOptionListener =
conditionId -> saveMode(mode -> {
mode.setCustomModeConditionId(mContext, conditionId);
return mode;
});
@VisibleForTesting @VisibleForTesting
protected Preference.OnPreferenceChangeListener mSwitchChangeListener = (p, newValue) -> { protected Preference.OnPreferenceChangeListener mSwitchChangeListener = (p, newValue) -> {
final boolean newEnabled = (Boolean) newValue; final boolean newEnabled = (Boolean) newValue;
@@ -103,5 +111,6 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
} }
return zenMode; return zenMode;
}); });
// TODO: b/342156843 - Do we want to jump to the corresponding schedule editing screen?
}; };
} }

View File

@@ -24,7 +24,6 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.Condition; import android.service.notification.Condition;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import android.util.Log; import android.util.Log;
@@ -194,19 +193,11 @@ class ZenModesBackend {
*/ */
@Nullable @Nullable
ZenMode addCustomMode(String name) { 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, AutomaticZenRule rule = new AutomaticZenRule.Builder(name,
ZenModeConfig.toScheduleConditionId(schedule)) ZenModeConfig.toCustomManualConditionId())
.setPackage(ZenModeConfig.getScheduleConditionProvider().getPackageName()) .setPackage(ZenModeConfig.getCustomManualConditionProvider().getPackageName())
.setType(AutomaticZenRule.TYPE_SCHEDULE_CALENDAR) .setType(AutomaticZenRule.TYPE_OTHER)
.setOwner(ZenModeConfig.getScheduleConditionProvider()) .setOwner(ZenModeConfig.getCustomManualConditionProvider())
.setTriggerDescription(SystemZenRules.getTriggerDescriptionForScheduleTime(
mContext, schedule))
.setManualInvocationAllowed(true) .setManualInvocationAllowed(true)
.build(); .build();

View File

@@ -29,7 +29,7 @@ class ZenSubSettingLauncher {
SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION); SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION);
} }
private static SubSettingLauncher forModeFragment(Context context, static SubSettingLauncher forModeFragment(Context context,
Class<? extends ZenModeFragmentBase> fragmentClass, String modeId, Class<? extends ZenModeFragmentBase> fragmentClass, String modeId,
int sourceMetricsCategory) { int sourceMetricsCategory) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();

View File

@@ -17,16 +17,32 @@
package com.android.settings.print package com.android.settings.print
import android.app.settings.SettingsEnums import android.app.settings.SettingsEnums
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.Settings
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.Image 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.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.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R 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_SERVICE_COMPONENT_NAME
import com.android.settings.print.PrintSettingsFragment.EXTRA_TITLE import com.android.settings.print.PrintSettingsFragment.EXTRA_TITLE
import com.android.settingslib.spa.framework.common.SettingsPageProvider 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.compose.rememberDrawablePainter
import com.android.settingslib.spa.framework.theme.SettingsDimension 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.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.scaffold.RegularScaffold import com.android.settingslib.spa.widget.scaffold.RegularScaffold
import com.android.settingslib.spa.widget.ui.Category 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 com.android.settingslib.spaprivileged.template.common.UserProfilePager
import kotlinx.coroutines.flow.Flow
object PrintSettingsPageProvider : SettingsPageProvider { object PrintSettingsPageProvider : SettingsPageProvider {
override val name = "PrintSettings" override val name = "PrintSettings"
@@ -52,29 +73,54 @@ object PrintSettingsPageProvider : SettingsPageProvider {
RegularScaffold(title = stringResource(R.string.print_settings)) { RegularScaffold(title = stringResource(R.string.print_settings)) {
val context = LocalContext.current val context = LocalContext.current
val printRepository = remember(context) { PrintRepository(context) } val printRepository = remember(context) { PrintRepository(context) }
UserProfilePager { UserProfilePager { PrintServices(printRepository) }
PrintServices(printRepository)
}
} }
} }
@Composable @Composable
private fun PrintServices(printRepository: PrintRepository) { private fun PrintServices(printRepository: PrintRepository) {
val printServiceDisplayInfos by remember { val printServiceDisplayInfos by
printRepository.printServiceDisplayInfosFlow() remember { printRepository.printServiceDisplayInfosFlow() }
}.collectAsStateWithLifecycle(initialValue = emptyList()) .collectAsStateWithLifecycle(initialValue = emptyList())
if (printServiceDisplayInfos.isEmpty()) {
NoServicesInstalled()
} else {
Category(title = stringResource(R.string.print_settings_title)) { Category(title = stringResource(R.string.print_settings_title)) {
for (printServiceDisplayInfo in printServiceDisplayInfos) { for (printServiceDisplayInfo in printServiceDisplayInfos) {
PrintService(printServiceDisplayInfo) 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 @VisibleForTesting
@Composable @Composable
fun PrintService(displayInfo: PrintServiceDisplayInfo) { fun PrintService(displayInfo: PrintServiceDisplayInfo) {
val context = LocalContext.current val context = LocalContext.current
Preference(model = object : PreferenceModel { Preference(
object : PreferenceModel {
override val title = displayInfo.title override val title = displayInfo.title
override val summary = { displayInfo.summary } override val summary = { displayInfo.summary }
override val icon: @Composable () -> Unit = { override val icon: @Composable () -> Unit = {
@@ -84,8 +130,14 @@ object PrintSettingsPageProvider : SettingsPageProvider {
modifier = Modifier.size(SettingsDimension.appIconItemSize), modifier = Modifier.size(SettingsDimension.appIconItemSize),
) )
} }
override val onClick = { override val onClick = { launchPrintServiceSettings(context, displayInfo) }
SubSettingLauncher(context).apply { }
)
}
private fun launchPrintServiceSettings(context: Context, displayInfo: PrintServiceDisplayInfo) {
SubSettingLauncher(context)
.apply {
setDestination(PrintServiceSettingsFragment::class.qualifiedName) setDestination(PrintServiceSettingsFragment::class.qualifiedName)
setArguments( setArguments(
bundleOf( bundleOf(
@@ -95,8 +147,27 @@ object PrintSettingsPageProvider : SettingsPageProvider {
) )
) )
setSourceMetricsCategory(SettingsEnums.PRINT_SETTINGS) setSourceMetricsCategory(SettingsEnums.PRINT_SETTINGS)
}.launch()
} }
}) .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)))
}
}
)
} }
} }

View File

@@ -35,6 +35,8 @@ import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.overlay.FeatureFactory;
import java.util.List; import java.util.List;
@@ -236,7 +238,12 @@ public class WifiDppConfiguratorActivity extends WifiDppBaseActivity implements
WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR); WifiDppUtils.TAG_FRAGMENT_QR_CODE_GENERATOR);
if (fragment == null) { if (fragment == null) {
if (Flags.enableWifiSharingRuntimeFragment()) {
fragment = FeatureFactory.getFeatureFactory().getWifiFeatureProvider()
.getWifiDppQrCodeGeneratorFragment();
} else {
fragment = new WifiDppQrCodeGeneratorFragment(); fragment = new WifiDppQrCodeGeneratorFragment();
}
} else { } else {
if (fragment.isVisible()) { if (fragment.isVisible()) {
return; return;

View File

@@ -56,7 +56,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
private static final String TAG = "WifiDppQrCodeGeneratorFragment"; private static final String TAG = "WifiDppQrCodeGeneratorFragment";
private ImageView mQrCodeView; 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_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon"; private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon";
@@ -258,7 +258,7 @@ public class WifiDppQrCodeGeneratorFragment extends WifiDppQrCodeBaseFragment {
return button; return button;
} }
private void setQrCode() { protected void setQrCode() {
try { try {
final int qrcodeSize = getContext().getResources().getDimensionPixelSize( final int qrcodeSize = getContext().getResources().getDimensionPixelSize(
R.dimen.qrcode_size); R.dimen.qrcode_size);

View File

@@ -27,6 +27,7 @@ import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner; import androidx.lifecycle.ViewModelStoreOwner;
import com.android.settings.wifi.details.WifiNetworkDetailsViewModel; 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.SharedConnectivityRepository;
import com.android.settings.wifi.repository.WifiHotspotRepository; import com.android.settings.wifi.repository.WifiHotspotRepository;
import com.android.settings.wifi.tether.WifiHotspotSecurityViewModel; import com.android.settings.wifi.tether.WifiHotspotSecurityViewModel;
@@ -146,6 +147,15 @@ public class WifiFeatureProvider {
return viewModel; 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. * Send a {@link Log#VERBOSE} log message.
* *

View File

@@ -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());
}
}

View File

@@ -34,6 +34,7 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import androidx.preference.DropDownPreference; import androidx.preference.DropDownPreference;
@@ -85,7 +86,9 @@ public class ZenModeSetCalendarPreferenceControllerTest {
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI}) @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
public void updateEventMode_updatesConditionAndTriggerDescription() { public void updateEventMode_updatesConditionAndTriggerDescription() {
ZenMode mode = new ZenMode("id", 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 true); // is active
// Explicitly update preference controller with mode info first, which will also call // 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 // apply event mode updater to existing mode
ZenMode out = mPrefController.updateEventMode(eventInfo).apply(mode); ZenMode out = mPrefController.updateEventMode(eventInfo).apply(mode);
assertThat(out.getRule().getOwner()).isEqualTo(ZenModeConfig.getEventConditionProvider());
assertThat(out.getRule().getConditionId()).isEqualTo( assertThat(out.getRule().getConditionId()).isEqualTo(
ZenModeConfig.toEventConditionId(eventInfo)); ZenModeConfig.toEventConditionId(eventInfo));
assertThat(out.getRule().getTriggerDescription()).isEqualTo("My events"); assertThat(out.getRule().getTriggerDescription()).isEqualTo("My events");

View File

@@ -29,6 +29,7 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ToggleButton; import android.widget.ToggleButton;
@@ -81,7 +82,9 @@ public class ZenModeSetSchedulePreferenceControllerTest {
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI}) @EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
public void updateScheduleRule_updatesConditionAndTriggerDescription() { public void updateScheduleRule_updatesConditionAndTriggerDescription() {
ZenMode mode = new ZenMode("id", 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 true); // is active
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo(); ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
@@ -93,6 +96,8 @@ public class ZenModeSetSchedulePreferenceControllerTest {
assertThat(out.getRule().getConditionId()) assertThat(out.getRule().getConditionId())
.isEqualTo(ZenModeConfig.toScheduleConditionId(scheduleInfo)); .isEqualTo(ZenModeConfig.toScheduleConditionId(scheduleInfo));
assertThat(out.getRule().getTriggerDescription()).isNotEmpty(); assertThat(out.getRule().getTriggerDescription()).isNotEmpty();
assertThat(out.getRule().getOwner()).isEqualTo(
ZenModeConfig.getScheduleConditionProvider());
} }
@Test @Test

View File

@@ -16,6 +16,7 @@
package com.android.settings.notification.modes; 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_CALENDAR;
import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME; import static android.app.AutomaticZenRule.TYPE_SCHEDULE_TIME;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; 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.AutomaticZenRule;
import android.app.Flags; import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule; import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
@@ -43,6 +44,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.PrimarySwitchPreference;
import org.junit.Before; import org.junit.Before;
@@ -57,6 +59,7 @@ import org.robolectric.RobolectricTestRunner;
import java.util.Calendar; import java.util.Calendar;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@EnableFlags(Flags.FLAG_MODES_UI)
public class ZenModeSetTriggerLinkPreferenceControllerTest { public class ZenModeSetTriggerLinkPreferenceControllerTest {
@Rule @Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
@@ -65,10 +68,13 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
private ZenModesBackend mBackend; private ZenModesBackend mBackend;
private Context mContext; private Context mContext;
private PrimarySwitchPreference mPreference;
@Mock @Mock
private PreferenceCategory mPrefCategory; private PreferenceCategory mPrefCategory;
@Mock @Mock
private PrimarySwitchPreference mPreference; private DashboardFragment mFragment;
private ZenModeSetTriggerLinkPreferenceController mPrefController; private ZenModeSetTriggerLinkPreferenceController mPrefController;
@Before @Before
@@ -77,12 +83,12 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
mContext = ApplicationProvider.getApplicationContext(); mContext = ApplicationProvider.getApplicationContext();
mPrefController = new ZenModeSetTriggerLinkPreferenceController(mContext, 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); when(mPrefCategory.findPreference(AUTOMATIC_TRIGGER_PREF_KEY)).thenReturn(mPreference);
} }
@Test @Test
@EnableFlags(Flags.FLAG_MODES_UI)
public void testIsAvailable() { public void testIsAvailable() {
// should not be available for manual DND // should not be available for manual DND
ZenMode manualMode = ZenMode.manualDndMode(new AutomaticZenRule.Builder("Do Not Disturb", 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 // Update preference controller with a zen mode that is not enabled
mPrefController.updateZenMode(mPrefCategory, zenMode); mPrefController.updateZenMode(mPrefCategory, zenMode);
verify(mPreference).setChecked(false); assertThat(mPreference.getCheckedState()).isFalse();
// Now with the rule enabled // Now with the rule enabled
zenMode.getRule().setEnabled(true); zenMode.getRule().setEnabled(true);
mPrefController.updateZenMode(mPrefCategory, zenMode); mPrefController.updateZenMode(mPrefCategory, zenMode);
verify(mPreference).setChecked(true); assertThat(mPreference.getCheckedState()).isTrue();
} }
@Test @Test
@@ -154,21 +160,24 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
eventInfo.calName = "My events"; eventInfo.calName = "My events";
ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name", ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
ZenModeConfig.toEventConditionId(eventInfo)) ZenModeConfig.toEventConditionId(eventInfo))
.setPackage(SystemZenRules.PACKAGE_ANDROID)
.setType(TYPE_SCHEDULE_CALENDAR) .setType(TYPE_SCHEDULE_CALENDAR)
.setTriggerDescription("My events") .setTriggerDescription("My events")
.build(), .build(),
true); // is active true); // is active
mPrefController.updateZenMode(mPrefCategory, mode); mPrefController.updateZenMode(mPrefCategory, mode);
verify(mPreference).setTitle(R.string.zen_mode_set_calendar_link); assertThat(mPreference.getTitle()).isNotNull();
verify(mPreference).setSummary(mode.getRule().getTriggerDescription()); 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 // Destination as written into the intent by SubSettingLauncher
assertThat( assertThat(mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
captor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo( .isEqualTo(ZenModeSetCalendarFragment.class.getName());
ZenModeSetCalendarFragment.class.getName());
} }
@Test @Test
@@ -179,20 +188,75 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
scheduleInfo.endHour = 15; scheduleInfo.endHour = 15;
ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name", ZenMode mode = new ZenMode("id", new AutomaticZenRule.Builder("name",
ZenModeConfig.toScheduleConditionId(scheduleInfo)) ZenModeConfig.toScheduleConditionId(scheduleInfo))
.setPackage(SystemZenRules.PACKAGE_ANDROID)
.setType(TYPE_SCHEDULE_TIME) .setType(TYPE_SCHEDULE_TIME)
.setTriggerDescription("some schedule") .setTriggerDescription("some schedule")
.build(), .build(),
true); // is active true); // is active
mPrefController.updateZenMode(mPrefCategory, mode); mPrefController.updateZenMode(mPrefCategory, mode);
verify(mPreference).setTitle(R.string.zen_mode_set_schedule_link); assertThat(mPreference.getTitle()).isNotNull();
verify(mPreference).setSummary(mode.getRule().getTriggerDescription()); 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 // Destination as written into the intent by SubSettingLauncher
assertThat( assertThat(mPreference.getIntent().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
captor.getValue().getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo( .isEqualTo(ZenModeSetScheduleFragment.class.getName());
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());
} }
} }

View File

@@ -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))
}

View File

@@ -21,24 +21,17 @@ import android.net.Uri
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.test.assertIsDisplayed 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.hasText
import androidx.compose.ui.test.isFocused
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onChild import androidx.compose.ui.test.onChild
import androidx.compose.ui.test.onChildAt import androidx.compose.ui.test.onChildAt
import androidx.compose.ui.test.onLast
import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollToNode import androidx.compose.ui.test.performScrollToNode
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R import com.android.settings.R
import com.google.common.truth.Truth import com.google.common.truth.Truth
import org.junit.Ignore
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -55,7 +48,6 @@ class ApnEditPageProviderTest {
private val port = "port" private val port = "port"
private val apnType = context.resources.getString(R.string.apn_type) private val apnType = context.resources.getString(R.string.apn_type)
private val apnRoaming = "IPv4" private val apnRoaming = "IPv4"
private val apnEnable = context.resources.getString(R.string.carrier_enabled)
private val apnProtocolOptions = private val apnProtocolOptions =
context.resources.getStringArray(R.array.apn_protocol_entries).toList() context.resources.getStringArray(R.array.apn_protocol_entries).toList()
private val passwordTitle = context.resources.getString(R.string.apn_password) private val passwordTitle = context.resources.getString(R.string.apn_password)
@@ -65,7 +57,6 @@ class ApnEditPageProviderTest {
port = port, port = port,
apnType = apnType, apnType = apnType,
apnRoaming = apnProtocolOptions.indexOf(apnRoaming), apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
apnEnable = true
) )
private val apnData = mutableStateOf( private val apnData = mutableStateOf(
apnInit apnInit
@@ -133,39 +124,6 @@ class ApnEditPageProviderTest {
composeTestRule.onNodeWithText(apnRoaming, true).assertIsDisplayed() 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 @Test
fun password_displayed() { fun password_displayed() {
composeTestRule.setContent { composeTestRule.setContent {

View File

@@ -17,6 +17,7 @@
package com.android.settings.print package com.android.settings.print
import android.content.Context import android.content.Context
import android.net.Uri
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.isDisplayed 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_CHECKED
import com.android.settings.print.PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME import com.android.settings.print.PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME
import com.android.settings.print.PrintSettingsFragment.EXTRA_TITLE import com.android.settings.print.PrintSettingsFragment.EXTRA_TITLE
import com.android.settings.print.PrintSettingsPageProvider.AddPrintService
import com.android.settings.print.PrintSettingsPageProvider.PrintService import com.android.settings.print.PrintSettingsPageProvider.PrintService
import kotlinx.coroutines.flow.flowOf
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -44,14 +47,15 @@ import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class PrintSettingsPageProviderTest { class PrintSettingsPageProviderTest {
@get:Rule @get:Rule val composeTestRule = createComposeRule()
val composeTestRule = createComposeRule()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) { private val context: Context =
spy(ApplicationProvider.getApplicationContext()) {
doNothing().whenever(mock).startActivity(any()) doNothing().whenever(mock).startActivity(any())
} }
private val displayInfo = PrintServiceDisplayInfo( private val displayInfo =
PrintServiceDisplayInfo(
title = TITLE, title = TITLE,
isEnabled = true, isEnabled = true,
summary = SUMMARY, summary = SUMMARY,
@@ -61,18 +65,14 @@ class PrintSettingsPageProviderTest {
@Test @Test
fun printService_titleDisplayed() { fun printService_titleDisplayed() {
composeTestRule.setContent { composeTestRule.setContent { PrintService(displayInfo) }
PrintService(displayInfo)
}
composeTestRule.onNodeWithText(TITLE).isDisplayed() composeTestRule.onNodeWithText(TITLE).isDisplayed()
} }
@Test @Test
fun printService_summaryDisplayed() { fun printService_summaryDisplayed() {
composeTestRule.setContent { composeTestRule.setContent { PrintService(displayInfo) }
PrintService(displayInfo)
}
composeTestRule.onNodeWithText(SUMMARY).isDisplayed() composeTestRule.onNodeWithText(SUMMARY).isDisplayed()
} }
@@ -80,25 +80,43 @@ class PrintSettingsPageProviderTest {
@Test @Test
fun printService_onClick() { fun printService_onClick() {
composeTestRule.setContent { composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) { CompositionLocalProvider(LocalContext provides context) { PrintService(displayInfo) }
PrintService(displayInfo)
}
} }
composeTestRule.onNodeWithText(TITLE).performClick() composeTestRule.onNodeWithText(TITLE).performClick()
verify(context).startActivity(argThat { verify(context)
.startActivity(
argThat {
val fragment = getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT) val fragment = getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)
val arguments = getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!! val arguments = getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)!!
fragment == PrintServiceSettingsFragment::class.qualifiedName && fragment == PrintServiceSettingsFragment::class.qualifiedName &&
arguments.getBoolean(EXTRA_CHECKED) == displayInfo.isEnabled && arguments.getBoolean(EXTRA_CHECKED) == displayInfo.isEnabled &&
arguments.getString(EXTRA_TITLE) == displayInfo.title && arguments.getString(EXTRA_TITLE) == displayInfo.title &&
arguments.getString(EXTRA_SERVICE_COMPONENT_NAME) == displayInfo.componentName 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 { private companion object {
const val TITLE = "Title" const val TITLE = "Title"
const val SUMMARY = "Summary" const val SUMMARY = "Summary"
const val SEARCH_URI = "search.uri"
} }
} }

View File

@@ -16,20 +16,16 @@
package com.android.settings.network; 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.eq;
import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.content.ContentProvider; import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkPolicyManager; import android.net.NetworkPolicyManager;
@@ -67,7 +63,7 @@ public class ResetNetworkOperationBuilderTest {
@Mock @Mock
private NetworkPolicyManager mNetworkPolicyManager; private NetworkPolicyManager mNetworkPolicyManager;
@Mock @Mock
private ContentProvider mContentProvider;; private ContentProviderClient mContentProviderClient;
private Context mContext; private Context mContext;
@@ -77,9 +73,8 @@ public class ResetNetworkOperationBuilderTest {
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
doReturn(ContentResolver.wrap(mContentProvider)).when(mContext).getContentResolver();
mBuilder = spy(new ResetNetworkOperationBuilder(mContext)); mBuilder = spy(new ResetNetworkOperationBuilder(mContext));
doReturn(mContentProviderClient).when(mBuilder).getUnstableTelephonyContentProviderClient();
} }
@Test @Test
@@ -184,38 +179,38 @@ public class ResetNetworkOperationBuilderTest {
} }
@Test @Test
public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash() { public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash()
doThrow(new IllegalArgumentException()).when(mContentProvider).call( throws Exception {
anyString(), anyString(), anyString(), any()); doReturn(null).when(mBuilder).getUnstableTelephonyContentProviderClient();
mBuilder.restartPhoneProcess().build().run(); mBuilder.restartPhoneProcess().build().run();
} }
@Test @Test
public void restartRild_withoutTelephonyContentProvider_shouldNotCrash() { public void restartRild_withoutTelephonyContentProvider_shouldNotCrash()
doThrow(new IllegalArgumentException()).when(mContentProvider).call( throws Exception {
anyString(), anyString(), anyString(), any()); doReturn(null).when(mBuilder).getUnstableTelephonyContentProviderClient();
mBuilder.restartRild().build().run(); mBuilder.restartRild().build().run();
} }
@Test @Test
public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess() { public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess()
throws Exception {
mBuilder.restartPhoneProcess().build().run(); mBuilder.restartPhoneProcess().build().run();
verify(mContentProvider).call( verify(mContentProviderClient).call(
eq(mBuilder.getResetTelephonyContentProviderAuthority()),
eq(ResetNetworkOperationBuilder.METHOD_RESTART_PHONE_PROCESS), eq(ResetNetworkOperationBuilder.METHOD_RESTART_PHONE_PROCESS),
isNull(), isNull(),
isNull()); isNull());
} }
@Test @Test
public void restartRild_withTelephonyContentProvider_shouldCallRestartRild() { public void restartRild_withTelephonyContentProvider_shouldCallRestartRild()
throws Exception {
mBuilder.restartRild().build().run(); mBuilder.restartRild().build().run();
verify(mContentProvider).call( verify(mContentProviderClient).call(
eq(mBuilder.getResetTelephonyContentProviderAuthority()),
eq(ResetNetworkOperationBuilder.METHOD_RESTART_RILD), eq(ResetNetworkOperationBuilder.METHOD_RESTART_RILD),
isNull(), isNull(),
isNull()); isNull());