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.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" />
|
||||||
|
|||||||
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]-->
|
<!-- 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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),
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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),
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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?
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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.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");
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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 {
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
Reference in New Issue
Block a user