Snap for 13166373 from d83aa9b83c to 25Q2-release
Change-Id: I1d00a67a8db1a54e72ec679e81248a5ef9ab91d4
This commit is contained in:
@@ -13,7 +13,10 @@
|
|||||||
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.
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:theme="@style/Theme.Material3.DynamicColors.DayNight"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -45,12 +48,17 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<TextView style="@style/vpn_label"
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:text="@string/vpn_name"
|
style="@style/vpn_label"
|
||||||
android:labelFor="@+id/name"/>
|
android:id="@+id/name_layout"
|
||||||
<EditText style="@style/vpn_value"
|
android:hint="@string/vpn_name"
|
||||||
|
app:endIconMode="clear_text"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:inputType="textCapWords"/>
|
android:inputType="textCapWords"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<TextView style="@style/vpn_label"
|
<TextView style="@style/vpn_label"
|
||||||
android:text="@string/vpn_type"
|
android:text="@string/vpn_type"
|
||||||
@@ -60,23 +68,34 @@
|
|||||||
android:prompt="@string/vpn_type"
|
android:prompt="@string/vpn_type"
|
||||||
android:entries="@array/vpn_types"/>
|
android:entries="@array/vpn_types"/>
|
||||||
|
|
||||||
<TextView style="@style/vpn_label"
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:text="@string/vpn_server"
|
style="@style/vpn_label"
|
||||||
android:labelFor="@+id/server"/>
|
android:id="@+id/server_layout"
|
||||||
<EditText style="@style/vpn_value"
|
android:hint="@string/vpn_server"
|
||||||
|
app:endIconMode="clear_text"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
android:id="@+id/server"/>
|
android:id="@+id/server"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/options_ipsec_identity"
|
<LinearLayout android:id="@+id/options_ipsec_identity"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
<TextView style="@style/vpn_label"
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:text="@string/vpn_ipsec_identifier"
|
style="@style/vpn_label"
|
||||||
android:labelFor="@+id/ipsec_identifier"/>
|
android:id="@+id/ipsec_identifier_layout"
|
||||||
<EditText style="@style/vpn_value"
|
android:hint="@string/vpn_ipsec_identifier"
|
||||||
android:id="@+id/ipsec_identifier"
|
app:endIconMode="clear_text"
|
||||||
android:hint="@string/vpn_not_used"/>
|
app:helperTextEnabled="true"
|
||||||
|
app:helperText="@string/vpn_not_used"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
|
android:id="@+id/ipsec_identifier"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/ipsec_psk"
|
<LinearLayout android:id="@+id/ipsec_psk"
|
||||||
@@ -84,12 +103,17 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
<TextView style="@style/vpn_label"
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:text="@string/vpn_ipsec_secret"
|
style="@style/vpn_label"
|
||||||
android:labelFor="@+id/ipsec_secret"/>
|
android:id="@+id/ipsec_secret_layout"
|
||||||
<EditText style="@style/vpn_value"
|
android:hint="@string/vpn_ipsec_secret"
|
||||||
|
app:endIconMode="password_toggle"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
android:id="@+id/ipsec_secret"
|
android:id="@+id/ipsec_secret"
|
||||||
android:password="true"/>
|
android:inputType="textPassword"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout android:id="@+id/ipsec_user"
|
<LinearLayout android:id="@+id/ipsec_user"
|
||||||
@@ -153,27 +177,33 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:visibility="gone" >
|
android:visibility="gone" >
|
||||||
|
|
||||||
<TextView
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
style="@style/vpn_label"
|
style="@style/vpn_label"
|
||||||
android:text="@string/proxy_hostname_label"
|
android:id="@+id/vpn_proxy_host_layout"
|
||||||
android:labelFor="@+id/vpn_proxy_host" />
|
android:hint="@string/proxy_hostname_label"
|
||||||
|
app:endIconMode="clear_text"
|
||||||
|
app:helperTextEnabled="true"
|
||||||
|
app:helperText="@string/proxy_hostname_hint"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
|
android:id="@+id/vpn_proxy_host"
|
||||||
|
android:inputType="textNoSuggestions"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<EditText
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/vpn_proxy_host"
|
|
||||||
style="@style/vpn_value"
|
|
||||||
android:hint="@string/proxy_hostname_hint"
|
|
||||||
android:inputType="textNoSuggestions" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
style="@style/vpn_label"
|
style="@style/vpn_label"
|
||||||
android:text="@string/proxy_port_label"
|
android:id="@+id/vpn_proxy_port_layout"
|
||||||
android:labelFor="@+id/vpn_proxy_port" />
|
android:hint="@string/proxy_port_label"
|
||||||
|
app:endIconMode="clear_text"
|
||||||
<EditText
|
app:helperTextEnabled="true"
|
||||||
android:id="@+id/vpn_proxy_port"
|
app:helperText="@string/proxy_port_hint"
|
||||||
style="@style/vpn_value"
|
app:errorEnabled="true">
|
||||||
android:hint="@string/proxy_port_hint"
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:inputType="number" />
|
style="@style/vpn_value"
|
||||||
|
android:id="@+id/vpn_proxy_port"
|
||||||
|
android:inputType="number"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -182,18 +212,28 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView style="@style/vpn_label"
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:text="@string/vpn_username"
|
style="@style/vpn_label"
|
||||||
android:labelFor="@+id/username"/>
|
android:id="@+id/username_layout"
|
||||||
<EditText style="@style/vpn_value"
|
android:hint="@string/vpn_username"
|
||||||
|
app:endIconMode="clear_text"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
android:id="@+id/username"/>
|
android:id="@+id/username"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<TextView style="@style/vpn_label"
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:text="@string/vpn_password"
|
style="@style/vpn_label"
|
||||||
android:labelFor="@+id/password"/>
|
android:id="@+id/password_layout"
|
||||||
<EditText style="@style/vpn_value"
|
android:hint="@string/vpn_password"
|
||||||
|
app:endIconMode="password_toggle"
|
||||||
|
app:errorEnabled="true">
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
style="@style/vpn_value"
|
||||||
android:id="@+id/password"
|
android:id="@+id/password"
|
||||||
android:password="true"/>
|
android:inputType="textPassword"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<CheckBox style="@style/vpn_value"
|
<CheckBox style="@style/vpn_value"
|
||||||
android:id="@+id/save_login"
|
android:id="@+id/save_login"
|
||||||
|
|||||||
@@ -1054,6 +1054,7 @@
|
|||||||
<!-- Watch unlock enrollment and settings --><skip />
|
<!-- Watch unlock enrollment and settings --><skip />
|
||||||
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
|
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
|
||||||
<string name ="security_settings_activeunlock_preference_title">Watch Unlock</string>
|
<string name ="security_settings_activeunlock_preference_title">Watch Unlock</string>
|
||||||
|
<string name="security_settings_activeunlock">Watch</string>
|
||||||
<!-- Introduction shown in face and fingerprint page to introduce the biometric feature. [CHAR LIMIT=NONE]-->
|
<!-- Introduction shown in face and fingerprint page to introduce the biometric feature. [CHAR LIMIT=NONE]-->
|
||||||
<string name="biometric_settings_intro_with_activeunlock">When you set up Face Unlock and Fingerprint Unlock, your phone will ask for your fingerprint when you wear a mask or are in a dark area.\n\nWatch Unlock is another convenient way to unlock your phone, for example, when your fingers are wet or face isn\u2019t recognized.</string>
|
<string name="biometric_settings_intro_with_activeunlock">When you set up Face Unlock and Fingerprint Unlock, your phone will ask for your fingerprint when you wear a mask or are in a dark area.\n\nWatch Unlock is another convenient way to unlock your phone, for example, when your fingers are wet or face isn\u2019t recognized.</string>
|
||||||
<!-- Introduction shown in fingerprint page to explain that watch unlock can be used if fingerprint isn't recognized. [CHAR LIMIT=NONE]-->
|
<!-- Introduction shown in fingerprint page to explain that watch unlock can be used if fingerprint isn't recognized. [CHAR LIMIT=NONE]-->
|
||||||
|
|||||||
@@ -28,11 +28,11 @@
|
|||||||
settings:controller="com.android.settings.inputmethod.MousePointerAccelerationPreferenceController" />
|
settings:controller="com.android.settings.inputmethod.MousePointerAccelerationPreferenceController" />
|
||||||
|
|
||||||
<com.android.settings.widget.SeekBarPreference
|
<com.android.settings.widget.SeekBarPreference
|
||||||
android:key="trackpad_pointer_speed"
|
android:key="pointer_speed"
|
||||||
android:title="@string/trackpad_pointer_speed"
|
android:title="@string/pointer_speed"
|
||||||
android:order="20"
|
android:order="20"
|
||||||
android:selectable="false"
|
android:selectable="false"
|
||||||
settings:controller="com.android.settings.inputmethod.TouchpadPointerSpeedPreferenceController"/>
|
settings:controller="com.android.settings.inputmethod.MousePointerSpeedPreferenceController"/>
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:key="mouse_swap_primary_button"
|
android:key="mouse_swap_primary_button"
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
android:title="@string/night_display_end_time_title"
|
android:title="@string/night_display_end_time_title"
|
||||||
settings:controller="com.android.settings.display.NightDisplayCustomEndTimePreferenceController"/>
|
settings:controller="com.android.settings.display.NightDisplayCustomEndTimePreferenceController"/>
|
||||||
|
|
||||||
<com.android.settings.widget.SeekBarPreference
|
<com.android.settingslib.widget.SliderPreference
|
||||||
android:key="night_display_temperature"
|
android:key="night_display_temperature"
|
||||||
android:title="@string/night_display_temperature_title"
|
android:title="@string/night_display_temperature_title"
|
||||||
settings:keywords="@string/keywords_display_night_display"
|
settings:keywords="@string/keywords_display_night_display"
|
||||||
|
|||||||
@@ -127,14 +127,13 @@ public class AccessibilityActivityPreference extends RestrictedPreference {
|
|||||||
final String htmlDescription = mA11yShortcutInfo.loadHtmlDescription(mPm);
|
final String htmlDescription = mA11yShortcutInfo.loadHtmlDescription(mPm);
|
||||||
final String settingsClassName = mA11yShortcutInfo.getSettingsActivityName();
|
final String settingsClassName = mA11yShortcutInfo.getSettingsActivityName();
|
||||||
final String tileServiceClassName = mA11yShortcutInfo.getTileServiceName();
|
final String tileServiceClassName = mA11yShortcutInfo.getTileServiceName();
|
||||||
final int metricsCategory = FeatureFactory.getFeatureFactory()
|
final int pageIdCategory = FeatureFactory.getFeatureFactory()
|
||||||
.getAccessibilityMetricsFeatureProvider()
|
.getAccessibilityPageIdFeatureProvider().getCategory(mComponentName);
|
||||||
.getDownloadedFeatureMetricsCategory(mComponentName);
|
|
||||||
|
|
||||||
ThreadUtils.getUiThreadHandler().post(() -> {
|
ThreadUtils.getUiThreadHandler().post(() -> {
|
||||||
RestrictedPreferenceHelper.putBasicExtras(
|
RestrictedPreferenceHelper.putBasicExtras(
|
||||||
this, prefKey, getTitle(), intro, description, imageRes,
|
this, prefKey, getTitle(), intro, description, imageRes,
|
||||||
htmlDescription, mComponentName, metricsCategory);
|
htmlDescription, mComponentName, pageIdCategory);
|
||||||
RestrictedPreferenceHelper.putSettingsExtras(this, getPackageName(), settingsClassName);
|
RestrictedPreferenceHelper.putSettingsExtras(this, getPackageName(), settingsClassName);
|
||||||
RestrictedPreferenceHelper.putTileServiceExtras(
|
RestrictedPreferenceHelper.putTileServiceExtras(
|
||||||
this, getPackageName(), tileServiceClassName);
|
this, getPackageName(), tileServiceClassName);
|
||||||
|
|||||||
@@ -228,10 +228,10 @@ public class AccessibilityDetailsSettingsFragment extends InstrumentedFragment {
|
|||||||
new ComponentName(packageName, tileServiceClassName).flattenToString());
|
new ComponentName(packageName, tileServiceClassName).flattenToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
final int metricsCategory = FeatureFactory.getFeatureFactory()
|
final int pageIdCategory = FeatureFactory.getFeatureFactory()
|
||||||
.getAccessibilityMetricsFeatureProvider()
|
.getAccessibilityPageIdFeatureProvider().getCategory(componentName);
|
||||||
.getDownloadedFeatureMetricsCategory(componentName);
|
extras.putInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY, pageIdCategory);
|
||||||
extras.putInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY, metricsCategory);
|
extras.putInt(AccessibilitySettings.EXTRA_FEEDBACK_CATEGORY, pageIdCategory);
|
||||||
extras.putParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME, componentName);
|
extras.putParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME, componentName);
|
||||||
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, info.getAnimatedImageRes());
|
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, info.getAnimatedImageRes());
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,11 +23,11 @@ import androidx.annotation.Nullable;
|
|||||||
public interface AccessibilityFeedbackFeatureProvider {
|
public interface AccessibilityFeedbackFeatureProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns value according to the {@code componentName}.
|
* Returns value according to the {@code pageId}.
|
||||||
*
|
*
|
||||||
* @param componentName the component name of the downloaded service or activity
|
* @param pageId The unique identifier of the page.
|
||||||
* @return Feedback bucket ID
|
* @return Feedback bucket ID associated with the page, or {@code null} if is not found.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
String getCategory(@Nullable ComponentName componentName);
|
String getCategory(int pageId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/** Default implementation of {@link AccessibilityFeedbackFeatureProvider}. */
|
/** Default implementation of {@link AccessibilityFeedbackFeatureProvider}. */
|
||||||
@@ -25,7 +23,7 @@ public class AccessibilityFeedbackFeatureProviderImpl implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public String getCategory(@Nullable ComponentName componentName) {
|
public String getCategory(int pageId) {
|
||||||
return "";
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import android.content.ComponentName;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider for Accessibility metrics related features.
|
* Provider for Accessibility page id related features.
|
||||||
*/
|
*/
|
||||||
public interface AccessibilityMetricsFeatureProvider {
|
public interface AccessibilityPageIdFeatureProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link android.app.settings.SettingsEnums} value according to the {@code
|
* Returns {@link android.app.settings.SettingsEnums} value according to the {@code
|
||||||
@@ -32,5 +32,5 @@ public interface AccessibilityMetricsFeatureProvider {
|
|||||||
* @param componentName the component name of the downloaded service or activity
|
* @param componentName the component name of the downloaded service or activity
|
||||||
* @return value in {@link android.app.settings.SettingsEnums}
|
* @return value in {@link android.app.settings.SettingsEnums}
|
||||||
*/
|
*/
|
||||||
int getDownloadedFeatureMetricsCategory(@Nullable ComponentName componentName);
|
int getCategory(@Nullable ComponentName componentName);
|
||||||
}
|
}
|
||||||
@@ -19,14 +19,16 @@ package com.android.settings.accessibility;
|
|||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider implementation for Accessibility metrics related features.
|
* Provider implementation for Accessibility page id related features.
|
||||||
*/
|
*/
|
||||||
public class AccessibilityMetricsFeatureProviderImpl implements
|
public class AccessibilityPageIdFeatureProviderImpl implements
|
||||||
AccessibilityMetricsFeatureProvider {
|
AccessibilityPageIdFeatureProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDownloadedFeatureMetricsCategory(ComponentName componentName) {
|
public int getCategory(@Nullable ComponentName componentName) {
|
||||||
return SettingsEnums.ACCESSIBILITY_SERVICE;
|
return SettingsEnums.ACCESSIBILITY_SERVICE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,13 +123,12 @@ public class AccessibilityServicePreference extends RestrictedPreference {
|
|||||||
final String settingsClassName = mA11yServiceInfo.getSettingsActivityName();
|
final String settingsClassName = mA11yServiceInfo.getSettingsActivityName();
|
||||||
final String tileServiceClassName = mA11yServiceInfo.getTileServiceName();
|
final String tileServiceClassName = mA11yServiceInfo.getTileServiceName();
|
||||||
final ResolveInfo resolveInfo = mA11yServiceInfo.getResolveInfo();
|
final ResolveInfo resolveInfo = mA11yServiceInfo.getResolveInfo();
|
||||||
final int metricsCategory = FeatureFactory.getFeatureFactory()
|
final int pageIdCategory = FeatureFactory.getFeatureFactory()
|
||||||
.getAccessibilityMetricsFeatureProvider()
|
.getAccessibilityPageIdFeatureProvider().getCategory(mComponentName);
|
||||||
.getDownloadedFeatureMetricsCategory(mComponentName);
|
|
||||||
ThreadUtils.getUiThreadHandler().post(() -> {
|
ThreadUtils.getUiThreadHandler().post(() -> {
|
||||||
RestrictedPreferenceHelper.putBasicExtras(
|
RestrictedPreferenceHelper.putBasicExtras(
|
||||||
this, prefKey, getTitle(), intro, description, imageRes,
|
this, prefKey, getTitle(), intro, description, imageRes,
|
||||||
htmlDescription, mComponentName, metricsCategory);
|
htmlDescription, mComponentName, pageIdCategory);
|
||||||
RestrictedPreferenceHelper.putServiceExtras(this, resolveInfo, mServiceEnabled);
|
RestrictedPreferenceHelper.putServiceExtras(this, resolveInfo, mServiceEnabled);
|
||||||
RestrictedPreferenceHelper.putSettingsExtras(this, getPackageName(), settingsClassName);
|
RestrictedPreferenceHelper.putSettingsExtras(this, getPackageName(), settingsClassName);
|
||||||
RestrictedPreferenceHelper.putTileServiceExtras(
|
RestrictedPreferenceHelper.putTileServiceExtras(
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
static final String EXTRA_HTML_DESCRIPTION = "html_description";
|
static final String EXTRA_HTML_DESCRIPTION = "html_description";
|
||||||
static final String EXTRA_TIME_FOR_LOGGING = "start_time_to_log_a11y_tool";
|
static final String EXTRA_TIME_FOR_LOGGING = "start_time_to_log_a11y_tool";
|
||||||
static final String EXTRA_METRICS_CATEGORY = "metrics_category";
|
static final String EXTRA_METRICS_CATEGORY = "metrics_category";
|
||||||
|
static final String EXTRA_FEEDBACK_CATEGORY = "feedback_category";
|
||||||
|
|
||||||
// Timeout before we update the services if packages are added/removed
|
// Timeout before we update the services if packages are added/removed
|
||||||
// since the AccessibilityManagerService has to do that processing first
|
// since the AccessibilityManagerService has to do that processing first
|
||||||
@@ -255,7 +256,7 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||||
if (getFeedbackManager().isAvailable()) {
|
if (getFeedbackManager().isAvailable()) {
|
||||||
menu.add(Menu.NONE, MENU_ID_SEND_FEEDBACK, Menu.NONE,
|
menu.add(Menu.NONE, MENU_ID_SEND_FEEDBACK, Menu.NONE,
|
||||||
getPrefContext().getText(R.string.accessibility_send_feedback_title));
|
R.string.accessibility_send_feedback_title);
|
||||||
}
|
}
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
}
|
}
|
||||||
@@ -286,7 +287,7 @@ public class AccessibilitySettings extends DashboardFragment implements
|
|||||||
|
|
||||||
private FeedbackManager getFeedbackManager() {
|
private FeedbackManager getFeedbackManager() {
|
||||||
if (mFeedbackManager == null) {
|
if (mFeedbackManager == null) {
|
||||||
mFeedbackManager = new FeedbackManager(getActivity());
|
mFeedbackManager = new FeedbackManager(getActivity(), SettingsEnums.ACCESSIBILITY);
|
||||||
}
|
}
|
||||||
return mFeedbackManager;
|
return mFeedbackManager;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
@@ -46,23 +45,14 @@ public class FeedbackManager {
|
|||||||
* Constructs a new FeedbackManager.
|
* Constructs a new FeedbackManager.
|
||||||
*
|
*
|
||||||
* @param activity The activity context. A WeakReference is used to prevent memory leaks.
|
* @param activity The activity context. A WeakReference is used to prevent memory leaks.
|
||||||
|
* @param pageId The unique identifier of the page associated with the feedback.
|
||||||
*/
|
*/
|
||||||
public FeedbackManager(@Nullable Activity activity) {
|
public FeedbackManager(@Nullable Activity activity, int pageId) {
|
||||||
this(activity, /* componentName= */ null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new FeedbackManager.
|
|
||||||
*
|
|
||||||
* @param activity The activity context. A WeakReference is used to prevent memory leaks.
|
|
||||||
* @param componentName The component name associated with the feedback.
|
|
||||||
*/
|
|
||||||
public FeedbackManager(@Nullable Activity activity, @Nullable ComponentName componentName) {
|
|
||||||
this(activity,
|
this(activity,
|
||||||
DeviceInfoUtils.getFeedbackReporterPackage(activity),
|
DeviceInfoUtils.getFeedbackReporterPackage(activity),
|
||||||
FeatureFactory.getFeatureFactory()
|
FeatureFactory.getFeatureFactory()
|
||||||
.getAccessibilityFeedbackFeatureProvider()
|
.getAccessibilityFeedbackFeatureProvider()
|
||||||
.getCategory(componentName));
|
.getCategory(pageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import android.os.UserHandle;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
@@ -59,6 +57,11 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature
|
|||||||
return getArguments().getInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY);
|
return getArguments().getInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFeedbackCategory() {
|
||||||
|
return getArguments().getInt(AccessibilitySettings.EXTRA_FEEDBACK_CATEGORY);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
@@ -115,13 +118,6 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature
|
|||||||
return mTileComponentName;
|
return mTileComponentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
// Do not call super. We don't want to see the "Help & feedback" option on this page so as
|
|
||||||
// not to confuse users who think they might be able to send feedback about a specific
|
|
||||||
// accessibility service from this page.
|
|
||||||
}
|
|
||||||
|
|
||||||
// IMPORTANT: Refresh the info since there are dynamically changing capabilities.
|
// IMPORTANT: Refresh the info since there are dynamically changing capabilities.
|
||||||
private AccessibilityShortcutInfo getAccessibilityShortcutInfo() {
|
private AccessibilityShortcutInfo getAccessibilityShortcutInfo() {
|
||||||
final List<AccessibilityShortcutInfo> infos = AccessibilityManager.getInstance(
|
final List<AccessibilityShortcutInfo> infos = AccessibilityManager.getInstance(
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ public class RestrictedPreferenceHelper {
|
|||||||
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, imageRes);
|
extras.putInt(AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES, imageRes);
|
||||||
extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
|
extras.putString(AccessibilitySettings.EXTRA_HTML_DESCRIPTION, htmlDescription);
|
||||||
extras.putInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY, metricsCategory);
|
extras.putInt(AccessibilitySettings.EXTRA_METRICS_CATEGORY, metricsCategory);
|
||||||
|
extras.putInt(AccessibilitySettings.EXTRA_FEEDBACK_CATEGORY, metricsCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ import android.os.SystemClock;
|
|||||||
import android.text.BidiFormatter;
|
import android.text.BidiFormatter;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
|
|
||||||
@@ -76,10 +74,8 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public int getFeedbackCategory() {
|
||||||
// Do not call super. We don't want to see the "Help & feedback" option on this page so as
|
return getArguments().getInt(AccessibilitySettings.EXTRA_FEEDBACK_CATEGORY);
|
||||||
// not to confuse users who think they might be able to send feedback about a specific
|
|
||||||
// accessibility service from this page.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ import android.service.quicksettings.TileService;
|
|||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
@@ -48,6 +51,7 @@ import android.widget.CompoundButton;
|
|||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -89,6 +93,7 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
|
|||||||
// <img src="R.drawable.fileName"/>, a11y settings will get the resources successfully.
|
// <img src="R.drawable.fileName"/>, a11y settings will get the resources successfully.
|
||||||
private static final String IMG_PREFIX = "R.drawable.";
|
private static final String IMG_PREFIX = "R.drawable.";
|
||||||
private static final String DRAWABLE_FOLDER = "drawable";
|
private static final String DRAWABLE_FOLDER = "drawable";
|
||||||
|
static final int MENU_ID_SEND_FEEDBACK = 0;
|
||||||
|
|
||||||
protected TopIntroPreference mTopIntroPreference;
|
protected TopIntroPreference mTopIntroPreference;
|
||||||
protected SettingsMainSwitchPreference mToggleServiceSwitchPreference;
|
protected SettingsMainSwitchPreference mToggleServiceSwitchPreference;
|
||||||
@@ -102,6 +107,7 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
|
|||||||
protected Intent mSettingsIntent;
|
protected Intent mSettingsIntent;
|
||||||
// The mComponentName maybe null, such as Magnify
|
// The mComponentName maybe null, such as Magnify
|
||||||
protected ComponentName mComponentName;
|
protected ComponentName mComponentName;
|
||||||
|
@Nullable private FeedbackManager mFeedbackManager;
|
||||||
protected CharSequence mFeatureName;
|
protected CharSequence mFeatureName;
|
||||||
protected Uri mImageUri;
|
protected Uri mImageUri;
|
||||||
protected CharSequence mHtmlDescription;
|
protected CharSequence mHtmlDescription;
|
||||||
@@ -240,6 +246,24 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
|
|||||||
removeActionBarToggleSwitch();
|
removeActionBarToggleSwitch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||||
|
if (getFeedbackManager().isAvailable()) {
|
||||||
|
menu.add(Menu.NONE, MENU_ID_SEND_FEEDBACK, Menu.NONE,
|
||||||
|
R.string.accessibility_send_feedback_title);
|
||||||
|
}
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||||
|
if (item.getItemId() == MENU_ID_SEND_FEEDBACK) {
|
||||||
|
getFeedbackManager().sendFeedback();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDialogMetricsCategory(int dialogId) {
|
public int getDialogMetricsCategory(int dialogId) {
|
||||||
switch (dialogId) {
|
switch (dialogId) {
|
||||||
@@ -739,4 +763,28 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
|
|||||||
super.onCreateRecyclerView(inflater, parent, savedInstanceState);
|
super.onCreateRecyclerView(inflater, parent, savedInstanceState);
|
||||||
return AccessibilityFragmentUtils.addCollectionInfoToAccessibilityDelegate(recyclerView);
|
return AccessibilityFragmentUtils.addCollectionInfoToAccessibilityDelegate(recyclerView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setFeedbackManager(FeedbackManager feedbackManager) {
|
||||||
|
this.mFeedbackManager = feedbackManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FeedbackManager getFeedbackManager() {
|
||||||
|
if (mFeedbackManager == null) {
|
||||||
|
mFeedbackManager = new FeedbackManager(getActivity(), getFeedbackCategory());
|
||||||
|
}
|
||||||
|
return mFeedbackManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the category of the feedback page.
|
||||||
|
*
|
||||||
|
* <p>By default, this method returns {@link SettingsEnums#PAGE_UNKNOWN}. This indicates that
|
||||||
|
* the feedback category is unknown, and the absence of a feedback menu.
|
||||||
|
*
|
||||||
|
* @return The feedback category, which is {@link SettingsEnums#PAGE_UNKNOWN} by default.
|
||||||
|
*/
|
||||||
|
protected int getFeedbackCategory() {
|
||||||
|
return SettingsEnums.PAGE_UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,12 @@ public class ToggleScreenReaderPreferenceFragmentForSetupWizard
|
|||||||
return SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER;
|
return SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFeedbackCategory() {
|
||||||
|
// The feedback options should not be displayed on the setup wizard page.
|
||||||
|
return SettingsEnums.PAGE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
// Log the final choice in value if it's different from the previous value.
|
// Log the final choice in value if it's different from the previous value.
|
||||||
|
|||||||
@@ -79,6 +79,12 @@ public class ToggleSelectToSpeakPreferenceFragmentForSetupWizard
|
|||||||
return SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK;
|
return SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFeedbackCategory() {
|
||||||
|
// The feedback options should not be displayed on the setup wizard page.
|
||||||
|
return SettingsEnums.PAGE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
// Log the final choice in value if it's different from the previous value.
|
// Log the final choice in value if it's different from the previous value.
|
||||||
|
|||||||
@@ -95,8 +95,7 @@ public class ExternalSourcesDetails extends AppInfoWithHeader
|
|||||||
userHandle)) {
|
userHandle)) {
|
||||||
if (RestrictedLockUtilsInternal.isPolicyEnforcedByAdvancedProtection(context,
|
if (RestrictedLockUtilsInternal.isPolicyEnforcedByAdvancedProtection(context,
|
||||||
DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, userHandle.getIdentifier())) {
|
DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, userHandle.getIdentifier())) {
|
||||||
return context.getString(com.android.settingslib.widget.restricted
|
return context.getString(com.android.settingslib.R.string.disabled);
|
||||||
.R.string.disabled_by_advanced_protection);
|
|
||||||
} else {
|
} else {
|
||||||
return context.getString(
|
return context.getString(
|
||||||
com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
|
com.android.settingslib.widget.restricted.R.string.disabled_by_admin);
|
||||||
|
|||||||
@@ -107,7 +107,10 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
// intent will include this extra containing a bundle of the form:
|
// intent will include this extra containing a bundle of the form:
|
||||||
// "modality" -> consented (boolean).
|
// "modality" -> consented (boolean).
|
||||||
public static final String EXTRA_PARENTAL_CONSENT_STATUS = "consent_status";
|
public static final String EXTRA_PARENTAL_CONSENT_STATUS = "consent_status";
|
||||||
|
// Whether the face enrollment should be launched first when there are multiple biometrics
|
||||||
|
// supported.
|
||||||
|
public static final String EXTRA_LAUNCH_FACE_ENROLL_FIRST =
|
||||||
|
"launch_face_enroll_first";
|
||||||
private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
|
private static final String SAVED_STATE_CONFIRMING_CREDENTIALS = "confirming_credentials";
|
||||||
private static final String SAVED_STATE_IS_SINGLE_ENROLLING =
|
private static final String SAVED_STATE_IS_SINGLE_ENROLLING =
|
||||||
"is_single_enrolling";
|
"is_single_enrolling";
|
||||||
@@ -130,6 +133,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
private boolean mIsFingerprintEnrollable = false;
|
private boolean mIsFingerprintEnrollable = false;
|
||||||
private boolean mParentalOptionsRequired = false;
|
private boolean mParentalOptionsRequired = false;
|
||||||
private boolean mSkipReturnToParent = false;
|
private boolean mSkipReturnToParent = false;
|
||||||
|
private boolean mLaunchFaceEnrollFirst = false;
|
||||||
private Bundle mParentalOptions;
|
private Bundle mParentalOptions;
|
||||||
@Nullable private Long mGkPwHandle;
|
@Nullable private Long mGkPwHandle;
|
||||||
@Nullable private ParentalConsentHelper mParentalConsentHelper;
|
@Nullable private ParentalConsentHelper mParentalConsentHelper;
|
||||||
@@ -214,6 +218,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
|
|
||||||
mParentalOptionsRequired = intent.getBooleanExtra(EXTRA_REQUIRE_PARENTAL_CONSENT, false);
|
mParentalOptionsRequired = intent.getBooleanExtra(EXTRA_REQUIRE_PARENTAL_CONSENT, false);
|
||||||
mSkipReturnToParent = intent.getBooleanExtra(EXTRA_SKIP_RETURN_TO_PARENT, false);
|
mSkipReturnToParent = intent.getBooleanExtra(EXTRA_SKIP_RETURN_TO_PARENT, false);
|
||||||
|
mLaunchFaceEnrollFirst = intent.getBooleanExtra(EXTRA_LAUNCH_FACE_ENROLL_FIRST, false);
|
||||||
|
|
||||||
// determine what can be enrolled
|
// determine what can be enrolled
|
||||||
final boolean isSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
|
final boolean isSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
|
||||||
@@ -221,6 +226,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
|
|
||||||
Log.d(TAG, "parentalOptionsRequired: " + mParentalOptionsRequired
|
Log.d(TAG, "parentalOptionsRequired: " + mParentalOptionsRequired
|
||||||
+ ", skipReturnToParent: " + mSkipReturnToParent
|
+ ", skipReturnToParent: " + mSkipReturnToParent
|
||||||
|
+ ", launchFaceEnrollFirst: " + mLaunchFaceEnrollFirst
|
||||||
+ ", isSetupWizard: " + isSetupWizard
|
+ ", isSetupWizard: " + isSetupWizard
|
||||||
+ ", isMultiSensor: " + isMultiSensor);
|
+ ", isMultiSensor: " + isMultiSensor);
|
||||||
|
|
||||||
@@ -356,7 +362,8 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
} else if (canUseFace || canUseFingerprint) {
|
} else if (canUseFace || canUseFingerprint) {
|
||||||
if (mGkPwHandle == null) {
|
if (mGkPwHandle == null) {
|
||||||
setOrConfirmCredentialsNow();
|
setOrConfirmCredentialsNow();
|
||||||
} else if (canUseFingerprint && mIsFingerprintEnrollable) {
|
} else if (canUseFingerprint && mIsFingerprintEnrollable
|
||||||
|
&& !(canUseFace && mIsFaceEnrollable && mLaunchFaceEnrollFirst)) {
|
||||||
launchFingerprintOnlyEnroll();
|
launchFingerprintOnlyEnroll();
|
||||||
} else if (canUseFace && mIsFaceEnrollable) {
|
} else if (canUseFace && mIsFaceEnrollable) {
|
||||||
launchFaceOnlyEnroll();
|
launchFaceOnlyEnroll();
|
||||||
@@ -510,7 +517,8 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
int requestCode, int resultCode, Intent data) {
|
int requestCode, int resultCode, Intent data) {
|
||||||
|
|
||||||
Log.d(TAG, "handleOnActivityResultWhileEnrolling, request = " + requestCode + ""
|
Log.d(TAG, "handleOnActivityResultWhileEnrolling, request = " + requestCode + ""
|
||||||
+ ", resultCode = " + resultCode);
|
+ ", resultCode = " + resultCode + ", launchFaceEnrollFirst="
|
||||||
|
+ mLaunchFaceEnrollFirst);
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_HANDOFF_PARENT:
|
case REQUEST_HANDOFF_PARENT:
|
||||||
setResult(RESULT_OK, newResultIntent());
|
setResult(RESULT_OK, newResultIntent());
|
||||||
@@ -526,7 +534,8 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
// SetupFingerprintEnrollIntroduction/FingerprintEnrollmentActivity
|
// SetupFingerprintEnrollIntroduction/FingerprintEnrollmentActivity
|
||||||
TransitionHelper.applyForwardTransition(this, TRANSITION_FADE_THROUGH);
|
TransitionHelper.applyForwardTransition(this, TRANSITION_FADE_THROUGH);
|
||||||
updateGatekeeperPasswordHandle(data);
|
updateGatekeeperPasswordHandle(data);
|
||||||
if (mIsFingerprintEnrollable) {
|
if (mIsFingerprintEnrollable
|
||||||
|
&& !(mIsFaceEnrollable && mLaunchFaceEnrollFirst)) {
|
||||||
launchFingerprintOnlyEnroll();
|
launchFingerprintOnlyEnroll();
|
||||||
} else {
|
} else {
|
||||||
launchFaceOnlyEnroll();
|
launchFaceOnlyEnroll();
|
||||||
@@ -548,7 +557,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
}
|
}
|
||||||
if ((resultCode == BiometricEnrollBase.RESULT_SKIP
|
if ((resultCode == BiometricEnrollBase.RESULT_SKIP
|
||||||
|| resultCode == BiometricEnrollBase.RESULT_FINISHED)
|
|| resultCode == BiometricEnrollBase.RESULT_FINISHED)
|
||||||
&& mIsFaceEnrollable) {
|
&& mIsFaceEnrollable && !mLaunchFaceEnrollFirst) {
|
||||||
// Apply forward animation during the transition from
|
// Apply forward animation during the transition from
|
||||||
// SetupFingerprintEnroll*/FingerprintEnrollmentActivity to
|
// SetupFingerprintEnroll*/FingerprintEnrollmentActivity to
|
||||||
// SetupFaceEnrollIntroduction
|
// SetupFaceEnrollIntroduction
|
||||||
@@ -556,6 +565,9 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
mIsPreviousEnrollmentCanceled =
|
mIsPreviousEnrollmentCanceled =
|
||||||
resultCode != BiometricEnrollBase.RESULT_FINISHED;
|
resultCode != BiometricEnrollBase.RESULT_FINISHED;
|
||||||
launchFaceOnlyEnroll();
|
launchFaceOnlyEnroll();
|
||||||
|
} else if (resultCode == Activity.RESULT_CANCELED && mIsFaceEnrollable
|
||||||
|
&& mLaunchFaceEnrollFirst) {
|
||||||
|
launchFaceOnlyEnroll();
|
||||||
} else {
|
} else {
|
||||||
notifySafetyIssueActionLaunchedIfNeeded(resultCode);
|
notifySafetyIssueActionLaunchedIfNeeded(resultCode);
|
||||||
finishOrLaunchHandToParent(resultCode);
|
finishOrLaunchHandToParent(resultCode);
|
||||||
@@ -563,7 +575,14 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
|
|||||||
break;
|
break;
|
||||||
case REQUEST_SINGLE_ENROLL_FACE:
|
case REQUEST_SINGLE_ENROLL_FACE:
|
||||||
mIsSingleEnrolling = false;
|
mIsSingleEnrolling = false;
|
||||||
if (resultCode == Activity.RESULT_CANCELED && mIsFingerprintEnrollable) {
|
if ((resultCode == BiometricEnrollBase.RESULT_SKIP
|
||||||
|
|| resultCode == BiometricEnrollBase.RESULT_FINISHED)
|
||||||
|
&& mIsFingerprintEnrollable && mLaunchFaceEnrollFirst) {
|
||||||
|
mIsPreviousEnrollmentCanceled =
|
||||||
|
resultCode != BiometricEnrollBase.RESULT_FINISHED;
|
||||||
|
launchFingerprintOnlyEnroll();
|
||||||
|
} else if (resultCode == Activity.RESULT_CANCELED && mIsFingerprintEnrollable
|
||||||
|
&& !mLaunchFaceEnrollFirst) {
|
||||||
mIsPreviousEnrollmentCanceled = true;
|
mIsPreviousEnrollmentCanceled = true;
|
||||||
launchFingerprintOnlyEnroll();
|
launchFingerprintOnlyEnroll();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.android.internal.widget.LockPatternUtils;
|
|||||||
import com.android.internal.widget.VerifyCredentialResponse;
|
import com.android.internal.widget.VerifyCredentialResponse;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SetupWizardUtils;
|
import com.android.settings.SetupWizardUtils;
|
||||||
|
import com.android.settings.biometrics.face.FaceEnroll;
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintEnroll;
|
import com.android.settings.biometrics.fingerprint.FingerprintEnroll;
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
|
import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor;
|
||||||
import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor;
|
import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor;
|
||||||
@@ -282,9 +283,7 @@ public class BiometricUtils {
|
|||||||
*/
|
*/
|
||||||
public static Intent getFaceIntroIntent(@NonNull Context context,
|
public static Intent getFaceIntroIntent(@NonNull Context context,
|
||||||
@NonNull Intent activityIntent) {
|
@NonNull Intent activityIntent) {
|
||||||
final Intent intent = new Intent(context,
|
final Intent intent = new Intent(context, FaceEnroll.class);
|
||||||
FeatureFactory.getFeatureFactory().getFaceFeatureProvider()
|
|
||||||
.getEnrollActivityClassProvider().getNext());
|
|
||||||
WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
|
WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.os.RemoteException;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
@@ -76,17 +77,22 @@ public class ActiveUnlockContentListener {
|
|||||||
mContentKey = contentKey;
|
mContentKey = contentKey;
|
||||||
String authority = new ActiveUnlockStatusUtils(mContext).getAuthority();
|
String authority = new ActiveUnlockStatusUtils(mContext).getAuthority();
|
||||||
if (authority != null) {
|
if (authority != null) {
|
||||||
mUri = new Uri.Builder()
|
mUri = getUri(authority);
|
||||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
|
||||||
.authority(authority)
|
|
||||||
.appendPath(CONTENT_PROVIDER_PATH)
|
|
||||||
.build();
|
|
||||||
} else {
|
} else {
|
||||||
mUri = null;
|
mUri = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns Active Unlock Uri. */
|
||||||
|
public static @NonNull Uri getUri(@NonNull String authority) {
|
||||||
|
return new Uri.Builder()
|
||||||
|
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
|
.authority(authority)
|
||||||
|
.appendPath(CONTENT_PROVIDER_PATH)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns true if start listening for updates from the ContentProvider, false otherwise. */
|
/** Returns true if start listening for updates from the ContentProvider, false otherwise. */
|
||||||
public synchronized boolean subscribe() {
|
public synchronized boolean subscribe() {
|
||||||
if (mSubscribed || mUri == null) {
|
if (mSubscribed || mUri == null) {
|
||||||
@@ -123,25 +129,40 @@ public class ActiveUnlockContentListener {
|
|||||||
Log.e(mLogTag, "Uri null when trying to fetch content");
|
Log.e(mLogTag, "Uri null when trying to fetch content");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ContentResolver contentResolver = mContext.getContentResolver();
|
|
||||||
ContentProviderClient client = contentResolver.acquireContentProviderClient(mUri);
|
@Nullable String newValue = getContentFromUri(
|
||||||
Bundle bundle;
|
mContext, mUri, mLogTag, mMethodName, mContentKey);
|
||||||
try {
|
|
||||||
bundle = client.call(mMethodName, null /* arg */, null /* extras */);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.e(mLogTag, "Failed to call contentProvider", e);
|
|
||||||
return;
|
|
||||||
} finally {
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
if (bundle == null) {
|
|
||||||
Log.e(mLogTag, "Null bundle returned from contentProvider");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String newValue = bundle.getString(mContentKey);
|
|
||||||
if (!TextUtils.equals(mContent, newValue)) {
|
if (!TextUtils.equals(mContent, newValue)) {
|
||||||
mContent = newValue;
|
mContent = newValue;
|
||||||
mContentChangedListener.onContentChanged(mContent);
|
mContentChangedListener.onContentChanged(mContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get the content from Uri. */
|
||||||
|
public static @Nullable String getContentFromUri(
|
||||||
|
@NonNull Context context,
|
||||||
|
@NonNull Uri uri,
|
||||||
|
@NonNull String logTag,
|
||||||
|
@NonNull String methodName,
|
||||||
|
@NonNull String contentKey) {
|
||||||
|
ContentResolver contentResolver = context.getContentResolver();
|
||||||
|
ContentProviderClient client = contentResolver.acquireContentProviderClient(uri);
|
||||||
|
|
||||||
|
@Nullable Bundle bundle = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
bundle = client.call(methodName, /* arg= */ null, /* extras = */ null);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(logTag, "Failed to call contentProvider", e);
|
||||||
|
} finally {
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bundle == null) {
|
||||||
|
Log.e(logTag, "Null bundle returned from contentProvider");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bundle.getString(contentKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import android.content.Context;
|
|||||||
/** Listens to device name updates from the content provider and fetches the latest value. */
|
/** Listens to device name updates from the content provider and fetches the latest value. */
|
||||||
public class ActiveUnlockDeviceNameListener {
|
public class ActiveUnlockDeviceNameListener {
|
||||||
private static final String TAG = "ActiveUnlockDeviceNameListener";
|
private static final String TAG = "ActiveUnlockDeviceNameListener";
|
||||||
private static final String METHOD_NAME = "getDeviceName";
|
static final String METHOD_NAME = "getDeviceName";
|
||||||
private static final String DEVICE_NAME_KEY = "com.android.settings.active_unlock.device_name";
|
static final String DEVICE_NAME_KEY = "com.android.settings.active_unlock.device_name";
|
||||||
|
|
||||||
private final ActiveUnlockContentListener mActiveUnlockContentListener;
|
private final ActiveUnlockContentListener mActiveUnlockContentListener;
|
||||||
public ActiveUnlockDeviceNameListener(
|
public ActiveUnlockDeviceNameListener(
|
||||||
|
|||||||
@@ -155,10 +155,17 @@ public class ActiveUnlockStatusUtils {
|
|||||||
return BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
return BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the title of active unlock only.
|
||||||
|
*/
|
||||||
|
public @NonNull String getTitleForActiveUnlockOnly() {
|
||||||
|
return mContext.getString(R.string.security_settings_activeunlock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the title of the combined biometric settings entity when active unlock is enabled.
|
* Returns the title of the combined biometric settings entity when active unlock is enabled.
|
||||||
*/
|
*/
|
||||||
public String getTitleForActiveUnlock() {
|
public @NonNull String getTitleForActiveUnlock() {
|
||||||
final boolean faceAllowed = Utils.hasFaceHardware(mContext);
|
final boolean faceAllowed = Utils.hasFaceHardware(mContext);
|
||||||
final boolean fingerprintAllowed = Utils.hasFingerprintHardware(mContext);
|
final boolean fingerprintAllowed = Utils.hasFingerprintHardware(mContext);
|
||||||
return mContext.getString(getTitleRes(faceAllowed, fingerprintAllowed));
|
return mContext.getString(getTitleRes(faceAllowed, fingerprintAllowed));
|
||||||
@@ -264,6 +271,30 @@ public class ActiveUnlockStatusUtils {
|
|||||||
return mContext.getString(getUseBiometricTitleRes(faceAllowed, fingerprintAllowed));
|
return mContext.getString(getUseBiometricTitleRes(faceAllowed, fingerprintAllowed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the summary from content provider.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static String getSummaryFromContentProvider(
|
||||||
|
@NonNull Context context, @NonNull String authority, @NonNull String logTag) {
|
||||||
|
return ActiveUnlockContentListener.getContentFromUri(
|
||||||
|
context, ActiveUnlockContentListener.getUri(authority), logTag,
|
||||||
|
ActiveUnlockSummaryListener.METHOD_NAME,
|
||||||
|
ActiveUnlockSummaryListener.SUMMARY_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the device name from content provider.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static String getDeviceNameFromContentProvider(
|
||||||
|
@NonNull Context context, @NonNull String authority, @NonNull String logTag) {
|
||||||
|
return ActiveUnlockContentListener.getContentFromUri(
|
||||||
|
context, ActiveUnlockContentListener.getUri(authority), logTag,
|
||||||
|
ActiveUnlockDeviceNameListener.METHOD_NAME,
|
||||||
|
ActiveUnlockDeviceNameListener.DEVICE_NAME_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
@StringRes
|
@StringRes
|
||||||
private static int getUseBiometricTitleRes(
|
private static int getUseBiometricTitleRes(
|
||||||
boolean isFaceAllowed, boolean isFingerprintAllowed) {
|
boolean isFaceAllowed, boolean isFingerprintAllowed) {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import android.content.Context;
|
|||||||
/** Listens to summary updates from the content provider and fetches the latest value. */
|
/** Listens to summary updates from the content provider and fetches the latest value. */
|
||||||
public class ActiveUnlockSummaryListener {
|
public class ActiveUnlockSummaryListener {
|
||||||
private static final String TAG = "ActiveUnlockSummaryListener";
|
private static final String TAG = "ActiveUnlockSummaryListener";
|
||||||
private static final String METHOD_NAME = "getSummary";
|
static final String METHOD_NAME = "getSummary";
|
||||||
private static final String SUMMARY_KEY = "com.android.settings.summary";
|
static final String SUMMARY_KEY = "com.android.settings.summary";
|
||||||
|
|
||||||
private final ActiveUnlockContentListener mContentListener;
|
private final ActiveUnlockContentListener mContentListener;
|
||||||
public ActiveUnlockSummaryListener(
|
public ActiveUnlockSummaryListener(
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int CONFIRM_REQUEST = 2001;
|
static final int CONFIRM_REQUEST = 2001;
|
||||||
private static final int CHOOSE_LOCK_REQUEST = 2002;
|
private static final int CHOOSE_LOCK_REQUEST = 2002;
|
||||||
protected static final int ACTIVE_UNLOCK_REQUEST = 2003;
|
public static final int ACTIVE_UNLOCK_REQUEST = 2003;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int BIOMETRIC_AUTH_REQUEST = 2004;
|
static final int BIOMETRIC_AUTH_REQUEST = 2004;
|
||||||
|
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ import androidx.preference.PreferenceScreen;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.SliderPreferenceController;
|
import com.android.settings.core.SliderPreferenceController;
|
||||||
import com.android.settings.widget.SeekBarPreference;
|
import com.android.settingslib.widget.SliderPreference;
|
||||||
|
|
||||||
public class NightDisplayIntensityPreferenceController extends SliderPreferenceController {
|
public class NightDisplayIntensityPreferenceController extends SliderPreferenceController {
|
||||||
|
|
||||||
private ColorDisplayManager mColorDisplayManager;
|
private final ColorDisplayManager mColorDisplayManager;
|
||||||
|
|
||||||
public NightDisplayIntensityPreferenceController(Context context, String key) {
|
public NightDisplayIntensityPreferenceController(Context context, String key) {
|
||||||
super(context, key);
|
super(context, key);
|
||||||
@@ -64,11 +64,11 @@ public class NightDisplayIntensityPreferenceController extends SliderPreferenceC
|
|||||||
@Override
|
@Override
|
||||||
public void displayPreference(PreferenceScreen screen) {
|
public void displayPreference(PreferenceScreen screen) {
|
||||||
super.displayPreference(screen);
|
super.displayPreference(screen);
|
||||||
final SeekBarPreference preference = screen.findPreference(getPreferenceKey());
|
SliderPreference preference = screen.findPreference(getPreferenceKey());
|
||||||
preference.setContinuousUpdates(true);
|
preference.setUpdatesContinuously(true);
|
||||||
preference.setMax(getMax());
|
preference.setMax(getMax());
|
||||||
preference.setMin(getMin());
|
preference.setMin(getMin());
|
||||||
preference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_ENDS);
|
// TODO(b/394828723) add haptic feedback
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.inputmethod;
|
||||||
|
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.input.InputSettings;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.settings.core.SliderPreferenceController;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
import com.android.settings.widget.SeekBarPreference;
|
||||||
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
|
|
||||||
|
public class MousePointerSpeedPreferenceController extends SliderPreferenceController {
|
||||||
|
|
||||||
|
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||||
|
|
||||||
|
public MousePointerSpeedPreferenceController(@NonNull Context context, @NonNull String key) {
|
||||||
|
super(context, key);
|
||||||
|
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void displayPreference(PreferenceScreen screen) {
|
||||||
|
super.displayPreference(screen);
|
||||||
|
SeekBarPreference preference = screen.findPreference(getPreferenceKey());
|
||||||
|
preference.setMax(getMax());
|
||||||
|
preference.setMin(getMin());
|
||||||
|
preference.setProgress(getSliderPosition());
|
||||||
|
updateState(preference);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setSliderPosition(int position) {
|
||||||
|
if (position < getMin() || position > getMax()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
InputSettings.setPointerSpeed(mContext, position);
|
||||||
|
mMetricsFeatureProvider.action(
|
||||||
|
mContext, SettingsEnums.ACTION_GESTURE_POINTER_SPEED_CHANGED, position);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSliderPosition() {
|
||||||
|
return InputSettings.getPointerSpeed(mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMin() {
|
||||||
|
return InputSettings.MIN_POINTER_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMax() {
|
||||||
|
return InputSettings.MAX_POINTER_SPEED;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,11 +26,6 @@ import android.content.DialogInterface;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.window.OnBackInvokedCallback;
|
import android.window.OnBackInvokedCallback;
|
||||||
import android.window.OnBackInvokedDispatcher;
|
import android.window.OnBackInvokedDispatcher;
|
||||||
|
|
||||||
@@ -57,6 +52,7 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
|
|||||||
static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
||||||
static final String ARG_TARGET_LOCALE = "arg_target_locale";
|
static final String ARG_TARGET_LOCALE = "arg_target_locale";
|
||||||
static final String ARG_SHOW_DIALOG = "arg_show_dialog";
|
static final String ARG_SHOW_DIALOG = "arg_show_dialog";
|
||||||
|
static final String ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED = "arg_show_dialog_for_not_translated";
|
||||||
|
|
||||||
private boolean mShouldKeepDialog;
|
private boolean mShouldKeepDialog;
|
||||||
private OnBackInvokedDispatcher mBackDispatcher;
|
private OnBackInvokedDispatcher mBackDispatcher;
|
||||||
@@ -185,6 +181,7 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
|
|||||||
private final int mDialogType;
|
private final int mDialogType;
|
||||||
private final LocaleStore.LocaleInfo mLocaleInfo;
|
private final LocaleStore.LocaleInfo mLocaleInfo;
|
||||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||||
|
private final boolean mShowDialogForNotTranslated;
|
||||||
|
|
||||||
private LocaleListEditor mParent;
|
private LocaleListEditor mParent;
|
||||||
|
|
||||||
@@ -194,6 +191,7 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
Bundle arguments = dialogFragment.getArguments();
|
Bundle arguments = dialogFragment.getArguments();
|
||||||
mDialogType = arguments.getInt(ARG_DIALOG_TYPE);
|
mDialogType = arguments.getInt(ARG_DIALOG_TYPE);
|
||||||
|
mShowDialogForNotTranslated = arguments.getBoolean(ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED);
|
||||||
mLocaleInfo = (LocaleStore.LocaleInfo) arguments.getSerializable(ARG_TARGET_LOCALE);
|
mLocaleInfo = (LocaleStore.LocaleInfo) arguments.getSerializable(ARG_TARGET_LOCALE);
|
||||||
mMetricsFeatureProvider =
|
mMetricsFeatureProvider =
|
||||||
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
|
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
|
||||||
@@ -215,6 +213,7 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
|
|||||||
bundle.putInt(ARG_DIALOG_TYPE, mDialogType);
|
bundle.putInt(ARG_DIALOG_TYPE, mDialogType);
|
||||||
bundle.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE, mLocaleInfo);
|
bundle.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE, mLocaleInfo);
|
||||||
intent.putExtras(bundle);
|
intent.putExtras(bundle);
|
||||||
|
intent.putExtra(ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED, mShowDialogForNotTranslated);
|
||||||
mParent.onActivityResult(mDialogType, result, intent);
|
mParent.onActivityResult(mDialogType, result, intent);
|
||||||
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_CHANGE_LANGUAGE,
|
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_CHANGE_LANGUAGE,
|
||||||
changed);
|
changed);
|
||||||
|
|||||||
@@ -364,12 +364,25 @@ class LocaleDragAndDropAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notifyListChanged(LocaleStore.LocaleInfo localeInfo) {
|
public void notifyListChanged(LocaleStore.LocaleInfo localeInfo) {
|
||||||
if (!localeInfo.getLocale().equals(mCacheItemList.get(0).getLocale())) {
|
if (listChanged()) {
|
||||||
mFeedItemList = new ArrayList<>(mCacheItemList);
|
mFeedItemList = new ArrayList<>(mCacheItemList);
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean listChanged() {
|
||||||
|
if (mFeedItemList.size() == mCacheItemList.size()) {
|
||||||
|
for (int i = 0; i < mFeedItemList.size(); i++) {
|
||||||
|
if (!mFeedItemList.get(i).getLocale().equals(mCacheItemList.get(i).getLocale())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setCacheItemList() {
|
public void setCacheItemList() {
|
||||||
mCacheItemList = new ArrayList<>(mFeedItemList);
|
mCacheItemList = new ArrayList<>(mFeedItemList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ public class LocaleLinearLayoutManager extends LinearLayoutManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
mLocaleListEditor.showConfirmDialog(false, mAdapter.getFeedItemList().get(0));
|
mLocaleListEditor.showConfirmDialog(mAdapter.getFeedItemList().get(0), null);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
@@ -235,7 +236,9 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
|
|||||||
localeInfo = mAdapter.getFeedItemList().get(0);
|
localeInfo = mAdapter.getFeedItemList().get(0);
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
mAdapter.doTheUpdate();
|
mAdapter.doTheUpdate();
|
||||||
if (!localeInfo.isTranslated()) {
|
boolean showNotTranslatedDialog = data.getBooleanExtra(
|
||||||
|
LocaleDialogFragment.ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED, true);
|
||||||
|
if (showNotTranslatedDialog && !localeInfo.isTranslated()) {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE,
|
args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE,
|
||||||
LocaleDialogFragment.DIALOG_NOT_AVAILABLE_LOCALE);
|
LocaleDialogFragment.DIALOG_NOT_AVAILABLE_LOCALE);
|
||||||
@@ -428,13 +431,10 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
|
|||||||
// to remove.
|
// to remove.
|
||||||
mRemoveMode = false;
|
mRemoveMode = false;
|
||||||
mShowingRemoveDialog = false;
|
mShowingRemoveDialog = false;
|
||||||
LocaleStore.LocaleInfo firstLocale =
|
Locale defaultBeforeRemoval = Locale.getDefault();
|
||||||
mAdapter.getFeedItemList().get(0);
|
|
||||||
mAdapter.removeChecked();
|
mAdapter.removeChecked();
|
||||||
boolean isFirstRemoved =
|
showConfirmDialog(mAdapter.getFeedItemList().get(0),
|
||||||
firstLocale != mAdapter.getFeedItemList().get(0);
|
defaultBeforeRemoval);
|
||||||
showConfirmDialog(isFirstRemoved, isFirstRemoved ? firstLocale
|
|
||||||
: mAdapter.getFeedItemList().get(0));
|
|
||||||
setRemoveMode(false);
|
setRemoveMode(false);
|
||||||
dialogHelper.getDialog().dismiss();
|
dialogHelper.getDialog().dismiss();
|
||||||
})
|
})
|
||||||
@@ -520,27 +520,73 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
|
|||||||
public boolean onTouch(View v, MotionEvent event) {
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
if (event.getAction() == MotionEvent.ACTION_UP
|
if (event.getAction() == MotionEvent.ACTION_UP
|
||||||
|| event.getAction() == MotionEvent.ACTION_CANCEL) {
|
|| event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||||
showConfirmDialog(false, mAdapter.getFeedItemList().get(0));
|
showConfirmDialog(mAdapter.getFeedItemList().get(0), null);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showConfirmDialog(boolean isFirstRemoved, LocaleStore.LocaleInfo localeInfo) {
|
protected void showConfirmDialog(LocaleStore.LocaleInfo localeInfo,
|
||||||
|
@Nullable Locale defaultLocaleBeforeRemoval) {
|
||||||
Locale currentSystemLocale = LocalePicker.getLocales().get(0);
|
Locale currentSystemLocale = LocalePicker.getLocales().get(0);
|
||||||
if (!localeInfo.getLocale().equals(currentSystemLocale)) {
|
if (!localeInfo.getLocale().equals(currentSystemLocale)) {
|
||||||
final LocaleDialogFragment localeDialogFragment =
|
displayDialogFragment(localeInfo, true);
|
||||||
LocaleDialogFragment.newInstance();
|
|
||||||
Bundle args = new Bundle();
|
|
||||||
args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
|
||||||
args.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE,
|
|
||||||
isFirstRemoved ? LocaleStore.getLocaleInfo(currentSystemLocale) : localeInfo);
|
|
||||||
localeDialogFragment.setArguments(args);
|
|
||||||
localeDialogFragment.show(mFragmentManager, TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
|
||||||
} else {
|
} else {
|
||||||
mAdapter.doTheUpdate();
|
if (!localeInfo.isTranslated()) {
|
||||||
|
if (defaultLocaleBeforeRemoval == null) {
|
||||||
|
showDialogDueToDragAndDrop();
|
||||||
|
} else {
|
||||||
|
showDialogDueToRemoval(defaultLocaleBeforeRemoval);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mAdapter.doTheUpdate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showDialogDueToDragAndDrop() {
|
||||||
|
LocaleStore.LocaleInfo newLocale = mAdapter.getFeedItemList().stream().filter(
|
||||||
|
i -> i.isTranslated()).findFirst().orElse(null);
|
||||||
|
if (newLocale == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LocaleStore.LocaleInfo oldLocale = null;
|
||||||
|
final LocaleList localeList = LocalePicker.getLocales();
|
||||||
|
for (int i = 0; i < localeList.size(); i++) {
|
||||||
|
LocaleStore.LocaleInfo temp = LocaleStore.getLocaleInfo(localeList.get(i));
|
||||||
|
if (temp.isTranslated()) {
|
||||||
|
oldLocale = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oldLocale != null && !newLocale.getLocale().equals(
|
||||||
|
oldLocale.getLocale())) {
|
||||||
|
displayDialogFragment(newLocale, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showDialogDueToRemoval(Locale preDefault) {
|
||||||
|
if (preDefault == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LocaleStore.LocaleInfo currentDefault = mAdapter.getFeedItemList().stream().filter(
|
||||||
|
i -> i.isTranslated()).findFirst().orElse(null);
|
||||||
|
if (currentDefault != null && !preDefault.equals(currentDefault.getLocale())) {
|
||||||
|
displayDialogFragment(currentDefault, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayDialogFragment(LocaleStore.LocaleInfo localeInfo,
|
||||||
|
boolean showDialogForNotTranslated) {
|
||||||
|
final LocaleDialogFragment localeDialogFragment = LocaleDialogFragment.newInstance();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putBoolean(LocaleDialogFragment.ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED,
|
||||||
|
showDialogForNotTranslated);
|
||||||
|
args.putInt(LocaleDialogFragment.ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
||||||
|
args.putSerializable(LocaleDialogFragment.ARG_TARGET_LOCALE, localeInfo);
|
||||||
|
localeDialogFragment.setArguments(args);
|
||||||
|
localeDialogFragment.show(mFragmentManager, TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
// Hide the "Remove" menu if there is only one locale in the list, show it otherwise
|
// Hide the "Remove" menu if there is only one locale in the list, show it otherwise
|
||||||
// This is called when the menu is first created, and then one add / remove locale
|
// This is called when the menu is first created, and then one add / remove locale
|
||||||
private void updateVisibilityOfRemoveMenu() {
|
private void updateVisibilityOfRemoveMenu() {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ package com.android.settings.overlay
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider
|
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider
|
import com.android.settings.accessibility.AccessibilityPageIdFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider
|
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider
|
||||||
import com.android.settings.accounts.AccountFeatureProvider
|
import com.android.settings.accounts.AccountFeatureProvider
|
||||||
import com.android.settings.applications.ApplicationFeatureProvider
|
import com.android.settings.applications.ApplicationFeatureProvider
|
||||||
@@ -145,9 +145,9 @@ abstract class FeatureFactory {
|
|||||||
abstract val accessibilitySearchFeatureProvider: AccessibilitySearchFeatureProvider
|
abstract val accessibilitySearchFeatureProvider: AccessibilitySearchFeatureProvider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves implementation for Accessibility metrics category feature.
|
* Retrieves implementation for Accessibility page id category feature.
|
||||||
*/
|
*/
|
||||||
abstract val accessibilityMetricsFeatureProvider: AccessibilityMetricsFeatureProvider
|
abstract val accessibilityPageIdFeatureProvider: AccessibilityPageIdFeatureProvider
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves implementation for advanced vpn feature.
|
* Retrieves implementation for advanced vpn feature.
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import android.net.VpnManager
|
|||||||
import android.os.UserManager
|
import android.os.UserManager
|
||||||
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider
|
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProviderImpl
|
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProviderImpl
|
||||||
import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider
|
import com.android.settings.accessibility.AccessibilityPageIdFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilityMetricsFeatureProviderImpl
|
import com.android.settings.accessibility.AccessibilityPageIdFeatureProviderImpl
|
||||||
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider
|
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilitySearchFeatureProviderImpl
|
import com.android.settings.accessibility.AccessibilitySearchFeatureProviderImpl
|
||||||
import com.android.settings.accounts.AccountFeatureProvider
|
import com.android.settings.accounts.AccountFeatureProvider
|
||||||
@@ -174,8 +174,8 @@ open class FeatureFactoryImpl : FeatureFactory() {
|
|||||||
AccessibilitySearchFeatureProviderImpl()
|
AccessibilitySearchFeatureProviderImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val accessibilityMetricsFeatureProvider: AccessibilityMetricsFeatureProvider by lazy {
|
override val accessibilityPageIdFeatureProvider: AccessibilityPageIdFeatureProvider by lazy {
|
||||||
AccessibilityMetricsFeatureProviderImpl()
|
AccessibilityPageIdFeatureProviderImpl()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val advancedVpnFeatureProvider by lazy { AdvancedVpnFeatureProviderImpl() }
|
override val advancedVpnFeatureProvider by lazy { AdvancedVpnFeatureProviderImpl() }
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ public final class LockScreenSafetySource {
|
|||||||
if (Flags.biometricsOnboardingEducation()) {
|
if (Flags.biometricsOnboardingEducation()) {
|
||||||
FaceSafetySource.onBiometricsChanged(context);
|
FaceSafetySource.onBiometricsChanged(context);
|
||||||
FingerprintSafetySource.onBiometricsChanged(context);
|
FingerprintSafetySource.onBiometricsChanged(context);
|
||||||
|
WearSafetySource.onBiometricsChanged(context);
|
||||||
} else {
|
} else {
|
||||||
BiometricsSafetySource.onBiometricsChanged(context);
|
BiometricsSafetySource.onBiometricsChanged(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ public class SafetySourceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
if (sourceIds.contains(FingerprintSafetySource.SAFETY_SOURCE_ID)) {
|
if (sourceIds.contains(FingerprintSafetySource.SAFETY_SOURCE_ID)) {
|
||||||
FingerprintSafetySource.setSafetySourceData(context, safetyEvent);
|
FingerprintSafetySource.setSafetySourceData(context, safetyEvent);
|
||||||
}
|
}
|
||||||
|
if (sourceIds.contains(WearSafetySource.SAFETY_SOURCE_ID)) {
|
||||||
|
WearSafetySource.setSafetySourceData(context, safetyEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void refreshAllSafetySources(Context context, SafetyEvent safetyEvent) {
|
private static void refreshAllSafetySources(Context context, SafetyEvent safetyEvent) {
|
||||||
@@ -95,5 +98,6 @@ public class SafetySourceBroadcastReceiver extends BroadcastReceiver {
|
|||||||
PrivateSpaceSafetySource.setSafetySourceData(context, safetyEvent);
|
PrivateSpaceSafetySource.setSafetySourceData(context, safetyEvent);
|
||||||
FaceSafetySource.setSafetySourceData(context, safetyEvent);
|
FaceSafetySource.setSafetySourceData(context, safetyEvent);
|
||||||
FingerprintSafetySource.setSafetySourceData(context, safetyEvent);
|
FingerprintSafetySource.setSafetySourceData(context, safetyEvent);
|
||||||
|
WearSafetySource.setSafetySourceData(context, safetyEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
147
src/com/android/settings/safetycenter/WearSafetySource.java
Normal file
147
src/com/android/settings/safetycenter/WearSafetySource.java
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* 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.safetycenter;
|
||||||
|
|
||||||
|
import static com.android.settings.biometrics.combination.BiometricsSettingsBase.ACTIVE_UNLOCK_REQUEST;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.safetycenter.SafetyEvent;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
|
||||||
|
import com.android.settings.flags.Flags;
|
||||||
|
|
||||||
|
/** Wear Safety Source for Safety Center. */
|
||||||
|
public final class WearSafetySource {
|
||||||
|
|
||||||
|
private static final String TAG = "WearSafetySource";
|
||||||
|
public static final String SAFETY_SOURCE_ID = "AndroidWearUnlock";
|
||||||
|
private static boolean sIsTestingEnv = false;
|
||||||
|
private static String sSummaryForTesting = "";
|
||||||
|
private static boolean sHasEnrolledForTesting;
|
||||||
|
|
||||||
|
private WearSafetySource() {}
|
||||||
|
|
||||||
|
/** Sets test value for summary. */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void setSummaryForTesting(@NonNull String summary) {
|
||||||
|
sIsTestingEnv = true;
|
||||||
|
sSummaryForTesting = summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets test value for hasEnrolled. */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static void setHasEnrolledForTesting(boolean hasEnrolled) {
|
||||||
|
sIsTestingEnv = true;
|
||||||
|
sHasEnrolledForTesting = hasEnrolled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets biometric safety data for Safety Center. */
|
||||||
|
public static void setSafetySourceData(
|
||||||
|
@NonNull Context context, @NonNull SafetyEvent safetyEvent) {
|
||||||
|
if (!SafetyCenterManagerWrapper.get().isEnabled(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Flags.biometricsOnboardingEducation()) { // this source is effectively turned off
|
||||||
|
sendNullData(context, safetyEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle private profile case.
|
||||||
|
UserManager userManager = UserManager.get(context);
|
||||||
|
if (android.os.Flags.allowPrivateProfile()
|
||||||
|
&& android.multiuser.Flags.enablePrivateSpaceFeatures()
|
||||||
|
&& userManager.isPrivateProfile()) {
|
||||||
|
// SC always expects a response from the source if the broadcast has been sent for this
|
||||||
|
// source, therefore, we need to send a null SafetySourceData.
|
||||||
|
sendNullData(context, safetyEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveUnlockStatusUtils activeUnlockStatusUtils = new ActiveUnlockStatusUtils(context);
|
||||||
|
if (!userManager.isProfile() && activeUnlockStatusUtils.isAvailable()) {
|
||||||
|
boolean hasEnrolled = false;
|
||||||
|
String summary = "";
|
||||||
|
|
||||||
|
if (sIsTestingEnv) {
|
||||||
|
hasEnrolled = sHasEnrolledForTesting;
|
||||||
|
summary = sSummaryForTesting;
|
||||||
|
} else {
|
||||||
|
String authority = new ActiveUnlockStatusUtils(context).getAuthority();
|
||||||
|
hasEnrolled = getHasEnrolledFromContentProvider(context, authority);
|
||||||
|
summary = getSummaryFromContentProvider(context, authority);
|
||||||
|
}
|
||||||
|
|
||||||
|
BiometricSourcesUtils.setBiometricSafetySourceData(
|
||||||
|
SAFETY_SOURCE_ID,
|
||||||
|
context,
|
||||||
|
activeUnlockStatusUtils.getTitleForActiveUnlockOnly(),
|
||||||
|
summary,
|
||||||
|
PendingIntent.getActivity(context, ACTIVE_UNLOCK_REQUEST,
|
||||||
|
activeUnlockStatusUtils.getIntent(),
|
||||||
|
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
|
/* enabled= */ true,
|
||||||
|
hasEnrolled,
|
||||||
|
safetyEvent);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendNullData(context, safetyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendNullData(Context context, SafetyEvent safetyEvent) {
|
||||||
|
SafetyCenterManagerWrapper.get()
|
||||||
|
.setSafetySourceData(
|
||||||
|
context, SAFETY_SOURCE_ID, /* safetySourceData= */ null, safetyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Notifies Safety Center of a change in wear biometrics settings. */
|
||||||
|
public static void onBiometricsChanged(@NonNull Context context) {
|
||||||
|
setSafetySourceData(
|
||||||
|
context,
|
||||||
|
new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean getHasEnrolledFromContentProvider(
|
||||||
|
@NonNull Context context, @Nullable String authority) {
|
||||||
|
if (authority == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ActiveUnlockStatusUtils.getDeviceNameFromContentProvider(context, authority, TAG)
|
||||||
|
!= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSummaryFromContentProvider(
|
||||||
|
@NonNull Context context, @Nullable String authority) {
|
||||||
|
if (authority == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String summary = ActiveUnlockStatusUtils.getSummaryFromContentProvider(
|
||||||
|
context, authority, TAG);
|
||||||
|
if (summary == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -91,10 +91,15 @@ private class AppInstallerInfoPresenter(
|
|||||||
}
|
}
|
||||||
}.sharedFlow()
|
}.sharedFlow()
|
||||||
|
|
||||||
val isAvailableFlow = installerLabelFlow.map { installerLabel ->
|
val isAvailableFlow = installerLabelFlow.map() { installerLabel ->
|
||||||
withContext(Dispatchers.IO) {
|
// Do not show the install info for the special case of the Play Store app.
|
||||||
!AppUtils.isMainlineModule(packageManager, app.packageName) &&
|
if (app.packageName == context.getString(R.string.config_mainline_module_update_package)) {
|
||||||
installerLabel != null
|
false
|
||||||
|
} else {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
val isMainlineModule = AppUtils.isMainlineModule(packageManager, app.packageName)
|
||||||
|
!isMainlineModule && installerLabel != null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static androidx.test.espresso.intent.Intents.intended;
|
|||||||
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
||||||
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
|
import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra;
|
||||||
|
|
||||||
|
import static com.android.settings.biometrics.BiometricEnrollActivity.EXTRA_LAUNCH_FACE_ENROLL_FIRST;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_BIOMETRICS;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FACE;
|
||||||
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
|
import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT;
|
||||||
@@ -39,6 +40,7 @@ import android.hardware.face.FaceManager;
|
|||||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
@@ -145,7 +147,7 @@ public class BiometricEnrollActivityTest {
|
|||||||
assumeTrue(mHasFace || mHasFingerprint);
|
assumeTrue(mHasFace || mHasFingerprint);
|
||||||
|
|
||||||
setPin();
|
setPin();
|
||||||
final Intent intent = getIntent(true /* useInternal */);
|
final Intent intent = getIntent(true /* useInternal */, null);
|
||||||
LockPatternChecker.verifyCredential(new LockPatternUtils(mContext),
|
LockPatternChecker.verifyCredential(new LockPatternUtils(mContext),
|
||||||
LockscreenCredential.createPin(TEST_PIN), UserHandle.myUserId(),
|
LockscreenCredential.createPin(TEST_PIN), UserHandle.myUserId(),
|
||||||
LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, (response, timeoutMs) -> {
|
LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, (response, timeoutMs) -> {
|
||||||
@@ -162,6 +164,26 @@ public class BiometricEnrollActivityTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void launchWithPinAndPwHandle_confirmsPin_firstEnrollmentIsFace() throws Exception {
|
||||||
|
assumeTrue(mHasFace && mHasFingerprint);
|
||||||
|
|
||||||
|
setPin();
|
||||||
|
final Intent intent = getFaceEnrollFirstIntent();
|
||||||
|
LockPatternChecker.verifyCredential(new LockPatternUtils(mContext),
|
||||||
|
LockscreenCredential.createPin(TEST_PIN), UserHandle.myUserId(),
|
||||||
|
LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, (response, timeoutMs) -> {
|
||||||
|
assertThat(response.containsGatekeeperPasswordHandle()).isTrue();
|
||||||
|
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
|
||||||
|
response.getGatekeeperPasswordHandle());
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
try (ActivityScenario<BiometricEnrollActivity> scenario =
|
||||||
|
ActivityScenario.launch(intent)) {
|
||||||
|
intended(hasComponent(FaceEnroll.class.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void launchWithStrongBiometricAllowed_doNotEnrollWeak() throws Exception {
|
public void launchWithStrongBiometricAllowed_doNotEnrollWeak() throws Exception {
|
||||||
assumeTrue(mHasFace || mHasFingerprint);
|
assumeTrue(mHasFace || mHasFingerprint);
|
||||||
@@ -184,13 +206,22 @@ public class BiometricEnrollActivityTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Intent getIntent() {
|
private Intent getIntent() {
|
||||||
return getIntent(false /* useInternal */);
|
return getIntent(false /* useInternal */, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Intent getIntent(boolean useInternal) {
|
private Intent getFaceEnrollFirstIntent() {
|
||||||
|
final Bundle bundle = new Bundle();
|
||||||
|
bundle.putBoolean(EXTRA_LAUNCH_FACE_ENROLL_FIRST, true);
|
||||||
|
return getIntent(true /* useInternal */, bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent getIntent(boolean useInternal, Bundle bundle) {
|
||||||
final Intent intent = new Intent(mContext, useInternal
|
final Intent intent = new Intent(mContext, useInternal
|
||||||
? BiometricEnrollActivity.InternalActivity.class : BiometricEnrollActivity.class);
|
? BiometricEnrollActivity.InternalActivity.class : BiometricEnrollActivity.class);
|
||||||
intent.setAction(ACTION_BIOMETRIC_ENROLL);
|
intent.setAction(ACTION_BIOMETRIC_ENROLL);
|
||||||
|
if (bundle != null && !bundle.isEmpty()) {
|
||||||
|
intent.putExtras(bundle);
|
||||||
|
}
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -458,12 +457,10 @@ public class AccessibilitySettingsTest {
|
|||||||
setupFragment();
|
setupFragment();
|
||||||
mFragment.setFeedbackManager(
|
mFragment.setFeedbackManager(
|
||||||
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
||||||
when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
|
|
||||||
|
|
||||||
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
||||||
|
|
||||||
verify(mMenu).add(anyInt(), eq(AccessibilitySettings.MENU_ID_SEND_FEEDBACK),
|
verify(mMenu).add(anyInt(), anyInt(), anyInt(), anyInt());
|
||||||
anyInt(), eq(mContext.getText(R.string.accessibility_send_feedback_title)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -472,12 +469,10 @@ public class AccessibilitySettingsTest {
|
|||||||
setupFragment();
|
setupFragment();
|
||||||
mFragment.setFeedbackManager(
|
mFragment.setFeedbackManager(
|
||||||
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
||||||
when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
|
|
||||||
|
|
||||||
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
||||||
|
|
||||||
verify(mMenu, never()).add(anyInt(), eq(AccessibilitySettings.MENU_ID_SEND_FEEDBACK),
|
verify(mMenu, never()).add(anyInt(), anyInt(), anyInt(), anyInt());
|
||||||
anyInt(), eq(mContext.getText(R.string.accessibility_send_feedback_title)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -486,8 +481,6 @@ public class AccessibilitySettingsTest {
|
|||||||
setupFragment();
|
setupFragment();
|
||||||
mFragment.setFeedbackManager(
|
mFragment.setFeedbackManager(
|
||||||
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
||||||
when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
|
|
||||||
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
|
||||||
when(mMenuItem.getItemId()).thenReturn(AccessibilitySettings.MENU_ID_SEND_FEEDBACK);
|
when(mMenuItem.getItemId()).thenReturn(AccessibilitySettings.MENU_ID_SEND_FEEDBACK);
|
||||||
|
|
||||||
mFragment.onOptionsItemSelected(mMenuItem);
|
mFragment.onOptionsItemSelected(mMenuItem);
|
||||||
@@ -502,8 +495,6 @@ public class AccessibilitySettingsTest {
|
|||||||
setupFragment();
|
setupFragment();
|
||||||
mFragment.setFeedbackManager(
|
mFragment.setFeedbackManager(
|
||||||
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
new FeedbackManager(mFragment.getActivity(), PACKAGE_NAME, DEFAULT_CATEGORY));
|
||||||
when(mMenu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mMenuItem);
|
|
||||||
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
|
||||||
when(mMenuItem.getItemId()).thenReturn(AccessibilitySettings.MENU_ID_SEND_FEEDBACK);
|
when(mMenuItem.getItemId()).thenReturn(AccessibilitySettings.MENU_ID_SEND_FEEDBACK);
|
||||||
|
|
||||||
mFragment.onOptionsItemSelected(mMenuItem);
|
mFragment.onOptionsItemSelected(mMenuItem);
|
||||||
|
|||||||
@@ -23,9 +23,12 @@ import static com.android.internal.accessibility.common.ShortcutConstants.UserSh
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.argThat;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -37,10 +40,13 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.icu.text.CaseMap;
|
import android.icu.text.CaseMap;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.platform.test.annotations.DisableFlags;
|
||||||
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.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
@@ -66,8 +72,9 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Answers;
|
import org.mockito.Answers;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
|
||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.shadow.api.Shadow;
|
import org.robolectric.shadow.api.Shadow;
|
||||||
@@ -83,6 +90,8 @@ import java.util.Locale;
|
|||||||
ShadowAccessibilityManager.class
|
ShadowAccessibilityManager.class
|
||||||
})
|
})
|
||||||
public class ToggleFeaturePreferenceFragmentTest {
|
public class ToggleFeaturePreferenceFragmentTest {
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mocks = MockitoJUnit.rule();
|
||||||
@Rule
|
@Rule
|
||||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||||
|
|
||||||
@@ -96,6 +105,7 @@ public class ToggleFeaturePreferenceFragmentTest {
|
|||||||
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
|
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
|
||||||
private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
|
private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
|
||||||
PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
|
PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
|
||||||
|
private static final String PLACEHOLDER_CATEGORY = "category";
|
||||||
private static final String PLACEHOLDER_DIALOG_TITLE = "title";
|
private static final String PLACEHOLDER_DIALOG_TITLE = "title";
|
||||||
private static final String DEFAULT_SUMMARY = "default summary";
|
private static final String DEFAULT_SUMMARY = "default summary";
|
||||||
private static final String DEFAULT_DESCRIPTION = "default description";
|
private static final String DEFAULT_DESCRIPTION = "default description";
|
||||||
@@ -120,10 +130,13 @@ public class ToggleFeaturePreferenceFragmentTest {
|
|||||||
private ContentResolver mContentResolver;
|
private ContentResolver mContentResolver;
|
||||||
@Mock
|
@Mock
|
||||||
private PackageManager mPackageManager;
|
private PackageManager mPackageManager;
|
||||||
|
@Mock
|
||||||
|
private Menu mMenu;
|
||||||
|
@Mock
|
||||||
|
private MenuItem mMenuItem;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUpTestFragment() {
|
public void setUpTestFragment() {
|
||||||
MockitoAnnotations.initMocks(this);
|
|
||||||
mShadowAccessibilityManager = Shadow.extract(
|
mShadowAccessibilityManager = Shadow.extract(
|
||||||
mContext.getSystemService(AccessibilityManager.class));
|
mContext.getSystemService(AccessibilityManager.class));
|
||||||
|
|
||||||
@@ -169,6 +182,61 @@ public class ToggleFeaturePreferenceFragmentTest {
|
|||||||
any(AccessibilitySettingsContentObserver.class));
|
any(AccessibilitySettingsContentObserver.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
|
||||||
|
public void onCreateOptionsMenu_enableLowVisionGenericFeedback_shouldAddSendFeedbackMenu() {
|
||||||
|
mFragment.setFeedbackManager(
|
||||||
|
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
|
||||||
|
|
||||||
|
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
||||||
|
|
||||||
|
verify(mMenu).add(anyInt(), eq(ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK),
|
||||||
|
anyInt(), eq(R.string.accessibility_send_feedback_title));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
|
||||||
|
public void onCreateOptionsMenu_disableLowVisionGenericFeedback_shouldNotAddSendFeedbackMenu() {
|
||||||
|
mFragment.setFeedbackManager(
|
||||||
|
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
|
||||||
|
|
||||||
|
mFragment.onCreateOptionsMenu(mMenu, /* inflater= */ null);
|
||||||
|
|
||||||
|
verify(mMenu, never()).add(anyInt(),
|
||||||
|
eq(ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK), anyInt(),
|
||||||
|
eq(R.string.accessibility_send_feedback_title));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
|
||||||
|
public void onOptionsItemSelected_enableLowVisionGenericFeedback_shouldStartSendFeedback() {
|
||||||
|
mFragment.setFeedbackManager(
|
||||||
|
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
|
||||||
|
when(mMenuItem.getItemId()).thenReturn(
|
||||||
|
ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK);
|
||||||
|
|
||||||
|
mFragment.onOptionsItemSelected(mMenuItem);
|
||||||
|
|
||||||
|
verify(mActivity).startActivityForResult(
|
||||||
|
argThat(intent -> intent != null
|
||||||
|
&& Intent.ACTION_BUG_REPORT.equals(intent.getAction())), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_LOW_VISION_GENERIC_FEEDBACK)
|
||||||
|
public void onOptionsItemSelected_disableLowVisionGenericFeedback_shouldNotStartSendFeedback() {
|
||||||
|
mFragment.setFeedbackManager(
|
||||||
|
new FeedbackManager(mActivity, PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CATEGORY));
|
||||||
|
when(mMenuItem.getItemId()).thenReturn(
|
||||||
|
ToggleFeaturePreferenceFragment.MENU_ID_SEND_FEEDBACK);
|
||||||
|
|
||||||
|
mFragment.onOptionsItemSelected(mMenuItem);
|
||||||
|
|
||||||
|
verify(mActivity, never()).startActivityForResult(
|
||||||
|
argThat(intent -> intent != null
|
||||||
|
&& Intent.ACTION_BUG_REPORT.equals(intent.getAction())), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void updateShortcutPreferenceData_assignDefaultValueToVariable() {
|
public void updateShortcutPreferenceData_assignDefaultValueToVariable() {
|
||||||
mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
|
mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ public class ExternalSourcesDetailsTest {
|
|||||||
|
|
||||||
@RequiresFlagsEnabled(android.security.Flags.FLAG_AAPM_FEATURE_DISABLE_INSTALL_UNKNOWN_SOURCES)
|
@RequiresFlagsEnabled(android.security.Flags.FLAG_AAPM_FEATURE_DISABLE_INSTALL_UNKNOWN_SOURCES)
|
||||||
@Test
|
@Test
|
||||||
public void getPreferenceSummary_restrictedGlobally_adminString() {
|
public void getPreferenceSummary_restrictedGloballyByAdmin_adminString() {
|
||||||
final EnforcingAdmin nonAdvancedProtectionEnforcingAdmin = new EnforcingAdmin("test.pkg",
|
final EnforcingAdmin nonAdvancedProtectionEnforcingAdmin = new EnforcingAdmin("test.pkg",
|
||||||
UnknownAuthority.UNKNOWN_AUTHORITY, mUserHandle, new ComponentName("", ""));
|
UnknownAuthority.UNKNOWN_AUTHORITY, mUserHandle, new ComponentName("", ""));
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ public class ExternalSourcesDetailsTest {
|
|||||||
|
|
||||||
@RequiresFlagsEnabled(Flags.FLAG_AAPM_FEATURE_DISABLE_INSTALL_UNKNOWN_SOURCES)
|
@RequiresFlagsEnabled(Flags.FLAG_AAPM_FEATURE_DISABLE_INSTALL_UNKNOWN_SOURCES)
|
||||||
@Test
|
@Test
|
||||||
public void getPreferenceSummary_restrictedGlobally_advancedProtectionString() {
|
public void getPreferenceSummary_restrictedGloballyByAdvancedProtection_disabledString() {
|
||||||
final EnforcingAdmin advancedProtectionEnforcingAdmin = new EnforcingAdmin("test.pkg",
|
final EnforcingAdmin advancedProtectionEnforcingAdmin = new EnforcingAdmin("test.pkg",
|
||||||
new UnknownAuthority(ADVANCED_PROTECTION_SYSTEM_ENTITY), mUserHandle,
|
new UnknownAuthority(ADVANCED_PROTECTION_SYSTEM_ENTITY), mUserHandle,
|
||||||
new ComponentName("", ""));
|
new ComponentName("", ""));
|
||||||
@@ -363,12 +363,10 @@ public class ExternalSourcesDetailsTest {
|
|||||||
advancedProtectionEnforcingAdmin);
|
advancedProtectionEnforcingAdmin);
|
||||||
when(mUserManager.hasUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
|
when(mUserManager.hasUserRestrictionForUser(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
|
||||||
mUserHandle)).thenReturn(true);
|
mUserHandle)).thenReturn(true);
|
||||||
when(mContext.getString(
|
when(mContext.getString(com.android.settingslib.R.string.disabled)).thenReturn("disabled");
|
||||||
com.android.settingslib.widget.restricted.R.string.disabled_by_advanced_protection))
|
|
||||||
.thenReturn("disabled_by_advanced_protection");
|
|
||||||
|
|
||||||
CharSequence summary = ExternalSourcesDetails.getPreferenceSummary(mContext, mAppEntry);
|
CharSequence summary = ExternalSourcesDetails.getPreferenceSummary(mContext, mAppEntry);
|
||||||
|
|
||||||
assertEquals("disabled_by_advanced_protection", summary.toString());
|
assertEquals("disabled", summary.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,4 +243,11 @@ public class ActiveUnlockStatusUtilsTest {
|
|||||||
.isEqualTo(mApplicationContext.getString(
|
.isEqualTo(mApplicationContext.getString(
|
||||||
R.string.biometric_settings_use_watch_for));
|
R.string.biometric_settings_use_watch_for));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getTitleForActiveUnlockOnly_returnsTile() {
|
||||||
|
assertThat(mActiveUnlockStatusUtils.getTitleForActiveUnlockOnly())
|
||||||
|
.isEqualTo(mApplicationContext.getString(
|
||||||
|
R.string.security_settings_activeunlock));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 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.inputmethod;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.hardware.input.InputSettings;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
/** Tests for {@link MousePointerSpeedPreferenceController} */
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
@Config(shadows = {
|
||||||
|
com.android.settings.testutils.shadow.ShadowSystemSettings.class,
|
||||||
|
})
|
||||||
|
public class MousePointerSpeedPreferenceControllerTest {
|
||||||
|
@Rule
|
||||||
|
public MockitoRule rule = MockitoJUnit.rule();
|
||||||
|
|
||||||
|
private static final String PREFERENCE_KEY = "pointer_speed";
|
||||||
|
private static final String SETTING_KEY = Settings.System.POINTER_SPEED;
|
||||||
|
|
||||||
|
private MousePointerSpeedPreferenceController mController;
|
||||||
|
private int mDefaultSpeed;
|
||||||
|
private FakeFeatureFactory mFeatureFactory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
|
mController = new MousePointerSpeedPreferenceController(context, PREFERENCE_KEY);
|
||||||
|
mDefaultSpeed = Settings.System.getIntForUser(
|
||||||
|
context.getContentResolver(),
|
||||||
|
SETTING_KEY,
|
||||||
|
InputSettings.DEFAULT_POINTER_SPEED,
|
||||||
|
UserHandle.USER_CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setSliderPosition_speedValue1_shouldReturnTrue() {
|
||||||
|
int inputSpeed = 1;
|
||||||
|
|
||||||
|
boolean result = mController.setSliderPosition(inputSpeed);
|
||||||
|
|
||||||
|
assertThat(result).isTrue();
|
||||||
|
assertThat(mController.getSliderPosition()).isEqualTo(inputSpeed);
|
||||||
|
verify(mFeatureFactory.metricsFeatureProvider).action(
|
||||||
|
any(),
|
||||||
|
eq(SettingsEnums.ACTION_GESTURE_POINTER_SPEED_CHANGED),
|
||||||
|
eq(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setSliderPosition_speedValueOverMaxValue_shouldReturnFalse() {
|
||||||
|
int inputSpeed = InputSettings.MAX_POINTER_SPEED + 1;
|
||||||
|
|
||||||
|
boolean result = mController.setSliderPosition(inputSpeed);
|
||||||
|
|
||||||
|
assertThat(result).isFalse();
|
||||||
|
assertThat(mController.getSliderPosition()).isEqualTo(mDefaultSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setSliderPosition_speedValueOverMinValue_shouldReturnFalse() {
|
||||||
|
int inputSpeed = InputSettings.MIN_POINTER_SPEED - 1;
|
||||||
|
|
||||||
|
boolean result = mController.setSliderPosition(inputSpeed);
|
||||||
|
|
||||||
|
assertThat(result).isFalse();
|
||||||
|
assertThat(mController.getSliderPosition()).isEqualTo(mDefaultSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,7 +36,6 @@ import android.app.Activity;
|
|||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.IActivityManager;
|
import android.app.IActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -100,6 +99,8 @@ public class LocaleListEditorTest {
|
|||||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
|
|
||||||
private static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
private static final String ARG_DIALOG_TYPE = "arg_dialog_type";
|
||||||
|
private static final String
|
||||||
|
ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED = "arg_show_dialog_for_not_translated";
|
||||||
private static final String TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT = "dialog_confirm_system_default";
|
private static final String TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT = "dialog_confirm_system_default";
|
||||||
private static final String TAG_DIALOG_NOT_AVAILABLE = "dialog_not_available_locale";
|
private static final String TAG_DIALOG_NOT_AVAILABLE = "dialog_not_available_locale";
|
||||||
private static final String TAG_DIALOG_ADD_SYSTEM_LOCALE = "dialog_add_system_locale";
|
private static final String TAG_DIALOG_ADD_SYSTEM_LOCALE = "dialog_add_system_locale";
|
||||||
@@ -123,6 +124,10 @@ public class LocaleListEditorTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private LocaleStore.LocaleInfo mLocaleInfo;
|
private LocaleStore.LocaleInfo mLocaleInfo;
|
||||||
@Mock
|
@Mock
|
||||||
|
private LocaleStore.LocaleInfo mLocaleInfo1;
|
||||||
|
@Mock
|
||||||
|
private LocaleStore.LocaleInfo mLocaleInfo2;
|
||||||
|
@Mock
|
||||||
private FragmentManager mFragmentManager;
|
private FragmentManager mFragmentManager;
|
||||||
@Mock
|
@Mock
|
||||||
private FragmentTransaction mFragmentTransaction;
|
private FragmentTransaction mFragmentTransaction;
|
||||||
@@ -270,7 +275,7 @@ public class LocaleListEditorTest {
|
|||||||
public void showConfirmDialog_systemLocaleSelected_shouldShowLocaleChangeDialog()
|
public void showConfirmDialog_systemLocaleSelected_shouldShowLocaleChangeDialog()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
//pre-condition
|
//pre-condition
|
||||||
setUpLocaleConditions();
|
setUpLocaleConditions(true);
|
||||||
final Configuration config = new Configuration();
|
final Configuration config = new Configuration();
|
||||||
config.setLocales((LocaleList.forLanguageTags("zh-TW,en-US")));
|
config.setLocales((LocaleList.forLanguageTags("zh-TW,en-US")));
|
||||||
when(mActivityService.getConfiguration()).thenReturn(config);
|
when(mActivityService.getConfiguration()).thenReturn(config);
|
||||||
@@ -299,6 +304,41 @@ public class LocaleListEditorTest {
|
|||||||
eq(TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT));
|
eq(TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void showConfirmDialog_2ndLocaleSelected_shouldShowLocaleChangeDialog()
|
||||||
|
throws Exception {
|
||||||
|
//pre-condition
|
||||||
|
Locale.setDefault(Locale.forLanguageTag("en-US"));
|
||||||
|
setUpLocaleConditions2();
|
||||||
|
final Configuration config = new Configuration();
|
||||||
|
config.setLocales((LocaleList.forLanguageTags("blo-BJ,en-US,zh-TW")));
|
||||||
|
when(mActivityService.getConfiguration()).thenReturn(config);
|
||||||
|
when(mAdapter.getFeedItemList()).thenReturn(mLocaleList);
|
||||||
|
when(mAdapter.getCheckedCount()).thenReturn(1);
|
||||||
|
when(mAdapter.getItemCount()).thenReturn(3);
|
||||||
|
when(mAdapter.isFirstLocaleChecked()).thenReturn(false);
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mRemoveMode", true);
|
||||||
|
ReflectionHelpers.setField(mLocaleListEditor, "mShowingRemoveDialog", true);
|
||||||
|
|
||||||
|
//launch the first dialog
|
||||||
|
mLocaleListEditor.showRemoveLocaleWarningDialog();
|
||||||
|
|
||||||
|
final Dialog dialog = ShadowDialog.getLatestDialog();
|
||||||
|
|
||||||
|
assertThat(dialog).isNotNull();
|
||||||
|
|
||||||
|
// click the remove button
|
||||||
|
dialog.findViewById(R.id.button_ok).performClick();
|
||||||
|
ShadowLooper.idleMainLooper();
|
||||||
|
|
||||||
|
assertThat(dialog.isShowing()).isFalse();
|
||||||
|
|
||||||
|
// check the second dialog is showing
|
||||||
|
verify(mFragmentTransaction).add(any(LocaleDialogFragment.class),
|
||||||
|
eq(TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void mayAppendUnicodeTags_appendUnicodeTags_success() {
|
public void mayAppendUnicodeTags_appendUnicodeTags_success() {
|
||||||
LocaleStore.LocaleInfo localeInfo = LocaleStore.fromLocale(Locale.forLanguageTag("en-US"));
|
LocaleStore.LocaleInfo localeInfo = LocaleStore.fromLocale(Locale.forLanguageTag("en-US"));
|
||||||
@@ -315,7 +355,8 @@ public class LocaleListEditorTest {
|
|||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putInt(ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
bundle.putInt(ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
||||||
mIntent.putExtras(bundle);
|
mIntent.putExtras(bundle);
|
||||||
setUpLocaleConditions();
|
mIntent.putExtra(ARG_SHOW_DIALOG_FOR_NOT_TRANSLATED, true);
|
||||||
|
setUpLocaleConditions(false);
|
||||||
mLocaleListEditor.onActivityResult(REQUEST_CONFIRM_SYSTEM_DEFAULT, Activity.RESULT_OK,
|
mLocaleListEditor.onActivityResult(REQUEST_CONFIRM_SYSTEM_DEFAULT, Activity.RESULT_OK,
|
||||||
mIntent);
|
mIntent);
|
||||||
|
|
||||||
@@ -328,7 +369,7 @@ public class LocaleListEditorTest {
|
|||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putInt(ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
bundle.putInt(ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
|
||||||
mIntent.putExtras(bundle);
|
mIntent.putExtras(bundle);
|
||||||
setUpLocaleConditions();
|
setUpLocaleConditions(true);
|
||||||
mLocaleListEditor.onActivityResult(REQUEST_CONFIRM_SYSTEM_DEFAULT, Activity.RESULT_CANCELED,
|
mLocaleListEditor.onActivityResult(REQUEST_CONFIRM_SYSTEM_DEFAULT, Activity.RESULT_CANCELED,
|
||||||
mIntent);
|
mIntent);
|
||||||
|
|
||||||
@@ -338,7 +379,7 @@ public class LocaleListEditorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void onTouch_dragDifferentLocaleToTop_showConfirmDialog() throws Exception {
|
public void onTouch_dragDifferentLocaleToTop_showConfirmDialog() throws Exception {
|
||||||
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0.0f, 0.0f, 0);
|
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0.0f, 0.0f, 0);
|
||||||
setUpLocaleConditions();
|
setUpLocaleConditions(true);
|
||||||
final Configuration config = new Configuration();
|
final Configuration config = new Configuration();
|
||||||
config.setLocales((LocaleList.forLanguageTags("zh-TW,en-US")));
|
config.setLocales((LocaleList.forLanguageTags("zh-TW,en-US")));
|
||||||
when(mActivityService.getConfiguration()).thenReturn(config);
|
when(mActivityService.getConfiguration()).thenReturn(config);
|
||||||
@@ -352,7 +393,7 @@ public class LocaleListEditorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void onTouch_dragSameLocaleToTop_updateAdapter() throws Exception {
|
public void onTouch_dragSameLocaleToTop_updateAdapter() throws Exception {
|
||||||
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0.0f, 0.0f, 0);
|
MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0.0f, 0.0f, 0);
|
||||||
setUpLocaleConditions();
|
setUpLocaleConditions(true);
|
||||||
final Configuration config = new Configuration();
|
final Configuration config = new Configuration();
|
||||||
config.setLocales((LocaleList.forLanguageTags("en-US,zh-TW")));
|
config.setLocales((LocaleList.forLanguageTags("en-US,zh-TW")));
|
||||||
when(mActivityService.getConfiguration()).thenReturn(config);
|
when(mActivityService.getConfiguration()).thenReturn(config);
|
||||||
@@ -490,12 +531,26 @@ public class LocaleListEditorTest {
|
|||||||
verify(mAdapter).setCheckBoxDescription(any(LocaleDragCell.class), any(), anyBoolean());
|
verify(mAdapter).setCheckBoxDescription(any(LocaleDragCell.class), any(), anyBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpLocaleConditions() {
|
private void setUpLocaleConditions(boolean isTranslated) {
|
||||||
ShadowActivityManager.setService(mActivityService);
|
ShadowActivityManager.setService(mActivityService);
|
||||||
mLocaleList = new ArrayList<>();
|
mLocaleList = new ArrayList<>();
|
||||||
mLocaleList.add(mLocaleInfo);
|
mLocaleList.add(mLocaleInfo);
|
||||||
when(mLocaleInfo.getFullNameNative()).thenReturn("English");
|
when(mLocaleInfo.getFullNameNative()).thenReturn("English");
|
||||||
when(mLocaleInfo.getLocale()).thenReturn(LocaleList.forLanguageTags("en-US").get(0));
|
when(mLocaleInfo.getLocale()).thenReturn(LocaleList.forLanguageTags("en-US").get(0));
|
||||||
|
when(mLocaleInfo.isTranslated()).thenReturn(isTranslated);
|
||||||
|
when(mAdapter.getFeedItemList()).thenReturn(mLocaleList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpLocaleConditions2() {
|
||||||
|
ShadowActivityManager.setService(mActivityService);
|
||||||
|
mLocaleList = new ArrayList<>();
|
||||||
|
mLocaleList.add(mLocaleInfo);
|
||||||
|
mLocaleList.add(mLocaleInfo1);
|
||||||
|
mLocaleList.add(mLocaleInfo2);
|
||||||
|
when(mLocaleInfo.getLocale()).thenReturn(Locale.forLanguageTag("blo-BJ"));
|
||||||
|
when(mLocaleInfo.isTranslated()).thenReturn(false);
|
||||||
|
when(mLocaleInfo2.getLocale()).thenReturn(Locale.forLanguageTag("zh-TW"));
|
||||||
|
when(mLocaleInfo2.isTranslated()).thenReturn(true);
|
||||||
when(mAdapter.getFeedItemList()).thenReturn(mLocaleList);
|
when(mAdapter.getFeedItemList()).thenReturn(mLocaleList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider;
|
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider;
|
||||||
import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider;
|
import com.android.settings.accessibility.AccessibilityPageIdFeatureProvider;
|
||||||
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider;
|
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider;
|
||||||
import com.android.settings.accounts.AccountFeatureProvider;
|
import com.android.settings.accounts.AccountFeatureProvider;
|
||||||
import com.android.settings.applications.ApplicationFeatureProvider;
|
import com.android.settings.applications.ApplicationFeatureProvider;
|
||||||
@@ -94,7 +94,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
public WifiTrackerLibProvider wifiTrackerLibProvider;
|
public WifiTrackerLibProvider wifiTrackerLibProvider;
|
||||||
public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
|
public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
|
||||||
public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
|
public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
|
||||||
public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider;
|
public AccessibilityPageIdFeatureProvider mAccessibilityPageIdFeatureProvider;
|
||||||
public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
|
public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
|
||||||
public WifiFeatureProvider mWifiFeatureProvider;
|
public WifiFeatureProvider mWifiFeatureProvider;
|
||||||
public KeyboardSettingsFeatureProvider mKeyboardSettingsFeatureProvider;
|
public KeyboardSettingsFeatureProvider mKeyboardSettingsFeatureProvider;
|
||||||
@@ -145,7 +145,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
|
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
|
||||||
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
|
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
|
||||||
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
|
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
|
||||||
mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class);
|
mAccessibilityPageIdFeatureProvider = mock(AccessibilityPageIdFeatureProvider.class);
|
||||||
mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
|
mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
|
||||||
mWifiFeatureProvider = mock(WifiFeatureProvider.class);
|
mWifiFeatureProvider = mock(WifiFeatureProvider.class);
|
||||||
mKeyboardSettingsFeatureProvider = mock(KeyboardSettingsFeatureProvider.class);
|
mKeyboardSettingsFeatureProvider = mock(KeyboardSettingsFeatureProvider.class);
|
||||||
@@ -294,8 +294,8 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() {
|
public AccessibilityPageIdFeatureProvider getAccessibilityPageIdFeatureProvider() {
|
||||||
return mAccessibilityMetricsFeatureProvider;
|
return mAccessibilityPageIdFeatureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -121,6 +121,25 @@ class AppInstallerInfoPreferenceTest {
|
|||||||
composeTestRule.onRoot().assertIsNotDisplayed()
|
composeTestRule.onRoot().assertIsNotDisplayed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenIsPlayStoreApp_notDisplayed() {
|
||||||
|
val playStorePackageName = "com.android.vending"
|
||||||
|
whenever(
|
||||||
|
AppStoreUtil.getInstallerPackageNameAndInstallSourceInfo(
|
||||||
|
any(),
|
||||||
|
eq(playStorePackageName)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.thenReturn(Pair(INSTALLER_PACKAGE_NAME, INSTALL_SOURCE_INFO))
|
||||||
|
val playStoreApp = ApplicationInfo().apply {
|
||||||
|
packageName = playStorePackageName
|
||||||
|
uid = UID
|
||||||
|
}
|
||||||
|
setContent(playStoreApp)
|
||||||
|
|
||||||
|
composeTestRule.onRoot().assertIsNotDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun whenStoreLinkIsNull_disabled() {
|
fun whenStoreLinkIsNull_disabled() {
|
||||||
whenever(AppStoreUtil.getAppStoreLink(context, INSTALLER_PACKAGE_NAME, PACKAGE_NAME))
|
whenever(AppStoreUtil.getAppStoreLink(context, INSTALLER_PACKAGE_NAME, PACKAGE_NAME))
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package com.android.settings.testutils
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider
|
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider
|
import com.android.settings.accessibility.AccessibilityPageIdFeatureProvider
|
||||||
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider
|
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider
|
||||||
import com.android.settings.accounts.AccountFeatureProvider
|
import com.android.settings.accounts.AccountFeatureProvider
|
||||||
import com.android.settings.applications.ApplicationFeatureProvider
|
import com.android.settings.applications.ApplicationFeatureProvider
|
||||||
@@ -130,7 +130,7 @@ class FakeFeatureFactory : FeatureFactory() {
|
|||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
override val accessibilitySearchFeatureProvider: AccessibilitySearchFeatureProvider
|
override val accessibilitySearchFeatureProvider: AccessibilitySearchFeatureProvider
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
override val accessibilityMetricsFeatureProvider: AccessibilityMetricsFeatureProvider
|
override val accessibilityPageIdFeatureProvider: AccessibilityPageIdFeatureProvider
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
override val advancedVpnFeatureProvider: AdvancedVpnFeatureProvider
|
override val advancedVpnFeatureProvider: AdvancedVpnFeatureProvider
|
||||||
get() = TODO("Not yet implemented")
|
get() = TODO("Not yet implemented")
|
||||||
|
|||||||
@@ -527,6 +527,9 @@ public class LockScreenSafetySourceTest {
|
|||||||
verify(mSafetyCenterManagerWrapper)
|
verify(mSafetyCenterManagerWrapper)
|
||||||
.setSafetySourceData(
|
.setSafetySourceData(
|
||||||
any(), eq(FingerprintSafetySource.SAFETY_SOURCE_ID), any(), any());
|
any(), eq(FingerprintSafetySource.SAFETY_SOURCE_ID), any(), any());
|
||||||
|
verify(mSafetyCenterManagerWrapper)
|
||||||
|
.setSafetySourceData(
|
||||||
|
any(), eq(WearSafetySource.SAFETY_SOURCE_ID), any(), any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -245,6 +245,25 @@ public class SafetySourceBroadcastReceiverTest {
|
|||||||
assertThat(captor.getValue()).isEqualTo(FaceSafetySource.SAFETY_SOURCE_ID);
|
assertThat(captor.getValue()).isEqualTo(FaceSafetySource.SAFETY_SOURCE_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onReceive_onRefresh_withWearUnlockSourceId_setsWearUnlockData() {
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
|
Intent intent =
|
||||||
|
new Intent()
|
||||||
|
.setAction(ACTION_REFRESH_SAFETY_SOURCES)
|
||||||
|
.putExtra(
|
||||||
|
EXTRA_REFRESH_SAFETY_SOURCE_IDS,
|
||||||
|
new String[] {WearSafetySource.SAFETY_SOURCE_ID})
|
||||||
|
.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, REFRESH_BROADCAST_ID);
|
||||||
|
|
||||||
|
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||||
|
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||||
|
verify(mSafetyCenterManagerWrapper, times(1))
|
||||||
|
.setSafetySourceData(any(), captor.capture(), any(), any());
|
||||||
|
|
||||||
|
assertThat(captor.getValue()).isEqualTo(WearSafetySource.SAFETY_SOURCE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onReceive_onRefresh_withFingerprintUnlockSourceId_setsFingerprintUnlockData() {
|
public void onReceive_onRefresh_withFingerprintUnlockSourceId_setsFingerprintUnlockData() {
|
||||||
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
@@ -332,7 +351,7 @@ public class SafetySourceBroadcastReceiverTest {
|
|||||||
|
|
||||||
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
new SafetySourceBroadcastReceiver().onReceive(mApplicationContext, intent);
|
||||||
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
|
||||||
verify(mSafetyCenterManagerWrapper, times(5))
|
verify(mSafetyCenterManagerWrapper, times(6))
|
||||||
.setSafetySourceData(any(), captor.capture(), any(), any());
|
.setSafetySourceData(any(), captor.capture(), any(), any());
|
||||||
List<String> safetySourceIdList = captor.getAllValues();
|
List<String> safetySourceIdList = captor.getAllValues();
|
||||||
|
|
||||||
@@ -353,6 +372,11 @@ public class SafetySourceBroadcastReceiverTest {
|
|||||||
.anyMatch(
|
.anyMatch(
|
||||||
id -> id.equals(FingerprintSafetySource.SAFETY_SOURCE_ID)))
|
id -> id.equals(FingerprintSafetySource.SAFETY_SOURCE_ID)))
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
assertThat(
|
||||||
|
safetySourceIdList.stream()
|
||||||
|
.anyMatch(
|
||||||
|
id -> id.equals(WearSafetySource.SAFETY_SOURCE_ID)))
|
||||||
|
.isTrue();
|
||||||
assertThat(
|
assertThat(
|
||||||
safetySourceIdList.stream()
|
safetySourceIdList.stream()
|
||||||
.anyMatch(
|
.anyMatch(
|
||||||
|
|||||||
@@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
* 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.safetycenter;
|
||||||
|
|
||||||
|
import static android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.any;
|
||||||
|
import static org.mockito.Mockito.anyInt;
|
||||||
|
import static org.mockito.Mockito.anyString;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ProviderInfo;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||||
|
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||||
|
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||||
|
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.safetycenter.SafetyEvent;
|
||||||
|
import android.safetycenter.SafetySourceData;
|
||||||
|
import android.safetycenter.SafetySourceStatus;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
|
import com.android.settings.biometrics.activeunlock.ActiveUnlockStatusUtils;
|
||||||
|
import com.android.settings.flags.Flags;
|
||||||
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
|
import com.android.settings.testutils.ResourcesUtils;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class WearSafetySourceTest {
|
||||||
|
|
||||||
|
private static final ComponentName COMPONENT_NAME = new ComponentName("package", "class");
|
||||||
|
private static final UserHandle USER_HANDLE = new UserHandle(UserHandle.myUserId());
|
||||||
|
private static final SafetyEvent EVENT_SOURCE_STATE_CHANGED =
|
||||||
|
new SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
|
||||||
|
public static final String TARGET = "com.active.unlock.target";
|
||||||
|
public static final String PROVIDER = "com.active.unlock.provider";
|
||||||
|
public static final String TARGET_SETTING = "active_unlock_target";
|
||||||
|
public static final String PROVIDER_SETTING = "active_unlock_provider";
|
||||||
|
public static final String SUMMARY = "Wear Summary";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||||
|
|
||||||
|
private Context mApplicationContext;
|
||||||
|
|
||||||
|
@Mock private PackageManager mPackageManager;
|
||||||
|
@Mock private DevicePolicyManager mDevicePolicyManager;
|
||||||
|
@Mock private FingerprintManager mFingerprintManager;
|
||||||
|
@Mock private LockPatternUtils mLockPatternUtils;
|
||||||
|
@Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mApplicationContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
|
when(mApplicationContext.getPackageManager()).thenReturn(mPackageManager);
|
||||||
|
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)).thenReturn(true);
|
||||||
|
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true);
|
||||||
|
when(mDevicePolicyManager.getProfileOwnerOrDeviceOwnerSupervisionComponent(USER_HANDLE))
|
||||||
|
.thenReturn(COMPONENT_NAME);
|
||||||
|
when(mApplicationContext.getSystemService(Context.FINGERPRINT_SERVICE))
|
||||||
|
.thenReturn(mFingerprintManager);
|
||||||
|
when(mApplicationContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
|
||||||
|
.thenReturn(mDevicePolicyManager);
|
||||||
|
FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
|
||||||
|
when(featureFactory.securityFeatureProvider.getLockPatternUtils(mApplicationContext))
|
||||||
|
.thenReturn(mLockPatternUtils);
|
||||||
|
doReturn(true).when(mLockPatternUtils).isSecure(anyInt());
|
||||||
|
SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
SafetyCenterManagerWrapper.sInstance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||||
|
public void setSafetyData_whenSafetyCenterIsDisabled_doesNotSetData() {
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(false);
|
||||||
|
|
||||||
|
WearSafetySource.setSafetySourceData(
|
||||||
|
mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
|
||||||
|
|
||||||
|
verify(mSafetyCenterManagerWrapper, never())
|
||||||
|
.setSafetySourceData(any(), any(), any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsDisabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||||
|
public void setSafetySourceData_whenSeparateBiometricsFlagOff_setsNullData() {
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
|
|
||||||
|
WearSafetySource.setSafetySourceData(
|
||||||
|
mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
|
||||||
|
|
||||||
|
verify(mSafetyCenterManagerWrapper)
|
||||||
|
.setSafetySourceData(
|
||||||
|
any(), eq(WearSafetySource.SAFETY_SOURCE_ID), eq(null), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||||
|
public void setSafetySourceData_whenSafetyCenterIsEnabled_activeUnlockDisabled_setsNullData() {
|
||||||
|
disableActiveUnlock(mApplicationContext);
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
|
|
||||||
|
WearSafetySource.setSafetySourceData(
|
||||||
|
mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
|
||||||
|
|
||||||
|
verify(mSafetyCenterManagerWrapper)
|
||||||
|
.setSafetySourceData(
|
||||||
|
any(), eq(WearSafetySource.SAFETY_SOURCE_ID), eq(null), any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||||
|
public void setSafetySourceData_setsDataWithCorrectSafetyEvent() {
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
|
|
||||||
|
WearSafetySource.setSafetySourceData(
|
||||||
|
mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
|
||||||
|
|
||||||
|
verify(mSafetyCenterManagerWrapper)
|
||||||
|
.setSafetySourceData(any(), any(), any(), eq(EVENT_SOURCE_STATE_CHANGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||||
|
public void setSafetySourceData_withWearEnabled_whenWearEnrolled_setsData() {
|
||||||
|
enableActiveUnlock(mApplicationContext);
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||||
|
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
|
||||||
|
|
||||||
|
WearSafetySource.setHasEnrolledForTesting(true);
|
||||||
|
WearSafetySource.setSummaryForTesting(SUMMARY);
|
||||||
|
|
||||||
|
WearSafetySource.setSafetySourceData(
|
||||||
|
mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
|
||||||
|
|
||||||
|
assertSafetySourceEnabledDataSet(
|
||||||
|
ResourcesUtils.getResourcesString(mApplicationContext,
|
||||||
|
"security_settings_activeunlock"),
|
||||||
|
SUMMARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_BIOMETRICS_ONBOARDING_EDUCATION)
|
||||||
|
public void setSafetySourceData_withWearEnabled_whenWearNotEnrolled_setsData() {
|
||||||
|
enableActiveUnlock(mApplicationContext);
|
||||||
|
when(mSafetyCenterManagerWrapper.isEnabled(mApplicationContext)).thenReturn(true);
|
||||||
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||||
|
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(false);
|
||||||
|
when(mDevicePolicyManager.getKeyguardDisabledFeatures(COMPONENT_NAME)).thenReturn(0);
|
||||||
|
|
||||||
|
WearSafetySource.setHasEnrolledForTesting(false);
|
||||||
|
WearSafetySource.setSummaryForTesting(SUMMARY);
|
||||||
|
|
||||||
|
WearSafetySource.setSafetySourceData(
|
||||||
|
mApplicationContext, EVENT_SOURCE_STATE_CHANGED);
|
||||||
|
|
||||||
|
assertSafetySourceDisabledDataSet(
|
||||||
|
ResourcesUtils.getResourcesString(mApplicationContext,
|
||||||
|
"security_settings_activeunlock"),
|
||||||
|
SUMMARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void disableActiveUnlock(Context context) {
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_REMOTE_AUTH,
|
||||||
|
ActiveUnlockStatusUtils.CONFIG_FLAG_NAME,
|
||||||
|
/* value= */ null,
|
||||||
|
/* makeDefault=*/ false);
|
||||||
|
Settings.Secure.putString(context.getContentResolver(), TARGET_SETTING, null);
|
||||||
|
Settings.Secure.putString(context.getContentResolver(), PROVIDER_SETTING, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void enableActiveUnlock(Context context) {
|
||||||
|
Settings.Secure.putString(
|
||||||
|
context.getContentResolver(), TARGET_SETTING, TARGET);
|
||||||
|
Settings.Secure.putString(
|
||||||
|
context.getContentResolver(), PROVIDER_SETTING, PROVIDER);
|
||||||
|
|
||||||
|
PackageManager packageManager = context.getPackageManager();
|
||||||
|
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||||
|
applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
|
||||||
|
|
||||||
|
ResolveInfo resolveInfo = new ResolveInfo();
|
||||||
|
resolveInfo.activityInfo = new ActivityInfo();
|
||||||
|
resolveInfo.activityInfo.applicationInfo = applicationInfo;
|
||||||
|
when(packageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
|
||||||
|
|
||||||
|
ProviderInfo providerInfo = new ProviderInfo();
|
||||||
|
providerInfo.authority = PROVIDER;
|
||||||
|
providerInfo.applicationInfo = applicationInfo;
|
||||||
|
when(packageManager.resolveContentProvider(anyString(), any())).thenReturn(providerInfo);
|
||||||
|
|
||||||
|
DeviceConfig.setProperty(
|
||||||
|
DeviceConfig.NAMESPACE_REMOTE_AUTH,
|
||||||
|
ActiveUnlockStatusUtils.CONFIG_FLAG_NAME,
|
||||||
|
"unlock_intent_layout",
|
||||||
|
false /* makeDefault */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSafetySourceDisabledDataSet(String expectedTitle, String expectedSummary) {
|
||||||
|
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
|
||||||
|
verify(mSafetyCenterManagerWrapper)
|
||||||
|
.setSafetySourceData(
|
||||||
|
any(),
|
||||||
|
eq(WearSafetySource.SAFETY_SOURCE_ID),
|
||||||
|
captor.capture(),
|
||||||
|
any());
|
||||||
|
SafetySourceData safetySourceData = captor.getValue();
|
||||||
|
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
|
||||||
|
|
||||||
|
assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle);
|
||||||
|
assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary);
|
||||||
|
assertThat(safetySourceStatus.isEnabled()).isTrue();
|
||||||
|
assertThat(safetySourceStatus.getSeverityLevel())
|
||||||
|
.isEqualTo(SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED);
|
||||||
|
|
||||||
|
Intent clickIntent = safetySourceStatus.getPendingIntent().getIntent();
|
||||||
|
assertThat(clickIntent).isNotNull();
|
||||||
|
assertThat(clickIntent.getAction()).isEqualTo(TARGET);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertSafetySourceEnabledDataSet(
|
||||||
|
String expectedTitle, String expectedSummary) {
|
||||||
|
ArgumentCaptor<SafetySourceData> captor = ArgumentCaptor.forClass(SafetySourceData.class);
|
||||||
|
verify(mSafetyCenterManagerWrapper)
|
||||||
|
.setSafetySourceData(
|
||||||
|
any(),
|
||||||
|
eq(WearSafetySource.SAFETY_SOURCE_ID),
|
||||||
|
captor.capture(),
|
||||||
|
any());
|
||||||
|
SafetySourceData safetySourceData = captor.getValue();
|
||||||
|
SafetySourceStatus safetySourceStatus = safetySourceData.getStatus();
|
||||||
|
|
||||||
|
assertThat(safetySourceStatus.getTitle().toString()).isEqualTo(expectedTitle);
|
||||||
|
assertThat(safetySourceStatus.getSummary().toString()).isEqualTo(expectedSummary);
|
||||||
|
assertThat(safetySourceStatus.isEnabled()).isTrue();
|
||||||
|
assertThat(safetySourceStatus.getSeverityLevel())
|
||||||
|
.isEqualTo(SafetySourceData.SEVERITY_LEVEL_INFORMATION);
|
||||||
|
Intent clickIntent = safetySourceStatus.getPendingIntent().getIntent();
|
||||||
|
assertThat(clickIntent).isNotNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider;
|
import com.android.settings.accessibility.AccessibilityFeedbackFeatureProvider;
|
||||||
import com.android.settings.accessibility.AccessibilityMetricsFeatureProvider;
|
import com.android.settings.accessibility.AccessibilityPageIdFeatureProvider;
|
||||||
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider;
|
import com.android.settings.accessibility.AccessibilitySearchFeatureProvider;
|
||||||
import com.android.settings.accounts.AccountFeatureProvider;
|
import com.android.settings.accounts.AccountFeatureProvider;
|
||||||
import com.android.settings.applications.ApplicationFeatureProvider;
|
import com.android.settings.applications.ApplicationFeatureProvider;
|
||||||
@@ -93,7 +93,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
public WifiTrackerLibProvider wifiTrackerLibProvider;
|
public WifiTrackerLibProvider wifiTrackerLibProvider;
|
||||||
public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
|
public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
|
||||||
public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
|
public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
|
||||||
public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider;
|
public AccessibilityPageIdFeatureProvider mAccessibilityPageIdFeatureProvider;
|
||||||
public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
|
public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
|
||||||
public WifiFeatureProvider mWifiFeatureProvider;
|
public WifiFeatureProvider mWifiFeatureProvider;
|
||||||
public KeyboardSettingsFeatureProvider mKeyboardSettingsFeatureProvider;
|
public KeyboardSettingsFeatureProvider mKeyboardSettingsFeatureProvider;
|
||||||
@@ -146,7 +146,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
|
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
|
||||||
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
|
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
|
||||||
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
|
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
|
||||||
mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class);
|
mAccessibilityPageIdFeatureProvider = mock(AccessibilityPageIdFeatureProvider.class);
|
||||||
mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
|
mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
|
||||||
mWifiFeatureProvider = mock(WifiFeatureProvider.class);
|
mWifiFeatureProvider = mock(WifiFeatureProvider.class);
|
||||||
mKeyboardSettingsFeatureProvider = mock(KeyboardSettingsFeatureProvider.class);
|
mKeyboardSettingsFeatureProvider = mock(KeyboardSettingsFeatureProvider.class);
|
||||||
@@ -295,8 +295,8 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() {
|
public AccessibilityPageIdFeatureProvider getAccessibilityPageIdFeatureProvider() {
|
||||||
return mAccessibilityMetricsFeatureProvider;
|
return mAccessibilityPageIdFeatureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user