Snap for 13256841 from 081fab1330
to 25Q2-release
Change-Id: I36755cf3e7b0e6de77eb961c135989c6cca80050
This commit is contained in:
25
res/drawable/ic_pin_outline.xml
Normal file
25
res/drawable/ic_pin_outline.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2025 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="960"
|
||||
android:viewportWidth="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM260,600L306,600L306,360L270,360L200,410L224,446L260,420L260,600ZM384,600L540,600L540,560L446,560L444,558Q465,538 478.5,524Q492,510 500,502Q518,484 527,466Q536,448 536,428Q536,399 514,379.5Q492,360 458,360Q432,360 411,375Q390,390 382,414L422,430Q427,417 436.5,409.5Q446,402 458,402Q473,402 482.5,410Q492,418 492,430Q492,441 488,450.5Q484,460 470,474Q459,485 438,506Q417,527 384,560L384,600ZM680,600Q716,600 738,580Q760,560 760,528Q760,510 750,496Q740,482 722,474L722,472Q736,464 744,451.5Q752,439 752,422Q752,395 731,377.5Q710,360 678,360Q653,360 631.5,374.5Q610,389 604,410L644,426Q648,414 657,407Q666,400 678,400Q691,400 699.5,407.5Q708,415 708,426Q708,440 698,448Q688,456 672,456L654,456L654,496L674,496Q694,496 705,504Q716,512 716,526Q716,539 705,548.5Q694,558 680,558Q663,558 654,550.5Q645,543 638,524L598,540Q605,569 626.5,584.5Q648,600 680,600ZM160,720L800,720Q800,720 800,720Q800,720 800,720L800,240Q800,240 800,240Q800,240 800,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720ZM160,720Q160,720 160,720Q160,720 160,720L160,240Q160,240 160,240Q160,240 160,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720Z" />
|
||||
</vector>
|
@@ -1358,6 +1358,10 @@
|
||||
<string name="lock_screen_pattern_skip_fingerprint_title">Skip setup for pattern and fingerprint?</string>
|
||||
<!-- Title of dialog shown when the user tries to skip setting up a pattern, warning them of potential consequences of not doing so [CHAR LIMIT=48]-->
|
||||
<string name="lock_screen_pattern_skip_biometrics_title">Skip setup for pattern, face, and fingerprint?</string>
|
||||
<!-- Accessibility action label for resuming animation -->
|
||||
<string name="resume_animation">Resume animation</string>
|
||||
<!-- Accessibility action label for pausing animation -->
|
||||
<string name="pause_animation">Pause animation</string>
|
||||
|
||||
<!-- Button text to setup screen lock in onboard dialog [CHAR LIMIT=34] -->
|
||||
<string name="security_settings_fingerprint_enroll_setup_screen_lock">Set up screen lock</string>
|
||||
@@ -5934,6 +5938,10 @@
|
||||
<string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
|
||||
<!-- Subtitle for the pair hearing device page. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_hearing_device_pairing_intro">You can pair ASHA and LE Audio hearing devices on this page. Make sure your hearing device is turned on and ready to pair.</string>
|
||||
<!-- Subtitle for the pair hearing device page. This string is for device that only supports ASHA hearing aids. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_hearing_device_pairing_asha_only_intro">You can pair ASHA hearing devices on this page. Make sure your hearing device is turned on and ready to pair.</string>
|
||||
<!-- Subtitle for the pair hearing device page. This string is for device that only supports LE Audio hearing aids. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_hearing_device_pairing_hap_only_intro">You can pair LE Audio hearing devices on this page. Make sure your hearing device is turned on and ready to pair.</string>
|
||||
<!-- Title for the preference category containing the list of the available hearing during and after bluetooth scanning devices. [CHAR LIMIT=30] -->
|
||||
<string name="accessibility_found_hearing_devices">Available hearing devices</string>
|
||||
<!-- Title for the preference category containing the all bluetooth devices during and after bluetooth scanning devices. Used when people can not find their hearing device in hearing device pairing list. [CHAR LIMIT=45] -->
|
||||
@@ -12764,6 +12772,10 @@ Data usage charges may apply.</string>
|
||||
<string name="title_satellite_supported_app_list_entry">see all apps</string>
|
||||
<!-- Title for a page of apps list page with Satellite service supported. [CHAR LIMIT=60] -->
|
||||
<string name="title_satellite_supported_app_list_page">Supported apps on your phone</string>
|
||||
<!-- Title for showing a dialog to notify user sim restriction. [CHAR LIMIT=60] -->
|
||||
<string name="title_satellite_dialog_for_sim_restriction">Can\u2019t add a SIM</string>
|
||||
<!-- Description for showing a dialog to notify user sim restriction. [CHAR LIMIT=NONE] -->
|
||||
<string name="description_satellite_dialog_for_sim_restriction">End the satellite connection before you add a SIM</string>
|
||||
|
||||
<!-- Title for Apn settings in mobile network settings [CHAR LIMIT=60] -->
|
||||
<string name="mobile_network_apn_title">Access Point Names</string>
|
||||
|
@@ -20,8 +20,10 @@
|
||||
android:title="@string/bluetooth_pairing_pref_title">
|
||||
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:key="hearing_device_pairing_intro"
|
||||
settings:searchable="false"
|
||||
android:title="@string/accessibility_hearing_device_pairing_intro" />
|
||||
android:title="@string/accessibility_hearing_device_pairing_intro"
|
||||
settings:controller="com.android.settings.accessibility.HearingDevicePairingIntroPreferenceController"/>
|
||||
|
||||
<com.android.settings.bluetooth.BluetoothProgressCategory
|
||||
android:key="available_hearing_devices"
|
||||
|
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
||||
public class HearingDevicePairingIntroPreferenceController extends BasePreferenceController {
|
||||
private final HearingAidHelper mHelper;
|
||||
|
||||
public HearingDevicePairingIntroPreferenceController(
|
||||
@NonNull Context context,
|
||||
@NonNull String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mHelper = new HearingAidHelper(context);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public HearingDevicePairingIntroPreferenceController(
|
||||
@NonNull Context context,
|
||||
@NonNull String preferenceKey,
|
||||
@NonNull HearingAidHelper hearingAidHelper) {
|
||||
super(context, preferenceKey);
|
||||
mHelper = hearingAidHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return mHelper.isHearingAidSupported() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
|
||||
final Preference pairingIntroPreference = screen.findPreference(getPreferenceKey());
|
||||
final boolean isAshaProfileSupported = mHelper.isAshaProfileSupported();
|
||||
final boolean isHapClientProfileSupported = mHelper.isHapClientProfileSupported();
|
||||
if (isAshaProfileSupported && isHapClientProfileSupported) {
|
||||
pairingIntroPreference.setTitle(
|
||||
mContext.getString(R.string.accessibility_hearing_device_pairing_intro));
|
||||
} else if (isAshaProfileSupported) {
|
||||
pairingIntroPreference.setTitle(
|
||||
mContext.getString(
|
||||
R.string.accessibility_hearing_device_pairing_asha_only_intro));
|
||||
} else if (isHapClientProfileSupported) {
|
||||
pairingIntroPreference.setTitle(
|
||||
mContext.getString(
|
||||
R.string.accessibility_hearing_device_pairing_hap_only_intro));
|
||||
} else {
|
||||
// Intentionally blank, getAvailabilityStatus() should handle visibility for
|
||||
// none-supported case.
|
||||
}
|
||||
}
|
||||
}
|
@@ -73,7 +73,7 @@ public interface FingerprintFeatureProvider {
|
||||
default FingerprintExtPreferencesProvider getExtPreferenceProvider(
|
||||
@NonNull Context context
|
||||
) {
|
||||
return new FingerprintExtPreferencesProvider();
|
||||
return new FingerprintExtPreferencesProvider(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -468,12 +468,10 @@ public class FingerprintSettings extends SubSettings {
|
||||
* Add new preferences from FingerprintExtPreferencesProvider
|
||||
*/
|
||||
public void setupExtFingerprintPreferences() {
|
||||
final FingerprintExtPreferencesProvider preferencesProvider =
|
||||
FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()
|
||||
.getExtPreferenceProvider(requireContext());
|
||||
FingerprintExtPreferencesProvider preferencesProvider = getExtPreferenceProvider();
|
||||
for (int index = 0; index < preferencesProvider.getSize(); ++index) {
|
||||
final RestrictedPreference preference = preferencesProvider.newPreference(
|
||||
index, this::inflateFromResource, requireContext());
|
||||
index, this::inflateFromResource);
|
||||
if (preference == null || findPreference(preference.getKey()) != null) {
|
||||
continue;
|
||||
}
|
||||
@@ -485,6 +483,12 @@ public class FingerprintSettings extends SubSettings {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private FingerprintExtPreferencesProvider getExtPreferenceProvider() {
|
||||
return FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()
|
||||
.getExtPreferenceProvider(requireContext());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -748,7 +752,8 @@ public class FingerprintSettings extends SubSettings {
|
||||
// This needs to be after setting ids, otherwise
|
||||
// |mRequireScreenOnToAuthPreferenceController.isChecked| is always checking the primary
|
||||
// user instead of the user with |mUserId|.
|
||||
if (isSfps() || (screenOffUnlockUdfps() && isScreenOffUnlcokSupported())) {
|
||||
if (isSfps() || (screenOffUnlockUdfps() && isScreenOffUnlcokSupported())
|
||||
|| getExtPreferenceProvider().getSize() > 0) {
|
||||
scrollToPreference(fpPrefKey);
|
||||
addFingerprintUnlockCategory();
|
||||
}
|
||||
@@ -1266,6 +1271,16 @@ public class FingerprintSettings extends SubSettings {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (mFingerprintUnlockCategoryPreferenceController == null
|
||||
&& getExtPreferenceProvider().getSize() > 0 && controllers != null) {
|
||||
for (AbstractPreferenceController controller : controllers) {
|
||||
if (KEY_FINGERPRINT_UNLOCK_CATEGORY.equals(controller.getPreferenceKey())) {
|
||||
mFingerprintUnlockCategoryPreferenceController =
|
||||
(FingerprintUnlockCategoryController) controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -1654,7 +1669,10 @@ public class FingerprintSettings extends SubSettings {
|
||||
|
||||
private static final String KEY_USER_ID = "user_id";
|
||||
private static final String KEY_SENSOR_PROPERTIES = "sensor_properties";
|
||||
private static final String EXTRA_FAILURE_COUNT = "failure_count";
|
||||
private static final int MAX_FAILURE_COUNT = 3;
|
||||
private int mUserId;
|
||||
private int mFailureCount;
|
||||
private @Nullable CancellationSignal mCancellationSignal;
|
||||
private @Nullable FingerprintSensorPropertiesInternal mSensorPropertiesInternal;
|
||||
|
||||
@@ -1663,6 +1681,9 @@ public class FingerprintSettings extends SubSettings {
|
||||
@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
mFailureCount = savedInstanceState.getInt(EXTRA_FAILURE_COUNT, 0);
|
||||
}
|
||||
return inflater.inflate(
|
||||
R.layout.fingerprint_check_enrolled_dialog, container, false);
|
||||
}
|
||||
@@ -1682,12 +1703,22 @@ public class FingerprintSettings extends SubSettings {
|
||||
final UdfpsCheckEnrolledView v =
|
||||
dialog.findViewById(R.id.udfps_check_enrolled_view);
|
||||
v.setSensorProperties(mSensorPropertiesInternal);
|
||||
v.setOnTouchListener((view, event) -> {
|
||||
Log.d(TAG, "CheckEnrollDialog dismissed: touch outside");
|
||||
dialog.dismiss();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(EXTRA_FAILURE_COUNT, mFailureCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
@@ -1752,6 +1783,11 @@ public class FingerprintSettings extends SubSettings {
|
||||
message.postDelayed(() -> {
|
||||
message.setText(R.string.fingerprint_check_enroll_touch_sensor);
|
||||
}, 2000);
|
||||
mFailureCount++;
|
||||
if (mFailureCount >= MAX_FAILURE_COUNT) {
|
||||
Log.d(TAG, "CheckEnrollDialog dismissed: failed 3 times");
|
||||
dialog.dismiss();
|
||||
}
|
||||
}
|
||||
},
|
||||
null /* handler */,
|
||||
|
@@ -24,6 +24,7 @@ import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.RotationUtils;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
@@ -61,6 +62,13 @@ public class UdfpsCheckEnrolledView extends RelativeLayout {
|
||||
super.onFinishInflate();
|
||||
mFingerprintView = findViewById(R.id.udfps_fingerprint_sensor_view);
|
||||
mFingerprintView.setImageDrawable(mFingerprintDrawable);
|
||||
mFingerprintView.setOnTouchListener((v, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
Log.d(TAG, "Fingerprint view touched!");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -27,14 +27,13 @@ import com.android.settingslib.RestrictedPreference
|
||||
*
|
||||
* @see com.android.settings.biometrics.fingerprint.FingerprintSettings
|
||||
*/
|
||||
open class FingerprintExtPreferencesProvider {
|
||||
open class FingerprintExtPreferencesProvider(protected val context: Context) {
|
||||
|
||||
open val size: Int = 0
|
||||
|
||||
open fun newPreference(
|
||||
index: Int,
|
||||
inflater: PreferenceInflater,
|
||||
context: Context
|
||||
): RestrictedPreference? = null
|
||||
|
||||
interface PreferenceInflater {
|
||||
|
@@ -60,6 +60,8 @@ import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
@@ -417,13 +419,17 @@ public class BluetoothDeviceDetailsFragment extends BluetoothDetailsConfigurable
|
||||
@Nullable
|
||||
private List<String> generateDisplayedPreferenceKeys(boolean bondingLoss) {
|
||||
if (bondingLoss) {
|
||||
return List.of(
|
||||
use(BluetoothDetailsBannerController.class).getPreferenceKey(),
|
||||
use(AdvancedBluetoothDetailsHeaderController.class).getPreferenceKey(),
|
||||
use(BluetoothDetailsHeaderController.class).getPreferenceKey(),
|
||||
use(LeAudioBluetoothDetailsHeaderController.class).getPreferenceKey(),
|
||||
use(BluetoothDetailsButtonsController.class).getPreferenceKey(),
|
||||
use(BluetoothDetailsMacAddressController.class).getPreferenceKey());
|
||||
ImmutableList.Builder<String> visibleKeys = new ImmutableList.Builder<>();
|
||||
visibleKeys
|
||||
.add(use(BluetoothDetailsBannerController.class).getPreferenceKey())
|
||||
.add(use(AdvancedBluetoothDetailsHeaderController.class).getPreferenceKey())
|
||||
.add(use(BluetoothDetailsHeaderController.class).getPreferenceKey())
|
||||
.add(use(LeAudioBluetoothDetailsHeaderController.class).getPreferenceKey())
|
||||
.add(use(BluetoothDetailsButtonsController.class).getPreferenceKey());
|
||||
if (!BluetoothUtils.isHeadset(mCachedDevice.getDevice())) {
|
||||
visibleKeys.add(use(BluetoothDetailsMacAddressController.class).getPreferenceKey());
|
||||
}
|
||||
return visibleKeys.build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@@ -296,6 +296,10 @@ public final class BluetoothDevicePreference extends GearPreference {
|
||||
void onPreferenceAttributesChanged() {
|
||||
try {
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
if (mCachedDevice.getDevice() != null) {
|
||||
Log.d(TAG, "onPreferenceAttributesChanged, start updating for device "
|
||||
+ mCachedDevice.getDevice().getAnonymizedAddress());
|
||||
}
|
||||
@Nullable String name = mCachedDevice.getName();
|
||||
// Null check is done at the framework
|
||||
@Nullable String connectionSummary = getConnectionSummary();
|
||||
@@ -325,6 +329,7 @@ public final class BluetoothDevicePreference extends GearPreference {
|
||||
notifyHierarchyChanged();
|
||||
}
|
||||
});
|
||||
Log.d(TAG, "onPreferenceAttributesChanged, complete updating for device " + name);
|
||||
});
|
||||
} catch (RejectedExecutionException e) {
|
||||
Log.w(TAG, "Handler thread unavailable, skipping getConnectionSummary!");
|
||||
|
@@ -335,6 +335,7 @@ public class AvailableMediaDeviceGroupController extends BasePreferenceControlle
|
||||
var unused =
|
||||
ThreadUtils.postOnBackgroundThread(
|
||||
() -> {
|
||||
Log.d(TAG, "updateTitle, check current status");
|
||||
int titleResId;
|
||||
if (isAudioModeOngoingCall(mContext)) {
|
||||
// in phone call
|
||||
@@ -347,6 +348,7 @@ public class AvailableMediaDeviceGroupController extends BasePreferenceControlle
|
||||
// without phone call, not audio sharing
|
||||
titleResId = R.string.connected_device_media_device_title;
|
||||
}
|
||||
Log.d(TAG, "updateTitle, title = " + titleResId);
|
||||
mContext.getMainExecutor()
|
||||
.execute(
|
||||
() -> {
|
||||
|
@@ -17,6 +17,7 @@ package com.android.settings.connecteddevice;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
@@ -34,18 +35,25 @@ import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.slices.SlicePreferenceController;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.HearingAidStatsLogUtils;
|
||||
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
|
||||
public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "ConnectedDeviceFrag";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final String SLICE_ACTION = "com.android.settings.SEARCH_RESULT_TRAMPOLINE";
|
||||
|
||||
private static final String SETTINGS_SEARCH_ACTION =
|
||||
"com.android.settings.SEARCH_RESULT_TRAMPOLINE";
|
||||
@VisibleForTesting static final String KEY_CONNECTED_DEVICES = "connected_device_list";
|
||||
@VisibleForTesting static final String KEY_AVAILABLE_DEVICES = "available_device_list";
|
||||
|
||||
private static final String ENTRYPOINT_SYSUI = "bt_settings_entrypoint_sysui";
|
||||
private static final String ENTRYPOINT_SETTINGS = "bt_settings_entrypoint_settings_click";
|
||||
private static final String ENTRYPOINT_SETTINGS_SEARCH =
|
||||
"bt_settings_entrypoint_settings_search";
|
||||
private static final String ENTRYPOINT_OTHER = "bt_settings_entrypoint_other";
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.SETTINGS_CONNECTED_DEVICE_CATEGORY;
|
||||
@@ -71,15 +79,16 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
super.onAttach(context);
|
||||
String callingAppPackageName =
|
||||
((SettingsActivity) getActivity()).getInitialCallingPackage();
|
||||
String action = getIntent() != null ? getIntent().getAction() : "";
|
||||
if (DEBUG) {
|
||||
Log.d(
|
||||
TAG,
|
||||
"onAttach() calling package name is : "
|
||||
+ callingAppPackageName
|
||||
+ ", action : "
|
||||
+ action);
|
||||
}
|
||||
Intent intent = getIntent();
|
||||
String action = intent != null ? intent.getAction() : "";
|
||||
|
||||
Log.d(
|
||||
TAG,
|
||||
"onAttach() calling package name is : "
|
||||
+ callingAppPackageName
|
||||
+ ", action : "
|
||||
+ action);
|
||||
|
||||
if (BluetoothUtils.isAudioSharingUIAvailable(context)) {
|
||||
use(AudioSharingDevicePreferenceController.class).init(this);
|
||||
}
|
||||
@@ -100,16 +109,51 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
|
||||
provider.sendActivityIfAvailable(category);
|
||||
}
|
||||
}
|
||||
|
||||
logPageEntrypoint(context, callingAppPackageName, intent);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isAlwaysDiscoverable(String callingAppPackageName, String action) {
|
||||
return TextUtils.equals(SLICE_ACTION, action)
|
||||
return TextUtils.equals(SETTINGS_SEARCH_ACTION, action)
|
||||
? false
|
||||
: TextUtils.equals(Utils.SETTINGS_PACKAGE_NAME, callingAppPackageName)
|
||||
|| TextUtils.equals(Utils.SYSTEMUI_PACKAGE_NAME, callingAppPackageName);
|
||||
}
|
||||
|
||||
private void logPageEntrypoint(Context context, String callingAppPackageName, Intent intent) {
|
||||
String action = intent != null ? intent.getAction() : "";
|
||||
if (TextUtils.equals(Utils.SYSTEMUI_PACKAGE_NAME, callingAppPackageName)) {
|
||||
mMetricsFeatureProvider.action(
|
||||
context, SettingsEnums.SETTINGS_CONNECTED_DEVICES_ENTRYPOINT, ENTRYPOINT_SYSUI);
|
||||
} else if (TextUtils.equals(Utils.SETTINGS_PACKAGE_NAME, callingAppPackageName)
|
||||
&& TextUtils.equals(Intent.ACTION_MAIN, action)) {
|
||||
String sourceCategory =
|
||||
intent != null
|
||||
? Integer.toString(
|
||||
getIntent()
|
||||
.getIntExtra(
|
||||
MetricsFeatureProvider
|
||||
.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
SettingsEnums.PAGE_UNKNOWN))
|
||||
: "";
|
||||
mMetricsFeatureProvider.action(
|
||||
context,
|
||||
SettingsEnums.SETTINGS_CONNECTED_DEVICES_ENTRYPOINT,
|
||||
ENTRYPOINT_SETTINGS + "_" + sourceCategory);
|
||||
} else if (TextUtils.equals(Utils.SETTINGS_PACKAGE_NAME, callingAppPackageName)
|
||||
&& TextUtils.equals(SETTINGS_SEARCH_ACTION, action)) {
|
||||
mMetricsFeatureProvider.action(
|
||||
context,
|
||||
SettingsEnums.SETTINGS_CONNECTED_DEVICES_ENTRYPOINT,
|
||||
ENTRYPOINT_SETTINGS_SEARCH);
|
||||
|
||||
} else {
|
||||
mMetricsFeatureProvider.action(
|
||||
context, SettingsEnums.SETTINGS_CONNECTED_DEVICES_ENTRYPOINT, ENTRYPOINT_OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
/** For Search. */
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.connected_devices);
|
||||
|
@@ -18,6 +18,14 @@ package com.android.settings.localepicker;
|
||||
|
||||
import static android.window.OnBackInvokedDispatcher.PRIORITY_DEFAULT;
|
||||
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.ARG_CALLING_PAGE;
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.CALLING_PAGE_LANGUAGE_CHOOSE_A_REGION;
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.DIALOG_CHANGE_SYSTEM_LOCALE_REGION;
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.DIALOG_CHANGE_PREFERRED_LOCALE_REGION;
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.ARG_DIALOG_TYPE;
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.ARG_TARGET_LOCALE;
|
||||
import static com.android.settings.regionalpreferences.RegionDialogFragment.ARG_REPLACED_TARGET_LOCALE;
|
||||
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -50,11 +58,6 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
|
||||
private static final String TAG = LocalePickerWithRegionActivity.class.getSimpleName();
|
||||
private static final String PARENT_FRAGMENT_NAME = "localeListEditor";
|
||||
private static final String CHILD_FRAGMENT_NAME = "LocalePickerWithRegion";
|
||||
private static final int DIALOG_CHANGE_SYSTEM_LOCALE_REGION = 1;
|
||||
private static final int DIALOG_CHANGE_PREFERRED_LOCALE_REGION = 2;
|
||||
private static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
||||
private static final String ARG_TARGET_LOCALE = "arg_target_locale";
|
||||
private static final String ARG_REPLACED_TARGET_LOCALE = "arg_replaced_target_locale";
|
||||
private static final String TAG_DIALOG_CHANGE_REGION = "dialog_change_region";
|
||||
private static final int DISPOSE = -1;
|
||||
private static final int SHOW_DIALOG_FOR_SYSTEM_LANGUAGE = 0;
|
||||
@@ -139,6 +142,7 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
|
||||
LocaleStore.LocaleInfo locale, FragmentManager fragmentManager) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_DIALOG_TYPE, DIALOG_CHANGE_SYSTEM_LOCALE_REGION);
|
||||
args.putInt(ARG_CALLING_PAGE, CALLING_PAGE_LANGUAGE_CHOOSE_A_REGION);
|
||||
args.putSerializable(ARG_TARGET_LOCALE, locale);
|
||||
RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance();
|
||||
regionDialogFragment.setArguments(args);
|
||||
@@ -149,6 +153,7 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity
|
||||
LocaleStore.LocaleInfo locale, Locale replacedLocale, FragmentManager fragmentManager) {
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(ARG_DIALOG_TYPE, DIALOG_CHANGE_PREFERRED_LOCALE_REGION);
|
||||
args.putInt(ARG_CALLING_PAGE, CALLING_PAGE_LANGUAGE_CHOOSE_A_REGION);
|
||||
args.putSerializable(ARG_TARGET_LOCALE, locale);
|
||||
args.putSerializable(ARG_REPLACED_TARGET_LOCALE, replacedLocale);
|
||||
RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance();
|
||||
|
@@ -16,11 +16,11 @@
|
||||
|
||||
package com.android.settings.network
|
||||
|
||||
import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY
|
||||
import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_MOBILE_NETWORK
|
||||
import android.content.Context
|
||||
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_MOBILE_NETWORK_ENABLED
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY
|
||||
import com.android.settings.contract.KEY_ADAPTIVE_MOBILE_NETWORK
|
||||
import com.android.settings.metrics.PreferenceActionMetricsProvider
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyValueStoreDelegate
|
||||
@@ -38,12 +38,12 @@ class AdaptiveMobileNetworkTogglePreference() :
|
||||
PreferenceActionMetricsProvider {
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_ADAPTIVE_CONNECTIVITY
|
||||
get() = ACTION_ADAPTIVE_MOBILE_NETWORK
|
||||
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY)
|
||||
override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_MOBILE_NETWORK)
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
AdaptiveMobileNetworkToggleStorage(context)
|
||||
|
@@ -25,6 +25,7 @@ import androidx.preference.Preference.OnPreferenceClickListener
|
||||
import com.android.settings.R
|
||||
import com.android.settings.flags.Flags
|
||||
import com.android.settings.network.AirplaneModePreference.Companion.isAirplaneModeOn
|
||||
import com.android.settings.network.SatelliteRepository.Companion.isSatelliteOn
|
||||
import com.android.settings.network.SubscriptionUtil.getUniqueSubscriptionDisplayName
|
||||
import com.android.settings.network.telephony.SimRepository
|
||||
import com.android.settings.network.telephony.SubscriptionRepository
|
||||
@@ -32,6 +33,7 @@ import com.android.settings.network.telephony.euicc.EuiccRepository
|
||||
import com.android.settings.restriction.PreferenceRestrictionMixin
|
||||
import com.android.settings.spa.network.getAddSimIntent
|
||||
import com.android.settings.spa.network.startAddSimFlow
|
||||
import com.android.settings.spa.network.startSatelliteWarningDialogFlow
|
||||
import com.android.settingslib.RestrictedPreference
|
||||
import com.android.settingslib.datastore.HandlerExecutor
|
||||
import com.android.settingslib.datastore.KeyedObserver
|
||||
@@ -120,7 +122,11 @@ class MobileNetworkListScreen :
|
||||
val summary = preference.summary ?: return true // no-op
|
||||
val context = preference.context
|
||||
if (summary == context.getString(R.string.mobile_network_summary_add_a_network)) {
|
||||
startAddSimFlow(context) // start intent
|
||||
if (isSatelliteOn(context, 3000)) {
|
||||
startSatelliteWarningDialogFlow(context) // start intent
|
||||
} else {
|
||||
startAddSimFlow(context) // start intent
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false // start fragment
|
||||
|
@@ -27,6 +27,7 @@ import com.android.settings.dashboard.DashboardFragment
|
||||
import com.android.settings.network.telephony.SimRepository
|
||||
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
|
||||
import com.android.settings.spa.network.startAddSimFlow
|
||||
import com.android.settings.spa.network.startSatelliteWarningDialogFlow
|
||||
import com.android.settingslib.RestrictedPreference
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBooleanFlow
|
||||
@@ -51,11 +52,13 @@ constructor(
|
||||
MobileNetworkSummaryRepository(context),
|
||||
private val airplaneModeOnFlow: Flow<Boolean> =
|
||||
context.settingsGlobalBooleanFlow(Settings.Global.AIRPLANE_MODE_ON),
|
||||
private val satelliteIsStartedFlow: Flow<Boolean> = SatelliteRepository(context).getIsSessionStartedFlow()
|
||||
) : BasePreferenceController(context, preferenceKey) {
|
||||
private val metricsFeatureProvider = featureFactory.metricsFeatureProvider
|
||||
private var preference: RestrictedPreference? = null
|
||||
|
||||
private var isAirplaneModeOn = false
|
||||
private var isSatelliteOn = false
|
||||
|
||||
override fun getAvailabilityStatus() =
|
||||
if (SimRepository(mContext).showMobileNetworkPageEntrance()) AVAILABLE
|
||||
@@ -74,6 +77,9 @@ constructor(
|
||||
isAirplaneModeOn = it
|
||||
updateEnabled()
|
||||
}
|
||||
satelliteIsStartedFlow.collectLatestWithLifecycle(viewLifecycleOwner) {
|
||||
isSatelliteOn = it
|
||||
}
|
||||
}
|
||||
|
||||
private fun update(state: MobileNetworkSummaryRepository.SubscriptionsState) {
|
||||
@@ -87,7 +93,10 @@ constructor(
|
||||
preference.onPreferenceClickListener =
|
||||
Preference.OnPreferenceClickListener {
|
||||
logPreferenceClick()
|
||||
startAddSimFlow(context)
|
||||
if (isSatelliteOn)
|
||||
startSatelliteWarningDialogFlow(context)
|
||||
else
|
||||
startAddSimFlow(context)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@@ -32,11 +32,20 @@ import com.android.settingslib.wifi.WifiUtils
|
||||
/** A dialog to show the warning message when device is under satellite mode. */
|
||||
class SatelliteWarningDialogActivity : SpaDialogWindowTypeActivity() {
|
||||
private var warningType = TYPE_IS_UNKNOWN
|
||||
|
||||
private var customizedContent: HashMap<Int, String> = HashMap<Int, String>()
|
||||
private var isCustomizedContent = false
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
warningType = intent.getIntExtra(EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, TYPE_IS_UNKNOWN)
|
||||
if (warningType == TYPE_IS_UNKNOWN) {
|
||||
finish()
|
||||
isCustomizedContent = intent.hasExtra(EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT)
|
||||
if (isCustomizedContent) {
|
||||
customizedContent =
|
||||
intent.getSerializableExtra(EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT)
|
||||
as HashMap<Int, String>
|
||||
} else {
|
||||
warningType =
|
||||
intent.getIntExtra(EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, TYPE_IS_UNKNOWN)
|
||||
if (warningType == TYPE_IS_UNKNOWN) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
@@ -48,23 +57,52 @@ class SatelliteWarningDialogActivity : SpaDialogWindowTypeActivity() {
|
||||
)
|
||||
}
|
||||
|
||||
fun getBodyString(): String {
|
||||
if (isCustomizedContent) {
|
||||
// For customized content
|
||||
return customizedContent.get(CUSTOM_CONTENT_DESCRIPTION).toString()
|
||||
} else {
|
||||
// For wifi, bluetooth, airplane mode
|
||||
return String.format(
|
||||
getString(R.string.satellite_warning_dialog_content),
|
||||
getTypeString(warningType)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getButtonString(): String {
|
||||
if (isCustomizedContent)
|
||||
// For customized content
|
||||
return customizedContent.get(CUSTOM_CONTENT_BUTTON_NAME).toString()
|
||||
else
|
||||
// For wifi, bluetooth, airplane mode
|
||||
return getString(com.android.settingslib.R.string.okay)
|
||||
}
|
||||
|
||||
fun getTitleString(): String {
|
||||
if (isCustomizedContent)
|
||||
// For customized content
|
||||
return customizedContent.get(CUSTOM_CONTENT_TITLE).toString()
|
||||
else
|
||||
// For wifi, bluetooth, airplane mode
|
||||
return String.format(
|
||||
getString(R.string.satellite_warning_dialog_title),
|
||||
getTypeString(warningType)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Content() {
|
||||
SettingsAlertDialogContent(
|
||||
dismissButton = null,
|
||||
confirmButton = AlertDialogButton(
|
||||
getString(com.android.settingslib.R.string.okay)
|
||||
getButtonString()
|
||||
) { finish() },
|
||||
title = String.format(
|
||||
getString(R.string.satellite_warning_dialog_title),
|
||||
getTypeString(warningType)
|
||||
),
|
||||
title = getTitleString(),
|
||||
text = {
|
||||
Text(
|
||||
String.format(
|
||||
getString(R.string.satellite_warning_dialog_content),
|
||||
getTypeString(warningType)
|
||||
),
|
||||
getBodyString(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
@@ -83,9 +121,14 @@ class SatelliteWarningDialogActivity : SpaDialogWindowTypeActivity() {
|
||||
companion object {
|
||||
const val EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG: String =
|
||||
"extra_type_of_satellite_warning_dialog"
|
||||
const val EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT: String =
|
||||
"extra_type_of_satellite_customized_content"
|
||||
const val TYPE_IS_UNKNOWN = -1
|
||||
const val TYPE_IS_WIFI = 0
|
||||
const val TYPE_IS_BLUETOOTH = 1
|
||||
const val TYPE_IS_AIRPLANE_MODE = 2
|
||||
const val CUSTOM_CONTENT_TITLE = 0
|
||||
const val CUSTOM_CONTENT_DESCRIPTION = 1
|
||||
const val CUSTOM_CONTENT_BUTTON_NAME = 2
|
||||
}
|
||||
}
|
@@ -17,13 +17,13 @@
|
||||
package com.android.settings.network
|
||||
|
||||
import android.Manifest
|
||||
import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_CONNECTIVITY
|
||||
import android.app.settings.SettingsEnums.ACTION_ADAPTIVE_WIFI_SCORER
|
||||
import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_WIFI_ENABLED
|
||||
import androidx.annotation.RequiresPermission
|
||||
import com.android.settings.R
|
||||
import com.android.settings.contract.KEY_ADAPTIVE_CONNECTIVITY
|
||||
import com.android.settings.contract.KEY_ADAPTIVE_WIFI_SCORER
|
||||
import com.android.settings.metrics.PreferenceActionMetricsProvider
|
||||
import com.android.settingslib.datastore.KeyValueStore
|
||||
import com.android.settingslib.datastore.KeyValueStoreDelegate
|
||||
@@ -42,12 +42,12 @@ class WifiScorerTogglePreference() :
|
||||
PreferenceActionMetricsProvider {
|
||||
|
||||
override val preferenceActionMetrics: Int
|
||||
get() = ACTION_ADAPTIVE_CONNECTIVITY
|
||||
get() = ACTION_ADAPTIVE_WIFI_SCORER
|
||||
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_CONNECTIVITY)
|
||||
override fun tags(context: Context) = arrayOf(KEY_ADAPTIVE_WIFI_SCORER)
|
||||
|
||||
override fun storage(context: Context): KeyValueStore =
|
||||
WifiScorerToggleStorage(context)
|
||||
|
@@ -101,6 +101,10 @@ public class SatelliteSettingAccountInfoController extends TelephonyBasePreferen
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
if (mConfigBundle.getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT)
|
||||
== CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
|
||||
return AVAILABLE;
|
||||
}
|
||||
return mConfigBundle.getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL)
|
||||
? AVAILABLE
|
||||
: CONDITIONALLY_UNAVAILABLE;
|
||||
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.privatespace;
|
||||
|
||||
import static com.android.settingslib.widget.preference.illustration.R.string.settingslib_action_label_pause;
|
||||
import static com.android.settingslib.widget.preference.illustration.R.string.settingslib_action_label_resume;
|
||||
import static com.android.settingslib.widget.preference.illustration.R.string.settingslib_illustration_content_description;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import androidx.core.view.AccessibilityDelegateCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
|
||||
public class PrivateSpaceAccessibilityUtils {
|
||||
|
||||
static void updateAccessibilityActionForAnimation(Context context,
|
||||
LottieAnimationView animationView, boolean isAnimationPlaying) {
|
||||
animationView.setContentDescription(
|
||||
context.getString(settingslib_illustration_content_description));
|
||||
ViewCompat.setAccessibilityDelegate(animationView, new AccessibilityDelegateCompat() {
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(
|
||||
View host, AccessibilityNodeInfoCompat info) {
|
||||
super.onInitializeAccessibilityNodeInfo(host, info);
|
||||
// Clearing the class name to ensure the animation is not called out as "button"
|
||||
// inside the TalkBack flows
|
||||
info.setClassName("");
|
||||
info.removeAction(
|
||||
AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK);
|
||||
|
||||
final AccessibilityNodeInfoCompat.AccessibilityActionCompat clickAction =
|
||||
new AccessibilityNodeInfoCompat.AccessibilityActionCompat(
|
||||
AccessibilityNodeInfo.ACTION_CLICK,
|
||||
getActionLabelForAnimation(context, isAnimationPlaying));
|
||||
info.addAction(clickAction);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String getActionLabelForAnimation(Context context, boolean isAnimationPlaying) {
|
||||
if (isAnimationPlaying) {
|
||||
return context.getString(settingslib_action_label_pause);
|
||||
} else {
|
||||
return context.getString(settingslib_action_label_resume);
|
||||
}
|
||||
}
|
||||
}
|
@@ -76,6 +76,8 @@ public class PrivateSpaceEducation extends InstrumentedFragment {
|
||||
LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation);
|
||||
LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView);
|
||||
lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView));
|
||||
PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(),
|
||||
lottieAnimationView, mIsAnimationPlaying);
|
||||
|
||||
TextView infoTextView = rootView.findViewById(R.id.learn_more);
|
||||
Pattern pattern = Pattern.compile(infoTextView.getText().toString());
|
||||
@@ -121,5 +123,7 @@ public class PrivateSpaceEducation extends InstrumentedFragment {
|
||||
lottieAnimationView.playAnimation();
|
||||
}
|
||||
mIsAnimationPlaying = !mIsAnimationPlaying;
|
||||
PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(),
|
||||
lottieAnimationView, mIsAnimationPlaying);
|
||||
}
|
||||
}
|
||||
|
@@ -94,6 +94,8 @@ public class PrivateSpaceSetLockFragment extends InstrumentedFragment {
|
||||
LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation);
|
||||
LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView);
|
||||
lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView));
|
||||
PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(),
|
||||
lottieAnimationView, mIsAnimationPlaying);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
@@ -141,5 +143,7 @@ public class PrivateSpaceSetLockFragment extends InstrumentedFragment {
|
||||
lottieAnimationView.playAnimation();
|
||||
}
|
||||
mIsAnimationPlaying = !mIsAnimationPlaying;
|
||||
PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(),
|
||||
lottieAnimationView, mIsAnimationPlaying);
|
||||
}
|
||||
}
|
||||
|
@@ -83,6 +83,8 @@ public class SetupSuccessFragment extends InstrumentedFragment {
|
||||
LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation);
|
||||
LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView);
|
||||
lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView));
|
||||
PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(),
|
||||
lottieAnimationView, mIsAnimationPlaying);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
@@ -152,5 +154,7 @@ public class SetupSuccessFragment extends InstrumentedFragment {
|
||||
lottieAnimationView.playAnimation();
|
||||
}
|
||||
mIsAnimationPlaying = !mIsAnimationPlaying;
|
||||
PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(),
|
||||
lottieAnimationView, mIsAnimationPlaying);
|
||||
}
|
||||
}
|
||||
|
@@ -16,8 +16,13 @@
|
||||
|
||||
package com.android.settings.regionalpreferences;
|
||||
|
||||
import static android.app.settings.SettingsEnums.ACTION_CHANGE_PREFERRED_LANGUAGE_REGION_POSITIVE_BTN_CLICKED;
|
||||
import static android.app.settings.SettingsEnums.ACTION_CHANGE_PREFERRED_LANGUAGE_REGION_NEGATIVE_BTN_CLICKED;
|
||||
import static android.app.settings.SettingsEnums.ACTION_CHANGE_REGION_DIALOG_NEGATIVE_BTN_CLICKED;
|
||||
import static android.app.settings.SettingsEnums.ACTION_CHANGE_REGION_DIALOG_POSITIVE_BTN_CLICKED;
|
||||
import static android.app.settings.SettingsEnums.CHANGE_REGION_DIALOG;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
@@ -46,12 +51,17 @@ import java.util.Set;
|
||||
* Create a dialog for system region events.
|
||||
*/
|
||||
public class RegionDialogFragment extends InstrumentedDialogFragment {
|
||||
|
||||
public static final String ARG_CALLING_PAGE = "arg_calling_page";
|
||||
public static final int CALLING_PAGE_LANGUAGE_CHOOSE_A_REGION = 0;
|
||||
public static final int CALLING_PAGE_REGIONAL_PREFERENCES_REGION_PICKER = 1;
|
||||
public static final int DIALOG_CHANGE_SYSTEM_LOCALE_REGION = 1;
|
||||
public static final int DIALOG_CHANGE_PREFERRED_LOCALE_REGION = 2;
|
||||
public static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
||||
public static final String ARG_TARGET_LOCALE = "arg_target_locale";
|
||||
public static final String ARG_REPLACED_TARGET_LOCALE = "arg_replaced_target_locale";
|
||||
|
||||
private static final String TAG = "RegionDialogFragment";
|
||||
static final int DIALOG_CHANGE_SYSTEM_LOCALE_REGION = 1;
|
||||
static final int DIALOG_CHANGE_PREFERRED_LOCALE_REGION = 2;
|
||||
static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
||||
static final String ARG_TARGET_LOCALE = "arg_target_locale";
|
||||
static final String ARG_REPLACED_TARGET_LOCALE = "arg_replaced_target_locale";
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
@@ -66,7 +76,7 @@ public class RegionDialogFragment extends InstrumentedDialogFragment {
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.CHANGE_REGION_DIALOG;
|
||||
return CHANGE_REGION_DIALOG;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -114,6 +124,7 @@ public class RegionDialogFragment extends InstrumentedDialogFragment {
|
||||
class RegionDialogController implements DialogInterface.OnClickListener {
|
||||
private final Context mContext;
|
||||
private final int mDialogType;
|
||||
private final int mCallingPage;
|
||||
private final LocaleStore.LocaleInfo mLocaleInfo;
|
||||
private final Locale mReplacedLocale;
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
@@ -123,6 +134,7 @@ public class RegionDialogFragment extends InstrumentedDialogFragment {
|
||||
mContext = context;
|
||||
Bundle arguments = dialogFragment.getArguments();
|
||||
mDialogType = arguments.getInt(ARG_DIALOG_TYPE);
|
||||
mCallingPage = arguments.getInt(ARG_CALLING_PAGE);
|
||||
mLocaleInfo = (LocaleStore.LocaleInfo) arguments.getSerializable(ARG_TARGET_LOCALE);
|
||||
mReplacedLocale = (Locale) arguments.getSerializable(ARG_REPLACED_TARGET_LOCALE);
|
||||
mMetricsFeatureProvider =
|
||||
@@ -137,8 +149,10 @@ public class RegionDialogFragment extends InstrumentedDialogFragment {
|
||||
updateRegion(mLocaleInfo.getLocale().toLanguageTag());
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext,
|
||||
SettingsEnums.ACTION_CHANGE_REGION_DIALOG_POSITIVE_BTN_CLICKED);
|
||||
// TODO: add new metrics for DIALOG_CHANGE_PREFERRED_LOCALE_REGION
|
||||
mDialogType == DIALOG_CHANGE_SYSTEM_LOCALE_REGION
|
||||
? ACTION_CHANGE_REGION_DIALOG_POSITIVE_BTN_CLICKED
|
||||
: ACTION_CHANGE_PREFERRED_LANGUAGE_REGION_POSITIVE_BTN_CLICKED,
|
||||
mCallingPage);
|
||||
dismiss();
|
||||
if (getActivity() != null) {
|
||||
getActivity().finish();
|
||||
@@ -146,8 +160,10 @@ public class RegionDialogFragment extends InstrumentedDialogFragment {
|
||||
} else {
|
||||
mMetricsFeatureProvider.action(
|
||||
mContext,
|
||||
SettingsEnums.ACTION_CHANGE_REGION_DIALOG_NEGATIVE_BTN_CLICKED);
|
||||
// TODO: add new metrics for DIALOG_CHANGE_PREFERRED_LOCALE_REGION
|
||||
mDialogType == DIALOG_CHANGE_SYSTEM_LOCALE_REGION
|
||||
? ACTION_CHANGE_REGION_DIALOG_NEGATIVE_BTN_CLICKED
|
||||
: ACTION_CHANGE_PREFERRED_LANGUAGE_REGION_NEGATIVE_BTN_CLICKED,
|
||||
mCallingPage);
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
@@ -167,8 +167,12 @@ public abstract class RegionPickerBaseListPreferenceController extends BasePrefe
|
||||
|
||||
mFragmentManager = mParent.getChildFragmentManager();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt(RegionDialogFragment.ARG_DIALOG_TYPE,
|
||||
args.putInt(
|
||||
RegionDialogFragment.ARG_DIALOG_TYPE,
|
||||
RegionDialogFragment.DIALOG_CHANGE_SYSTEM_LOCALE_REGION);
|
||||
args.putInt(
|
||||
RegionDialogFragment.ARG_CALLING_PAGE,
|
||||
RegionDialogFragment.CALLING_PAGE_REGIONAL_PREFERENCES_REGION_PICKER);
|
||||
args.putSerializable(RegionDialogFragment.ARG_TARGET_LOCALE, localeInfo);
|
||||
RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance();
|
||||
regionDialogFragment.setArguments(args);
|
||||
|
@@ -35,6 +35,10 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_BUTTON_NAME
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_DESCRIPTION
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_TITLE
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settings.network.telephony.MobileNetworkUtils
|
||||
import com.android.settings.network.telephony.SubscriptionActivationRepository
|
||||
@@ -143,3 +147,14 @@ fun getAddSimIntent() = Intent(EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTI
|
||||
setPackage(Utils.PHONE_PACKAGE_NAME)
|
||||
putExtra(EuiccManager.EXTRA_FORCE_PROVISION, true)
|
||||
}
|
||||
|
||||
fun startSatelliteWarningDialogFlow(context: Context) = context.startActivity(getSatelliteWarningDialogIntent(context))
|
||||
|
||||
fun getSatelliteWarningDialogIntent(context: Context) = Intent(context,
|
||||
SatelliteWarningDialogActivity::class.java).apply {
|
||||
val content = HashMap<Int, String>()
|
||||
content.put(CUSTOM_CONTENT_TITLE, context.getString(R.string.title_satellite_dialog_for_sim_restriction))
|
||||
content.put(CUSTOM_CONTENT_DESCRIPTION, context.getString(R.string.description_satellite_dialog_for_sim_restriction))
|
||||
content.put(CUSTOM_CONTENT_BUTTON_NAME, context.getString(R.string.okay))
|
||||
putExtra(SatelliteWarningDialogActivity.EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT, content)
|
||||
}
|
||||
|
54
src/com/android/settings/supervision/SupervisionHelper.kt
Normal file
54
src/com/android/settings/supervision/SupervisionHelper.kt
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.supervision
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.content.Context
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING
|
||||
import androidx.annotation.VisibleForTesting
|
||||
|
||||
/** Convenience methods for interacting with the supervising user profile. */
|
||||
open class SupervisionHelper private constructor(context: Context) {
|
||||
private val mUserManager = context.getSystemService(UserManager::class.java)
|
||||
private val mKeyguardManager = context.getSystemService(KeyguardManager::class.java)
|
||||
|
||||
fun getSupervisingUserHandle(): UserHandle? {
|
||||
for (user in (mUserManager?.users ?: emptyList())) {
|
||||
if (user.userType.equals(USER_TYPE_PROFILE_SUPERVISING)) {
|
||||
return user.userHandle
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun isSupervisingCredentialSet(): Boolean {
|
||||
val supervisingUserId = getSupervisingUserHandle()?.identifier ?: return false
|
||||
return mKeyguardManager?.isDeviceSecure(supervisingUserId) ?: false
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Volatile @VisibleForTesting var sInstance: SupervisionHelper? = null
|
||||
|
||||
fun getInstance(context: Context): SupervisionHelper {
|
||||
return sInstance
|
||||
?: synchronized(this) {
|
||||
sInstance ?: SupervisionHelper(context).also { sInstance = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -83,6 +83,7 @@ class SupervisionMainSwitchPreference(context: Context) :
|
||||
val newValue = !supervisionMainSwitchStorage.getBoolean(KEY)!!
|
||||
mainSwitchPreference.setChecked(newValue)
|
||||
updateDependentPreferencesEnabledState(mainSwitchPreference, newValue)
|
||||
context.notifyPreferenceChange(SupervisionPinManagementScreen.KEY)
|
||||
}
|
||||
|
||||
return true
|
||||
@@ -110,10 +111,7 @@ class SupervisionMainSwitchPreference(context: Context) :
|
||||
isChecked: Boolean,
|
||||
) {
|
||||
preference?.parent?.forEachRecursively {
|
||||
if (
|
||||
it.parent?.key == SupervisionDashboardScreen.SUPERVISION_DYNAMIC_GROUP_1 ||
|
||||
it.key == SupervisionPinManagementScreen.KEY
|
||||
) {
|
||||
if (it.parent?.key == SupervisionDashboardScreen.SUPERVISION_DYNAMIC_GROUP_1) {
|
||||
it.isEnabled = isChecked
|
||||
}
|
||||
}
|
||||
|
@@ -17,16 +17,20 @@ package com.android.settings.supervision
|
||||
|
||||
import android.content.Context
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.metadata.PreferenceAvailabilityProvider
|
||||
import com.android.settingslib.metadata.ProvidePreferenceScreen
|
||||
import com.android.settingslib.metadata.preferenceHierarchy
|
||||
import com.android.settingslib.preference.PreferenceScreenCreator
|
||||
|
||||
/** Pin Management landing page (Settings > Supervision > Manage Pin). */
|
||||
@ProvidePreferenceScreen(SupervisionPinManagementScreen.KEY)
|
||||
class SupervisionPinManagementScreen : PreferenceScreenCreator {
|
||||
class SupervisionPinManagementScreen : PreferenceScreenCreator, PreferenceAvailabilityProvider {
|
||||
override val key: String
|
||||
get() = KEY
|
||||
|
||||
override fun isAvailable(context: Context) =
|
||||
SupervisionHelper.getInstance(context).isSupervisingCredentialSet()
|
||||
|
||||
override val title: Int
|
||||
get() = R.string.supervision_pin_management_preference_title
|
||||
|
||||
@@ -36,7 +40,7 @@ class SupervisionPinManagementScreen : PreferenceScreenCreator {
|
||||
|
||||
// TODO(b/391994031): dynamically update the icon according to PIN status.
|
||||
override val icon: Int
|
||||
get() = R.drawable.ic_pin
|
||||
get() = R.drawable.ic_pin_outline
|
||||
|
||||
override fun fragmentClass() = SupervisionPinManagementFragment::class.java
|
||||
|
||||
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.accessibility;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.widget.TopIntroPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/**
|
||||
* Tests for {@link HearingDevicePairingIntroPreferenceController}.
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class HearingDevicePairingIntroPreferenceControllerTest {
|
||||
|
||||
@Rule
|
||||
public final MockitoRule mockito = MockitoJUnit.rule();
|
||||
|
||||
@Spy
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Spy
|
||||
private final Resources mResources = mContext.getResources();
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private HearingAidHelper mHelper;
|
||||
private HearingDevicePairingIntroPreferenceController mController;
|
||||
private TopIntroPreference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new HearingDevicePairingIntroPreferenceController(mContext, "test_key",
|
||||
mHelper);
|
||||
mPreference = new TopIntroPreference(mContext);
|
||||
mPreference.setKey("test_key");
|
||||
|
||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hearingAidSupported_available() {
|
||||
when(mHelper.isHearingAidSupported()).thenReturn(true);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_hearingAidNotSupported_unsupportedOnDevice() {
|
||||
when(mHelper.isHearingAidSupported()).thenReturn(false);
|
||||
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_ashaHapSupported_expectedTitle() {
|
||||
when(mHelper.isAshaProfileSupported()).thenReturn(true);
|
||||
when(mHelper.isHapClientProfileSupported()).thenReturn(true);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_hearing_device_pairing_intro));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_ashaSupported_expectedTitle() {
|
||||
when(mHelper.isAshaProfileSupported()).thenReturn(true);
|
||||
when(mHelper.isHapClientProfileSupported()).thenReturn(false);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_hearing_device_pairing_asha_only_intro));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_hapSupported_expectedTitle() {
|
||||
when(mHelper.isAshaProfileSupported()).thenReturn(false);
|
||||
when(mHelper.isHapClientProfileSupported()).thenReturn(true);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
assertThat(mPreference.getTitle().toString()).isEqualTo(
|
||||
mContext.getString(R.string.accessibility_hearing_device_pairing_hap_only_intro));
|
||||
}
|
||||
}
|
@@ -70,6 +70,7 @@ import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.biometrics.fingerprint.feature.FingerprintExtPreferencesProvider;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settings.password.ConfirmDeviceCredentialActivity;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
@@ -79,6 +80,7 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||
import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
|
||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||
import com.android.settings.testutils.shadow.ShadowUtils;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -123,6 +125,12 @@ public class FingerprintSettingsFragmentTest {
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private BiometricManager mBiometricManager;
|
||||
@Mock
|
||||
private FingerprintExtPreferencesProvider mExtPreferencesProvider;
|
||||
@Mock
|
||||
private RestrictedPreference mRestrictedPreference0;
|
||||
@Mock
|
||||
private RestrictedPreference mRestrictedPreference1;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<CancellationSignal> mCancellationSignalArgumentCaptor =
|
||||
@@ -159,6 +167,11 @@ public class FingerprintSettingsFragmentTest {
|
||||
when(mFakeFeatureFactory.getFingerprintFeatureProvider()
|
||||
.getFingerprintSettingsFeatureProvider())
|
||||
.thenReturn(mFingerprintSettingsFeatureProvider);
|
||||
|
||||
when(mFakeFeatureFactory.getFingerprintFeatureProvider()
|
||||
.getExtPreferenceProvider(mContext))
|
||||
.thenReturn(mExtPreferencesProvider);
|
||||
when(mExtPreferencesProvider.getSize()).thenReturn(0);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -417,6 +430,33 @@ public class FingerprintSettingsFragmentTest {
|
||||
assertThat(checkEnrolledPerf).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasExtPreferences() {
|
||||
String key0 = "ExtKey0";
|
||||
String key1 = "ExtKey1";
|
||||
when(mRestrictedPreference0.getKey()).thenReturn(key0);
|
||||
when(mRestrictedPreference1.getKey()).thenReturn(key1);
|
||||
when(mExtPreferencesProvider.getSize()).thenReturn(2);
|
||||
when(mExtPreferencesProvider.newPreference(eq(0),
|
||||
any(FingerprintExtPreferencesProvider.PreferenceInflater.class)))
|
||||
.thenReturn(mRestrictedPreference0);
|
||||
when(mExtPreferencesProvider.newPreference(eq(1),
|
||||
any(FingerprintExtPreferencesProvider.PreferenceInflater.class)))
|
||||
.thenReturn(mRestrictedPreference1);
|
||||
|
||||
Fingerprint fingerprint = new Fingerprint("Test", 0, 0);
|
||||
doReturn(List.of(fingerprint)).when(mFingerprintManager).getEnrolledFingerprints(anyInt());
|
||||
setUpFragment(false, PRIMARY_USER_ID, TYPE_UDFPS_OPTICAL, 5);
|
||||
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
Preference preference0 = mFragment.findPreference(key0);
|
||||
assertThat(preference0).isEqualTo(mRestrictedPreference0);
|
||||
|
||||
Preference preference1 = mFragment.findPreference(key1);
|
||||
assertThat(preference1).isEqualTo(mRestrictedPreference1);
|
||||
}
|
||||
|
||||
private void setSensor(@FingerprintSensorProperties.SensorType int sensorType,
|
||||
int maxFingerprints) {
|
||||
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
|
||||
|
@@ -65,7 +65,7 @@ class SupervisionDashboardScreenTest {
|
||||
val mainSwitchPreference =
|
||||
fragment.findPreference<MainSwitchPreference>(SupervisionMainSwitchPreference.KEY)!!
|
||||
val childPreference =
|
||||
fragment.findPreference<Preference>(SupervisionPinManagementScreen.KEY)!!
|
||||
fragment.findPreference<Preference>(SupervisionWebContentFiltersScreen.KEY)!!
|
||||
|
||||
assertThat(childPreference.isEnabled).isFalse()
|
||||
|
||||
@@ -89,7 +89,7 @@ class SupervisionDashboardScreenTest {
|
||||
val mainSwitchPreference =
|
||||
fragment.findPreference<MainSwitchPreference>(SupervisionMainSwitchPreference.KEY)!!
|
||||
val childPreference =
|
||||
fragment.findPreference<Preference>(SupervisionPinManagementScreen.KEY)!!
|
||||
fragment.findPreference<Preference>(SupervisionWebContentFiltersScreen.KEY)!!
|
||||
|
||||
assertThat(childPreference.isEnabled).isFalse()
|
||||
|
||||
|
@@ -15,25 +15,73 @@
|
||||
*/
|
||||
package com.android.settings.supervision
|
||||
|
||||
import android.app.KeyguardManager
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.pm.UserInfo
|
||||
import android.os.UserManager
|
||||
import android.os.UserManager.USER_TYPE_PROFILE_SUPERVISING
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SupervisionPinManagementScreenTest {
|
||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||
private val mockKeyguardManager = mock<KeyguardManager>()
|
||||
private val mockUserManager = mock<UserManager>()
|
||||
|
||||
private val context: Context =
|
||||
object : ContextWrapper(ApplicationProvider.getApplicationContext()) {
|
||||
override fun getSystemService(name: String): Any? =
|
||||
when (name) {
|
||||
Context.KEYGUARD_SERVICE -> mockKeyguardManager
|
||||
Context.USER_SERVICE -> mockUserManager
|
||||
else -> super.getSystemService(name)
|
||||
}
|
||||
}
|
||||
|
||||
private val supervisionPinManagementScreen = SupervisionPinManagementScreen()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
SupervisionHelper.sInstance = null
|
||||
}
|
||||
|
||||
@Test
|
||||
fun key() {
|
||||
assertThat(supervisionPinManagementScreen.key).isEqualTo(SupervisionPinManagementScreen.KEY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isAvailable() {
|
||||
whenever(mockUserManager.users).thenReturn(listOf(SUPERVISING_USER_INFO))
|
||||
whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true)
|
||||
|
||||
assertThat(supervisionPinManagementScreen.isAvailable(context)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isAvailable_noSupervisingUser_returnsFalse() {
|
||||
whenever(mockUserManager.users).thenReturn(emptyList())
|
||||
whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true)
|
||||
|
||||
assertThat(supervisionPinManagementScreen.isAvailable(context)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isAvailable_noSupervisingCredential_returnsFalse() {
|
||||
whenever(mockUserManager.users).thenReturn(listOf(SUPERVISING_USER_INFO))
|
||||
whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(false)
|
||||
|
||||
assertThat(supervisionPinManagementScreen.isAvailable(context)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getTitle() {
|
||||
assertThat(supervisionPinManagementScreen.title)
|
||||
@@ -45,4 +93,16 @@ class SupervisionPinManagementScreenTest {
|
||||
assertThat(supervisionPinManagementScreen.summary)
|
||||
.isEqualTo(R.string.supervision_pin_management_preference_summary_add)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val SUPERVISING_USER_ID = 5
|
||||
val SUPERVISING_USER_INFO =
|
||||
UserInfo(
|
||||
SUPERVISING_USER_ID,
|
||||
/* name */ "supervising",
|
||||
/* iconPath */ "",
|
||||
/* flags */ 0,
|
||||
USER_TYPE_PROFILE_SUPERVISING,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -28,6 +28,10 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_BUTTON_NAME
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_DESCRIPTION
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.CUSTOM_CONTENT_TITLE
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.TYPE_IS_AIRPLANE_MODE
|
||||
import com.android.settings.network.SatelliteWarningDialogActivity.Companion.TYPE_IS_BLUETOOTH
|
||||
@@ -74,6 +78,33 @@ class SatelliteWarningDialogActivityTest {
|
||||
scenario.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun launchActivity_checkCustomizedContent_hasContentIntent() {
|
||||
val scenario = launchCustomizedDialogActivity()
|
||||
|
||||
scenario.onActivity { activity ->
|
||||
assert(activity.intent.hasExtra(EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT))
|
||||
}
|
||||
scenario.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCustomizedDialogIsExisted() {
|
||||
val scenario = launchCustomizedDialogActivity()
|
||||
|
||||
composeTestRule.onNodeWithText(
|
||||
getSatelliteTestContent().get(CUSTOM_CONTENT_BUTTON_NAME).toString()
|
||||
).assertIsDisplayed()
|
||||
composeTestRule.onNodeWithText(
|
||||
getSatelliteTestContent().get(CUSTOM_CONTENT_TITLE).toString()
|
||||
).assertIsDisplayed()
|
||||
composeTestRule.onNodeWithText(
|
||||
getSatelliteTestContent().get(CUSTOM_CONTENT_DESCRIPTION).toString()
|
||||
).assertIsDisplayed()
|
||||
|
||||
scenario.close()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun launchActivity_unknownType_destroyActivity() {
|
||||
val scenario = launchDialogActivity(TYPE_IS_UNKNOWN)
|
||||
@@ -117,10 +148,31 @@ class SatelliteWarningDialogActivityTest {
|
||||
scenario.close()
|
||||
}
|
||||
|
||||
private fun launchDialogActivity(type: Int): ActivityScenario<SatelliteWarningDialogActivity> = launch(
|
||||
Intent(
|
||||
private fun launchDialogActivity(type: Int): ActivityScenario<SatelliteWarningDialogActivity> =
|
||||
launch(Intent(
|
||||
context,
|
||||
SatelliteWarningDialogActivity::class.java
|
||||
).putExtra(EXTRA_TYPE_OF_SATELLITE_WARNING_DIALOG, type)
|
||||
)
|
||||
|
||||
private fun launchCustomizedDialogActivity(): ActivityScenario<SatelliteWarningDialogActivity> =
|
||||
launch(Intent(
|
||||
context,
|
||||
SatelliteWarningDialogActivity::class.java
|
||||
).putExtra(EXTRA_TYPE_OF_SATELLITE_CUSTOMIZED_CONTENT, getSatelliteTestContent())
|
||||
)
|
||||
|
||||
private fun getSatelliteTestContent(): HashMap<Int, String> {
|
||||
val content = HashMap<Int, String>()
|
||||
content.put(CUSTOM_CONTENT_TITLE, TEST_TITLE)
|
||||
content.put(CUSTOM_CONTENT_DESCRIPTION, TEST_DESCRIPTION)
|
||||
content.put(CUSTOM_CONTENT_BUTTON_NAME, TEST_BUTTON_NAME)
|
||||
return content
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TEST_TITLE = "TEST_TITLE"
|
||||
const val TEST_DESCRIPTION = "TEST_DESCRIPTION"
|
||||
const val TEST_BUTTON_NAME = "TEST_BUTTON_NAME"
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.settings.network.telephony.satellite;
|
||||
|
||||
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC;
|
||||
import static android.telephony.CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL;
|
||||
import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT;
|
||||
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
@@ -81,6 +84,8 @@ public class SatelliteSettingAccountInfoControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_entitlementNotSupport_returnConditionalUnavailable() {
|
||||
mPersistableBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
|
||||
CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
|
||||
when(mContext.getSystemService(SatelliteManager.class)).thenReturn(null);
|
||||
mController.init(TEST_SUB_ID, mPersistableBundle, false, false);
|
||||
|
||||
@@ -91,6 +96,8 @@ public class SatelliteSettingAccountInfoControllerTest {
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_entitlementIsSupported_returnConditionalUnavailable() {
|
||||
mPersistableBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
|
||||
CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
|
||||
mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
|
||||
mController.init(TEST_SUB_ID, mPersistableBundle, false, false);
|
||||
|
||||
@@ -99,6 +106,17 @@ public class SatelliteSettingAccountInfoControllerTest {
|
||||
assertThat(result).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_connectionTypeISManual_returnAvailable() {
|
||||
mPersistableBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
|
||||
CARRIER_ROAMING_NTN_CONNECT_MANUAL);
|
||||
mController.init(TEST_SUB_ID, mPersistableBundle, false, false);
|
||||
|
||||
int result = mController.getAvailabilityStatus(TEST_SUB_ID);
|
||||
|
||||
assertThat(result).isEqualTo(AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_showCategoryTitle_correctOperatorName() {
|
||||
mPersistableBundle.putBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
|
||||
|
@@ -40,6 +40,7 @@ import com.android.settings.testutils.ResourcesUtils;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
@@ -115,6 +116,7 @@ public class SatelliteSettingFooterControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("b/405279842")
|
||||
public void displayPreferenceScreen_emergencyMsgSupport_noEmergencyContent() {
|
||||
mPersistableBundle.putBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, true);
|
||||
PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
|
||||
|
Reference in New Issue
Block a user