summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt1
-rw-r--r--core/java/android/view/WindowManager.java13
-rw-r--r--core/java/android/widget/Editor.java37
-rw-r--r--core/jni/AndroidRuntime.cpp32
-rw-r--r--core/res/AndroidManifest.xml9
-rw-r--r--packages/SystemUI/res/values/config.xml5
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozePauser.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeUi.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java162
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java71
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java36
-rw-r--r--services/core/java/com/android/server/wm/Session.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java45
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java42
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java4
34 files changed, 992 insertions, 229 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index ca5898670a40..9d116953992c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -120,6 +120,7 @@ package android {
field public static final java.lang.String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final java.lang.String HDMI_CEC = "android.permission.HDMI_CEC";
+ field public static final java.lang.String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
field public static final java.lang.String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS";
field public static final java.lang.String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER";
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3fd459958ed4..050aa4d66c14 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1403,15 +1403,14 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE = 0x00040000;
/**
- * Flag to indicate that this window is used as a task snapshot window. A task snapshot
- * window is a starting window that gets shown with a screenshot from the previous state
- * that is active until the app has drawn its first frame.
- *
- * <p>If this flag is set, SystemUI flags are ignored such that the real window behind can
- * set the SystemUI flags.
+ * Flag to indicate that any window added by an application process that is of type
+ * {@link #TYPE_TOAST} or that requires
+ * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
+ * this window is visible.
* @hide
*/
- public static final int PRIVATE_FLAG_TASK_SNAPSHOT = 0x00080000;
+ @RequiresPermission(android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
+ public static final int PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 0x00080000;
/**
* Flag to indicate that this window should be ignored when determining what parts of the
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 1f2e3d02144a..f21545fe8636 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3914,25 +3914,30 @@ public class Editor {
menu.removeItem(TextView.ID_ASSIST);
final TextClassification textClassification =
getSelectionActionModeHelper().getTextClassification();
- if (textClassification != null) {
- final Drawable icon = textClassification.getIcon();
- final CharSequence label = textClassification.getLabel();
- final OnClickListener onClickListener =
- textClassification.getOnClickListener();
- final Intent intent = textClassification.getIntent();
- if ((icon != null || !TextUtils.isEmpty(label))
- && (onClickListener != null || intent != null)) {
- menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
- .setIcon(icon)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- mMetricsLogger.write(
- new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST)
- .setType(MetricsEvent.TYPE_OPEN)
- .setSubtype(textClassification.getLogType()));
- }
+ if (canAssist()) {
+ menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST,
+ textClassification.getLabel())
+ .setIcon(textClassification.getIcon())
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ mMetricsLogger.write(
+ new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST)
+ .setType(MetricsEvent.TYPE_OPEN)
+ .setSubtype(textClassification.getLogType()));
}
}
+ private boolean canAssist() {
+ final TextClassification textClassification =
+ getSelectionActionModeHelper().getTextClassification();
+ return mTextView.isDeviceProvisioned()
+ && textClassification != null
+ && (textClassification.getIcon() != null
+ || !TextUtils.isEmpty(textClassification.getLabel()))
+ && (textClassification.getOnClickListener() != null
+ || (textClassification.getIntent() != null
+ && mTextView.getContext().canStartActivityForResult()));
+ }
+
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
getSelectionActionModeHelper().onSelectionAction();
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9d9828ead705..89e137b7c399 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -792,19 +792,27 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
"--compiler-filter=", "-Ximage-compiler-option");
}
- // Make sure there is a preloaded-classes file.
- if (!hasFile("/system/etc/preloaded-classes")) {
- ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
- strerror(errno));
- return -1;
- }
- addOption("-Ximage-compiler-option");
- addOption("--image-classes=/system/etc/preloaded-classes");
-
- // If there is a compiled-classes file, push it.
- if (hasFile("/system/etc/compiled-classes")) {
+ // If there is a boot profile, it takes precedence over the image and preloaded classes.
+ if (hasFile("/system/etc/boot-image.prof")) {
+ addOption("-Ximage-compiler-option");
+ addOption("--profile-file=/system/etc/boot-image.prof");
+ addOption("-Ximage-compiler-option");
+ addOption("--compiler-filter=speed-profile");
+ } else {
+ // Make sure there is a preloaded-classes file.
+ if (!hasFile("/system/etc/preloaded-classes")) {
+ ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
+ strerror(errno));
+ return -1;
+ }
addOption("-Ximage-compiler-option");
- addOption("--compiled-classes=/system/etc/compiled-classes");
+ addOption("--image-classes=/system/etc/preloaded-classes");
+
+ // If there is a compiled-classes file, push it.
+ if (hasFile("/system/etc/compiled-classes")) {
+ addOption("-Ximage-compiler-option");
+ addOption("--compiled-classes=/system/etc/compiled-classes");
+ }
}
property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index be7934ba3fe5..6fa91abf71a5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2394,6 +2394,15 @@
<permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to use
+ {@link android.view.WindowManager.LayoutsParams#PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS}
+ to hide non-system-overlay windows.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"
+ android:protectionLevel="signature|installer" />
+
<!-- @SystemApi Allows an application to manage (create, destroy,
Z-order) application tokens in the window manager.
<p>Not for use by third-party applications.
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c0068d3b2957..02a2e8fc5313 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -247,6 +247,11 @@
-->
<string name="doze_pickup_subtype_performs_proximity_check"></string>
+ <!-- Type of a sensor that provides a low-power estimate of the desired display
+ brightness, suitable to listen to while the device is asleep (e.g. during
+ always-on display) -->
+ <string name="doze_brightness_sensor_type" translatable="false"></string>
+
<!-- Doze: pulse parameter - how long does it take to fade in? -->
<integer name="doze_pulse_duration_in">900</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 8506734036dc..e92ed2f75d49 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -34,7 +34,6 @@ import android.view.accessibility.AccessibilityManager;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.analytics.DataCollector;
-import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.statusbar.StatusBarState;
import java.io.PrintWriter;
@@ -76,6 +75,7 @@ public class FalsingManager implements SensorEventListener {
private boolean mSessionActive = false;
private int mState = StatusBarState.SHADE;
private boolean mScreenOn;
+ private boolean mShowingAod;
private Runnable mPendingWtf;
protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@@ -122,7 +122,7 @@ public class FalsingManager implements SensorEventListener {
.append(" mState=").append(StatusBarState.toShortString(mState))
.toString()
);
- return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD);
+ return isEnabled() && mScreenOn && (mState == StatusBarState.KEYGUARD) && !mShowingAod;
}
private boolean sessionEntrypoint() {
@@ -144,6 +144,14 @@ public class FalsingManager implements SensorEventListener {
}
}
+ public void updateSessionActive() {
+ if (shouldSessionBeActive()) {
+ sessionEntrypoint();
+ } else {
+ sessionExitpoint(false /* force */);
+ }
+ }
+
private void onSessionStart() {
if (FalsingLog.ENABLED) {
FalsingLog.i("onSessionStart", "classifierEnabled=" + isClassiferEnabled());
@@ -249,6 +257,11 @@ public class FalsingManager implements SensorEventListener {
return mEnforceBouncer;
}
+ public void setShowingAod(boolean showingAod) {
+ mShowingAod = showingAod;
+ updateSessionActive();
+ }
+
public void setStatusBarState(int state) {
if (FalsingLog.ENABLED) {
FalsingLog.i("setStatusBarState", new StringBuilder()
@@ -257,11 +270,7 @@ public class FalsingManager implements SensorEventListener {
.toString());
}
mState = state;
- if (shouldSessionBeActive()) {
- sessionEntrypoint();
- } else {
- sessionExitpoint(false /* force */);
- }
+ updateSessionActive();
}
public void onScreenTurningOn() {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 1cc10c22082a..4804ac23f3af 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -19,11 +19,14 @@ package com.android.systemui.doze;
import android.app.AlarmManager;
import android.app.Application;
import android.content.Context;
+import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Handler;
import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
+import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.DelayedWakeLock;
import com.android.systemui.util.wakelock.WakeLock;
@@ -46,25 +49,38 @@ public class DozeFactory {
WakeLock wakeLock = new DelayedWakeLock(handler,
WakeLock.createPartial(context, "Doze"));
- DozeMachine machine = new DozeMachine(
- DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
- DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params), params),
- config,
- wakeLock);
+ DozeMachine.Service wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
+ DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params), params);
+ DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
machine.setParts(new DozeMachine.Part[]{
- createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
- machine),
+ new DozePauser(handler, machine, alarmManager),
+ new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
+ createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
+ handler, wakeLock, machine),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
+ createDozeScreenState(wrappedService),
+ createDozeScreenBrightness(context, wrappedService, sensorManager, handler),
});
return machine;
}
+ private DozeMachine.Part createDozeScreenState(DozeMachine.Service service) {
+ return new DozeScreenState(service);
+ }
+
+ private DozeMachine.Part createDozeScreenBrightness(Context context,
+ DozeMachine.Service service, SensorManager sensorManager, Handler handler) {
+ Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
+ context.getString(R.string.doze_brightness_sensor_type));
+ return new DozeScreenBrightness(context, service, sensorManager, sensor, handler);
+ }
+
private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
- DozeHost host, AmbientDisplayConfiguration config, DozeParameters params,
- Handler handler, WakeLock wakeLock, DozeMachine machine) {
+ DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
+ DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine) {
boolean allowPulseTriggers = true;
- return new DozeTriggers(context, machine, host, config, params,
+ return new DozeTriggers(context, machine, host, alarmManager, config, params,
sensorManager, handler, wakeLock, allowPulseTriggers);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
new file mode 100644
index 000000000000..00ca9a48386e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFalsingManagerAdapter.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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.systemui.doze;
+
+import com.android.systemui.classifier.FalsingManager;
+
+/**
+ * Notifies FalsingManager of whether or not AOD is showing.
+ */
+public class DozeFalsingManagerAdapter implements DozeMachine.Part {
+
+ private final FalsingManager mFalsingManager;
+
+ public DozeFalsingManagerAdapter(FalsingManager falsingManager) {
+ mFalsingManager = falsingManager;
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ mFalsingManager.setShowingAod(isAodMode(newState));
+ }
+
+ private boolean isAodMode(DozeMachine.State state) {
+ switch (state) {
+ case DOZE_AOD:
+ case DOZE_AOD_PAUSING:
+ case DOZE_AOD_PAUSED:
+ return true;
+ default:
+ return false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 5526e6ba3f45..0be4eda8a069 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -60,13 +60,16 @@ public class DozeMachine {
/** Doze is done. DozeService is finished. */
FINISH,
/** AOD, but the display is temporarily off. */
- DOZE_AOD_PAUSED;
+ DOZE_AOD_PAUSED,
+ /** AOD, prox is near, transitions to DOZE_AOD_PAUSED after a timeout. */
+ DOZE_AOD_PAUSING;
boolean canPulse() {
switch (this) {
case DOZE:
case DOZE_AOD:
case DOZE_AOD_PAUSED:
+ case DOZE_AOD_PAUSING:
return true;
default:
return false;
@@ -93,6 +96,7 @@ public class DozeMachine {
case DOZE_PULSING:
return Display.STATE_ON;
case DOZE_AOD:
+ case DOZE_AOD_PAUSING:
return Display.STATE_DOZE_SUSPEND;
default:
return Display.STATE_UNKNOWN;
@@ -222,7 +226,6 @@ public class DozeMachine {
updatePulseReason(newState, oldState, pulseReason);
performTransitionOnComponents(oldState, newState);
- updateScreenState(newState);
updateWakeLockState(newState);
resolveIntermediateState(newState);
@@ -284,7 +287,8 @@ public class DozeMachine {
if (mState == State.FINISH) {
return State.FINISH;
}
- if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD || mState == State.DOZE)
+ if ((mState == State.DOZE_AOD_PAUSED || mState == State.DOZE_AOD_PAUSING
+ || mState == State.DOZE_AOD || mState == State.DOZE)
&& requestedState == State.DOZE_PULSE_DONE) {
Log.i(TAG, "Dropping pulse done because current state is already done: " + mState);
return mState;
@@ -307,13 +311,6 @@ public class DozeMachine {
}
}
- private void updateScreenState(State newState) {
- int state = newState.screenState();
- if (state != Display.STATE_UNKNOWN) {
- mDozeService.setDozeScreenState(state);
- }
- }
-
private void resolveIntermediateState(State state) {
switch (state) {
case INITIALIZED:
@@ -360,5 +357,36 @@ public class DozeMachine {
/** Request waking up. */
void requestWakeUp();
+
+ /** Set screen brightness */
+ void setDozeScreenBrightness(int brightness);
+
+ class Delegate implements Service {
+ private final Service mDelegate;
+
+ public Delegate(Service delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public void finish() {
+ mDelegate.finish();
+ }
+
+ @Override
+ public void setDozeScreenState(int state) {
+ mDelegate.setDozeScreenState(state);
+ }
+
+ @Override
+ public void requestWakeUp() {
+ mDelegate.requestWakeUp();
+ }
+
+ @Override
+ public void setDozeScreenBrightness(int brightness) {
+ mDelegate.setDozeScreenBrightness(brightness);
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java b/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java
new file mode 100644
index 000000000000..a33b454c6430
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozePauser.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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.systemui.doze;
+
+import android.app.AlarmManager;
+import android.os.Handler;
+
+import com.android.systemui.util.AlarmTimeout;
+
+/**
+ * Moves the doze machine from the pausing to the paused state after a timeout.
+ */
+public class DozePauser implements DozeMachine.Part {
+ public static final String TAG = DozePauser.class.getSimpleName();
+ private static final long TIMEOUT = 10 * 1000;
+ private final AlarmTimeout mPauseTimeout;
+ private final DozeMachine mMachine;
+
+ public DozePauser(Handler handler, DozeMachine machine, AlarmManager alarmManager) {
+ mMachine = machine;
+ mPauseTimeout = new AlarmTimeout(alarmManager, this::onTimeout, TAG, handler);
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ switch (newState) {
+ case DOZE_AOD_PAUSING:
+ mPauseTimeout.schedule(TIMEOUT, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ break;
+ default:
+ mPauseTimeout.cancel();
+ break;
+ }
+ }
+
+ private void onTimeout() {
+ mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
new file mode 100644
index 000000000000..e461986da5e0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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.systemui.doze;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+
+/**
+ * Controls the screen brightness when dozing.
+ */
+public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListener {
+ private final Context mContext;
+ private final DozeMachine.Service mDozeService;
+ private final Handler mHandler;
+ private final SensorManager mSensorManager;
+ private final Sensor mLightSensor;
+ private boolean mRegistered;
+
+ public DozeScreenBrightness(Context context, DozeMachine.Service service,
+ SensorManager sensorManager, Sensor lightSensor, Handler handler) {
+ mContext = context;
+ mDozeService = service;
+ mSensorManager = sensorManager;
+ mLightSensor = lightSensor;
+ mHandler = handler;
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ switch (newState) {
+ case INITIALIZED:
+ resetBrightnessToDefault();
+ break;
+ case DOZE_AOD:
+ case DOZE_REQUEST_PULSE:
+ setLightSensorEnabled(true);
+ break;
+ case DOZE:
+ case DOZE_AOD_PAUSED:
+ setLightSensorEnabled(false);
+ resetBrightnessToDefault();
+ break;
+ case FINISH:
+ setLightSensorEnabled(false);
+ break;
+ }
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (mRegistered) {
+ mDozeService.setDozeScreenBrightness(Math.max(1, (int) event.values[0]));
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ private void resetBrightnessToDefault() {
+ mDozeService.setDozeScreenBrightness(mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDoze));
+ }
+
+ private void setLightSensorEnabled(boolean enabled) {
+ if (enabled && !mRegistered && mLightSensor != null) {
+ mRegistered = mSensorManager.registerListener(this, mLightSensor,
+ SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+ } else if (!enabled && mRegistered) {
+ mSensorManager.unregisterListener(this);
+ mRegistered = false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
new file mode 100644
index 000000000000..846ec27c451e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.systemui.doze;
+
+import android.content.Context;
+import android.view.Display;
+
+/**
+ * Controls the screen when dozing.
+ */
+public class DozeScreenState implements DozeMachine.Part {
+ private final DozeMachine.Service mDozeService;
+
+ public DozeScreenState(DozeMachine.Service service) {
+ mDozeService = service;
+ }
+
+ @Override
+ public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+ int screenState = newState.screenState();
+ if (screenState != Display.STATE_UNKNOWN) {
+ mDozeService.setDozeScreenState(screenState);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index ad5897aa71c2..5d0a9d70e99d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -24,18 +24,11 @@ import com.android.systemui.statusbar.phone.DozeParameters;
/**
* Prevents usage of doze screen states on devices that don't support them.
*/
-public class DozeScreenStatePreventingAdapter implements DozeMachine.Service {
-
- private final DozeMachine.Service mInner;
+public class DozeScreenStatePreventingAdapter extends DozeMachine.Service.Delegate {
@VisibleForTesting
DozeScreenStatePreventingAdapter(DozeMachine.Service inner) {
- mInner = inner;
- }
-
- @Override
- public void finish() {
- mInner.finish();
+ super(inner);
}
@Override
@@ -43,12 +36,7 @@ public class DozeScreenStatePreventingAdapter implements DozeMachine.Service {
if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
state = Display.STATE_ON;
}
- mInner.setDozeScreenState(state);
- }
-
- @Override
- public void requestWakeUp() {
- mInner.requestWakeUp();
+ super.setDozeScreenState(state);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 23da716706d3..67de020cdfde 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -18,6 +18,7 @@ package com.android.systemui.doze;
import android.annotation.AnyThread;
import android.app.ActivityManager;
+import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -29,6 +30,7 @@ import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.net.Uri;
import android.os.Handler;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -38,6 +40,7 @@ import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.WakeLock;
import java.io.PrintWriter;
@@ -51,6 +54,7 @@ public class DozeSensors {
private static final String TAG = "DozeSensors";
private final Context mContext;
+ private final AlarmManager mAlarmManager;
private final SensorManager mSensorManager;
private final TriggerSensor[] mSensors;
private final ContentResolver mResolver;
@@ -65,10 +69,12 @@ public class DozeSensors {
private final ProxSensor mProxSensor;
- public DozeSensors(Context context, SensorManager sensorManager, DozeParameters dozeParameters,
+ public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
+ DozeParameters dozeParameters,
AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback,
Consumer<Boolean> proxCallback) {
mContext = context;
+ mAlarmManager = alarmManager;
mSensorManager = sensorManager;
mDozeParameters = dozeParameters;
mConfig = config;
@@ -100,10 +106,14 @@ public class DozeSensors {
}
private Sensor findSensorWithType(String type) {
+ return findSensorWithType(mSensorManager, type);
+ }
+
+ static Sensor findSensorWithType(SensorManager sensorManager, String type) {
if (TextUtils.isEmpty(type)) {
return null;
}
- List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (Sensor s : sensorList) {
if (type.equals(s.getStringType())) {
return s;
@@ -140,7 +150,7 @@ public class DozeSensors {
}
public void setProxListening(boolean listen) {
- mProxSensor.setRegistered(listen);
+ mProxSensor.setRequested(listen);
}
private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@@ -168,11 +178,23 @@ public class DozeSensors {
private class ProxSensor implements SensorEventListener {
+ static final long COOLDOWN_TRIGGER = 2 * 1000;
+ static final long COOLDOWN_PERIOD = 5 * 1000;
+
+ boolean mRequested;
boolean mRegistered;
Boolean mCurrentlyFar;
+ long mLastNear;
+ final AlarmTimeout mCooldownTimer;
- void setRegistered(boolean register) {
- if (mRegistered == register) {
+
+ public ProxSensor() {
+ mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
+ "prox_cooldown", mHandler);
+ }
+
+ void setRequested(boolean requested) {
+ if (mRequested == requested) {
// Send an update even if we don't re-register.
mHandler.post(() -> {
if (mCurrentlyFar != null) {
@@ -181,6 +203,18 @@ public class DozeSensors {
});
return;
}
+ mRequested = requested;
+ updateRegistered();
+ }
+
+ private void updateRegistered() {
+ setRegistered(mRequested && !mCooldownTimer.isScheduled());
+ }
+
+ private void setRegistered(boolean register) {
+ if (mRegistered == register) {
+ return;
+ }
if (register) {
mRegistered = mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
@@ -196,6 +230,17 @@ public class DozeSensors {
public void onSensorChanged(SensorEvent event) {
mCurrentlyFar = event.values[0] >= event.sensor.getMaximumRange();
mProxCallback.accept(mCurrentlyFar);
+
+ long now = SystemClock.elapsedRealtime();
+ if (!mCurrentlyFar) {
+ mLastNear = now;
+ } else if (mCurrentlyFar && now - mLastNear < COOLDOWN_TRIGGER) {
+ // If the last near was very recent, we might be using more power for prox
+ // wakeups than we're saving from turning of the screen. Instead, turn it off
+ // for a while.
+ mCooldownTimer.schedule(COOLDOWN_PERIOD, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
+ updateRegistered();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index d9fb087a6041..98b110619a1c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -76,8 +76,6 @@ public class DozeService extends DreamService
super.onDreamingStarted();
mDozeMachine.requestState(DozeMachine.State.INITIALIZED);
startDozing();
- setDozeScreenBrightness(getResources().getInteger(
- com.android.internal.R.integer.config_screenBrightnessDoze));
if (mDozePlugin != null) {
mDozePlugin.onDreamingStarted();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
index 1e067974e3cc..1c6521f641bf 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
@@ -24,18 +24,11 @@ import com.android.systemui.statusbar.phone.DozeParameters;
/**
* Prevents usage of doze screen states on devices that don't support them.
*/
-public class DozeSuspendScreenStatePreventingAdapter implements DozeMachine.Service {
-
- private final DozeMachine.Service mInner;
+public class DozeSuspendScreenStatePreventingAdapter extends DozeMachine.Service.Delegate {
@VisibleForTesting
DozeSuspendScreenStatePreventingAdapter(DozeMachine.Service inner) {
- mInner = inner;
- }
-
- @Override
- public void finish() {
- mInner.finish();
+ super(inner);
}
@Override
@@ -43,12 +36,7 @@ public class DozeSuspendScreenStatePreventingAdapter implements DozeMachine.Serv
if (state == Display.STATE_DOZE_SUSPEND) {
state = Display.STATE_DOZE;
}
- mInner.setDozeScreenState(state);
- }
-
- @Override
- public void requestWakeUp() {
- mInner.requestWakeUp();
+ super.setDozeScreenState(state);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 8d1d6e0ce460..610eaffec34b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -16,6 +16,7 @@
package com.android.systemui.doze;
+import android.app.AlarmManager;
import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -70,7 +71,7 @@ public class DozeTriggers implements DozeMachine.Part {
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
- AmbientDisplayConfiguration config,
+ AlarmManager alarmManager, AmbientDisplayConfiguration config,
DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
WakeLock wakeLock, boolean allowPulseTriggers) {
mContext = context;
@@ -82,8 +83,8 @@ public class DozeTriggers implements DozeMachine.Part {
mHandler = handler;
mWakeLock = wakeLock;
mAllowPulseTriggers = allowPulseTriggers;
- mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
- wakeLock, this::onSensor, this::onProximityFar);
+ mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
+ config, wakeLock, this::onSensor, this::onProximityFar);
mUiModeManager = mContext.getSystemService(UiModeManager.class);
}
@@ -152,18 +153,22 @@ public class DozeTriggers implements DozeMachine.Part {
private void onProximityFar(boolean far) {
final boolean near = !far;
- DozeMachine.State state = mMachine.getState();
+ final DozeMachine.State state = mMachine.getState();
+ final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
+ final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
+ final boolean aod = (state == DozeMachine.State.DOZE_AOD);
+
if (near && state == DozeMachine.State.DOZE_PULSING) {
if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse");
DozeLog.tracePulseCanceledByProx(mContext);
mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
}
- if (far && state == DozeMachine.State.DOZE_AOD_PAUSED) {
+ if (far && (paused || pausing)) {
if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
mMachine.requestState(DozeMachine.State.DOZE_AOD);
- } else if (near && state == DozeMachine.State.DOZE_AOD) {
+ } else if (near && aod) {
if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
- mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSED);
+ mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
}
}
@@ -192,6 +197,7 @@ public class DozeTriggers implements DozeMachine.Part {
}
break;
case DOZE_AOD_PAUSED:
+ case DOZE_AOD_PAUSING:
mDozeSensors.setProxListening(true);
mDozeSensors.setListening(false);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index cf87fca56f39..1dc37cdbca7a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -23,6 +23,7 @@ import android.os.SystemClock;
import android.text.format.Formatter;
import android.util.Log;
+import com.android.systemui.util.AlarmTimeout;
import com.android.systemui.util.wakelock.WakeLock;
import java.util.Calendar;
@@ -35,26 +36,23 @@ public class DozeUi implements DozeMachine.Part {
private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
private final Context mContext;
- private final AlarmManager mAlarmManager;
private final DozeHost mHost;
private final Handler mHandler;
private final WakeLock mWakeLock;
private final DozeMachine mMachine;
- private final AlarmManager.OnAlarmListener mTimeTick;
+ private final AlarmTimeout mTimeTicker;
- private boolean mTimeTickScheduled = false;
private long mLastTimeTickElapsed = 0;
public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
WakeLock wakeLock, DozeHost host, Handler handler) {
mContext = context;
- mAlarmManager = alarmManager;
mMachine = machine;
mWakeLock = wakeLock;
mHost = host;
mHandler = handler;
- mTimeTick = this::onTimeTick;
+ mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
}
private void pulseWhileDozing(int reason) {
@@ -76,6 +74,7 @@ public class DozeUi implements DozeMachine.Part {
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
case DOZE_AOD:
+ case DOZE_AOD_PAUSING:
scheduleTimeTick();
break;
case DOZE:
@@ -112,25 +111,21 @@ public class DozeUi implements DozeMachine.Part {
}
private void scheduleTimeTick() {
- if (mTimeTickScheduled) {
+ if (mTimeTicker.isScheduled()) {
return;
}
long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis();
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
-
- mTimeTickScheduled = true;
+ mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
mLastTimeTickElapsed = SystemClock.elapsedRealtime();
}
private void unscheduleTimeTick() {
- if (!mTimeTickScheduled) {
+ if (!mTimeTicker.isScheduled()) {
return;
}
verifyLastTimeTick();
- mAlarmManager.cancel(mTimeTick);
- mTimeTickScheduled = false;
+ mTimeTicker.cancel();
}
private void verifyLastTimeTick() {
@@ -153,10 +148,6 @@ public class DozeUi implements DozeMachine.Part {
}
private void onTimeTick() {
- if (!mTimeTickScheduled) {
- // Alarm was canceled, but we still got the callback. Ignore.
- return;
- }
verifyLastTimeTick();
mHost.dozeTimeTick();
@@ -164,7 +155,6 @@ public class DozeUi implements DozeMachine.Part {
// Keep wakelock until a frame has been pushed.
mHandler.post(mWakeLock.wrap(() -> {}));
- mTimeTickScheduled = false;
scheduleTimeTick();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 09ae521ceb2b..6f2c6e0bb60a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -131,9 +131,6 @@ public class NavigationBarInflaterView extends FrameLayout
mRot90.setId(R.id.rot90);
addView(mRot90);
updateAlternativeOrder();
- if (getParent() instanceof NavigationBarView) {
- ((NavigationBarView) getParent()).updateRotatedViews();
- }
}
protected String getDefaultLayout() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 426444158b11..03dd41ff1ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -558,7 +558,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
public void onFinishInflate() {
mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
R.id.navigation_inflater);
- updateRotatedViews();
mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -567,16 +566,14 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
mDockedStackExists = exists;
updateRecentsIcon();
}));
+ updateRotatedViews();
}
- void updateRotatedViews() {
+ private void updateRotatedViews() {
mRotatedViews[Surface.ROTATION_0] =
mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
mRotatedViews[Surface.ROTATION_270] =
mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
-
- mCurrentRotation = -1;
- reorient();
}
public boolean needsReorient(int rotation) {
@@ -615,9 +612,9 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
}
mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
- if (getRootView() instanceof NavigationBarFrame) {
- ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
- }
+
+ ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
+
mDeadZone.setDisplayRotation(mCurrentRotation);
// force the low profile & disabled states into compliance
@@ -757,6 +754,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ reorient();
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(this,
NavGesture.class, false /* Only one */);
diff --git a/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
new file mode 100644
index 000000000000..f7f61aff9849
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/AlarmTimeout.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 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.systemui.util;
+
+import android.app.AlarmManager;
+import android.os.Handler;
+import android.os.SystemClock;
+
+/**
+ * Schedules a timeout through AlarmManager. Ensures that the timeout is called even when
+ * the device is asleep.
+ */
+public class AlarmTimeout implements AlarmManager.OnAlarmListener {
+
+ public static final int MODE_CRASH_IF_SCHEDULED = 0;
+ public static final int MODE_IGNORE_IF_SCHEDULED = 1;
+ public static final int MODE_RESCHEDULE_IF_SCHEDULED = 2;
+
+ private final AlarmManager mAlarmManager;
+ private final AlarmManager.OnAlarmListener mListener;
+ private final String mTag;
+ private final Handler mHandler;
+ private boolean mScheduled;
+
+ public AlarmTimeout(AlarmManager alarmManager, AlarmManager.OnAlarmListener listener,
+ String tag, Handler handler) {
+ mAlarmManager = alarmManager;
+ mListener = listener;
+ mTag = tag;
+ mHandler = handler;
+ }
+
+ public void schedule(long timeout, int mode) {
+ switch (mode) {
+ case MODE_CRASH_IF_SCHEDULED:
+ if (mScheduled) {
+ throw new IllegalStateException(mTag + " timeout is already scheduled");
+ }
+ break;
+ case MODE_IGNORE_IF_SCHEDULED:
+ if (mScheduled) {
+ return;
+ }
+ break;
+ case MODE_RESCHEDULE_IF_SCHEDULED:
+ if (mScheduled) {
+ cancel();
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal mode: " + mode);
+ }
+
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + timeout, mTag, this, mHandler);
+ mScheduled = true;
+ }
+
+ public boolean isScheduled() {
+ return mScheduled;
+ }
+
+ public void cancel() {
+ if (mScheduled) {
+ mAlarmManager.cancel(this);
+ mScheduled = false;
+ }
+ }
+
+ @Override
+ public void onAlarm() {
+ if (!mScheduled) {
+ // We canceled the alarm, but it still fired. Ignore.
+ return;
+ }
+ mScheduled = false;
+ mListener.onAlarm();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 3a09ce07288e..368c814f8e0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -215,54 +215,6 @@ public class DozeMachineTest extends SysuiTestCase {
}
@Test
- public void testScreen_offInDoze() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE);
-
- assertEquals(Display.STATE_OFF, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_onInAod() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE_AOD);
-
- assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_onInPulse() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
- mMachine.requestState(DOZE_PULSING);
-
- assertEquals(Display.STATE_ON, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_offInRequestPulseWithoutAoD() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE);
- mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
-
- assertEquals(Display.STATE_OFF, mServiceFake.screenState);
- }
-
- @Test
- public void testScreen_onInRequestPulseWithoutAoD() {
- mMachine.requestState(INITIALIZED);
-
- mMachine.requestState(DOZE_AOD);
- mMachine.requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
-
- assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
- }
-
- @Test
public void testTransitions_canRequestTransitions() {
mMachine.requestState(INITIALIZED);
mMachine.requestState(DOZE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
new file mode 100644
index 000000000000..514dc8b94de5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2017 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.systemui.doze;
+
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
+import static com.android.systemui.doze.DozeMachine.State.FINISH;
+import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
+import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.PowerManager;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.utils.hardware.FakeSensorManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DozeScreenBrightnessTest extends SysuiTestCase {
+
+ DozeServiceFake mServiceFake;
+ DozeScreenBrightness mScreen;
+ FakeSensorManager.FakeGenericSensor mSensor;
+ FakeSensorManager mSensorManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mServiceFake = new DozeServiceFake();
+ mSensorManager = new FakeSensorManager(mContext);
+ mSensor = mSensorManager.getFakeLightSensor();
+ mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
+ mSensor.getSensor(), null /* handler */);
+ }
+
+ @Test
+ public void testInitialize_setsScreenBrightnessToValidValue() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+
+ assertNotEquals(PowerManager.BRIGHTNESS_DEFAULT, mServiceFake.screenBrightness);
+ assertTrue(mServiceFake.screenBrightness <= PowerManager.BRIGHTNESS_ON);
+ }
+
+ @Test
+ public void testAod_usesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testPausingAod_pausesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1000);
+
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+
+ mSensor.sendSensorEvent(1001);
+
+ assertNotEquals(1001, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testPausingAod_resetsBrightness() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1000);
+
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+
+ assertNotEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testPulsing_usesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testDozingAfterPulsing_pausesLightSensor() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+ mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
+ mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE);
+ mScreen.transitionTo(DOZE_PULSE_DONE, DOZE);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertNotEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testNullSensor() throws Exception {
+ mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
+ null /* sensor */, null /* handler */);
+
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSED);
+ }
+
+ @Test
+ public void testNoBrightnessDeliveredAfterFinish() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.transitionTo(DOZE_AOD, FINISH);
+
+ mSensor.sendSensorEvent(1000);
+
+ assertNotEquals(1000, mServiceFake.screenBrightness);
+ }
+
+ @Test
+ public void testBrightness_atLeastOne() throws Exception {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(0);
+
+ assertTrue("Brightness must be at least 1, but was " + mServiceFake.screenBrightness,
+ mServiceFake.screenBrightness >= 1);
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
new file mode 100644
index 000000000000..203876b9a2f5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 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.systemui.doze;
+
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
+import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
+import static com.android.systemui.doze.DozeMachine.State.INITIALIZED;
+import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class DozeScreenStateTest extends SysuiTestCase {
+
+ DozeServiceFake mServiceFake;
+ DozeScreenState mScreen;
+
+ @Before
+ public void setUp() throws Exception {
+ mServiceFake = new DozeServiceFake();
+ mScreen = new DozeScreenState(mServiceFake);
+ }
+
+ @Test
+ public void testScreen_offInDoze() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_onInAod() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_onInPulse() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+ mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
+
+ assertEquals(Display.STATE_ON, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_offInRequestPulseWithoutAoD() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE);
+
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+
+ assertEquals(Display.STATE_OFF, mServiceFake.screenState);
+ }
+
+ @Test
+ public void testScreen_onInRequestPulseWithAoD() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
+
+ assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
+ }
+
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
index c1e7fe46de8e..34026b0b6145 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeServiceFake.java
@@ -16,6 +16,7 @@
package com.android.systemui.doze;
+import android.os.PowerManager;
import android.view.Display;
public class DozeServiceFake implements DozeMachine.Service {
@@ -23,6 +24,7 @@ public class DozeServiceFake implements DozeMachine.Service {
public boolean finished;
public int screenState;
public boolean requestedWakeup;
+ public int screenBrightness;
public DozeServiceFake() {
reset();
@@ -38,13 +40,19 @@ public class DozeServiceFake implements DozeMachine.Service {
screenState = state;
}
- public void reset() {
- finished = false;
- screenState = Display.STATE_UNKNOWN;
- }
-
@Override
public void requestWakeUp() {
requestedWakeup = true;
}
+
+ @Override
+ public void setDozeScreenBrightness(int brightness) {
+ screenBrightness = brightness;
+ }
+
+ public void reset() {
+ finished = false;
+ screenState = Display.STATE_UNKNOWN;
+ screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 8641faca5d6e..a8ea1c0770da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AlarmManager;
import android.app.Instrumentation;
import android.os.Handler;
import android.os.Looper;
@@ -56,6 +57,7 @@ public class DozeTriggersTest extends SysuiTestCase {
private Handler mHandler;
private WakeLock mWakeLock;
private Instrumentation mInstrumentation;
+ private AlarmManager mAlarmManager;
@BeforeClass
public static void setupSuite() {
@@ -67,6 +69,7 @@ public class DozeTriggersTest extends SysuiTestCase {
public void setUp() throws Exception {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mMachine = mock(DozeMachine.class);
+ mAlarmManager = mock(AlarmManager.class);
mHost = new DozeHostFake();
mConfig = DozeConfigurationUtil.createMockConfig();
mParameters = DozeConfigurationUtil.createMockParameters();
@@ -75,7 +78,7 @@ public class DozeTriggersTest extends SysuiTestCase {
mWakeLock = new WakeLockFake();
mInstrumentation.runOnMainSync(() -> {
- mTriggers = new DozeTriggers(mContext, mMachine, mHost,
+ mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager,
mConfig, mParameters, mSensors, mHandler, mWakeLock, true);
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
index 30be6658d4b6..a4ae166d0675 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
@@ -30,13 +30,15 @@ import android.os.MemoryFile;
import android.os.SystemClock;
import android.util.ArraySet;
-import com.google.android.collect.Lists;
+import com.android.internal.util.Preconditions;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Rudimentary fake for SensorManager
@@ -49,6 +51,8 @@ import java.util.List;
public class FakeSensorManager extends SensorManager {
private final MockProximitySensor mMockProximitySensor;
+ private final FakeGenericSensor mFakeLightSensor;
+ private final FakeGenericSensor[] mSensors;
public FakeSensorManager(Context context) throws Exception {
Sensor proxSensor = context.getSystemService(SensorManager.class)
@@ -57,13 +61,21 @@ public class FakeSensorManager extends SensorManager {
// No prox? Let's create a fake one!
proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
}
- mMockProximitySensor = new MockProximitySensor(proxSensor);
+
+ mSensors = new FakeGenericSensor[]{
+ mMockProximitySensor = new MockProximitySensor(proxSensor),
+ mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT)),
+ };
}
public MockProximitySensor getMockProximitySensor() {
return mMockProximitySensor;
}
+ public FakeGenericSensor getFakeLightSensor() {
+ return mFakeLightSensor;
+ }
+
@Override
public Sensor getDefaultSensor(int type) {
Sensor s = super.getDefaultSensor(type);
@@ -77,7 +89,10 @@ public class FakeSensorManager extends SensorManager {
@Override
protected List<Sensor> getFullSensorList() {
- return Lists.newArrayList(mMockProximitySensor.sensor);
+ return Arrays
+ .stream(mSensors)
+ .map(i -> i.mSensor)
+ .collect(Collectors.toList());
}
@Override
@@ -87,8 +102,11 @@ public class FakeSensorManager extends SensorManager {
@Override
protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
- if (sensor == mMockProximitySensor.sensor || sensor == null) {
- mMockProximitySensor.listeners.remove(listener);
+ Preconditions.checkNotNull(listener);
+ for (FakeGenericSensor s : mSensors) {
+ if (sensor == null || s.mSensor == sensor) {
+ s.mListeners.remove(listener);
+ }
}
}
@@ -96,9 +114,13 @@ public class FakeSensorManager extends SensorManager {
protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
int delayUs,
Handler handler, int maxReportLatencyUs, int reservedFlags) {
- if (sensor == mMockProximitySensor.sensor) {
- mMockProximitySensor.listeners.add(listener);
- return true;
+ Preconditions.checkNotNull(sensor);
+ Preconditions.checkNotNull(listener);
+ for (FakeGenericSensor s : mSensors) {
+ if (s.mSensor == sensor) {
+ s.mListeners.add(listener);
+ return true;
+ }
}
return false;
}
@@ -196,18 +218,35 @@ public class FakeSensorManager extends SensorManager {
setter.invoke(sensor, type);
}
- public class MockProximitySensor {
- final Sensor sensor;
- final ArraySet<SensorEventListener> listeners = new ArraySet<>();
+ public class MockProximitySensor extends FakeGenericSensor {
private MockProximitySensor(Sensor sensor) {
- this.sensor = sensor;
+ super(sensor);
}
public void sendProximityResult(boolean far) {
- SensorEvent event = createSensorEvent(1);
- event.values[0] = far ? sensor.getMaximumRange() : 0;
- for (SensorEventListener listener : listeners) {
+ sendSensorEvent(far ? getSensor().getMaximumRange() : 0);
+ }
+ }
+
+ public class FakeGenericSensor {
+
+ private final Sensor mSensor;
+ private final ArraySet<SensorEventListener> mListeners = new ArraySet<>();
+
+ public FakeGenericSensor(
+ Sensor sensor) {
+ this.mSensor = sensor;
+ }
+
+ public Sensor getSensor() {
+ return mSensor;
+ }
+
+ public void sendSensorEvent(float... values) {
+ SensorEvent event = createSensorEvent(values.length);
+ System.arraycopy(values, 0, event.values, 0, values.length);
+ for (SensorEventListener listener : mListeners) {
listener.onSensorChanged(event);
}
}
@@ -222,7 +261,7 @@ public class FakeSensorManager extends SensorManager {
} catch (Exception e) {
throw new RuntimeException(e);
}
- event.sensor = sensor;
+ event.sensor = mSensor;
event.timestamp = SystemClock.elapsedRealtimeNanos();
return event;
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 61057dd25444..75206e48aa8b 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -86,6 +86,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final int ACTIVE_LOG_MAX_SIZE = 20;
private static final int CRASH_LOG_MAX_SIZE = 100;
private static final String REASON_AIRPLANE_MODE = "airplane mode";
+ private static final String REASON_DISALLOWED = "disallowed by system";
+ private static final String REASON_SHARING_DISALLOWED = "sharing disallowed by system";
private static final String REASON_RESTARTED = "automatic restart";
private static final String REASON_START_CRASH = "turn-on crash";
private static final String REASON_SYSTEM_BOOT = "system boot";
@@ -227,25 +229,26 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
@Override
public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
Bundle prevRestrictions) {
- if (!UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
- UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_BLUETOOTH_SHARING)) {
- return; // No relevant changes, nothing to do.
- }
- final boolean disallowed = newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
+ if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
+ UserManager.DISALLOW_BLUETOOTH_SHARING)) {
+ updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
+ UserManager.DISALLOW_BLUETOOTH_SHARING));
+ }
- // DISALLOW_BLUETOOTH is a global restriction that can only be set by DO or PO on the
- // system user, so we only look at the system user.
- if (userId == UserHandle.USER_SYSTEM && disallowed && (mEnable || mEnableExternal)) {
- try {
- disable(null /* packageName */, true /* persist */);
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception when disabling Bluetooth", e);
+ // DISALLOW_BLUETOOTH can only be set by DO or PO on the system user.
+ if (userId == UserHandle.USER_SYSTEM &&
+ UserRestrictionsUtils.restrictionsChanged(
+ prevRestrictions, newRestrictions, UserManager.DISALLOW_BLUETOOTH)) {
+ if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
+ UserManager.DISALLOW_BLUETOOTH)) {
+ updateOppLauncherComponentState(userId, true); // Sharing disallowed
+ sendDisableMsg(REASON_DISALLOWED);
+ } else {
+ updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
+ UserManager.DISALLOW_BLUETOOTH_SHARING));
}
}
- final boolean sharingDisallowed = disallowed
- || newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH_SHARING);
- updateOppLauncherComponentState(userId, sharingDisallowed);
}
};
@@ -2118,7 +2121,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
: PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
try {
final IPackageManager imp = AppGlobals.getPackageManager();
- imp.setComponentEnabledSetting(oppLauncherComponent, newState, 0 /* flags */, userId);
+ imp.setComponentEnabledSetting(oppLauncherComponent, newState,
+ PackageManager.DONT_KILL_APP, userId);
} catch (Exception e) {
// The component was not found, do nothing.
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 22b0f5bcdf07..7a8c2f91b4e9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
@@ -82,6 +83,7 @@ public class Session extends IWindowSession.Stub
// Set of visible alert window surfaces connected to this session.
private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
final boolean mCanAddInternalSystemWindow;
+ final boolean mCanHideNonSystemOverlayWindows;
private AlertWindowNotification mAlertWindowNotification;
private boolean mShowingAlertWindowNotificationAllowed;
private boolean mClientDead = false;
@@ -99,6 +101,8 @@ public class Session extends IWindowSession.Stub
mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission(
INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
+ mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
+ HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
StringBuilder sb = new StringBuilder();
sb.append("Session{");
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 469dab4e0a3e..802f9edc92dc 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -33,7 +33,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
@@ -166,8 +165,7 @@ class TaskSnapshotSurface implements StartingSurface {
layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
| FLAG_NOT_FOCUSABLE
| FLAG_NOT_TOUCHABLE;
- layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT
- | (windowPrivateFlags & PRIVATE_FLAG_INHERITS);
+ layoutParams.privateFlags = windowPrivateFlags & PRIVATE_FLAG_INHERITS;
layoutParams.token = token.token;
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 613c830f31f2..20d9286781bb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -495,12 +495,15 @@ public class WindowManagerService extends IWindowManager.Stub
*/
Runnable mWaitingForDrawnCallback;
+ /** List of window currently causing non-system overlay windows to be hidden. */
+ private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
+
/**
* Stores for each user whether screencapture is disabled
* This array is essentially a cache for all userId for
* {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
*/
- SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
+ private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
IInputMethodManager mInputMethodManager;
@@ -1715,6 +1718,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mPendingRemove.remove(win);
mResizingWindows.remove(win);
+ updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
mWindowsChanged = true;
if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Final remove of window: " + win);
@@ -6484,6 +6488,21 @@ public class WindowManagerService extends IWindowManager.Stub
ArrayList<WindowState> windows) {
mRoot.dumpWindowsNoHeader(pw, dumpAll, windows);
+ if (!mHidingNonSystemOverlayWindows.isEmpty()) {
+ pw.println();
+ pw.println(" Hiding System Alert Windows:");
+ for (int i = mHidingNonSystemOverlayWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = mHidingNonSystemOverlayWindows.get(i);
+ pw.print(" #"); pw.print(i); pw.print(' ');
+ pw.print(w);
+ if (dumpAll) {
+ pw.println(":");
+ w.dump(pw, " ", true);
+ } else {
+ pw.println();
+ }
+ }
+ }
if (mPendingRemove.size() > 0) {
pw.println();
pw.println(" Remove pending for:");
@@ -7598,4 +7617,28 @@ public class WindowManagerService extends IWindowManager.Stub
boolean hasWideColorGamutSupport() {
return mHasWideColorGamutSupport;
}
+
+ void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
+ if (!win.hideNonSystemOverlayWindowsWhenVisible()) {
+ return;
+ }
+ final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
+ if (surfaceShown) {
+ if (!mHidingNonSystemOverlayWindows.contains(win)) {
+ mHidingNonSystemOverlayWindows.add(win);
+ }
+ } else {
+ mHidingNonSystemOverlayWindows.remove(win);
+ }
+
+ final boolean hideSystemAlertWindows = !mHidingNonSystemOverlayWindows.isEmpty();
+
+ if (systemAlertWindowsHidden == hideSystemAlertWindows) {
+ return;
+ }
+
+ mRoot.forAllWindows((w) -> {
+ w.setForceHideNonSystemOverlayWindowIfNeeded(hideSystemAlertWindows);
+ }, false /* traverseTopToBottom */);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index d1fbf900ef70..001019b43f9c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -46,6 +46,7 @@ import static android.view.WindowManager.LayoutParams.FORMAT_CHANGED;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
@@ -59,7 +60,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
@@ -208,6 +211,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
boolean mPolicyVisibilityAfterAnim = true;
private boolean mAppOpVisibility = true;
boolean mPermanentlyHidden; // the window should never be shown again
+ // This is a non-system overlay window that is currently force hidden.
+ private boolean mForceHideNonSystemOverlayWindow;
boolean mAppFreezing;
boolean mHidden; // Used to determine if to show child windows.
boolean mWallpaperVisible; // for wallpaper, what was last vis report?
@@ -2370,6 +2375,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// to handle their windows being removed from under them.
return false;
}
+ if (mForceHideNonSystemOverlayWindow) {
+ // This is an alert window that is currently force hidden.
+ return false;
+ }
if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
// Already showing.
return false;
@@ -2446,6 +2455,22 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return true;
}
+ void setForceHideNonSystemOverlayWindowIfNeeded(boolean forceHide) {
+ if (mOwnerCanAddInternalSystemWindow
+ || (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
+ return;
+ }
+ if (mForceHideNonSystemOverlayWindow == forceHide) {
+ return;
+ }
+ mForceHideNonSystemOverlayWindow = forceHide;
+ if (forceHide) {
+ hideLw(true /* doAnimation */, true /* requestAnim */);
+ } else {
+ showLw(true /* doAnimation */, true /* requestAnim */);
+ }
+ }
+
public void setAppOpVisibilityLw(boolean state) {
if (mAppOpVisibility != state) {
mAppOpVisibility = state;
@@ -3327,7 +3352,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
pw.println(Integer.toHexString(mSystemUiVisibility));
}
if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
- || isParentWindowHidden()|| mPermanentlyHidden) {
+ || isParentWindowHidden()|| mPermanentlyHidden || mForceHideNonSystemOverlayWindow) {
pw.print(prefix); pw.print("mPolicyVisibility=");
pw.print(mPolicyVisibility);
pw.print(" mPolicyVisibilityAfterAnim=");
@@ -3335,7 +3360,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
pw.print(" mAppOpVisibility=");
pw.print(mAppOpVisibility);
pw.print(" parentHidden="); pw.print(isParentWindowHidden());
- pw.print(" mPermanentlyHidden="); pw.println(mPermanentlyHidden);
+ pw.print(" mPermanentlyHidden="); pw.print(mPermanentlyHidden);
+ pw.print(" mForceHideNonSystemOverlayWindow="); pw.println(
+ mForceHideNonSystemOverlayWindow);
}
if (!mRelayoutCalled || mLayoutNeeded) {
pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
@@ -3590,6 +3617,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
}
+ /**
+ * Returns true if any window added by an application process that if of type
+ * {@link android.view.WindowManager.LayoutParams#TYPE_TOAST} or that requires that requires
+ * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
+ * this window is visible.
+ */
+ boolean hideNonSystemOverlayWindowsWhenVisible() {
+ return (mAttrs.privateFlags & PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0
+ && mSession.mCanHideNonSystemOverlayWindows;
+ }
+
/** Returns the parent window if this is a child of another window, else null. */
WindowState getParentWindow() {
// NOTE: We are not calling getParent() directly as the WindowState might be a child of a
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 27927e6c0693..1728cfbb6ef0 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -24,10 +24,8 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static android.view.Surface.SCALING_MODE_FREEZE;
import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
-import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -514,6 +512,8 @@ class WindowSurfaceController {
void setShown(boolean surfaceShown) {
mSurfaceShown = surfaceShown;
+ mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown);
+
if (mWindowSession != null) {
mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
}