Snap for 8638406 from 7a0d268d7a to udc-release

Change-Id: I9c3076252082d200288ccef0764ab62c6dcd10f2
This commit is contained in:
Android Build Coastguard Worker
2022-05-25 03:26:11 +00:00
17 changed files with 196 additions and 94 deletions

View File

@@ -38,7 +38,6 @@
android:id="@+id/size_spinner"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:entries="@array/bytes_picker_sizes" />
android:layout_gravity="center_vertical" />
</LinearLayout>

View File

@@ -18,7 +18,8 @@
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -11606,11 +11606,6 @@
<!-- Text for the setting on whether you can type text into notifications without unlocking the device. -->
<string name="lockscreen_remote_input">If device is locked, prevent typing replies or other text in notifications</string>
<string-array name="bytes_picker_sizes" translatable="false">
<item>@*android:string/megabyteShort</item>
<item>@*android:string/gigabyteShort</item>
</string-array>
<!-- [CHAR LIMIT=30] Label for setting to control the default spell checker -->
<string name="default_spell_checker">Default spell checker</string>

View File

@@ -27,7 +27,6 @@
<com.android.settings.widget.LabeledSeekBarPreference
android:key="font_size"
android:selectable="true"
android:summary="@string/short_summary_font_size"
android:title="@string/title_font_size"
settings:iconEnd="@drawable/ic_add_24dp"
@@ -38,7 +37,6 @@
<com.android.settings.widget.LabeledSeekBarPreference
android:key="display_size"
android:selectable="true"
android:summary="@string/screen_zoom_short_summary"
android:title="@string/screen_zoom_title"
settings:iconEnd="@drawable/ic_add_24dp"

View File

@@ -46,7 +46,6 @@
android:key="gesture_left_back_sensitivity"
android:title="@string/left_edge"
android:max="2"
android:selectable="true"
settings:textStart="@string/low_label"
settings:textEnd="@string/high_label"/>
@@ -54,7 +53,6 @@
android:key="gesture_right_back_sensitivity"
android:title="@string/right_edge"
android:max="2"
android:selectable="true"
settings:textStart="@string/low_label"
settings:textEnd="@string/high_label"/>
</PreferenceCategory>

View File

@@ -36,7 +36,6 @@
android:key="gesture_power_menu_long_press_for_assist_sensitivity"
android:title="@string/power_menu_long_press_for_assist_sensitivity_title"
android:summary="@string/power_menu_long_press_for_assist_sensitivity_summary"
android:selectable="true"
settings:textStart="@string/power_menu_long_press_for_assist_sensitivity_low_label"
settings:textEnd="@string/power_menu_long_press_for_assist_sensitivity_high_label"
settings:controller="com.android.settings.gestures.LongPressPowerSensitivityPreferenceController"

View File

@@ -185,9 +185,9 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
&& ActivityEmbeddingUtils.isEmbeddingActivityEnabled(mContext)) {
// Highlight the preference whenever it's clicked
final TopLevelSettings topLevelSettings = (TopLevelSettings) fragment;
topLevelSettings.setHighlightPreferenceKey(key);
highlightMixin = topLevelSettings.getHighlightMixin();
isDuplicateClick = topLevelSettings.isDuplicateClick(preference);
topLevelSettings.setHighlightPreferenceKey(key);
}
launchIntentOrSelectProfile(activity, tile, intent, sourceMetricsCategory,
highlightMixin, isDuplicateClick);

View File

@@ -22,6 +22,8 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.icu.text.MeasureFormat;
import android.icu.util.MeasureUnit;
import android.net.NetworkPolicy;
import android.net.NetworkTemplate;
import android.os.Bundle;
@@ -30,6 +32,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.Spinner;
@@ -301,6 +304,17 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements
: editor.getPolicyWarningBytes(template);
final long limitDisabled = isLimit ? LIMIT_DISABLED : WARNING_DISABLED;
final MeasureFormat formatter = MeasureFormat.getInstance(
getContext().getResources().getConfiguration().locale,
MeasureFormat.FormatWidth.SHORT);
final String[] unitNames = new String[] {
formatter.getUnitDisplayName(MeasureUnit.MEGABYTE),
formatter.getUnitDisplayName(MeasureUnit.GIGABYTE)
};
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getContext(), android.R.layout.simple_spinner_item, unitNames);
type.setAdapter(adapter);
final boolean unitInGigaBytes = (bytes > 1.5f * GIB_IN_BYTES);
final String bytesText = formatText(bytes,
unitInGigaBytes ? GIB_IN_BYTES : MIB_IN_BYTES);

View File

@@ -168,8 +168,8 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
if (subs.size() == 1) {
mPreference.setEnabled(false);
mPreference.setSummaryProvider(pref ->
SubscriptionUtil.getUniqueSubscriptionDisplayName(subs.get(0), mContext));
mPreference.setSummary(SubscriptionUtil.getUniqueSubscriptionDisplayName(
subs.get(0), mContext));
return;
}

View File

@@ -27,30 +27,43 @@ import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
import android.app.settings.SettingsEnums;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import com.android.settings.R;
import com.android.settings.bluetooth.Utils;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.media.MediaOutputConstants;
import java.util.ArrayList;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* Panel data class for Volume settings.
*/
public class VolumePanel implements PanelContent, LifecycleObserver {
private static final String TAG = "VolumePanel";
private final Context mContext;
private PanelContentCallback mCallback;
private LocalBluetoothProfileManager mProfileManager;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -67,6 +80,21 @@ public class VolumePanel implements PanelContent, LifecycleObserver {
private VolumePanel(Context context) {
mContext = context.getApplicationContext();
final FutureTask<LocalBluetoothManager> localBtManagerFutureTask = new FutureTask<>(
// Avoid StrictMode ThreadPolicy violation
() -> Utils.getLocalBtManager(mContext));
LocalBluetoothManager localBluetoothManager;
try {
localBtManagerFutureTask.run();
localBluetoothManager = localBtManagerFutureTask.get();
} catch (InterruptedException | ExecutionException e) {
Log.w(TAG, "Error getting LocalBluetoothManager.");
return;
}
if (localBluetoothManager != null) {
mProfileManager = localBluetoothManager.getProfileManager();
}
}
/** Invoked when the panel is resumed. */
@@ -95,6 +123,11 @@ public class VolumePanel implements PanelContent, LifecycleObserver {
uris.add(REMOTE_MEDIA_SLICE_URI);
uris.add(VOLUME_MEDIA_URI);
Uri controlUri = getExtraControlUri();
if (controlUri != null) {
Log.d(TAG, "add extra control slice");
uris.add(controlUri);
}
uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
uris.add(VOLUME_CALL_URI);
uris.add(VOLUME_RINGER_URI);
@@ -121,4 +154,33 @@ public class VolumePanel implements PanelContent, LifecycleObserver {
public void registerCallback(PanelContentCallback callback) {
mCallback = callback;
}
private Uri getExtraControlUri() {
Uri controlUri = null;
final BluetoothDevice bluetoothDevice = findActiveDevice();
if (bluetoothDevice != null) {
final int width = mContext.getResources().getDimensionPixelSize(
R.dimen.settings_panel_width);
final String uri = BluetoothUtils.getControlUriMetaData(bluetoothDevice);
if (!TextUtils.isEmpty(uri)) {
try {
controlUri = Uri.parse(String.format(uri, width));
} catch (IllegalFormatException | NullPointerException exception) {
Log.d(TAG, "unable to parse uri");
controlUri = null;
}
}
}
return controlUri;
}
private BluetoothDevice findActiveDevice() {
if (mProfileManager != null) {
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
if (a2dpProfile != null) {
return a2dpProfile.getActiveDevice();
}
}
return null;
}
}

View File

@@ -16,11 +16,20 @@
package com.android.settings.utils;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.icu.text.DecimalFormat;
import android.icu.text.MeasureFormat;
import android.icu.text.NumberFormat;
import android.icu.util.Measure;
import android.icu.util.MeasureUnit;
import android.text.BidiFormatter;
import android.text.format.Formatter;
import android.text.TextUtils;
import android.view.View;
import java.math.BigDecimal;
import java.util.Locale;
/**
* Utility class to aid in formatting file sizes always with the same unit. This is modified from
@@ -31,6 +40,61 @@ public final class FileSizeFormatter {
public static final long MEGABYTE_IN_BYTES = KILOBYTE_IN_BYTES * 1000;
public static final long GIGABYTE_IN_BYTES = MEGABYTE_IN_BYTES * 1000;
private static class RoundedBytesResult {
public final float value;
public final MeasureUnit units;
public final int fractionDigits;
public final long roundedBytes;
private RoundedBytesResult(
float value, MeasureUnit units, int fractionDigits, long roundedBytes) {
this.value = value;
this.units = units;
this.fractionDigits = fractionDigits;
this.roundedBytes = roundedBytes;
}
}
private static Locale localeFromContext(@NonNull Context context) {
return context.getResources().getConfiguration().locale;
}
private static String bidiWrap(@NonNull Context context, String source) {
final Locale locale = localeFromContext(context);
if (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL) {
return BidiFormatter.getInstance(true /* RTL*/).unicodeWrap(source);
} else {
return source;
}
}
private static NumberFormat getNumberFormatter(Locale locale, int fractionDigits) {
final NumberFormat numberFormatter = NumberFormat.getInstance(locale);
numberFormatter.setMinimumFractionDigits(fractionDigits);
numberFormatter.setMaximumFractionDigits(fractionDigits);
numberFormatter.setGroupingUsed(false);
if (numberFormatter instanceof DecimalFormat) {
// We do this only for DecimalFormat, since in the general NumberFormat case, calling
// setRoundingMode may throw an exception.
numberFormatter.setRoundingMode(BigDecimal.ROUND_HALF_UP);
}
return numberFormatter;
}
private static String formatMeasureShort(Locale locale, NumberFormat numberFormatter,
float value, MeasureUnit units) {
final MeasureFormat measureFormatter = MeasureFormat.getInstance(
locale, MeasureFormat.FormatWidth.SHORT, numberFormatter);
return measureFormatter.format(new Measure(value, units));
}
private static String formatRoundedBytesResult(
@NonNull Context context, @NonNull RoundedBytesResult input) {
final Locale locale = localeFromContext(context);
final NumberFormat numberFormatter = getNumberFormatter(locale, input.fractionDigits);
return formatMeasureShort(locale, numberFormatter, input.value, input.units);
}
/**
* Formats a content size to be in the form of bytes, kilobytes, megabytes, etc.
*
@@ -47,23 +111,17 @@ public final class FileSizeFormatter {
*
* @param context Context to use to load the localized units
* @param sizeBytes size value to be formatted, in bytes
* @param suffix String id for the unit suffix.
* @param mult Amount of bytes in the unit. * @return formatted string with the number
* @param unit The unit used for formatting.
* @param mult Amount of bytes in the unit.
* @return formatted string with the number
*/
public static String formatFileSize(
@Nullable Context context, long sizeBytes, int suffix, long mult) {
@Nullable Context context, long sizeBytes, MeasureUnit unit, long mult) {
if (context == null) {
return "";
}
final Formatter.BytesResult res =
formatBytes(context.getResources(), sizeBytes, suffix, mult);
return BidiFormatter.getInstance()
.unicodeWrap(context.getString(getFileSizeSuffix(context), res.value, res.units));
}
private static int getFileSizeSuffix(Context context) {
final Resources res = context.getResources();
return res.getIdentifier("fileSizeSuffix", "string", "android");
final RoundedBytesResult res = formatBytes(sizeBytes, unit, mult);
return bidiWrap(context, formatRoundedBytesResult(context, res));
}
/**
@@ -76,8 +134,8 @@ public final class FileSizeFormatter {
* @param suffix String id for the unit suffix.
* @param mult Amount of bytes in the unit.
*/
private static Formatter.BytesResult formatBytes(
Resources res, long sizeBytes, int suffix, long mult) {
private static RoundedBytesResult formatBytes(
long sizeBytes, MeasureUnit unit, long mult) {
final boolean isNegative = (sizeBytes < 0);
float result = isNegative ? -sizeBytes : sizeBytes;
result = result / mult;
@@ -85,32 +143,29 @@ public final class FileSizeFormatter {
// compute the rounded value. String.format("%f", 0.1) might not return "0.1" due to
// floating point errors.
final int roundFactor;
final String roundFormat;
final int roundDigits;
if (mult == 1) {
roundFactor = 1;
roundFormat = "%.0f";
roundDigits = 0;
} else if (result < 1) {
roundFactor = 100;
roundFormat = "%.2f";
roundDigits = 2;
} else if (result < 10) {
roundFactor = 10;
roundFormat = "%.1f";
roundDigits = 1;
} else { // 10 <= result < 100
roundFactor = 1;
roundFormat = "%.0f";
roundDigits = 0;
}
if (isNegative) {
result = -result;
}
final String roundedString = String.format(roundFormat, result);
// Note this might overflow if abs(result) >= Long.MAX_VALUE / 100, but that's like 80PB so
// it's okay (for now)...
final long roundedBytes = (((long) Math.round(result * roundFactor)) * mult / roundFactor);
final String units = res.getString(suffix);
return new Formatter.BytesResult(roundedString, units, roundedBytes);
return new RoundedBytesResult(result, unit, roundDigits, roundedBytes);
}
}

View File

@@ -26,12 +26,12 @@ import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.PreferenceViewHolder;
import com.android.internal.util.Preconditions;
import com.android.settings.R;
import com.android.settings.Utils;
/**
* A labeled {@link SeekBarPreference} with left and right text label, icon label, or both.
@@ -61,8 +61,6 @@ public class LabeledSeekBarPreference extends SeekBarPreference {
private final int mIconStartContentDescriptionId;
private final int mIconEndContentDescriptionId;
private OnPreferenceChangeListener mStopListener;
@Nullable
private CharSequence mSummary;
private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener;
public LabeledSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
@@ -97,8 +95,6 @@ public class LabeledSeekBarPreference extends SeekBarPreference {
Preconditions.checkArgument(!(mIconEndContentDescriptionId != 0 && mIconEndId == 0),
"The resource of the iconEnd attribute may be invalid or not set, "
+ "you should set the iconEnd attribute and have the valid resource.");
mSummary = styledAttrs.getText(R.styleable.Preference_android_summary);
styledAttrs.recycle();
}
@@ -112,6 +108,17 @@ public class LabeledSeekBarPreference extends SeekBarPreference {
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
boolean isSummaryVisible = false;
if (summaryView != null) {
isSummaryVisible = (summaryView.getVisibility() == View.VISIBLE);
}
final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
if (titleView != null && !isSelectable() && isEnabled() && isSummaryVisible) {
titleView.setTextColor(
Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary));
}
final TextView startText = (TextView) holder.findViewById(android.R.id.text1);
if (mTextStartId > 0) {
startText.setText(mTextStartId);
@@ -132,15 +139,6 @@ public class LabeledSeekBarPreference extends SeekBarPreference {
seekBar.setTickMark(tickMark);
}
final TextView summary = (TextView) holder.findViewById(android.R.id.summary);
if (mSummary != null) {
summary.setText(mSummary);
summary.setVisibility(View.VISIBLE);
} else {
summary.setText(null);
summary.setVisibility(View.GONE);
}
final ViewGroup iconStartFrame = (ViewGroup) holder.findViewById(R.id.icon_start_frame);
final ImageView iconStartView = (ImageView) holder.findViewById(R.id.icon_start);
updateIconStartIfNeeded(iconStartFrame, iconStartView, seekBar);
@@ -188,25 +186,6 @@ public class LabeledSeekBarPreference extends SeekBarPreference {
notifyChanged();
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(summary);
mSummary = summary;
notifyChanged();
}
@Override
public void setSummary(int summaryResId) {
super.setSummary(summaryResId);
mSummary = getContext().getText(summaryResId);
notifyChanged();
}
@Override
public CharSequence getSummary() {
return mSummary;
}
public void setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener seekBarChangeListener) {
mSeekBarChangeListener = seekBarChangeListener;
}

View File

@@ -82,12 +82,7 @@ public class SeekBarPreference extends RestrictedPreference
com.android.internal.R.layout.preference_widget_seekbar);
a.recycle();
a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.Preference, defStyleAttr, defStyleRes);
final boolean isSelectable = a.getBoolean(
com.android.settings.R.styleable.Preference_android_selectable, false);
setSelectable(isSelectable);
a.recycle();
setSelectable(false);
setLayoutResource(layoutResId);
}
@@ -174,11 +169,6 @@ public class SeekBarPreference extends RestrictedPreference
});
}
@Override
public CharSequence getSummary() {
return null;
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setProgress(restoreValue ? getPersistedInt(mProgress)

View File

@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
@@ -82,6 +83,10 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
ssidScannerButton.setOnClickListener(this);
mUIController = new WifiConfigController2(this, rootView, null, getMode());
// Resize the layout when keyboard opens.
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
return rootView;
}

View File

@@ -31,6 +31,7 @@ import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import androidx.annotation.VisibleForTesting;
@@ -124,6 +125,10 @@ public class ConfigureWifiEntryFragment extends InstrumentedFragment implements
actionBar.setDisplayShowHomeEnabled(false);
}
// Resize the layout when keyboard opens.
getActivity().getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
return rootView;
}

View File

@@ -18,9 +18,11 @@ package com.android.settings.utils;
import static com.android.settings.utils.FileSizeFormatter.GIGABYTE_IN_BYTES;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.icu.util.MeasureUnit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -46,7 +48,7 @@ public class FileSizeFormatterTest {
FileSizeFormatter.formatFileSize(
mContext,
0 /* size */,
com.android.internal.R.string.gigabyteShort,
MeasureUnit.GIGABYTE,
GIGABYTE_IN_BYTES))
.isEqualTo("0.00 GB");
}
@@ -57,7 +59,7 @@ public class FileSizeFormatterTest {
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * 11 /* size */,
com.android.internal.R.string.gigabyteShort,
MeasureUnit.GIGABYTE,
GIGABYTE_IN_BYTES))
.isEqualTo("0.01 GB");
}
@@ -68,7 +70,7 @@ public class FileSizeFormatterTest {
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * 155 /* size */,
com.android.internal.R.string.gigabyteShort,
MeasureUnit.GIGABYTE,
GIGABYTE_IN_BYTES))
.isEqualTo("0.16 GB");
}
@@ -79,7 +81,7 @@ public class FileSizeFormatterTest {
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * 1551 /* size */,
com.android.internal.R.string.gigabyteShort,
MeasureUnit.GIGABYTE,
GIGABYTE_IN_BYTES))
.isEqualTo("1.6 GB");
}
@@ -91,7 +93,7 @@ public class FileSizeFormatterTest {
FileSizeFormatter.formatFileSize(
mContext,
GIGABYTE_IN_BYTES * 15 + MEGABYTE_IN_BYTES * 50 /* size */,
com.android.internal.R.string.gigabyteShort,
MeasureUnit.GIGABYTE,
GIGABYTE_IN_BYTES))
.isEqualTo("15 GB");
}
@@ -102,7 +104,7 @@ public class FileSizeFormatterTest {
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * -155 /* size */,
com.android.internal.R.string.gigabyteShort,
MeasureUnit.GIGABYTE,
GIGABYTE_IN_BYTES))
.isEqualTo("-0.16 GB");
}

View File

@@ -7,14 +7,14 @@ $ atest -c <YourClassName>
// The following instructions show how to run the test suite using make + adb //
To build the tests you can use the following command at the root of your android source tree
$ make SettingsUnitTests
$ make -j SettingsUnitTests
The test apk then needs to be installed onto your test device. The apk's location will vary
depending on your device model and architecture. At the end of the make command's output, there
should be a line similar to the following:
"Copy: out/target/product/shamu/testcases/SettingsUnitTests/arm64/SettingsUnitTests.apk"
"Copy: ${ANDROID_PRODUCT_OUT}/testcases/SettingsUnitTests/arm64/SettingsUnitTests.apk"
Install via the following command:
$ adb install -r out/target/product/shamu/testcases/SettingsUnitTests/arm64/SettingsUnitTests.apk
$ adb install -r ${ANDROID_PRODUCT_OUT}/testcases/SettingsUnitTests/arm64/SettingsUnitTests.apk
To run all tests:
$ adb shell am instrument -w com.android.settings.tests.unit/androidx.test.runner.AndroidJUnitRunner