Merge "DO NOT MERGE - Remove RetailDemoModeService" into oc-dr1-dev
diff --git a/Android.mk b/Android.mk
index cc34767..3b44255 100644
--- a/Android.mk
+++ b/Android.mk
@@ -247,6 +247,7 @@
core/java/android/nfc/INfcCardEmulation.aidl \
core/java/android/nfc/INfcFCardEmulation.aidl \
core/java/android/nfc/INfcUnlockHandler.aidl \
+ core/java/android/nfc/INfcDta.aidl \
core/java/android/nfc/ITagRemovedCallback.aidl \
core/java/android/os/IBatteryPropertiesListener.aidl \
core/java/android/os/IBatteryPropertiesRegistrar.aidl \
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index f991efe..6801618 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -29,6 +29,7 @@
import android.nfc.INfcFCardEmulation;
import android.nfc.INfcUnlockHandler;
import android.nfc.ITagRemovedCallback;
+import android.nfc.INfcDta;
import android.os.Bundle;
/**
@@ -40,7 +41,7 @@
INfcCardEmulation getNfcCardEmulationInterface();
INfcFCardEmulation getNfcFCardEmulationInterface();
INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
-
+ INfcDta getNfcDtaInterface(in String pkg);
int getState();
boolean disable(boolean saveState);
boolean enable();
diff --git a/core/java/android/nfc/INfcDta.aidl b/core/java/android/nfc/INfcDta.aidl
new file mode 100644
index 0000000..4cc5927
--- /dev/null
+++ b/core/java/android/nfc/INfcDta.aidl
@@ -0,0 +1,34 @@
+ /*
+ * Copyright (C) 2017 NXP Semiconductors
+ *
+ * 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 android.nfc;
+
+import android.os.Bundle;
+
+/**
+ * {@hide}
+ */
+interface INfcDta {
+
+ void enableDta();
+ void disableDta();
+ boolean enableServer(String serviceName, int serviceSap, int miu,
+ int rwSize,int testCaseId);
+ void disableServer();
+ boolean enableClient(String serviceName, int miu, int rwSize,
+ int testCaseId);
+ void disableClient();
+ boolean registerMessageService(String msgServiceName);
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 48869c7..debef63 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -16,8 +16,6 @@
package android.nfc;
-import java.util.HashMap;
-
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -43,6 +41,7 @@
import android.util.Log;
import java.io.IOException;
+import java.util.HashMap;
/**
* Represents the local NFC adapter.
@@ -627,6 +626,23 @@
}
/**
+ * Returns the binder interface to the NFC-DTA test interface.
+ * @hide
+ */
+ public INfcDta getNfcDtaInterface() {
+ if (mContext == null) {
+ throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
+ + " NFC extras APIs");
+ }
+ try {
+ return sService.getNfcDtaInterface(mContext.getPackageName());
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return null;
+ }
+ }
+
+ /**
* NFC service dead - attempt best effort recovery
* @hide
*/
diff --git a/core/java/android/nfc/dta/NfcDta.java b/core/java/android/nfc/dta/NfcDta.java
new file mode 100644
index 0000000..8801662
--- /dev/null
+++ b/core/java/android/nfc/dta/NfcDta.java
@@ -0,0 +1,167 @@
+/*
+ * 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 android.nfc.dta;
+
+import android.content.Context;
+import android.nfc.INfcDta;
+import android.nfc.NfcAdapter;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * This class provides the primary API for DTA operations.
+ * @hide
+ */
+public final class NfcDta {
+ private static final String TAG = "NfcDta";
+
+ private static INfcDta sService;
+ private static HashMap<Context, NfcDta> sNfcDtas = new HashMap<Context, NfcDta>();
+
+ private final Context mContext;
+
+ private NfcDta(Context context, INfcDta service) {
+ mContext = context.getApplicationContext();
+ sService = service;
+ }
+
+ /**
+ * Helper to get an instance of this class.
+ *
+ * @param adapter A reference to an NfcAdapter object.
+ * @return
+ */
+ public static synchronized NfcDta getInstance(NfcAdapter adapter) {
+ if (adapter == null) throw new NullPointerException("NfcAdapter is null");
+ Context context = adapter.getContext();
+ if (context == null) {
+ Log.e(TAG, "NfcAdapter context is null.");
+ throw new UnsupportedOperationException();
+ }
+
+ NfcDta manager = sNfcDtas.get(context);
+ if (manager == null) {
+ INfcDta service = adapter.getNfcDtaInterface();
+ if (service == null) {
+ Log.e(TAG, "This device does not implement the INfcDta interface.");
+ throw new UnsupportedOperationException();
+ }
+ manager = new NfcDta(context, service);
+ sNfcDtas.put(context, manager);
+ }
+ return manager;
+ }
+
+ /**
+ * Enables DTA mode
+ *
+ * @return true/false if enabling was successful
+ */
+ public boolean enableDta() {
+ try {
+ sService.enableDta();
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Disables DTA mode
+ *
+ * @return true/false if disabling was successful
+ */
+ public boolean disableDta() {
+ try {
+ sService.disableDta();
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Enables Server
+ *
+ * @return true/false if enabling was successful
+ */
+ public boolean enableServer(String serviceName, int serviceSap, int miu,
+ int rwSize, int testCaseId) {
+ try {
+ return sService.enableServer(serviceName, serviceSap, miu, rwSize, testCaseId);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Disables Server
+ *
+ * @return true/false if disabling was successful
+ */
+ public boolean disableServer() {
+ try {
+ sService.disableServer();
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Enables Client
+ *
+ * @return true/false if enabling was successful
+ */
+ public boolean enableClient(String serviceName, int miu, int rwSize,
+ int testCaseId) {
+ try {
+ return sService.enableClient(serviceName, miu, rwSize, testCaseId);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Disables client
+ *
+ * @return true/false if disabling was successful
+ */
+ public boolean disableClient() {
+ try {
+ sService.disableClient();
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Registers Message Service
+ *
+ * @return true/false if registration was successful
+ */
+ public boolean registerMessageService(String msgServiceName) {
+ try {
+ return sService.registerMessageService(msgServiceName);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+}
diff --git a/core/java/android/service/vr/IVrListener.aidl b/core/java/android/service/vr/IVrListener.aidl
index afb13d3..acca3fa 100644
--- a/core/java/android/service/vr/IVrListener.aidl
+++ b/core/java/android/service/vr/IVrListener.aidl
@@ -20,5 +20,5 @@
/** @hide */
oneway interface IVrListener {
- void focusedActivityChanged(in ComponentName component);
+ void focusedActivityChanged(in ComponentName component, boolean running2dInVr, int pid);
}
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index 5da4560..fa3d065 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -70,8 +70,10 @@
private final IVrListener.Stub mBinder = new IVrListener.Stub() {
@Override
- public void focusedActivityChanged(ComponentName component) {
- mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, component).sendToTarget();
+ public void focusedActivityChanged(
+ ComponentName component, boolean running2dInVr, int pid) {
+ mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, running2dInVr ? 1 : 0,
+ pid, component).sendToTarget();
}
};
@@ -84,7 +86,8 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ON_CURRENT_VR_ACTIVITY_CHANGED: {
- VrListenerService.this.onCurrentVrActivityChanged((ComponentName) msg.obj);
+ VrListenerService.this.onCurrentVrActivityChanged(
+ (ComponentName) msg.obj, msg.arg1 == 1, msg.arg2);
} break;
}
}
@@ -120,6 +123,29 @@
}
/**
+ * An extended version of onCurrentVrActivityChanged
+ *
+ * <p>This will be called when this service is initially bound, but is not
+ * guaranteed to be called before onUnbind. In general, this is intended to be used to
+ * determine when user focus has transitioned between two VR activities, or between a
+ * VR activity and a 2D activity. This should be overridden instead of the above
+ * onCurrentVrActivityChanged as that version is deprecated.</p>
+ *
+ * @param component the {@link ComponentName} of the VR activity or the 2D intent.
+ * @param running2dInVr true if the component is a 2D component.
+ * @param pid the process the component is running in.
+ *
+ * @see android.app.Activity#setVrModeEnabled
+ * @see android.R.attr#enableVrMode
+ * @hide
+ */
+ public void onCurrentVrActivityChanged(
+ ComponentName component, boolean running2dInVr, int pid) {
+ // Override to implement. Default to old behaviour of sending null for 2D.
+ onCurrentVrActivityChanged(running2dInVr ? null : component);
+ }
+
+ /**
* Checks if the given component is enabled in user settings.
*
* <p>If this component is not enabled in the user's settings, it will not be started when
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index 2f1abe9..0122e49 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -202,6 +202,15 @@
}
/**
+ * @hide
+ * Checks if the original or backup file exists.
+ * @return whether the original or backup file exists.
+ */
+ public boolean exists() {
+ return mBaseName.exists() || mBackupName.exists();
+ }
+
+ /**
* Gets the last modified time of the atomic file.
* {@hide}
*
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 7346a21..263d3ff 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1133,6 +1133,15 @@
}
/**
+ * Returns true if the display may be in a reduced operating mode while in the
+ * specified display power state.
+ * @hide
+ */
+ public static boolean isDozeState(int state) {
+ return state == STATE_DOZE || state == STATE_DOZE_SUSPEND;
+ }
+
+ /**
* A mode supported by a given display.
*
* @see Display#getSupportedModes()
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9b881fd..faf3e125 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2591,5 +2591,16 @@
encoder.addProperty("type", type);
encoder.addProperty("flags", flags);
}
+
+ /**
+ * @hide
+ * @return True if the layout parameters will cause the window to cover the full screen;
+ * false otherwise.
+ */
+ public boolean isFullscreen() {
+ return x == 0 && y == 0
+ && width == WindowManager.LayoutParams.MATCH_PARENT
+ && height == WindowManager.LayoutParams.MATCH_PARENT;
+ }
}
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 60db8ca..f817ab3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1862,6 +1862,11 @@
states. -->
<bool name="config_dozeAlwaysOnDisplayAvailable">false</bool>
+ <!-- Whether the display hardware requires we go to the off state before transitioning
+ out of any doze states. -->
+ <bool name="config_displayTransitionOffAfterDoze">false</bool>
+
+
<!-- Power Management: Specifies whether to decouple the auto-suspend state of the
device from the display on/off state.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c49763f..7670c7b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3064,6 +3064,7 @@
<java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
<java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
<java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
+ <java-symbol type="bool" name="config_displayTransitionOffAfterDoze" />
<java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
<java-symbol type="string" name="config_headlineFontFamily" />
<java-symbol type="string" name="config_headlineFontFamilyLight" />
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index ec3b520..0400e24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1065,7 +1065,7 @@
// are still seen, we will investigate further.
update(config); // Notifies the AccessPointListener of the change
}
- if (mRssi != info.getRssi()) {
+ if (mRssi != info.getRssi() && info.getRssi() != WifiInfo.INVALID_RSSI) {
mRssi = info.getRssi();
updated = true;
} else if (mNetworkInfo != null && networkInfo != null
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 9ccd332..5a35da9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -365,7 +365,7 @@
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
mRegistered = false;
}
- unregisterAndClearScoreCache();
+ unregisterScoreCache();
pauseScanning();
mContext.getContentResolver().unregisterContentObserver(mObserver);
@@ -375,11 +375,14 @@
mStaleScanResults = true;
}
- private void unregisterAndClearScoreCache() {
+ private void unregisterScoreCache() {
mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
- mScoreCache.clearScores();
- // Synchronize on mLock to avoid concurrent modification during updateAccessPoints
+ // We do not want to clear the existing scores in the cache, as this method is called during
+ // stop tracking on activity pause. Hence, on resumption we want the ability to show the
+ // last known, potentially stale, scores. However, by clearing requested scores, the scores
+ // will be requested again upon resumption of tracking, and if any changes have occurred
+ // the listeners (UI) will be updated accordingly.
synchronized (mLock) {
mRequestedScores.clear();
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index c08dd6e..2f02b9b 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -626,6 +626,57 @@
}
@Test
+ public void testUpdateWithDifferentRssi_returnsTrue() {
+ int networkId = 123;
+ int rssi = -55;
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = networkId;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(networkId);
+ wifiInfo.setRssi(rssi);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(networkId)
+ .setRssi(rssi)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+ wifiInfo.setRssi(rssi + 1);
+ assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
+ }
+
+ @Test
+ public void testUpdateWithInvalidRssi_returnsFalse() {
+ int networkId = 123;
+ int rssi = -55;
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = networkId;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(networkId);
+ wifiInfo.setRssi(rssi);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(networkId)
+ .setRssi(rssi)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+ wifiInfo.setRssi(WifiInfo.INVALID_RSSI);
+ assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
+ }
+ @Test
public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener() {
int networkId = 123;
int rssi = -55;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index b6d0c45..c87d01a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -473,6 +473,17 @@
}
@Test
+ public void stopTracking_shouldNotClearExistingScores()
+ throws InterruptedException {
+ // Start the tracker and inject the initial scan results and then stop tracking
+ WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
+ updateScoresAndWaitForAccessPointsChangedCallback(tracker);
+ tracker.stopTracking();
+
+ assertThat(mScoreCacheCaptor.getValue().getScoredNetwork(NETWORK_KEY_1)).isNotNull();
+ }
+
+ @Test
public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged()
throws InterruptedException {
WifiTracker tracker = createMockedWifiTracker();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f5d7dd8..ad2ec0b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2597,7 +2597,7 @@
synchronized (mLock) {
final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
File globalFile = getSettingsFile(key);
- if (globalFile.exists()) {
+ if (SettingsState.stateFileExists(globalFile)) {
return;
}
@@ -2634,7 +2634,7 @@
// Every user has secure settings and if no file we need to migrate.
final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
File secureFile = getSettingsFile(secureKey);
- if (secureFile.exists()) {
+ if (SettingsState.stateFileExists(secureFile)) {
return;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 5f4b239..d3ac11a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -689,17 +689,11 @@
private void readStateSyncLocked() {
FileInputStream in;
- if (!mStatePersistFile.exists()) {
- Slog.i(LOG_TAG, "No settings state " + mStatePersistFile);
- addHistoricalOperationLocked(HISTORICAL_OPERATION_INITIALIZE, null);
- return;
- }
try {
in = new AtomicFile(mStatePersistFile).openRead();
} catch (FileNotFoundException fnfe) {
- String message = "No settings state " + mStatePersistFile;
- Slog.wtf(LOG_TAG, message);
- Slog.i(LOG_TAG, message);
+ Slog.i(LOG_TAG, "No settings state " + mStatePersistFile);
+ addHistoricalOperationLocked(HISTORICAL_OPERATION_INITIALIZE, null);
return;
}
try {
@@ -715,6 +709,16 @@
}
}
+ /**
+ * Uses AtomicFile to check if the file or its backup exists.
+ * @param file The file to check for existence
+ * @return whether the original or backup exist
+ */
+ public static boolean stateFileExists(File file) {
+ AtomicFile stateFile = new AtomicFile(file);
+ return stateFile.exists();
+ }
+
private void parseStateLocked(XmlPullParser parser)
throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1705f79..58117bd 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -273,6 +273,9 @@
<!-- Doze: the brightness value to use for the higher brightness AOD mode -->
<integer name="config_doze_aod_brightness_high">27</integer>
+ <!-- Doze: the brightness value to use for the sunlight AOD mode -->
+ <integer name="config_doze_aod_brightness_sunlight">28</integer>
+
<!-- Doze: whether the double tap sensor reports 2D touch coordinates -->
<bool name="doze_double_tap_reports_touch_coordinates">false</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fcbe3e9..94687de 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -784,6 +784,9 @@
<!-- The shortest-edge size of the expanded PiP. -->
<dimen name="pip_expanded_shortest_edge_size">160dp</dimen>
+ <!-- The additional offset to apply to the IME animation to account for the input field. -->
+ <dimen name="pip_ime_offset">48dp</dimen>
+
<!-- The padding between actions in the PiP in landscape Note that the PiP does not reflect
the configuration of the device, so we can't use -land resources. -->
<dimen name="pip_between_action_padding_land">8dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 44cf003..fe8373f 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -98,7 +98,7 @@
*/
@Override
public GradientColors getColors(int which) {
- return getColors(which, TYPE_NORMAL);
+ return getColors(which, TYPE_DARK);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 0be4eda..a1dfeb3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -91,6 +91,7 @@
case UNINITIALIZED:
case INITIALIZED:
case DOZE:
+ case DOZE_REQUEST_PULSE:
case DOZE_AOD_PAUSED:
return Display.STATE_OFF;
case DOZE_PULSING:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 28a45aa..ed4b131 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -39,6 +39,7 @@
private final int mHighBrightness;
private final int mLowBrightness;
+ private final int mSunlightBrightness;
public DozeScreenBrightness(Context context, DozeMachine.Service service,
SensorManager sensorManager, Sensor lightSensor, Handler handler) {
@@ -52,6 +53,8 @@
R.integer.config_doze_aod_brightness_low);
mHighBrightness = context.getResources().getInteger(
R.integer.config_doze_aod_brightness_high);
+ mSunlightBrightness = context.getResources().getInteger(
+ R.integer.config_doze_aod_brightness_sunlight);
}
@Override
@@ -83,9 +86,12 @@
}
private int computeBrightness(int sensorValue) {
- // The sensor reports 0 for off, 1 for low brightness and 2 for high brightness.
- // We currently use DozeScreenState for screen off, so we treat off as low brightness.
- if (sensorValue >= 2) {
+ // The sensor reports 0 for off, 1 for low brightness, 2 for high brightness, and 3 for
+ // sunlight. We currently use DozeScreenState for screen off, so we treat off as low
+ // brightness.
+ if (sensorValue >= 3) {
+ return mSunlightBrightness;
+ } else if (sensorValue == 2) {
return mHighBrightness;
} else {
return mLowBrightness;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 9b113d8..ad177a7 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -25,8 +25,10 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.HardwareUiLayout;
+import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.volume.VolumeDialogMotion.LogAccelerateInterpolator;
import com.android.systemui.volume.VolumeDialogMotion.LogDecelerateInterpolator;
@@ -65,6 +67,7 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import android.util.MathUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -112,6 +115,8 @@
private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
+ private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
+
private final Context mContext;
private final GlobalActionsManager mWindowManagerFuncs;
private final AudioManager mAudioManager;
@@ -1291,7 +1296,7 @@
.alpha(1)
.translationX(0)
.setDuration(300)
- .setInterpolator(new LogDecelerateInterpolator())
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setUpdateListener(animation -> {
int alpha = (int) ((Float) animation.getAnimatedValue()
* ScrimController.GRADIENT_SCRIM_ALPHA * 255);
@@ -1329,9 +1334,8 @@
.setInterpolator(new LogAccelerateInterpolator())
.setUpdateListener(animation -> {
float frac = animation.getAnimatedFraction();
- float alpha = frac *(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY
- - ScrimController.GRADIENT_SCRIM_ALPHA)
- + ScrimController.GRADIENT_SCRIM_ALPHA;
+ float alpha = NotificationUtils.interpolate(
+ ScrimController.GRADIENT_SCRIM_ALPHA, SHUTDOWN_SCRIM_ALPHA, frac);
mGradientDrawable.setAlpha((int) (alpha * 255));
})
.start();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6d10d94..e23875f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -811,6 +811,7 @@
synchronized (this) {
mDeviceInteractive = false;
mGoingToSleep = false;
+ mWakeAndUnlocking = false;
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
@@ -1957,7 +1958,6 @@
if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff");
mStatusBarKeyguardViewManager.onScreenTurnedOff();
mDrawnCallback = null;
- mWakeAndUnlocking = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 278fdc3..d3be19d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -27,6 +27,7 @@
import android.app.IActivityManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -122,6 +123,7 @@
private boolean mIsMinimized;
private boolean mIsImeShowing;
private int mImeHeight;
+ private int mImeOffset;
private float mSavedSnapFraction = -1f;
private boolean mSendingHoverAccessibilityEvents;
private boolean mMovementWithinMinimize;
@@ -192,8 +194,11 @@
};
mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mMenuController,
mSnapAlgorithm, mFlingAnimationUtils);
- mExpandedShortestEdgeSize = context.getResources().getDimensionPixelSize(
+
+ Resources res = context.getResources();
+ mExpandedShortestEdgeSize = res.getDimensionPixelSize(
R.dimen.pip_expanded_shortest_edge_size);
+ mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
// Register the listener for input consumer touch events
inputConsumerController.setTouchListener(this::handleTouchEvent);
@@ -265,7 +270,6 @@
mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
mIsImeShowing ? mImeHeight : 0);
-
// If this is from an IME adjustment, then we should move the PiP so that it is not occluded
// by the IME
if (fromImeAdjustement) {
@@ -278,18 +282,22 @@
? expandedMovementBounds
: normalMovementBounds;
if (mIsImeShowing) {
- // IME visible
+ // IME visible, apply the IME offset if the space allows for it
+ final int imeOffset = toMovementBounds.bottom - Math.max(toMovementBounds.top,
+ toMovementBounds.bottom - mImeOffset);
if (bounds.top == mMovementBounds.bottom) {
// If the PIP is currently resting on top of the IME, then adjust it with
- // the hiding IME
- bounds.offsetTo(bounds.left, toMovementBounds.bottom);
+ // the showing IME
+ bounds.offsetTo(bounds.left, toMovementBounds.bottom - imeOffset);
} else {
- bounds.offset(0, Math.min(0, toMovementBounds.bottom - bounds.top));
+ bounds.offset(0, Math.min(0, toMovementBounds.bottom - imeOffset
+ - bounds.top));
}
} else {
// IME hidden
- if (bounds.top == mMovementBounds.bottom) {
- // If the PIP is resting on top of the IME, then adjust it with the hiding IME
+ if (bounds.top >= (mMovementBounds.bottom - mImeOffset)) {
+ // If the PIP is resting on top of the IME, then adjust it with the hiding
+ // IME
bounds.offsetTo(bounds.left, toMovementBounds.bottom);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index f591524..2dc467f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -114,6 +114,7 @@
// be invoked when we're done so that the caller can drop the pulse wakelock.
mPulseCallback = callback;
mPulseReason = reason;
+ mScrimController.setDozeInFrontAlpha(1f);
mHandler.post(mPulseIn);
}
@@ -290,10 +291,6 @@
// Signal that the pulse is ready to turn the screen on and draw.
pulseStarted();
-
- if (mDozeParameters.getAlwaysOn()) {
- mHandler.post(DozeScrimController.this::onScreenTurnedOn);
- }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 5af80f5..df059e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -285,7 +285,7 @@
if (!mUpdateMonitor.isDeviceInteractive()) {
if (!mStatusBarKeyguardViewManager.isShowing()) {
return MODE_ONLY_WAKE;
- } else if (pulsingOrAod() && unlockingAllowed) {
+ } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
return MODE_WAKE_AND_UNLOCK_PULSING;
} else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
return MODE_WAKE_AND_UNLOCK;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index a8b1c91..62d4b73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -25,7 +25,6 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.util.Log;
import android.util.MathUtils;
import android.view.View;
import android.view.ViewGroup;
@@ -120,6 +119,12 @@
private boolean mKeyguardFadingOutInProgress;
private boolean mAnimatingDozeUnlock;
private ValueAnimator mKeyguardFadeoutAnimation;
+ /** Wake up from AOD transition is starting; need fully opaque front scrim */
+ private boolean mWakingUpFromAodStarting;
+ /** Wake up from AOD transition is in progress; need black tint */
+ private boolean mWakingUpFromAodInProgress;
+ /** Wake up from AOD transition is animating; need to reset when animation finishes */
+ private boolean mWakingUpFromAodAnimationRunning;
public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
ScrimView scrimInFront, View headsUpScrim) {
@@ -187,9 +192,32 @@
scheduleUpdate();
}
+ public void prepareWakeUpFromAod() {
+ mWakingUpFromAodInProgress = true;
+ mWakingUpFromAodStarting = true;
+ mAnimateChange = false;
+ scheduleUpdate();
+ onPreDraw();
+ }
+
+ public void wakeUpFromAod() {
+ if (mWakeAndUnlocking || mAnimateKeyguardFadingOut) {
+ // Wake and unlocking has a separate transition that must not be interfered with.
+ mWakingUpFromAodStarting = false;
+ return;
+ }
+ if (mWakingUpFromAodStarting) {
+ mWakingUpFromAodInProgress = true;
+ mWakingUpFromAodStarting = false;
+ mAnimateChange = true;
+ scheduleUpdate();
+ }
+ }
+
public void setWakeAndUnlocking() {
mWakeAndUnlocking = true;
mAnimatingDozeUnlock = true;
+ mWakingUpFromAodStarting = false;
scheduleUpdate();
}
@@ -356,7 +384,11 @@
setScrimBehindAlpha(mScrimBehindAlpha);
} else {
float fraction = Math.max(0, Math.min(mFraction, 1));
- setScrimInFrontAlpha(0f);
+ if (mWakingUpFromAodStarting) {
+ setScrimInFrontAlpha(1f);
+ } else {
+ setScrimInFrontAlpha(0f);
+ }
setScrimBehindAlpha(fraction
* (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
+ mScrimBehindAlphaUnlocking);
@@ -426,7 +458,10 @@
scrimView.setViewAlpha(alpha);
int dozeTint = Color.TRANSPARENT;
- if (mAnimatingDozeUnlock || mDozing) {
+
+ boolean dozing = mAnimatingDozeUnlock || mDozing;
+ boolean frontScrimDozing = mWakingUpFromAodInProgress;
+ if (dozing || frontScrimDozing && scrim == mScrimInFront) {
dozeTint = Color.BLACK;
}
scrimView.setTint(dozeTint);
@@ -458,6 +493,10 @@
mKeyguardFadingOutInProgress = false;
mAnimatingDozeUnlock = false;
}
+ if (mWakingUpFromAodAnimationRunning) {
+ mWakingUpFromAodAnimationRunning = false;
+ mWakingUpFromAodInProgress = false;
+ }
scrim.setTag(TAG_KEY_ANIM, null);
scrim.setTag(TAG_KEY_ANIM_TARGET, null);
}
@@ -467,6 +506,9 @@
mKeyguardFadingOutInProgress = true;
mKeyguardFadeoutAnimation = anim;
}
+ if (mWakingUpFromAodInProgress) {
+ mWakingUpFromAodAnimationRunning = true;
+ }
if (mSkipFirstFrame) {
anim.setCurrentPlayTime(16);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index e90d1c1..9e1a2a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -21,6 +21,9 @@
import static android.app.StatusBarManager.windowStateToString;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
@@ -4208,13 +4211,16 @@
}
private boolean updateIsKeyguard() {
+ boolean wakeAndUnlocking = mFingerprintUnlockController.getMode()
+ == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+
// For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
// there's no surface we can show to the user. Note that the device goes fully interactive
// late in the transition, so we also allow the device to start dozing once the screen has
// turned off fully.
boolean keyguardForDozing = mDozingRequested &&
(!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
- boolean shouldBeKeyguard = mKeyguardRequested || keyguardForDozing;
+ boolean shouldBeKeyguard = (mKeyguardRequested || keyguardForDozing) && !wakeAndUnlocking;
if (keyguardForDozing) {
updatePanelExpansionForKeyguard();
}
@@ -4256,7 +4262,8 @@
}
private void updatePanelExpansionForKeyguard() {
- if (mState == StatusBarState.KEYGUARD) {
+ if (mState == StatusBarState.KEYGUARD && mFingerprintUnlockController.getMode()
+ != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) {
instantExpandNotificationsPanel();
} else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
instantCollapseNotificationPanel();
@@ -5156,6 +5163,13 @@
public void onScreenTurningOn() {
mFalsingManager.onScreenTurningOn();
mNotificationPanel.onScreenTurningOn();
+
+ int wakefulness = mWakefulnessLifecycle.getWakefulness();
+ if (mDozing && (wakefulness == WAKEFULNESS_WAKING
+ || wakefulness == WAKEFULNESS_ASLEEP) && !isPulsing()) {
+ mScrimController.prepareWakeUpFromAod();
+ }
+
if (mLaunchCameraOnScreenTurningOn) {
mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
mLaunchCameraOnScreenTurningOn = false;
@@ -5164,13 +5178,18 @@
@Override
public void onScreenTurnedOn() {
+ mScrimController.wakeUpFromAod();
mDozeScrimController.onScreenTurnedOn();
}
@Override
public void onScreenTurnedOff() {
mFalsingManager.onScreenOff();
- updateIsKeyguard();
+ // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard
+ // in that case destroys the HeadsUpManager state, so don't do it in that case.
+ if (!isPulsing()) {
+ updateIsKeyguard();
+ }
}
};
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 203876b..e54c792 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -86,13 +86,13 @@
}
@Test
- public void testScreen_onInRequestPulseWithAoD() {
+ public void testScreen_offInRequestPulseWithAoD() {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
- assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
+ assertEquals(Display.STATE_OFF, mServiceFake.screenState);
}
}
\ No newline at end of file
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index abfc31e..a27a77e 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -123,8 +123,8 @@
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
-
import com.android.server.power.BatterySaverPolicy.ServiceType;
+
import libcore.io.IoUtils;
import java.io.BufferedInputStream;
@@ -691,6 +691,7 @@
final SparseArray<Operation> mCurrentOperations = new SparseArray<Operation>();
final Object mCurrentOpLock = new Object();
final Random mTokenGenerator = new Random();
+ final AtomicInteger mNextToken = new AtomicInteger();
final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<AdbParams>();
@@ -763,15 +764,13 @@
@GuardedBy("mQueueLock")
ArrayList<FullBackupEntry> mFullBackupQueue;
- // Utility: build a new random integer token
+ // Utility: build a new random integer token. The low bits are the ordinal of the
+ // operation for near-time uniqueness, and the upper bits are random for app-
+ // side unpredictability.
@Override
public int generateRandomIntegerToken() {
- int token;
- do {
- synchronized (mTokenGenerator) {
- token = mTokenGenerator.nextInt();
- }
- } while (token < 0);
+ int token = mTokenGenerator.nextInt() & ~0xFF;
+ token |= (mNextToken.incrementAndGet() & 0xFF);
return token;
}
diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index 048bef7..feddfe3 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -163,6 +163,7 @@
ComponentName requestedPackage;
ComponentName callingPackage;
int userId;
+ int processId = -1;
boolean changed = false;
synchronized (mGlobalAmLock) {
vrMode = record.requestedVrComponent != null;
@@ -172,11 +173,15 @@
// Tell the VrController that a VR mode change is requested.
changed = changeVrModeLocked(vrMode, record.app);
+
+ if (record.app != null) {
+ processId = record.app.pid;
+ }
}
// Tell VrManager that a VR mode changed is requested, VrManager will handle
// notifying all non-AM dependencies if needed.
- vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage);
+ vrService.setVrMode(vrMode, requestedPackage, userId, processId, callingPackage);
return changed;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e82724d..cbd02ac 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -165,6 +165,12 @@
// a stylish color fade animation instead.
private boolean mColorFadeFadesConfig;
+ // True if we need to transition to the off state when coming out of a doze state.
+ // Some display hardware will show artifacts (flickers, etc) when transitioning from a doze
+ // to a fully on state. In order to hide these, we first transition to off to let the system
+ // animate the screen on as it normally would, which is a much smoother experience.
+ private boolean mTransitionOffAfterDozeConfig;
+
// The pending power request.
// Initially null until the first call to requestPowerState.
// Guarded by mLock.
@@ -410,6 +416,9 @@
mColorFadeFadesConfig = resources.getBoolean(
com.android.internal.R.bool.config_animateScreenLights);
+ mTransitionOffAfterDozeConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_displayTransitionOffAfterDoze);
+
if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (mProximitySensor != null) {
@@ -877,6 +886,10 @@
}
private boolean setScreenState(int state) {
+ return setScreenState(state, false /*force*/);
+ }
+
+ private boolean setScreenState(int state, boolean force) {
final boolean isOff = (state == Display.STATE_OFF);
if (mPowerState.getScreenState() != state) {
@@ -887,9 +900,17 @@
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_OFF;
blockScreenOff();
mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
- return false;
+ if (force) {
+ // If we're forcing the power state transition then immediately
+ // unblock the screen off event. This keeps the lifecycle consistent,
+ // so WindowManagerPolicy will always see screenTurningOff before
+ // screenTurnedOff, but we don't actually block on them for the state
+ // change.
+ unblockScreenOff();
+ } else {
+ return false;
+ }
} else if (mPendingScreenOffUnblocker != null) {
-
// Abort doing the state change until screen off is unblocked.
return false;
}
@@ -968,6 +989,17 @@
mPendingScreenOff = false;
}
+ if (mTransitionOffAfterDozeConfig &&
+ Display.isDozeState(mPowerState.getScreenState())
+ && !Display.isDozeState(target)) {
+ setScreenState(Display.STATE_OFF, true /*force*/);
+ // Skip the screen off animation and add a black surface to hide the
+ // contents of the screen. This will also trigger another power state update so that we
+ // end up converging on the target state.
+ mColorFadeOffAnimator.end();
+ return;
+ }
+
// If we were in the process of turning off the screen but didn't quite
// finish. Then finish up now to prevent a jarring transition back
// to screen on if we skipped blocking screen on as usual.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8e2097a..d36d2f1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5417,7 +5417,7 @@
// represent should be hidden or if we should hide the lockscreen. For attached app
// windows we defer the decision to the window it is attached to.
if (appWindow && attached == null) {
- if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
+ if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5456,7 +5456,7 @@
// separately, because both the "real fullscreen" opaque window and the one for the docked
// stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
- && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
+ && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
mTopDockedOpaqueWindowState = win;
if (mTopDockedOpaqueOrDimmingWindowState == null) {
mTopDockedOpaqueOrDimmingWindowState = win;
@@ -5481,12 +5481,6 @@
}
}
- private boolean isFullscreen(WindowManager.LayoutParams attrs) {
- return attrs.x == 0 && attrs.y == 0
- && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
- && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
- }
-
/** {@inheritDoc} */
@Override
public int finishPostLayoutPolicyLw() {
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 1f75640..bdd9de0 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -52,10 +52,11 @@
* @param enabled {@code true} to enable VR mode.
* @param packageName The package name of the requested VrListenerService to bind.
* @param userId the user requesting the VrListenerService component.
+ * @param processId the process the component is running in.
* @param calling the component currently using VR mode, or null to leave unchanged.
*/
public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
- int userId, @NonNull ComponentName calling);
+ int userId, int processId, @NonNull ComponentName calling);
/**
* Set whether the system has acquired a sleep token.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index f13cc76..e737328 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -125,6 +125,8 @@
private boolean mVrModeAllowed;
private boolean mVrModeEnabled;
private boolean mPersistentVrModeEnabled;
+ private boolean mRunning2dInVr;
+ private int mVrAppProcessId;
private EnabledComponentsObserver mComponentObserver;
private ManagedApplicationService mCurrentVrService;
private ComponentName mDefaultVrService;
@@ -174,7 +176,7 @@
}
consumeAndApplyPendingStateLocked();
if (mBootsToVr && !mVrModeEnabled) {
- setVrMode(true, mDefaultVrService, 0, null);
+ setVrMode(true, mDefaultVrService, 0, -1, null);
}
} else {
// Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
@@ -183,12 +185,12 @@
// Set pending state to current state.
mPendingState = (mVrModeEnabled && mCurrentVrService != null)
- ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
- mCurrentVrService.getUserId(), mCurrentVrModeComponent)
+ ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
+ mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
: null;
// Unbind current VR service and do necessary callbacks.
- updateCurrentVrServiceLocked(false, null, 0, null);
+ updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
}
}
}
@@ -270,26 +272,33 @@
private static class VrState {
final boolean enabled;
+ final boolean running2dInVr;
final int userId;
+ final int processId;
final ComponentName targetPackageName;
final ComponentName callingPackage;
final long timestamp;
final boolean defaultPermissionsGranted;
- VrState(boolean enabled, ComponentName targetPackageName, int userId,
- ComponentName callingPackage) {
+
+ VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+ int processId, ComponentName callingPackage) {
this.enabled = enabled;
+ this.running2dInVr = running2dInVr;
this.userId = userId;
+ this.processId = processId;
this.targetPackageName = targetPackageName;
this.callingPackage = callingPackage;
this.defaultPermissionsGranted = false;
this.timestamp = System.currentTimeMillis();
}
- VrState(boolean enabled, ComponentName targetPackageName, int userId,
- ComponentName callingPackage, boolean defaultPermissionsGranted) {
+ VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+ int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
this.enabled = enabled;
+ this.running2dInVr = running2dInVr;
this.userId = userId;
+ this.processId = processId;
this.targetPackageName = targetPackageName;
this.callingPackage = callingPackage;
this.defaultPermissionsGranted = defaultPermissionsGranted;
@@ -390,8 +399,9 @@
}
// There is an active service, update it if needed
- updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
- mCurrentVrService.getUserId(), mCurrentVrModeComponent);
+ updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
+ mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
+ mVrAppProcessId, mCurrentVrModeComponent);
}
}
@@ -527,9 +537,9 @@
*/
private final class LocalService extends VrManagerInternal {
@Override
- public void setVrMode(boolean enabled, ComponentName packageName, int userId,
+ public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
ComponentName callingPackage) {
- VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+ VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
}
@Override
@@ -704,14 +714,16 @@
* Note: Must be called while holding {@code mLock}.
*
* @param enabled new state for VR mode.
+ * @param running2dInVr true if we have a top-level 2D intent.
* @param component new component to be bound as a VR listener.
* @param userId user owning the component to be bound.
- * @param calling the component currently using VR mode.
+ * @param processId the process hosting the activity specified by calling.
+ * @param calling the component currently using VR mode or a 2D intent.
*
* @return {@code true} if the component/user combination specified is valid.
*/
- private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
- int userId, ComponentName calling) {
+ private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
+ @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
boolean sendUpdatedCaller = false;
final long identity = Binder.clearCallingIdentity();
@@ -771,6 +783,8 @@
sendUpdatedCaller = true;
}
mCurrentVrModeComponent = calling;
+ mRunning2dInVr = running2dInVr;
+ mVrAppProcessId = processId;
if (mCurrentVrModeUser != userId) {
mCurrentVrModeUser = userId;
@@ -788,11 +802,13 @@
if (mCurrentVrService != null && sendUpdatedCaller) {
final ComponentName c = mCurrentVrModeComponent;
+ final boolean b = running2dInVr;
+ final int pid = processId;
mCurrentVrService.sendEvent(new PendingEvent() {
@Override
public void runEvent(IInterface service) throws RemoteException {
IVrListener l = (IVrListener) service;
- l.focusedActivityChanged(c);
+ l.focusedActivityChanged(c, b, pid);
}
});
}
@@ -1017,20 +1033,20 @@
*/
private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
if (mPendingState != null) {
- updateCurrentVrServiceLocked(mPendingState.enabled,
- mPendingState.targetPackageName, mPendingState.userId,
+ updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
+ mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
mPendingState.callingPackage);
mPendingState = null;
} else if (disconnectIfNoPendingState) {
- updateCurrentVrServiceLocked(false, null, 0, null);
+ updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
}
}
private void logStateLocked() {
ComponentName currentBoundService = (mCurrentVrService == null) ? null :
mCurrentVrService.getComponent();
- VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
- mCurrentVrModeComponent, mWasDefaultGranted);
+ VrState current = new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
+ mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted);
if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
mLoggingDeque.removeFirst();
}
@@ -1074,27 +1090,24 @@
* Implementation of VrManagerInternal calls. These are callable from system services.
*/
private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
- int userId, @NonNull ComponentName callingPackage) {
+ int userId, int processId, @NonNull ComponentName callingPackage) {
synchronized (mLock) {
VrState pending;
ComponentName targetListener;
- ComponentName foregroundVrComponent;
// If the device is in persistent VR mode, then calls to disable VR mode are ignored,
// and the system default VR listener is used.
boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
- if (!enabled && mPersistentVrModeEnabled) {
+ boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
+ if (running2dInVr) {
targetListener = mDefaultVrService;
-
- // Current foreground component isn't a VR one (in 2D app case)
- foregroundVrComponent = null;
} else {
targetListener = targetPackageName;
- foregroundVrComponent = callingPackage;
}
- pending = new VrState(
- targetEnabledState, targetListener, userId, foregroundVrComponent);
+
+ pending = new VrState(targetEnabledState, running2dInVr, targetListener,
+ userId, processId, callingPackage);
if (!mVrModeAllowed) {
// We're not allowed to be in VR mode. Make this state pending. This will be
@@ -1119,8 +1132,8 @@
mPendingState = null;
}
- updateCurrentVrServiceLocked(
- targetEnabledState, targetListener, userId, foregroundVrComponent);
+ updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
+ userId, processId, callingPackage);
}
}
@@ -1129,7 +1142,7 @@
setPersistentModeAndNotifyListenersLocked(enabled);
// Disabling persistent mode when not showing a VR should disable the overall vr mode.
if (!enabled && mCurrentVrModeComponent == null) {
- setVrMode(false, null, 0, null);
+ setVrMode(false, null, 0, -1, null);
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05f4626..a37b2e5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2992,14 +2992,14 @@
// Don't include wallpaper in bounds calculation
if (!w.mIsWallpaper && !mutableIncludeFullDisplay.value) {
if (includeDecor) {
- final TaskStack stack = w.getStack();
- if (stack != null) {
- stack.getBounds(frame);
- }
+ final Task task = w.getTask();
+ if (task != null) {
+ task.getBounds(frame);
+ } else {
- // We want to screenshot with the exact bounds of the surface of the app. Thus,
- // intersect it with the frame.
- frame.intersect(w.mFrame);
+ // No task bounds? Too bad! Ain't no screenshot then.
+ return true;
+ }
} else {
final Rect wf = w.mFrame;
final Rect cr = w.mContentInsets;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc3b146..e5055e9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -624,6 +624,17 @@
return token != null ? token.findMainWindow() : null;
}
+ AppWindowToken getTopFullscreenAppToken() {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final AppWindowToken token = mChildren.get(i);
+ final WindowState win = token.findMainWindow();
+ if (win != null && win.mAttrs.isFullscreen()) {
+ return token;
+ }
+ }
+ return null;
+ }
+
AppWindowToken getTopVisibleAppToken() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final AppWindowToken token = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 469dab4..d7f0496 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -151,14 +151,27 @@
final int currentOrientation;
synchronized (service.mWindowMap) {
final WindowState mainWindow = token.findMainWindow();
- if (mainWindow == null) {
+ final Task task = token.getTask();
+ if (task == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token="
+ + token);
+ return null;
+ }
+ final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken();
+ if (topFullscreenToken == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
+ + task);
+ return null;
+ }
+ final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow();
+ if (mainWindow == null || topFullscreenWindow == null) {
Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+ token);
return null;
}
- sysUiVis = mainWindow.getSystemUiVisibility();
- windowFlags = mainWindow.getAttrs().flags;
- windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+ sysUiVis = topFullscreenWindow.getSystemUiVisibility();
+ windowFlags = topFullscreenWindow.getAttrs().flags;
+ windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags;
layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
layoutParams.type = TYPE_APPLICATION_STARTING;
@@ -172,22 +185,17 @@
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = LayoutParams.MATCH_PARENT;
layoutParams.systemUiVisibility = sysUiVis;
- final Task task = token.getTask();
- if (task != null) {
- layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
+ layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
- final TaskDescription taskDescription = task.getTaskDescription();
- if (taskDescription != null) {
- backgroundColor = taskDescription.getBackgroundColor();
- statusBarColor = taskDescription.getStatusBarColor();
- navigationBarColor = taskDescription.getNavigationBarColor();
- }
- taskBounds = new Rect();
- task.getBounds(taskBounds);
- } else {
- taskBounds = null;
+ final TaskDescription taskDescription = task.getTaskDescription();
+ if (taskDescription != null) {
+ backgroundColor = taskDescription.getBackgroundColor();
+ statusBarColor = taskDescription.getStatusBarColor();
+ navigationBarColor = taskDescription.getNavigationBarColor();
}
- currentOrientation = mainWindow.getConfiguration().orientation;
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ currentOrientation = topFullscreenWindow.getConfiguration().orientation;
}
try {
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
index 984a484..ea207f1 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
@@ -58,7 +58,7 @@
}
public void testTaskIdsPersistence() {
- SparseBooleanArray taskIdsOnFile = mTaskPersister.loadPersistedTaskIdsForUser(testUserId);
+ SparseBooleanArray taskIdsOnFile = new SparseBooleanArray();
for (int i = 0; i < 100; i++) {
taskIdsOnFile.put(getRandomTaskIdForUser(testUserId), true);
}