Snap for 8492734 from 32f8460aac to tm-qpr1-release
Change-Id: I6fa078468c2f91d4874a2bdd7cbdf5227f5a3526
This commit is contained in:
@@ -3193,6 +3193,8 @@
|
||||
<string name="style_suggestion_summary">Try different styles, wallpapers, and more</string>
|
||||
<!-- Display settings screen, trigger for screen saver options [CHAR LIMIT=30] -->
|
||||
<string name="screensaver_settings_title">Screen saver</string>
|
||||
<!-- List of synonyms used in the settings search bar to find the “Screen saver”. [CHAR LIMIT=NONE] -->
|
||||
<string name="keywords_screensaver">screensaver</string>
|
||||
<!-- The title for the toggle which disables/enables screen savers [CHAR_LIMIT=30] -->
|
||||
<string name="screensaver_settings_toggle_title">Use screen saver</string>
|
||||
<!-- Display settings screen, summary fragment for screen saver options, activated when docked or asleep and charging [CHAR LIMIT=35] -->
|
||||
|
||||
@@ -144,7 +144,8 @@
|
||||
<Preference
|
||||
android:key="screensaver"
|
||||
android:title="@string/screensaver_settings_title"
|
||||
android:fragment="com.android.settings.dream.DreamSettings"/>
|
||||
android:fragment="com.android.settings.dream.DreamSettings"
|
||||
settings:keywords="@string/keywords_screensaver"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="camera_gesture"
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/screensaver_settings_title">
|
||||
android:key="screensaver_settings_screen"
|
||||
android:title="@string/screensaver_settings_title"
|
||||
settings:keywords="@string/keywords_screensaver">
|
||||
|
||||
<com.android.settingslib.widget.MainSwitchPreference
|
||||
android:key="dream_main_settings_switch"
|
||||
|
||||
@@ -163,7 +163,9 @@ public class AccessibilityDetailsSettingsFragment extends InstrumentedFragment {
|
||||
try {
|
||||
final int mode = mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
|
||||
uid, packageName);
|
||||
return mode != AppOpsManager.MODE_ERRORED && mode != AppOpsManager.MODE_IGNORED;
|
||||
final boolean ecmEnabled = getContext().getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
|
||||
return !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
|
||||
} catch (Exception e) {
|
||||
// Fallback in case if app ops is not available in testing.
|
||||
return true;
|
||||
|
||||
@@ -233,7 +233,9 @@ public class RestrictedPreferenceHelper {
|
||||
final int mode = mAppOps.noteOpNoThrow(
|
||||
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
|
||||
preference.getUid(), preference.getPackageName());
|
||||
appOpsAllowed = mode == AppOpsManager.MODE_ALLOWED;
|
||||
final boolean ecmEnabled = mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
|
||||
appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
|
||||
serviceAllowed = appOpsAllowed;
|
||||
} catch (Exception e) {
|
||||
// Allow service in case if app ops is not available in testing.
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
@@ -75,7 +76,12 @@ public class SimStatusDialogFragment extends InstrumentedDialogFragment {
|
||||
mRootView = LayoutInflater.from(builder.getContext())
|
||||
.inflate(R.layout.dialog_sim_status, null /* parent */);
|
||||
mController.initialize();
|
||||
return builder.setView(mRootView).create();
|
||||
|
||||
Dialog dlg = builder.setView(mRootView).create();
|
||||
dlg.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE);
|
||||
|
||||
return dlg;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +100,7 @@ public class SimStatusDialogFragment extends InstrumentedDialogFragment {
|
||||
/**
|
||||
* View ID(s) which is digit format (instead of decimal number) text.
|
||||
**/
|
||||
private static final int [] sViewIdsInDigitFormat = IntStream
|
||||
private static final int[] sViewIdsInDigitFormat = IntStream
|
||||
.of(SimStatusDialogController.ICCID_INFO_VALUE_ID,
|
||||
SimStatusDialogController.PHONE_NUMBER_VALUE_ID,
|
||||
SimStatusDialogController.EID_INFO_VALUE_ID)
|
||||
@@ -107,8 +113,7 @@ public class SimStatusDialogFragment extends InstrumentedDialogFragment {
|
||||
}
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
text = getResources().getString(R.string.device_info_default);
|
||||
}
|
||||
else if (Arrays.binarySearch(sViewIdsInDigitFormat, viewId) >= 0) {
|
||||
} else if (Arrays.binarySearch(sViewIdsInDigitFormat, viewId) >= 0) {
|
||||
text = PhoneNumberUtil.expandByTts(text);
|
||||
}
|
||||
textView.setText(text);
|
||||
|
||||
@@ -35,7 +35,6 @@ import android.provider.Settings;
|
||||
import android.service.rotationresolver.RotationResolverService;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import androidx.preference.Preference;
|
||||
@@ -82,10 +81,6 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
|
||||
context);
|
||||
}
|
||||
|
||||
public void init(Lifecycle lifecycle) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (!isRotationResolverServiceAvailable(mContext)) {
|
||||
|
||||
@@ -64,7 +64,6 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
use(SmartAutoRotateController.class).init(getLifecycle());
|
||||
DeviceStateAutoRotationHelper.initControllers(
|
||||
getLifecycle(),
|
||||
useAll(DeviceStateAutoRotateSettingController.class)
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.helper;
|
||||
|
||||
import androidx.annotation.AnyThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A {@link LifecycleCallbackAdapter} which support carrying a result from any threads back to UI
|
||||
* thread through {@link #postResult(T)}.
|
||||
*
|
||||
* A {@link Consumer<T>} would be invoked from UI thread for further processing on the result.
|
||||
*
|
||||
* Note: Result not in STARTED or RESUMED stage will be discarded silently.
|
||||
* This is to align with the criteria set within
|
||||
* {@link LifecycleCallbackAdapter#onStateChanged()}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public class LifecycleCallbackConverter<T> extends LifecycleCallbackAdapter {
|
||||
private static final String TAG = "LifecycleCallbackConverter";
|
||||
|
||||
private final Thread mUiThread;
|
||||
private final Consumer<T> mResultCallback;
|
||||
|
||||
/**
|
||||
* A record of number of active status change.
|
||||
* Even numbers (0, 2, 4, 6 ...) are inactive status.
|
||||
* Odd numbers (1, 3, 5, 7 ...) are active status.
|
||||
*/
|
||||
private final AtomicLong mNumberOfActiveStatusChange = new AtomicLong();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param lifecycle {@link Lifecycle} to monitor
|
||||
* @param resultCallback for further processing the result
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@UiThread
|
||||
public LifecycleCallbackConverter(
|
||||
@NonNull Lifecycle lifecycle, @NonNull Consumer<T> resultCallback) {
|
||||
super(lifecycle);
|
||||
mUiThread = Thread.currentThread();
|
||||
mResultCallback = resultCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a result (from any thread) back to UI thread.
|
||||
*
|
||||
* @param result the object ready to be passed back to {@link Consumer<T>}.
|
||||
*/
|
||||
@AnyThread
|
||||
@VisibleForTesting
|
||||
public void postResult(T result) {
|
||||
/**
|
||||
* Since mNumberOfActiveStatusChange only increase, it is a concept of sequence number.
|
||||
* Carry it when sending data in between different threads allow to verify if the data
|
||||
* has arrived on time. And drop the data when expired.
|
||||
*/
|
||||
long currentNumberOfChange = mNumberOfActiveStatusChange.get();
|
||||
if (Thread.currentThread() == mUiThread) {
|
||||
dispatchExtResult(currentNumberOfChange, result); // Dispatch directly
|
||||
} else {
|
||||
postResultToUiThread(currentNumberOfChange, result);
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
protected void postResultToUiThread(long numberOfStatusChange, T result) {
|
||||
ThreadUtils.postOnMainThread(() -> dispatchExtResult(numberOfStatusChange, result));
|
||||
}
|
||||
|
||||
@UiThread
|
||||
protected void dispatchExtResult(long numberOfStatusChange, T result) {
|
||||
/**
|
||||
* For a postResult() sending in between different threads, not only create a latency
|
||||
* but also enqueued into main UI thread for dispatch.
|
||||
*
|
||||
* To align behavior within {@link LifecycleCallbackAdapter#onStateChanged()},
|
||||
* some checking on both numberOfStatusChange and {@link Lifecycle} status are required.
|
||||
*/
|
||||
if (isActiveStatus(numberOfStatusChange)
|
||||
&& (numberOfStatusChange == mNumberOfActiveStatusChange.get())
|
||||
&& getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
|
||||
mResultCallback.accept(result);
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean isActiveStatus(long numberOfStatusChange) {
|
||||
return ((numberOfStatusChange & 1L) != 0L);
|
||||
}
|
||||
|
||||
/* Implementation of LifecycleCallbackAdapter */
|
||||
@UiThread
|
||||
public boolean isCallbackActive() {
|
||||
return isActiveStatus(mNumberOfActiveStatusChange.get());
|
||||
}
|
||||
|
||||
/* Implementation of LifecycleCallbackAdapter */
|
||||
@UiThread
|
||||
public void setCallbackActive(boolean updatedActiveStatus) {
|
||||
/**
|
||||
* Make sure only increase when active status got changed.
|
||||
* This is to implement the definition of mNumberOfActiveStatusChange.
|
||||
*/
|
||||
if (isCallbackActive() != updatedActiveStatus) {
|
||||
mNumberOfActiveStatusChange.getAndIncrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.network.helper;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.concurrent.Phaser;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LifecycleCallbackConverterTest implements LifecycleOwner {
|
||||
|
||||
private final LifecycleRegistry mRegistry = LifecycleRegistry.createUnsafe(this);
|
||||
|
||||
private Object mTestData;
|
||||
private TestConsumer mConsumer;
|
||||
private LifecycleCallbackConverter<Object> mConverter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mTestData = new Object();
|
||||
mConsumer = new TestConsumer();
|
||||
mConverter = new LifecycleCallbackConverter<Object>(getLifecycle(), mConsumer);
|
||||
}
|
||||
|
||||
public Lifecycle getLifecycle() {
|
||||
return mRegistry;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converter_dropResult_whenInActive() {
|
||||
mConverter.postResult(mTestData);
|
||||
|
||||
assertThat(mConsumer.getCallbackCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converter_callbackResult_whenActive() {
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
|
||||
|
||||
mConverter.postResult(mTestData);
|
||||
assertThat(mConsumer.getCallbackCount()).isEqualTo(1);
|
||||
assertThat(mConsumer.getData()).isEqualTo(mTestData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converter_dropResult_whenBackToInActive() {
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
|
||||
|
||||
mConverter.postResult(mTestData);
|
||||
assertThat(mConsumer.getCallbackCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void converter_passResultToUiThread_whenActive() {
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
|
||||
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
|
||||
|
||||
final Phaser phaser = new Phaser(1);
|
||||
Thread executionThread = new Thread(() -> {
|
||||
mConverter.postResult(phaser);
|
||||
});
|
||||
executionThread.start();
|
||||
phaser.awaitAdvance(0);
|
||||
|
||||
assertThat(mConsumer.getData()).isEqualTo(phaser);
|
||||
assertThat(mConsumer.getCallbackCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
public static class TestConsumer implements Consumer<Object> {
|
||||
long mNumberOfCallback;
|
||||
AtomicReference<Object> mLatestData;
|
||||
|
||||
public TestConsumer() {
|
||||
mLatestData = new AtomicReference<Object>();
|
||||
}
|
||||
|
||||
public void accept(Object data) {
|
||||
mLatestData.set(data);
|
||||
mNumberOfCallback ++;
|
||||
if ((data != null) && (data instanceof Phaser)) {
|
||||
((Phaser)data).arrive();
|
||||
}
|
||||
}
|
||||
|
||||
protected long getCallbackCount() {
|
||||
return mNumberOfCallback;
|
||||
}
|
||||
|
||||
protected Object getData() {
|
||||
return mLatestData.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user