Merge "Introduce EditorInfo#locales."
diff --git a/api/current.txt b/api/current.txt
index 34a0d46..fac3b2b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28,6 +28,7 @@
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+ field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -5529,6 +5530,8 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
+ method public boolean isNightModeLocked();
+ method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -8285,6 +8288,7 @@
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+ field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
@@ -33148,6 +33152,35 @@
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
}
+ public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+ ctor public NotificationAssistantService();
+ method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+ method public final void clearAnnotation(java.lang.String);
+ method public void onNotificationActionClick(java.lang.String, long, int);
+ method public void onNotificationClick(java.lang.String, long);
+ method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public void onNotificationRemoved(java.lang.String, long, int);
+ method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+ method public final void setAnnotation(java.lang.String, android.app.Notification);
+ field public static final int REASON_APP_CANCEL = 8; // 0x8
+ field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+ field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+ field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+ field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+ field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+ field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+ field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+ field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+ field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+ field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+ field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_USER_STOPPED = 6; // 0x6
+ }
+
+ public class NotificationAssistantService.Adjustment {
+ ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+ }
+
public abstract class NotificationListenerService extends android.app.Service {
ctor public NotificationListenerService();
method public final void cancelAllNotifications();
@@ -33184,11 +33217,19 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public int getImportance();
+ method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public int getRank();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
+ field public static final int IMPORTANCE_DEFAULT = 0; // 0x0
+ field public static final int IMPORTANCE_HIGH = 1; // 0x1
+ field public static final int IMPORTANCE_LOW = -1; // 0xffffffff
+ field public static final int IMPORTANCE_MAX = 2; // 0x2
+ field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe
+ field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
}
public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index f509b05..6e15f93 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -41,6 +41,7 @@
field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+ field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -133,6 +134,7 @@
field public static final java.lang.String MODIFY_AUDIO_ROUTING = "android.permission.MODIFY_AUDIO_ROUTING";
field public static final java.lang.String MODIFY_AUDIO_SETTINGS = "android.permission.MODIFY_AUDIO_SETTINGS";
field public static final java.lang.String MODIFY_CELL_BROADCASTS = "android.permission.MODIFY_CELL_BROADCASTS";
+ field public static final java.lang.String MODIFY_DAY_NIGHT_MODE = "android.permission.MODIFY_DAY_NIGHT_MODE";
field public static final java.lang.String MODIFY_NETWORK_ACCOUNTING = "android.permission.MODIFY_NETWORK_ACCOUNTING";
field public static final java.lang.String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
field public static final java.lang.String MODIFY_PHONE_STATE = "android.permission.MODIFY_PHONE_STATE";
@@ -5648,6 +5650,8 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
+ method public boolean isNightModeLocked();
+ method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -8542,6 +8546,7 @@
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+ field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
@@ -35265,6 +35270,35 @@
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
}
+ public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+ ctor public NotificationAssistantService();
+ method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+ method public final void clearAnnotation(java.lang.String);
+ method public void onNotificationActionClick(java.lang.String, long, int);
+ method public void onNotificationClick(java.lang.String, long);
+ method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public void onNotificationRemoved(java.lang.String, long, int);
+ method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+ method public final void setAnnotation(java.lang.String, android.app.Notification);
+ field public static final int REASON_APP_CANCEL = 8; // 0x8
+ field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+ field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+ field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+ field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+ field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+ field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+ field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+ field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+ field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+ field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+ field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_USER_STOPPED = 6; // 0x6
+ }
+
+ public class NotificationAssistantService.Adjustment {
+ ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+ }
+
public abstract class NotificationListenerService extends android.app.Service {
ctor public NotificationListenerService();
method public final void cancelAllNotifications();
@@ -35308,11 +35342,19 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public int getImportance();
+ method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public int getRank();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
+ field public static final int IMPORTANCE_DEFAULT = 0; // 0x0
+ field public static final int IMPORTANCE_HIGH = 1; // 0x1
+ field public static final int IMPORTANCE_LOW = -1; // 0xffffffff
+ field public static final int IMPORTANCE_MAX = 2; // 0x2
+ field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe
+ field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
}
public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 299b38a..fba944c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -28,6 +28,7 @@
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
field public static final java.lang.String BIND_MIDI_DEVICE_SERVICE = "android.permission.BIND_MIDI_DEVICE_SERVICE";
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
+ field public static final java.lang.String BIND_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE";
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
@@ -5529,6 +5530,8 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
+ method public boolean isNightModeLocked();
+ method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -8285,6 +8288,7 @@
field public static final java.lang.String ACTION_INSERT_OR_EDIT = "android.intent.action.INSERT_OR_EDIT";
field public static final java.lang.String ACTION_INSTALL_PACKAGE = "android.intent.action.INSTALL_PACKAGE";
field public static final java.lang.String ACTION_LOCALE_CHANGED = "android.intent.action.LOCALE_CHANGED";
+ field public static final java.lang.String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
field public static final java.lang.String ACTION_MAIN = "android.intent.action.MAIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_ADDED = "android.intent.action.MANAGED_PROFILE_ADDED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_REMOVED = "android.intent.action.MANAGED_PROFILE_REMOVED";
@@ -33150,6 +33154,35 @@
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
}
+ public abstract class NotificationAssistantService extends android.service.notification.NotificationListenerService {
+ ctor public NotificationAssistantService();
+ method public final void adjustImportance(java.lang.String, android.service.notification.NotificationAssistantService.Adjustment);
+ method public final void clearAnnotation(java.lang.String);
+ method public void onNotificationActionClick(java.lang.String, long, int);
+ method public void onNotificationClick(java.lang.String, long);
+ method public abstract android.service.notification.NotificationAssistantService.Adjustment onNotificationEnqueued(android.service.notification.StatusBarNotification, int, boolean);
+ method public void onNotificationRemoved(java.lang.String, long, int);
+ method public void onNotificationVisibilityChanged(java.lang.String, long, boolean);
+ method public final void setAnnotation(java.lang.String, android.app.Notification);
+ field public static final int REASON_APP_CANCEL = 8; // 0x8
+ field public static final int REASON_APP_CANCEL_ALL = 9; // 0x9
+ field public static final int REASON_DELEGATE_CANCEL = 2; // 0x2
+ field public static final int REASON_DELEGATE_CANCEL_ALL = 3; // 0x3
+ field public static final int REASON_DELEGATE_CLICK = 1; // 0x1
+ field public static final int REASON_DELEGATE_ERROR = 4; // 0x4
+ field public static final int REASON_GROUP_OPTIMIZATION = 13; // 0xd
+ field public static final int REASON_GROUP_SUMMARY_CANCELED = 12; // 0xc
+ field public static final int REASON_LISTENER_CANCEL = 10; // 0xa
+ field public static final int REASON_LISTENER_CANCEL_ALL = 11; // 0xb
+ field public static final int REASON_PACKAGE_BANNED = 7; // 0x7
+ field public static final int REASON_PACKAGE_CHANGED = 5; // 0x5
+ field public static final int REASON_USER_STOPPED = 6; // 0x6
+ }
+
+ public class NotificationAssistantService.Adjustment {
+ ctor public NotificationAssistantService.Adjustment(int, java.lang.CharSequence, android.net.Uri);
+ }
+
public abstract class NotificationListenerService extends android.app.Service {
ctor public NotificationListenerService();
method public final void cancelAllNotifications();
@@ -33186,11 +33219,19 @@
public static class NotificationListenerService.Ranking {
ctor public NotificationListenerService.Ranking();
+ method public int getImportance();
+ method public java.lang.CharSequence getImportanceExplanation();
method public java.lang.String getKey();
method public int getRank();
method public int getSuppressedVisualEffects();
method public boolean isAmbient();
method public boolean matchesInterruptionFilter();
+ field public static final int IMPORTANCE_DEFAULT = 0; // 0x0
+ field public static final int IMPORTANCE_HIGH = 1; // 0x1
+ field public static final int IMPORTANCE_LOW = -1; // 0xffffffff
+ field public static final int IMPORTANCE_MAX = 2; // 0x2
+ field public static final int IMPORTANCE_NONE = -2; // 0xfffffffe
+ field public static final int IMPORTANCE_UNSPECIFIED = -1000; // 0xfffffc18
}
public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 74f0c0e..c264368 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4841,7 +4841,7 @@
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
-
+ instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
index 7e9873e..cae54b6 100644
--- a/core/java/android/app/IUiModeManager.aidl
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -51,4 +51,14 @@
* 2 for night, and 3 for automatic mode switching.
*/
int getNightMode();
+
+ /**
+ * Tells if UI mode is locked or not.
+ */
+ boolean isUiModeLocked();
+
+ /**
+ * Tells if Night mode is locked or not.
+ */
+ boolean isNightModeLocked();
}
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 0f6ce12..44164158 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -233,4 +233,35 @@
}
return -1;
}
+
+ /**
+ * @return If UI mode is locked or not. When UI mode is locked, calls to change UI mode
+ * like {@link #enableCarMode(int)} will silently fail.
+ */
+ public boolean isUiModeLocked() {
+ if (mService != null) {
+ try {
+ return mService.isUiModeLocked();
+ } catch (RemoteException e) {
+ Log.e(TAG, "isUiModeLocked: RemoteException", e);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return If Night mode is locked or not. When Night mode is locked, changing Night mode
+ * is only allowed to privileged system components and normal application's call
+ * to change Night mode using {@link #setNightMode(int)} will silently fail.
+ */
+ public boolean isNightModeLocked() {
+ if (mService != null) {
+ try {
+ return mService.isNightModeLocked();
+ } catch (RemoteException e) {
+ Log.e(TAG, "isNightModeLocked: RemoteException", e);
+ }
+ }
+ return true;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index d27dfa0..cd5c205 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -25,6 +25,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.ParcelUuid;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -823,6 +824,9 @@
return false;
}
try {
+ Log.i(TAG, "createBond() for device " + getAddress() +
+ " called by pid: " + Process.myPid() +
+ " tid: " + Process.myTid());
return sService.createBond(this, TRANSPORT_AUTO);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
@@ -854,6 +858,9 @@
throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
}
try {
+ Log.i(TAG, "createBond() for device " + getAddress() +
+ " called by pid: " + Process.myPid() +
+ " tid: " + Process.myTid());
return sService.createBond(this, transport);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
@@ -922,6 +929,9 @@
return false;
}
try {
+ Log.i(TAG, "cancelBondProcess() for device " + getAddress() +
+ " called by pid: " + Process.myPid() +
+ " tid: " + Process.myTid());
return sService.cancelBondProcess(this);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
@@ -943,6 +953,9 @@
return false;
}
try {
+ Log.i(TAG, "removeBond() for device " + getAddress() +
+ " called by pid: " + Process.myPid() +
+ " tid: " + Process.myTid());
return sService.removeBond(this);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 853bc6c..9d0ebc2 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -986,6 +986,7 @@
stableProvider = acquireProvider(uri);
}
releaseUnstableProvider(unstableProvider);
+ unstableProvider = null;
ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
fd.getParcelFileDescriptor(), stableProvider);
@@ -1130,6 +1131,7 @@
stableProvider = acquireProvider(uri);
}
releaseUnstableProvider(unstableProvider);
+ unstableProvider = null;
ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
fd.getParcelFileDescriptor(), stableProvider);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2178c38..b65d825 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1926,6 +1926,24 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED";
+
+ /**
+ * Broadcast Action: This is broadcast once, after the system has finished
+ * booting and the user is in a "locked" state. A user is locked when their
+ * credential-encrypted private app data storage is unavailable. Once the
+ * user has entered their credentials (such as a lock pattern or PIN) for
+ * the first time, the {@link #ACTION_BOOT_COMPLETED} broadcast will be
+ * sent.
+ * <p>
+ * You must hold the
+ * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission in
+ * order to receive this broadcast.
+ * <p class="note">
+ * This is a protected intent that can only be sent by the system.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_LOCKED_BOOT_COMPLETED = "android.intent.action.LOCKED_BOOT_COMPLETED";
+
/**
* Broadcast Action: This is broadcast once, after the system has finished
* booting. It can be used to perform application-specific initialization,
@@ -1938,6 +1956,7 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
+
/**
* Broadcast Action: This is broadcast when a user action should request a
* temporary system dialog to dismiss. Some examples of temporary system
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 8b2c74f..f1672df 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1931,9 +1931,9 @@
// so we'll report it and bail on all of the current strict mode violations
// we currently are maintaining for this thread.
// First, drain the remaining violations from the parcel.
- while (i < numViolations) {
+ i++; // Skip the current entry.
+ for (; i < numViolations; i++) {
info = new ViolationInfo(p, !currentlyGathering);
- i++;
}
// Next clear out all gathered violations.
clearGatheredViolations();
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
new file mode 100644
index 0000000..5d1317c
--- /dev/null
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2015 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.service.notification;
+
+import android.app.Notification;
+import android.net.Uri;
+
+/**
+ * A service that helps the user manage notifications by modifying the
+ * relative importance of notifications.
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * <service android:name=".NotificationAssistant"
+ * android:label="@string/service_name"
+ * android:permission="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.notification.NotificationAssistantService" />
+ * </intent-filter>
+ * </service></pre>
+ */
+public abstract class NotificationAssistantService extends NotificationListenerService {
+ /** Notification was canceled by the status bar reporting a click. */
+ public static final int REASON_DELEGATE_CLICK = 1;
+
+ /** Notification was canceled by the status bar reporting a user dismissal. */
+ public static final int REASON_DELEGATE_CANCEL = 2;
+
+ /** Notification was canceled by the status bar reporting a user dismiss all. */
+ public static final int REASON_DELEGATE_CANCEL_ALL = 3;
+
+ /** Notification was canceled by the status bar reporting an inflation error. */
+ public static final int REASON_DELEGATE_ERROR = 4;
+
+ /** Notification was canceled by the package manager modifying the package. */
+ public static final int REASON_PACKAGE_CHANGED = 5;
+
+ /** Notification was canceled by the owning user context being stopped. */
+ public static final int REASON_USER_STOPPED = 6;
+
+ /** Notification was canceled by the user banning the package. */
+ public static final int REASON_PACKAGE_BANNED = 7;
+
+ /** Notification was canceled by the app canceling this specific notification. */
+ public static final int REASON_APP_CANCEL = 8;
+
+ /** Notification was canceled by the app cancelling all its notifications. */
+ public static final int REASON_APP_CANCEL_ALL = 9;
+
+ /** Notification was canceled by a listener reporting a user dismissal. */
+ public static final int REASON_LISTENER_CANCEL = 10;
+
+ /** Notification was canceled by a listener reporting a user dismiss all. */
+ public static final int REASON_LISTENER_CANCEL_ALL = 11;
+
+ /** Notification was canceled because it was a member of a canceled group. */
+ public static final int REASON_GROUP_SUMMARY_CANCELED = 12;
+
+ /** Notification was canceled because it was an invisible member of a group. */
+ public static final int REASON_GROUP_OPTIMIZATION = 13;
+
+ public class Adjustment {
+ int mImportance;
+ CharSequence mExplanation;
+ Uri mReference;
+
+ /**
+ * Create a notification importance adjustment.
+ *
+ * @param importance The final importance of the notification.
+ * @param explanation A human-readable justification for the adjustment.
+ * @param reference A reference to an external object that augments the
+ * explanation, such as a
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI},
+ * or null.
+ */
+ public Adjustment(int importance, CharSequence explanation, Uri reference) {
+ mImportance = importance;
+ mExplanation = explanation;
+ mReference = reference;
+ }
+ }
+
+ /**
+ * A notification was posted by an app. Called before alert.
+ *
+ * @param sbn the new notification
+ * @param importance the initial importance of the notification.
+ * @param user true if the initial importance reflects an explicit user preference.
+ * @return an adjustment or null to take no action, within 100ms.
+ */
+ abstract public Adjustment onNotificationEnqueued(StatusBarNotification sbn,
+ int importance, boolean user);
+
+ /**
+ * The visibility of a notification has changed.
+ *
+ * @param key the notification key
+ * @param time milliseconds since midnight, January 1, 1970 UTC.
+ * @param visible true if the notification became visible, false if hidden.
+ */
+ public void onNotificationVisibilityChanged(String key, long time, boolean visible)
+ {
+ // Do nothing, Override this to collect visibility statistics.
+ }
+
+ /**
+ * The user clicked on a notification.
+ *
+ * @param key the notification key
+ * @param time milliseconds since midnight, January 1, 1970 UTC.
+ */
+ public void onNotificationClick(String key, long time)
+ {
+ // Do nothing, Override this to collect click statistics
+ }
+
+ /**
+ * The user clicked on a notification action.
+ *
+ * @param key the notification key
+ * @param time milliseconds since midnight, January 1, 1970 UTC.
+ * @param actionIndex the index of the action button that was pressed.
+ */
+ public void onNotificationActionClick(String key, long time, int actionIndex)
+ {
+ // Do nothing, Override this to collect action button click statistics
+ }
+
+ /**
+ * A notification was removed.
+
+ * @param key the notification key
+ * @param time milliseconds since midnight, January 1, 1970 UTC.
+ * @param reason see {@link #REASON_LISTENER_CANCEL}, etc.
+ */
+ public void onNotificationRemoved(String key, long time, int reason) {
+ // Do nothing, Override this to collect dismissal statistics
+ }
+
+ /**
+ * Change the importance of an existing notification. N.B. this won’t cause
+ * an existing notification to alert, but might allow a future update to
+ * this notification to alert.
+ *
+ * @param key the notification key
+ * @param adjustment the new importance with an explanation
+ */
+ public final void adjustImportance(String key, Adjustment adjustment)
+ {
+ // TODO: pack up the adjustment and send it to the NotificationManager.
+ }
+
+ /**
+ * Add an annotation to a an existing notification. The delete intent will
+ * be fired when the host notification is deleted, or when this annotation
+ * is removed or replaced.
+ *
+ * @param key the notification key
+ * @param annotation the new annotation object
+ */
+ public final void setAnnotation(String key, Notification annotation)
+ {
+ // TODO: pack up the annotation and send it to the NotificationManager.
+ }
+
+ /**
+ * Remove the annotation from a notification.
+ *
+ * @param key the notification key
+ */
+ public final void clearAnnotation(String key)
+ {
+ // TODO: ask the NotificationManager to clear the annotation.
+ }
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index ee97e8e..d741f1a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -822,6 +822,41 @@
* @hide */
public static final int VISIBILITY_NO_OVERRIDE = -1000;
+ /**
+ * Value signifying thatn the has not expressed an importance.
+ *
+ * This value is for persisting preferences, and should never ve associated with
+ * an actual notification.
+ */
+ public static final int IMPORTANCE_UNSPECIFIED = -1000;
+
+ /**
+ * A notification with no importance: shows nowhere, is blocked.
+ */
+ public static final int IMPORTANCE_NONE = -2;
+
+ /**
+ * Low notification importance: only shows in the shade, below the fold.
+ */
+ public static final int IMPORTANCE_LOW = -1;
+
+ /**
+ * Default notification importance: shows everywhere, but is not intrusive.
+ */
+ public static final int IMPORTANCE_DEFAULT = 0;
+
+ /**
+ * Higher notification importance: shows everywhere, makes noise,
+ * but does not visually intrude.
+ */
+ public static final int IMPORTANCE_HIGH = 1;
+
+ /**
+ * Highest notification importance: shows everywhere, makes noise,
+ * and also visually intrudes.
+ */
+ public static final int IMPORTANCE_MAX = 2;
+
private String mKey;
private int mRank = -1;
private boolean mIsAmbient;
@@ -875,7 +910,6 @@
return mSuppressedVisualEffects;
}
-
/**
* Returns whether the notification matches the user's interruption
* filter.
@@ -887,6 +921,27 @@
return mMatchesInterruptionFilter;
}
+ /**
+ * Returns the importance of the notification, which dictates its
+ * modes of presentation, see: {@link #IMPORTANCE_DEFAULT}, etc.
+ *
+ * @return the rank of the notification
+ */
+ public int getImportance() {
+ return IMPORTANCE_DEFAULT; // TODO implement;
+ }
+
+ /**
+ * If the importance has been overriden by user preference, or by a
+ * {@link NotificationAssistantService}, then this will be non-null,
+ * and should be displayed to the user.
+ *
+ * @return the explanation for the importance, or null if it is the natural importance
+ */
+ public CharSequence getImportanceExplanation() {
+ return null; // TODO implement
+ }
+
private void populate(String key, int rank, boolean isAmbient,
boolean matchesInterruptionFilter, int visibilityOverride,
int suppressedVisualEffects) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3669d97..fc347ea 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3057,14 +3057,29 @@
/**
* @hide
*
- * Makes system ui transparent.
+ * Makes navigation bar transparent (but not the status bar).
*/
- public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
+ public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
+
+ /**
+ * @hide
+ *
+ * Makes status bar transparent (but not the navigation bar).
+ */
+ public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
+
+ /**
+ * @hide
+ *
+ * Makes both status bar and navigation bar transparent.
+ */
+ public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
+ | STATUS_BAR_TRANSPARENT;
/**
* @hide
*/
- public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
+ public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
/**
* These are the system UI flags that can be cleared by events outside
@@ -5505,20 +5520,26 @@
}
/**
- * Bring up the context menu for this view.
+ * Shows the context menu for this view.
*
- * @return Whether a context menu was displayed.
+ * @return {@code true} if the context menu was shown, {@code false}
+ * otherwise
+ * @see #showContextMenu(float, float)
*/
public boolean showContextMenu() {
return getParent().showContextMenuForChild(this);
}
/**
- * Bring up the context menu for this view, referring to the item under the specified point.
+ * Shows the context menu for this view anchored to the specified
+ * view-relative coordinate.
*
- * @param x The referenced x coordinate.
- * @param y The referenced y coordinate.
- * @return Whether a context menu was displayed.
+ * @param x the X coordinate in pixels relative to the view to which the
+ * menu should be anchored
+ * @param y the Y coordinate in pixels relative to the view to which the
+ * menu should be anchored
+ * @return {@code true} if the context menu was shown, {@code false}
+ * otherwise
*/
public boolean showContextMenu(float x, float y) {
return getParent().showContextMenuForChild(this, x, y);
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 6ae448a..f2ab35e 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -174,26 +174,38 @@
public void focusableViewAvailable(View v);
/**
- * Bring up a context menu for the specified view or its ancestors.
- *
- * <p>In most cases, a subclass does not need to override this. However, if
+ * Shows the context menu for the specified view or its ancestors.
+ * <p>
+ * In most cases, a subclass does not need to override this. However, if
* the subclass is added directly to the window manager (for example,
* {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
- * then it should override this and show the context menu.</p>
- *
- * @param originalView The source view where the context menu was first invoked
- * @return true if a context menu was displayed
+ * then it should override this and show the context menu.
+ *
+ * @param originalView the source view where the context menu was first
+ * invoked
+ * @return {@code true} if the context menu was shown, {@code false}
+ * otherwise
+ * @see #showContextMenuForChild(View, float, float)
*/
public boolean showContextMenuForChild(View originalView);
/**
- * Bring up a context menu for the specified view at the given x/y offset from
- * the top left corner.
+ * Shows the context menu for the specified view or its ancestors anchored
+ * to the specified view-relative coordinate.
+ * <p>
+ * In most cases, a subclass does not need to override this. However, if
+ * the subclass is added directly to the window manager (for example,
+ * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
+ * then it should override this and show the context menu.
*
- * @param originalView
- * @param x The x offset at which to open the menu
- * @param y The y offset at which to open the menu
- * @return true if a context menu was displayed
+ * @param originalView the source view where the context menu was first
+ * invoked
+ * @param x the X coordinate in pixels relative to the original view to
+ * which the menu should be anchored
+ * @param y the Y coordinate in pixels relative to the original view to
+ * which the menu should be anchored
+ * @return {@code true} if the context menu was shown, {@code false}
+ * otherwise
*/
public boolean showContextMenuForChild(View originalView, float x, float y);
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 41f1ce7..0032f17 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -933,7 +933,7 @@
super(context, menu, anchorView, overflowOnly,
com.android.internal.R.attr.actionOverflowMenuStyle);
setGravity(Gravity.END);
- setCallback(mPopupPresenterCallback);
+ setPresenterCallback(mPopupPresenterCallback);
}
@Override
@@ -956,7 +956,7 @@
setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
}
- setCallback(mPopupPresenterCallback);
+ setPresenterCallback(mPopupPresenterCallback);
}
@Override
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 01ac22e..f0c1094 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -371,17 +371,17 @@
}
// TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}.
String[] localeParams = localeStr.split("_", 3);
+ if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
+ // Convert a locale whose language is "tl" to one whose language is "fil".
+ // For example, "tl_PH" will get converted to "fil_PH".
+ // Versions of Android earlier than Lollipop did not support three letter language
+ // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
+ // On Lollipop and above, the current three letter version must be used.
+ localeParams[0] = "fil";
+ }
// The length of localeStr is guaranteed to always return a 1 <= value <= 3
// because localeStr is not empty.
if (localeParams.length == 1) {
- if (localeParams.length >= 1 && "tl".equals(localeParams[0])) {
- // Convert a locale whose language is "tl" to one whose language is "fil".
- // For example, "tl_PH" will get converted to "fil_PH".
- // Versions of Android earlier than Lollipop did not support three letter language
- // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino).
- // On Lollipop and above, the current three letter version must be used.
- localeParams[0] = "fil";
- }
return new Locale(localeParams[0]);
} else if (localeParams.length == 2) {
return new Locale(localeParams[0], localeParams[1]);
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index b101733..75ca639 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -17,6 +17,7 @@
package com.android.internal.policy;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.view.Choreographer;
@@ -44,6 +45,7 @@
// The render nodes for the multi threaded renderer.
private ThreadedRenderer mRenderer;
private RenderNode mFrameAndBackdropNode;
+ private RenderNode mSystemBarBackgroundNode;
private final Rect mOldTargetRect = new Rect();
private final Rect mNewTargetRect = new Rect();
@@ -62,13 +64,16 @@
private Drawable mCaptionBackgroundDrawable;
private Drawable mResizingBackgroundDrawable;
+ private ColorDrawable mStatusBarColor;
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
- Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable) {
+ Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
+ int statusBarColor) {
setName("ResizeFrame");
mRenderer = renderer;
- onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable);
+ onResourcesLoaded(decorView, resizingBackgroundDrawable, captionBackgroundDrawable,
+ statusBarColor);
// Create a render node for the content and frame backdrop
// which can be resized independently from the content.
@@ -87,10 +92,24 @@
}
void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
- Drawable captionBackgroundDrawableDrawable) {
+ Drawable captionBackgroundDrawableDrawable, int statusBarColor) {
mDecorView = decorView;
mResizingBackgroundDrawable = resizingBackgroundDrawable;
mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable;
+ if (statusBarColor != 0) {
+ mStatusBarColor = new ColorDrawable(statusBarColor);
+ addSystemBarNodeIfNeeded();
+ } else {
+ mStatusBarColor = null;
+ }
+ }
+
+ private void addSystemBarNodeIfNeeded() {
+ if (mSystemBarBackgroundNode != null) {
+ return;
+ }
+ mSystemBarBackgroundNode = RenderNode.create("SystemBarBackgroundNode", null);
+ mRenderer.addRenderNode(mSystemBarBackgroundNode, false);
}
/**
@@ -132,6 +151,9 @@
// Remove the render node again
// (see comment above - better to do that only once).
mRenderer.removeRenderNode(mFrameAndBackdropNode);
+ if (mSystemBarBackgroundNode != null) {
+ mRenderer.removeRenderNode(mSystemBarBackgroundNode);
+ }
mRenderer = null;
@@ -232,6 +254,8 @@
// inaccessible. For that case we remember the previous metrics to avoid flashes.
// Note that even when there is no visible caption, the caption child will exist.
final int captionHeight = mDecorView.getCaptionHeight();
+ final int statusBarHeight = mDecorView.getStatusBarHeight();
+
// The caption height will probably never dynamically change while we are resizing.
// Once set to something other then 0 it should be kept that way.
if (captionHeight != 0) {
@@ -256,7 +280,7 @@
mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
// Draw the caption and content backdrops in to our render node.
- final DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
+ DisplayListCanvas canvas = mFrameAndBackdropNode.start(width, height);
mCaptionBackgroundDrawable.setBounds(0, 0, left + width, top + mLastCaptionHeight);
mCaptionBackgroundDrawable.draw(canvas);
@@ -265,6 +289,15 @@
mResizingBackgroundDrawable.draw(canvas);
mFrameAndBackdropNode.end(canvas);
+ if (mSystemBarBackgroundNode != null && mStatusBarColor != null) {
+ canvas = mSystemBarBackgroundNode.start(width, height);
+ mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
+ mStatusBarColor.setBounds(0, 0, left + width, statusBarHeight);
+ mStatusBarColor.draw(canvas);
+ mSystemBarBackgroundNode.end(canvas);
+ mRenderer.drawRenderNode(mSystemBarBackgroundNode);
+ }
+
// We need to render the node explicitly
mRenderer.drawRenderNode(mFrameAndBackdropNode);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 27fe03c..9107b1f 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -21,8 +21,7 @@
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.StandaloneActionMode;
import com.android.internal.view.menu.ContextMenuBuilder;
-import com.android.internal.view.menu.MenuDialogHelper;
-import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuHelper;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.DecorCaptionView;
@@ -152,6 +151,8 @@
private final Interpolator mShowInterpolator;
private final Interpolator mHideInterpolator;
private final int mBarEnterExitDuration;
+ private final boolean mForceWindowDrawsStatusBarBackground;
+ private final int mSemiTransparentStatusBarColor;
private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
@@ -198,6 +199,10 @@
mBarEnterExitDuration = context.getResources().getInteger(
R.integer.dock_enter_exit_duration);
+ mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean(
+ R.bool.config_forceWindowDrawsStatusBarBackground);
+ mSemiTransparentStatusBarColor = context.getResources().getColor(
+ R.color.system_bar_background_semi_transparent, null /* theme */);
setWindow(window);
}
@@ -659,30 +664,23 @@
@Override
public boolean showContextMenuForChild(View originalView) {
- // Reuse the context menu builder
- if (mWindow.mContextMenu == null) {
- mWindow.mContextMenu = new ContextMenuBuilder(getContext());
- mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
- } else {
- mWindow.mContextMenu.clearAll();
- }
-
- final MenuDialogHelper helper = mWindow.mContextMenu.show(originalView,
- originalView.getWindowToken());
- if (helper != null) {
- helper.setPresenterCallback(mWindow.mContextMenuCallback);
- } else if (mWindow.mContextMenuHelper != null) {
- // No menu to show, but if we have a menu currently showing it just became blank.
- // Close it.
- mWindow.mContextMenuHelper.dismiss();
- }
- mWindow.mContextMenuHelper = helper;
- return helper != null;
+ return showContextMenuForChildInternal(originalView, 0, 0, false);
}
@Override
public boolean showContextMenuForChild(View originalView, float x, float y) {
- // Reuse the context menu builder
+ return showContextMenuForChildInternal(originalView, x, y, true);
+ }
+
+ private boolean showContextMenuForChildInternal(View originalView,
+ float x, float y, boolean isPopup) {
+ // Only allow one context menu at a time.
+ if (mWindow.mContextMenuHelper != null) {
+ mWindow.mContextMenuHelper.dismiss();
+ mWindow.mContextMenuHelper = null;
+ }
+
+ // Reuse the context menu builder.
if (mWindow.mContextMenu == null) {
mWindow.mContextMenu = new ContextMenuBuilder(getContext());
mWindow.mContextMenu.setCallback(mWindow.mContextMenuCallback);
@@ -690,16 +688,18 @@
mWindow.mContextMenu.clearAll();
}
- final MenuPopupHelper helper = mWindow.mContextMenu.showPopup(
- getContext(), originalView, x, y);
- if (helper != null) {
- helper.setCallback(mWindow.mContextMenuCallback);
- } else if (mWindow.mContextMenuPopupHelper != null) {
- // No menu to show, but if we have a menu currently showing it just became blank.
- // Close it.
- mWindow.mContextMenuPopupHelper.dismiss();
+ final MenuHelper helper;
+ if (isPopup) {
+ helper = mWindow.mContextMenu.showPopup(getContext(), originalView, x, y);
+ } else {
+ helper = mWindow.mContextMenu.showDialog(originalView, originalView.getWindowToken());
}
- mWindow.mContextMenuPopupHelper = helper;
+
+ if (helper != null) {
+ helper.setPresenterCallback(mWindow.mContextMenuCallback);
+ }
+
+ mWindow.mContextMenuHelper = helper;
return helper != null;
}
@@ -890,14 +890,15 @@
int navBarSize = navBarToRightEdge ? mLastRightInset : mLastBottomInset;
updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge,
- 0 /* rightInset */, animate && !disallowAnimate);
+ 0 /* rightInset */, animate && !disallowAnimate, false /* force */);
boolean statusBarNeedsRightInset = navBarToRightEdge
&& mNavigationColorViewState.present;
int statusBarRightInset = statusBarNeedsRightInset ? mLastRightInset : 0;
- updateColorViewInt(mStatusColorViewState, sysUiVisibility, mWindow.mStatusBarColor,
- mLastTopInset, false /* matchVertical */, statusBarRightInset,
- animate && !disallowAnimate);
+ updateColorViewInt(mStatusColorViewState, sysUiVisibility,
+ calculateStatusBarColor(), mLastTopInset,
+ false /* matchVertical */, statusBarRightInset, animate && !disallowAnimate,
+ mForceWindowDrawsStatusBarBackground);
}
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
@@ -941,6 +942,21 @@
return insets;
}
+ private int calculateStatusBarColor() {
+ int flags = mWindow.getAttributes().flags;
+ return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? mSemiTransparentStatusBarColor
+ : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? mWindow.mStatusBarColor
+ : Color.BLACK;
+ }
+
+ private int getCurrentColor(ColorViewState state) {
+ if (state.visible) {
+ return state.color;
+ } else {
+ return 0;
+ }
+ }
+
/**
* Update a color view
*
@@ -954,13 +970,15 @@
* @param animate if true, the change will be animated.
*/
private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
- int size, boolean verticalBar, int rightMargin, boolean animate) {
+ int size, boolean verticalBar, int rightMargin, boolean animate, boolean force) {
state.present = size > 0 && (sysUiVis & state.systemUiHideFlag) == 0
&& (mWindow.getAttributes().flags & state.hideWindowFlag) == 0
- && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ && ((mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ || force);
boolean show = state.present
&& (color & Color.BLACK) != 0
- && (mWindow.getAttributes().flags & state.translucentFlag) == 0;
+ && ((mWindow.getAttributes().flags & state.translucentFlag) == 0 || force);
+ boolean showView = show && !isResizing();
boolean visibilityChanged = false;
View view = state.view;
@@ -970,7 +988,7 @@
int resolvedGravity = verticalBar ? state.horizontalGravity : state.verticalGravity;
if (view == null) {
- if (show) {
+ if (showView) {
state.view = view = new View(mContext);
view.setBackgroundColor(color);
view.setTransitionName(state.transitionName);
@@ -986,7 +1004,7 @@
updateColorViewTranslations();
}
} else {
- int vis = show ? VISIBLE : INVISIBLE;
+ int vis = showView ? VISIBLE : INVISIBLE;
visibilityChanged = state.targetVisibility != vis;
state.targetVisibility = vis;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
@@ -998,14 +1016,14 @@
lp.rightMargin = rightMargin;
view.setLayoutParams(lp);
}
- if (show) {
+ if (showView) {
view.setBackgroundColor(color);
}
}
if (visibilityChanged) {
view.animate().cancel();
- if (animate) {
- if (show) {
+ if (animate && !isResizing()) {
+ if (showView) {
if (view.getVisibility() != VISIBLE) {
view.setVisibility(VISIBLE);
view.setAlpha(0.0f);
@@ -1025,9 +1043,11 @@
}
} else {
view.setAlpha(1.0f);
- view.setVisibility(show ? VISIBLE : INVISIBLE);
+ view.setVisibility(showView ? VISIBLE : INVISIBLE);
}
}
+ state.visible = show;
+ state.color = color;
}
private void updateColorViewTranslations() {
@@ -1559,7 +1579,8 @@
if (mBackdropFrameRenderer != null) {
mBackdropFrameRenderer.onResourcesLoaded(
- this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+ this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
+ getCurrentColor(mStatusColorViewState));
}
mDecorCaptionView = createDecorCaptionView(inflater);
@@ -1674,9 +1695,15 @@
if (mDecorCaptionView != null) {
mDecorCaptionView.removeContentView();
} else {
- // This window doesn't have caption, so we need to just remove the
- // children of the decor view.
- removeAllViews();
+ // This window doesn't have caption, so we need to remove everything except our views
+ // we might have added.
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ View v = getChildAt(i);
+ if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
+ && v != mStatusGuard && v != mNavigationGuard) {
+ removeViewAt(i);
+ }
+ }
}
}
@@ -1700,18 +1727,22 @@
final ThreadedRenderer renderer = (ThreadedRenderer) getHardwareRenderer();
if (renderer != null) {
mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
- initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
+ initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
+ getCurrentColor(mStatusColorViewState));
// Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
// If we want to get the shadow shown while resizing, we would need to elevate a new
// element which owns the caption and has the elevation.
updateElevation();
+
+ updateColorViews(null /* insets */, false);
}
}
@Override
public void onWindowDragResizeEnd() {
releaseThreadedRenderer();
+ updateColorViews(null /* insets */, false);
}
@Override
@@ -1744,6 +1775,10 @@
}
}
+ private boolean isResizing() {
+ return mBackdropFrameRenderer != null;
+ }
+
/**
* The elevation gets set for the first time and the framework needs to be informed that
* the surface layer gets created with the shadow size in mind.
@@ -1759,8 +1794,7 @@
final boolean wasAdjustedForStack = mElevationAdjustedForStack;
// Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
// since the shadow is bound to the content size and not the target size.
- if (ActivityManager.StackId.hasWindowShadow(mStackId)
- && mBackdropFrameRenderer == null) {
+ if (ActivityManager.StackId.hasWindowShadow(mStackId) && !isResizing()) {
elevation = hasWindowFocus() ?
DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
// TODO(skuhne): Remove this if clause once b/22668382 got fixed.
@@ -1790,6 +1824,10 @@
return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
}
+ int getStatusBarHeight() {
+ return mStatusColorViewState.view != null ? mStatusColorViewState.view.getHeight() : 0;
+ }
+
/**
* Converts a DIP measure into physical pixels.
* @param dip The dip value.
@@ -1804,6 +1842,8 @@
View view = null;
int targetVisibility = View.INVISIBLE;
boolean present = false;
+ boolean visible;
+ int color;
final int id;
final int systemUiHideFlag;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 6e7e5cf..57d2244 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -53,7 +53,7 @@
import com.android.internal.view.menu.ListMenuPresenter;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuDialogHelper;
-import com.android.internal.view.menu.MenuPopupHelper;
+import com.android.internal.view.menu.MenuHelper;
import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
import com.android.internal.widget.DecorContentParent;
@@ -232,8 +232,7 @@
private boolean mAlwaysReadCloseOnTouchAttr = false;
ContextMenuBuilder mContextMenu;
- MenuDialogHelper mContextMenuHelper;
- MenuPopupHelper mContextMenuPopupHelper;
+ MenuHelper mContextMenuHelper;
private boolean mClosingActionMenu;
private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
@@ -1103,10 +1102,6 @@
mContextMenuHelper.dismiss();
mContextMenuHelper = null;
}
- if (mContextMenuPopupHelper != null) {
- mContextMenuPopupHelper.dismiss();
- mContextMenuPopupHelper = null;
- }
}
@Override
@@ -2411,6 +2406,13 @@
setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
}
+ if (!mForcedStatusBarColor) {
+ mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
+ }
+ if (!mForcedNavigationBarColor) {
+ mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
+ }
+
// Non-floating windows on high end devices must put up decor beneath the system bars and
// therefore must know about visibility changes of those.
if (!mIsFloating && ActivityManager.isHighEndGfx()) {
@@ -2421,12 +2423,6 @@
FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
}
}
- if (!mForcedStatusBarColor) {
- mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
- }
- if (!mForcedNavigationBarColor) {
- mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
- }
if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
decor.setSystemUiVisibility(
decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
diff --git a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
index aaa1bf1..82f061c 100644
--- a/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/ContextMenuBuilder.java
@@ -17,7 +17,6 @@
package com.android.internal.view.menu;
import android.content.Context;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.util.EventLog;
@@ -35,7 +34,7 @@
* <p>
* To use this class, instantiate it via {@link #ContextMenuBuilder(Context)},
* and optionally populate it with any of your custom items. Finally,
- * call {@link #show(View, IBinder)} which will populate the menu
+ * call {@link #showDialog(View, IBinder)} which will populate the menu
* with a view's context menu items and show the context menu.
*/
public class ContextMenuBuilder extends MenuBuilder implements ContextMenu {
@@ -75,7 +74,7 @@
* @return If the context menu was shown, the {@link MenuDialogHelper} for
* dismissing it. Otherwise, null.
*/
- public MenuDialogHelper show(View originalView, IBinder token) {
+ public MenuDialogHelper showDialog(View originalView, IBinder token) {
if (originalView != null) {
// Let relevant views and their populate context listeners populate
// the context menu
diff --git a/core/java/com/android/internal/view/menu/MenuDialogHelper.java b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
index b9e0e40..ecab29f 100644
--- a/core/java/com/android/internal/view/menu/MenuDialogHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuDialogHelper.java
@@ -26,13 +26,10 @@
import android.view.WindowManager;
/**
- * Helper for menus that appear as Dialogs (context and submenus).
- *
- * @hide
+ * Presents a menu as a modal dialog.
*/
-public class MenuDialogHelper implements DialogInterface.OnKeyListener,
- DialogInterface.OnClickListener,
- DialogInterface.OnDismissListener,
+public class MenuDialogHelper implements MenuHelper, DialogInterface.OnKeyListener,
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
MenuPresenter.Callback {
private MenuBuilder mMenu;
private AlertDialog mDialog;
@@ -125,6 +122,7 @@
}
+ @Override
public void setPresenterCallback(MenuPresenter.Callback cb) {
mPresenterCallback = cb;
}
@@ -134,6 +132,7 @@
*
* @see Dialog#dismiss()
*/
+ @Override
public void dismiss() {
if (mDialog != null) {
mDialog.dismiss();
diff --git a/core/java/com/android/internal/view/menu/MenuHelper.java b/core/java/com/android/internal/view/menu/MenuHelper.java
new file mode 100644
index 0000000..9534722
--- /dev/null
+++ b/core/java/com/android/internal/view/menu/MenuHelper.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 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.internal.view.menu;
+
+/**
+ * Interface for a helper capable of presenting a menu.
+ */
+public interface MenuHelper {
+ void setPresenterCallback(MenuPresenter.Callback cb);
+ void dismiss();
+}
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 59d5f94..044ee6e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -30,7 +30,7 @@
/**
* Presents a menu as a small, simple popup anchored to another view.
*/
-public class MenuPopupHelper {
+public class MenuPopupHelper implements MenuHelper {
private final Context mContext;
// Immutable cached popup menu properties.
@@ -244,6 +244,7 @@
/**
* Dismisses the popup, if showing.
*/
+ @Override
public void dismiss() {
if (isShowing()) {
mPopup.dismiss();
@@ -270,7 +271,8 @@
return mPopup != null && mPopup.isShowing();
}
- public void setCallback(@Nullable MenuPresenter.Callback cb) {
+ @Override
+ public void setPresenterCallback(@Nullable MenuPresenter.Callback cb) {
mPresenterCallback = cb;
if (mPopup != null) {
mPopup.setCallback(cb);
diff --git a/core/java/com/android/internal/view/menu/StandardMenuPopup.java b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
index caee0d2..6a5f6d8 100644
--- a/core/java/com/android/internal/view/menu/StandardMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/StandardMenuPopup.java
@@ -245,7 +245,7 @@
MenuPopupHelper subPopup = new MenuPopupHelper(
mContext, subMenu, mShownAnchorView, mOverflowOnly, mPopupStyleAttr,
mPopupStyleRes);
- subPopup.setCallback(mPresenterCallback);
+ subPopup.setPresenterCallback(mPresenterCallback);
subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
if (subPopup.tryShow()) {
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index c139cd7..ae109c6 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -711,6 +711,9 @@
jniThrowException(env, "java/lang/RuntimeException",
"Not allowed to write file descriptors here");
break;
+ case UNEXPECTED_NULL:
+ jniThrowNullPointerException(env, NULL);
+ break;
case -EBADF:
jniThrowException(env, "java/lang/RuntimeException",
"Bad file descriptor");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9bbbdca..ee493019 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2607,6 +2607,14 @@
<permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:protectionLevel="signature" />
+ <!-- Must be required by an {@link
+ android.service.notification.NotificationAssistantService},
+ to ensure that only the system can bind to it.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- Must be required by a {@link
android.service.chooser.ChooserTargetService}, to ensure that
only the system can bind to it.
@@ -2712,6 +2720,13 @@
<permission android:name="android.permission.DISPATCH_NFC_MESSAGE"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows changing day / night mode when system is configured with
+ config_lockDayNightMode set to true. If requesting app does not have permission,
+ it will be ignored.
+ @hide -->
+ <permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"
+ android:protectionLevel="signature|privileged" />
+
<!-- The system process is explicitly the only one allowed to launch the
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 09a63aa..454e4b6 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -37,7 +37,7 @@
Or string format of ApnSettingV3.
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string-array translatable="false" name="config_tether_apndata">
- <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,54</item>
+ <item>[ApnSettingV3]TELUS ISP,isp.telus.com,,,,,,,,,302,220,,DUN,IP,IP,true,0,,,,,,,gid,54</item>
<item>[ApnSettingV3]Tethered Mobile Internet,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,50</item>
<item>[ApnSettingV3]Tethered Public Mobile,isp.mb.com,,,,,,,,,302,220,,DUN,,,true,0,,,,,,,gid,4D4F</item>
</string-array>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index dad68ba..af8ff2e 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -173,4 +173,7 @@
<color name="Red_800">#ffb93221</color>
<color name="chooser_service_row_background_color">#fff5f5f5</color>
+
+ <!-- Status bar color for semi transparent mode. -->
+ <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d9e0472..ea6cf11 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -716,6 +716,13 @@
<bool name="config_carDockEnablesAccelerometer">true</bool>
+ <!-- Control whether to launch Car dock home app when user presses home button or when
+ car dock intent is fired.
+ In mobile device, usually separate home app is expected in car mode, and this should be
+ enabled. But in environments like real car, default home app may be enough, and in that
+ case, this can be disabled (set to false). -->
+ <bool name="config_enableCarDockHomeLaunch">true</bool>
+
<!-- HDMI behavior -->
<!-- The number of degrees to rotate the display when the device has HDMI connected
@@ -733,6 +740,15 @@
Any other values will have surprising consequences. -->
<integer name="config_defaultUiModeType">1</integer>
+ <!-- Control whether to lock UI mode to what is selected from config_defaultUiModeType.
+ Once UI mode is locked, applications cannot change it anymore. -->
+ <bool name="config_lockUiMode">false</bool>
+
+ <!-- Control whether to lock day/night mode change from normal application. When it is
+ true, day / night mode change is only allowed to apps with MODIFY_DAY_NIGHT_MODE
+ permission. -->
+ <bool name="config_lockDayNightMode">false</bool>
+
<!-- Control the default night mode to use when there is no other mode override set.
One of the following values (see UiModeManager.java):
0 - MODE_NIGHT_AUTO
@@ -2384,4 +2400,9 @@
The duplication is necessary, because this information is used before the features are
available to the system.-->
<bool name="config_freeformWindowManagement">false</bool>
+
+ <!-- If set, this will force all windows to draw the status bar background, including the apps
+ that have not requested doing so (via the WindowManager.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
+ flag). -->
+ <bool name="config_forceWindowDrawsStatusBarBackground">true</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3860f68..dd44997 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1476,11 +1476,14 @@
<java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
<java-symbol type="bool" name="config_deskDockEnablesAccelerometer" />
<java-symbol type="bool" name="config_disableMenuKeyInLockScreen" />
+ <java-symbol type="bool" name="config_enableCarDockHomeLaunch" />
<java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
<java-symbol type="bool" name="config_enableLockScreenRotation" />
<java-symbol type="bool" name="config_enableLockScreenTranslucentDecor" />
<java-symbol type="bool" name="config_enableTranslucentDecor" />
<java-symbol type="bool" name="config_lidControlsSleep" />
+ <java-symbol type="bool" name="config_lockDayNightMode" />
+ <java-symbol type="bool" name="config_lockUiMode" />
<java-symbol type="bool" name="config_reverseDefaultRotation" />
<java-symbol type="bool" name="config_showNavigationBar" />
<java-symbol type="bool" name="config_supportAutoRotation" />
@@ -2344,6 +2347,8 @@
<java-symbol type="string" name="config_packagedKeyboardName" />
<java-symbol type="string" name="default_notification_topic_label" />
+ <java-symbol type="bool" name="config_forceWindowDrawsStatusBarBackground" />
+ <java-symbol type="color" name="system_bar_background_semi_transparent" />
<!-- EditText suggestion popup. -->
<java-symbol type="id" name="suggestionContainer" />
diff --git a/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml b/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml
index b7645b0..c56079f8 100644
--- a/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/permUse/AndroidManifest.xml
@@ -21,11 +21,11 @@
<key-sets>
<key-set android:name="A">
<public-key android:name="keyA"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ=="/>
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB"/>
</key-set>
<key-set android:name="B">
<public-key android:name="keyB"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+ android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
</key-set>
<upgrade-key-set android:name="A"/>
<upgrade-key-set android:name="B"/>
diff --git a/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml
index f31b75f..8c440f5 100644
--- a/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uA/AndroidManifest.xml
@@ -20,7 +20,7 @@
<key-sets>
<key-set android:name="A" >
<public-key android:name="keyA"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ=="/>
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB"/>
</key-set>
<upgrade-key-set android:name="A"/>
</key-sets>
diff --git a/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml
index 8ad3471..015c3ad 100644
--- a/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uAB/AndroidManifest.xml
@@ -20,9 +20,9 @@
<key-sets>
<key-set android:name="AB" >
<public-key android:name="keyA"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ==" />
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB" />
<public-key android:name="keyB"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+ android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
</key-set>
<upgrade-key-set android:name="AB"/>
</key-sets>
diff --git a/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml
index cdbd639..9491dbea 100644
--- a/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uAuB/AndroidManifest.xml
@@ -20,11 +20,11 @@
<key-sets>
<key-set android:name="A" >
<public-key android:name="keyA"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ==" />
+ android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMpNthdOxud7roPDZMMomOqXgJJdRfIWpkKEqmC61Mv+Nf6QY3TorEwJeghjSmqj7IbBKrtvfQq4E2XJO1HuspmQO4Ng2gvn+r+6EwNfKc9k55d6s+27SR867jKurBbHNtZMG+tjL1yH4r+tNzcuJCsgyAFqLmxFdcxEwzNvREyRpoYc5RDR0mmTwkMCUhJ6CId1EYEKiCEdNzxv+fWPEb21u+/MWpleGCILs8kglRVb2q/WOzAAvGr4FY5plfaE6N+lr7+UschQ+aMi1+uqewo2o0qPFVmZP5hnwj55K4UMzu/NhhDqQQsX4cSGES1KgHo5MTqRqZjN/I7emw5pFQIDAQAB" />
</key-set>
<key-set android:name="B" >
<public-key android:name="keyB"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+ android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
</key-set>
<upgrade-key-set android:name="A"/>
<upgrade-key-set android:name="B"/>
diff --git a/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml b/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml
index 61063c3..f491840 100644
--- a/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml
+++ b/core/tests/coretests/apks/keyset/uB/AndroidManifest.xml
@@ -20,7 +20,7 @@
<key-sets>
<key-set android:name="B" >
<public-key android:name="keyB"
- android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMTfQsY8UuXiXmvw/y7Tpr7HoyfAC0nE/8Qdk3ZtEr9asa5qqP0F6xzCI1PGVFV+WLVRwm6FdB9StENL5EKyQFcCAwEAAQ==" />
+ android:value="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEtGr5cL2N7ztHiHmphB1/1eq+43lEAmP36iiEJAfX+cVReGSPFXqNnnM8Vptd2boAe332lrFw9rKPmbkZA+jOTA==" />
</key-set>
<upgrade-key-set android:name="B"/>
</key-sets>
diff --git a/core/tests/coretests/certs/keyset_A.pk8 b/core/tests/coretests/certs/keyset_A.pk8
index 3976b94..4076313 100644
--- a/core/tests/coretests/certs/keyset_A.pk8
+++ b/core/tests/coretests/certs/keyset_A.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/keyset_A.x509.pem b/core/tests/coretests/certs/keyset_A.x509.pem
index 0fe334e..548bf13 100644
--- a/core/tests/coretests/certs/keyset_A.x509.pem
+++ b/core/tests/coretests/certs/keyset_A.x509.pem
@@ -1,14 +1,18 @@
-----BEGIN CERTIFICATE-----
-MIICKjCCAdQCCQCpDXPnNpO5UjANBgkqhkiG9w0BAQUFADCBmzELMAkGA1UEBhMC
-VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcx
-DzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEYMBYGA1UEAxMPd3d3
-LmV4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNkY2FzaG1hbkBnb29nbGUuY29t
-MB4XDTE0MDQyMTE4MTkwM1oXDTE3MDQyMDE4MTkwM1owgZsxCzAJBgNVBAYTAlVT
-MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8w
-DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxGDAWBgNVBAMTD3d3dy5l
-eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZGNhc2htYW5AZ29vZ2xlLmNvbTBc
-MA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCaDdTbIKn9FeAv22zfMKPDtl/0uQ++vuTG
-/ZpSLB5FE1E2xwjZPi8RyFGC5vPWGz/cyJq1dG1By1AGVMqDFAojAgMBAAEwDQYJ
-KoZIhvcNAQEFBQADQQCPTVDKxVZpxFH6Nm7sxpRplLzxbs/xyGELLIjEBVrgB0CM
-HAxFpPRHDSFpTxGG2mBCSrf+lD2Bf+WiIojx+RLY
+MIIC+TCCAeGgAwIBAgIJALuyfpZeCDiwMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
+BAMMCGtleXNldF9BMB4XDTE1MTIwMjIxMTEzNFoXDTQzMDQxOTIxMTEzNFowEzER
+MA8GA1UEAwwIa2V5c2V0X0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwyk22F07G53uug8NkwyiY6peAkl1F8hamQoSqYLrUy/41/pBjdOisTAl6CGNK
+aqPshsEqu299CrgTZck7Ue6ymZA7g2DaC+f6v7oTA18pz2Tnl3qz7btJHzruMq6s
+Fsc21kwb62MvXIfiv603Ny4kKyDIAWoubEV1zETDM29ETJGmhhzlENHSaZPCQwJS
+EnoIh3URgQqIIR03PG/59Y8RvbW778xamV4YIguzySCVFVvar9Y7MAC8avgVjmmV
+9oTo36Wvv5SxyFD5oyLX66p7CjajSo8VWZk/mGfCPnkrhQzO782GEOpBCxfhxIYR
+LUqAejkxOpGpmM38jt6bDmkVAgMBAAGjUDBOMB0GA1UdDgQWBBTVcIVD9u9538W/
+NE2Y36YiPtYmPzAfBgNVHSMEGDAWgBTVcIVD9u9538W/NE2Y36YiPtYmPzAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCjTN3mgaKep55wR1ULf4ULIc/m
+mjfZK7ZnJcynBEIGyjAqt4mMIfKRV/DllLsf997r7bz12qUSLbhWGFSq4a2ceOIp
+RG0+CGXV8Ez5Hz4o99MAP37Zdd5Lfq8fdlg2Mro2MMr21Tf3i2Y2LOfkXEZrW7rQ
+A5ZRVksoRcPQWaaNA85LGRSCiC2XSjg8TLn1qKwQUXVGQ6fwLKqAeeV2+hynADih
+FUaf7HxE5H3bHLByLmLKtab3Ta/g8VXxxRYuyd/rYsWMAHsjZge6xoVajm6Wvj5Q
+AvIxV99+PK7dkjVpg3O2oN1O4DQlqqvxdhjNP733DI4cihfJYV9Vn+wKj3TA
-----END CERTIFICATE-----
diff --git a/core/tests/coretests/certs/keyset_B.pk8 b/core/tests/coretests/certs/keyset_B.pk8
index a44ebb3..839d96c 100644
--- a/core/tests/coretests/certs/keyset_B.pk8
+++ b/core/tests/coretests/certs/keyset_B.pk8
Binary files differ
diff --git a/core/tests/coretests/certs/keyset_B.x509.pem b/core/tests/coretests/certs/keyset_B.x509.pem
index 2806de5..537e047 100644
--- a/core/tests/coretests/certs/keyset_B.x509.pem
+++ b/core/tests/coretests/certs/keyset_B.x509.pem
@@ -1,14 +1,10 @@
-----BEGIN CERTIFICATE-----
-MIICKjCCAdQCCQC+5GnAgmYS6DANBgkqhkiG9w0BAQUFADCBmzELMAkGA1UEBhMC
-VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcx
-DzANBgNVBAoTBkdvb2dsZTEQMA4GA1UECxMHQW5kcm9pZDEYMBYGA1UEAxMPd3d3
-LmV4YW1wbGUuY29tMSIwIAYJKoZIhvcNAQkBFhNkY2FzaG1hbkBnb29nbGUuY29t
-MB4XDTE0MDQyMTE4MjczM1oXDTE3MDQyMDE4MjczM1owgZsxCzAJBgNVBAYTAlVT
-MRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8w
-DQYDVQQKEwZHb29nbGUxEDAOBgNVBAsTB0FuZHJvaWQxGDAWBgNVBAMTD3d3dy5l
-eGFtcGxlLmNvbTEiMCAGCSqGSIb3DQEJARYTZGNhc2htYW5AZ29vZ2xlLmNvbTBc
-MA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDE30LGPFLl4l5r8P8u06a+x6MnwAtJxP/E
-HZN2bRK/WrGuaqj9BescwiNTxlRVfli1UcJuhXQfUrRDS+RCskBXAgMBAAEwDQYJ
-KoZIhvcNAQEFBQADQQCYYyur2/sMB88MOhQE8RHNmdO0zEQYAz66z3ctTNqiNsbK
-T9iKj0CT3cjqgfN5ex4onhnoIIPtON7DIHFWke5x
+MIIBbDCCAROgAwIBAgIJALP/7jQfVyFBMAoGCCqGSM49BAMCMBMxETAPBgNVBAMM
+CGtleXNldF9CMB4XDTE1MTIwMzIwNDgwNFoXDTQzMDQyMDIwNDgwNFowEzERMA8G
+A1UEAwwIa2V5c2V0X0IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS0avlwvY3v
+O0eIeamEHX/V6r7jeUQCY/fqKIQkB9f5xVF4ZI8Veo2eczxWm13ZugB7ffaWsXD2
+so+ZuRkD6M5Mo1AwTjAdBgNVHQ4EFgQUHrv1BwZU/MchAsa3VL0n458IwVswHwYD
+VR0jBBgwFoAUHrv1BwZU/MchAsa3VL0n458IwVswDAYDVR0TBAUwAwEB/zAKBggq
+hkjOPQQDAgNHADBEAiBp2nTHHhywNIyLpe8mYUsbwozVWM5/2xFidQe9Edua0AIg
+Wt9BCfzrcsBh2Rlje9Im9sq6hIyLSS1pe6ZcI3+lDis=
-----END CERTIFICATE-----
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index c279c8f..d133a12 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -1191,4 +1191,25 @@
InputMethodUtils.buildInputMethodsAndSubtypesString(map)));
}
}
+
+ @SmallTest
+ public void testConstructLocaleFromString() throws Exception {
+ assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en"));
+ assertEquals(new Locale("en", "US"), InputMethodUtils.constructLocaleFromString("en_US"));
+ assertEquals(new Locale("en", "US", "POSIX"),
+ InputMethodUtils.constructLocaleFromString("en_US_POSIX"));
+
+ // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not
+ // support three letter language codes, and used "tl" (Tagalog) as the language string for
+ // "fil" (Filipino).
+ assertEquals(new Locale("fil"), InputMethodUtils.constructLocaleFromString("tl"));
+ assertEquals(new Locale("fil", "PH"), InputMethodUtils.constructLocaleFromString("tl_PH"));
+ assertEquals(new Locale("fil", "PH", "POSIX"),
+ InputMethodUtils.constructLocaleFromString("tl_PH_POSIX"));
+
+ // So far rejecting an invalid/unexpected locale string is out of the scope of this method.
+ assertEquals(new Locale("a"), InputMethodUtils.constructLocaleFromString("a"));
+ assertEquals(new Locale("a b c"), InputMethodUtils.constructLocaleFromString("a b c"));
+ assertEquals(new Locale("en-US"), InputMethodUtils.constructLocaleFromString("en-US"));
+ }
}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index fc4916c..d98497b 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -30,7 +30,6 @@
utils/StringUtils.cpp \
utils/TestWindowContext.cpp \
utils/VectorDrawableUtils.cpp \
- utils/TestUtils.cpp \
AmbientShadow.cpp \
AnimationContext.cpp \
Animator.cpp \
@@ -90,6 +89,9 @@
VectorDrawablePath.cpp \
protos/hwui.proto
+hwui_test_common_src_files := \
+ tests/common/TestUtils.cpp
+
hwui_cflags := \
-DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES \
-DATRACE_TAG=ATRACE_TAG_VIEW -DLOG_TAG=\"OpenGLRenderer\" \
@@ -180,8 +182,8 @@
-DHWUI_NULL_GPU
LOCAL_SRC_FILES := \
$(hwui_src_files) \
- tests/nullegl.cpp \
- tests/nullgles.cpp
+ tests/common/nullegl.cpp \
+ tests/common/nullgles.cpp
LOCAL_C_INCLUDES := $(hwui_c_includes) $(call hwui_proto_include)
LOCAL_EXPORT_C_INCLUDE_DIRS := $(hwui_c_includes) $(call hwui_proto_include)
@@ -215,28 +217,29 @@
-DHWUI_NULL_GPU
LOCAL_SRC_FILES += \
- unit_tests/CanvasStateTests.cpp \
- unit_tests/ClipAreaTests.cpp \
- unit_tests/DamageAccumulatorTests.cpp \
- unit_tests/DeviceInfoTests.cpp \
- unit_tests/FatVectorTests.cpp \
- unit_tests/LayerUpdateQueueTests.cpp \
- unit_tests/LinearAllocatorTests.cpp \
- unit_tests/VectorDrawableTests.cpp \
- unit_tests/OffscreenBufferPoolTests.cpp \
- unit_tests/StringUtilsTests.cpp
+ $(hwui_test_common_src_files) \
+ tests/unit/CanvasStateTests.cpp \
+ tests/unit/ClipAreaTests.cpp \
+ tests/unit/DamageAccumulatorTests.cpp \
+ tests/unit/DeviceInfoTests.cpp \
+ tests/unit/FatVectorTests.cpp \
+ tests/unit/LayerUpdateQueueTests.cpp \
+ tests/unit/LinearAllocatorTests.cpp \
+ tests/unit/VectorDrawableTests.cpp \
+ tests/unit/OffscreenBufferPoolTests.cpp \
+ tests/unit/StringUtilsTests.cpp
ifeq (true, $(HWUI_NEW_OPS))
LOCAL_SRC_FILES += \
- unit_tests/BakedOpStateTests.cpp \
- unit_tests/RecordingCanvasTests.cpp \
- unit_tests/OpReordererTests.cpp
+ tests/unit/BakedOpStateTests.cpp \
+ tests/unit/RecordingCanvasTests.cpp \
+ tests/unit/OpReordererTests.cpp
endif
include $(BUILD_NATIVE_TEST)
# ------------------------
-# test app
+# Macro-bench app
# ------------------------
include $(CLEAR_VARS)
@@ -255,11 +258,12 @@
LOCAL_WHOLE_STATIC_LIBRARIES := libhwui_static
LOCAL_SRC_FILES += \
- tests/TestContext.cpp \
- tests/TestSceneRunner.cpp \
- tests/main.cpp
+ $(hwui_test_common_src_files) \
+ tests/macrobench/TestContext.cpp \
+ tests/macrobench/TestSceneRunner.cpp \
+ tests/macrobench/main.cpp
-LOCAL_SRC_FILES += $(call all-cpp-files-under, tests/scenes)
+LOCAL_SRC_FILES += $(call all-cpp-files-under, tests/common/scenes)
include $(BUILD_EXECUTABLE)
@@ -285,14 +289,15 @@
LOCAL_STATIC_LIBRARIES := libbenchmark libbase
LOCAL_SRC_FILES += \
- microbench/DisplayListCanvasBench.cpp \
- microbench/LinearAllocatorBench.cpp \
- microbench/PathParserBench.cpp \
- microbench/ShadowBench.cpp
+ $(hwui_test_common_src_files) \
+ tests/microbench/DisplayListCanvasBench.cpp \
+ tests/microbench/LinearAllocatorBench.cpp \
+ tests/microbench/PathParserBench.cpp \
+ tests/microbench/ShadowBench.cpp
ifeq (true, $(HWUI_NEW_OPS))
LOCAL_SRC_FILES += \
- microbench/OpReordererBench.cpp
+ tests/microbench/OpReordererBench.cpp
endif
include $(BUILD_EXECUTABLE)
diff --git a/libs/hwui/tests/TestScene.h b/libs/hwui/tests/common/TestScene.h
similarity index 100%
rename from libs/hwui/tests/TestScene.h
rename to libs/hwui/tests/common/TestScene.h
diff --git a/libs/hwui/utils/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
similarity index 100%
rename from libs/hwui/utils/TestUtils.cpp
rename to libs/hwui/tests/common/TestUtils.cpp
diff --git a/libs/hwui/utils/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
similarity index 100%
rename from libs/hwui/utils/TestUtils.h
rename to libs/hwui/tests/common/TestUtils.h
diff --git a/libs/hwui/tests/nullegl.cpp b/libs/hwui/tests/common/nullegl.cpp
similarity index 100%
rename from libs/hwui/tests/nullegl.cpp
rename to libs/hwui/tests/common/nullegl.cpp
diff --git a/libs/hwui/tests/nullgles.cpp b/libs/hwui/tests/common/nullgles.cpp
similarity index 100%
rename from libs/hwui/tests/nullgles.cpp
rename to libs/hwui/tests/common/nullgles.cpp
diff --git a/libs/hwui/tests/scenes/HwLayerAnimation.cpp b/libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/HwLayerAnimation.cpp
rename to libs/hwui/tests/common/scenes/HwLayerAnimation.cpp
diff --git a/libs/hwui/tests/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/ListViewAnimation.cpp
rename to libs/hwui/tests/common/scenes/ListViewAnimation.cpp
diff --git a/libs/hwui/tests/scenes/OvalAnimation.cpp b/libs/hwui/tests/common/scenes/OvalAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/OvalAnimation.cpp
rename to libs/hwui/tests/common/scenes/OvalAnimation.cpp
diff --git a/libs/hwui/tests/scenes/PartialDamageAnimation.cpp b/libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/PartialDamageAnimation.cpp
rename to libs/hwui/tests/common/scenes/PartialDamageAnimation.cpp
diff --git a/libs/hwui/tests/scenes/RecentsAnimation.cpp b/libs/hwui/tests/common/scenes/RecentsAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/RecentsAnimation.cpp
rename to libs/hwui/tests/common/scenes/RecentsAnimation.cpp
diff --git a/libs/hwui/tests/scenes/RectGridAnimation.cpp b/libs/hwui/tests/common/scenes/RectGridAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/RectGridAnimation.cpp
rename to libs/hwui/tests/common/scenes/RectGridAnimation.cpp
diff --git a/libs/hwui/tests/scenes/SaveLayerAnimation.cpp b/libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/SaveLayerAnimation.cpp
rename to libs/hwui/tests/common/scenes/SaveLayerAnimation.cpp
diff --git a/libs/hwui/tests/scenes/ShadowGrid2Animation.cpp b/libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/ShadowGrid2Animation.cpp
rename to libs/hwui/tests/common/scenes/ShadowGrid2Animation.cpp
diff --git a/libs/hwui/tests/scenes/ShadowGridAnimation.cpp b/libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
similarity index 100%
rename from libs/hwui/tests/scenes/ShadowGridAnimation.cpp
rename to libs/hwui/tests/common/scenes/ShadowGridAnimation.cpp
diff --git a/libs/hwui/tests/scenes/TestSceneBase.h b/libs/hwui/tests/common/scenes/TestSceneBase.h
similarity index 86%
rename from libs/hwui/tests/scenes/TestSceneBase.h
rename to libs/hwui/tests/common/scenes/TestSceneBase.h
index a208509..8a24149 100644
--- a/libs/hwui/tests/scenes/TestSceneBase.h
+++ b/libs/hwui/tests/common/scenes/TestSceneBase.h
@@ -19,10 +19,10 @@
#include "DisplayListCanvas.h"
#include "RecordingCanvas.h"
#include "RenderNode.h"
-#include "tests/Benchmark.h"
-#include "tests/TestContext.h"
-#include "tests/TestScene.h"
-#include "utils/TestUtils.h"
+#include "tests/macrobench/Benchmark.h"
+#include "tests/macrobench/TestContext.h"
+#include "tests/common/TestScene.h"
+#include "tests/common/TestUtils.h"
#include <functional>
diff --git a/libs/hwui/tests/Benchmark.h b/libs/hwui/tests/macrobench/Benchmark.h
similarity index 97%
rename from libs/hwui/tests/Benchmark.h
rename to libs/hwui/tests/macrobench/Benchmark.h
index 3f87d7f..aad8eb3 100644
--- a/libs/hwui/tests/Benchmark.h
+++ b/libs/hwui/tests/macrobench/Benchmark.h
@@ -16,7 +16,7 @@
#ifndef TESTS_BENCHMARK_H
#define TESTS_BENCHMARK_H
-#include "TestScene.h"
+#include "tests/common/TestScene.h"
#include <string>
#include <vector>
diff --git a/libs/hwui/tests/TestContext.cpp b/libs/hwui/tests/macrobench/TestContext.cpp
similarity index 100%
rename from libs/hwui/tests/TestContext.cpp
rename to libs/hwui/tests/macrobench/TestContext.cpp
diff --git a/libs/hwui/tests/TestContext.h b/libs/hwui/tests/macrobench/TestContext.h
similarity index 100%
rename from libs/hwui/tests/TestContext.h
rename to libs/hwui/tests/macrobench/TestContext.h
diff --git a/libs/hwui/tests/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
similarity index 98%
rename from libs/hwui/tests/TestSceneRunner.cpp
rename to libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 0376e10..1e1c6a1 100644
--- a/libs/hwui/tests/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -18,7 +18,7 @@
#include "Benchmark.h"
#include "RenderNode.h"
#include "TestContext.h"
-#include "scenes/TestSceneBase.h"
+#include "tests/common/scenes/TestSceneBase.h"
#include "renderthread/RenderProxy.h"
#include "renderthread/RenderTask.h"
diff --git a/libs/hwui/tests/how_to_run.txt b/libs/hwui/tests/macrobench/how_to_run.txt
similarity index 100%
rename from libs/hwui/tests/how_to_run.txt
rename to libs/hwui/tests/macrobench/how_to_run.txt
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/macrobench/main.cpp
similarity index 100%
rename from libs/hwui/tests/main.cpp
rename to libs/hwui/tests/macrobench/main.cpp
diff --git a/libs/hwui/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
similarity index 98%
rename from libs/hwui/microbench/DisplayListCanvasBench.cpp
rename to libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index 4be1f99..2e59eb4 100644
--- a/libs/hwui/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -22,8 +22,8 @@
#else
#include "DisplayListCanvas.h"
#endif
-#include "microbench/MicroBench.h"
-#include "utils/TestUtils.h"
+#include "tests/common/TestUtils.h"
+#include "tests/microbench/MicroBench.h"
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/microbench/LinearAllocatorBench.cpp b/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
similarity index 97%
rename from libs/hwui/microbench/LinearAllocatorBench.cpp
rename to libs/hwui/tests/microbench/LinearAllocatorBench.cpp
index 75f57cb..28513e4 100644
--- a/libs/hwui/microbench/LinearAllocatorBench.cpp
+++ b/libs/hwui/tests/microbench/LinearAllocatorBench.cpp
@@ -16,8 +16,8 @@
#include <benchmark/Benchmark.h>
+#include "tests/microbench/MicroBench.h"
#include "utils/LinearAllocator.h"
-#include "microbench/MicroBench.h"
#include <vector>
diff --git a/libs/hwui/microbench/MicroBench.h b/libs/hwui/tests/microbench/MicroBench.h
similarity index 100%
rename from libs/hwui/microbench/MicroBench.h
rename to libs/hwui/tests/microbench/MicroBench.h
diff --git a/libs/hwui/microbench/OpReordererBench.cpp b/libs/hwui/tests/microbench/OpReordererBench.cpp
similarity index 98%
rename from libs/hwui/microbench/OpReordererBench.cpp
rename to libs/hwui/tests/microbench/OpReordererBench.cpp
index 53b64c3..406bfcc 100644
--- a/libs/hwui/microbench/OpReordererBench.cpp
+++ b/libs/hwui/tests/microbench/OpReordererBench.cpp
@@ -23,7 +23,7 @@
#include "OpReorderer.h"
#include "RecordedOp.h"
#include "RecordingCanvas.h"
-#include "utils/TestUtils.h"
+#include "tests/common/TestUtils.h"
#include "Vector.h"
#include "microbench/MicroBench.h"
diff --git a/libs/hwui/microbench/PathParserBench.cpp b/libs/hwui/tests/microbench/PathParserBench.cpp
similarity index 100%
rename from libs/hwui/microbench/PathParserBench.cpp
rename to libs/hwui/tests/microbench/PathParserBench.cpp
diff --git a/libs/hwui/microbench/ShadowBench.cpp b/libs/hwui/tests/microbench/ShadowBench.cpp
similarity index 98%
rename from libs/hwui/microbench/ShadowBench.cpp
rename to libs/hwui/tests/microbench/ShadowBench.cpp
index 1b0f5ea..98ec4d9 100644
--- a/libs/hwui/microbench/ShadowBench.cpp
+++ b/libs/hwui/tests/microbench/ShadowBench.cpp
@@ -21,7 +21,7 @@
#include "Vector.h"
#include "VertexBuffer.h"
#include "TessellationCache.h"
-#include "microbench/MicroBench.h"
+#include "tests/microbench/MicroBench.h"
#include <SkPath.h>
diff --git a/libs/hwui/microbench/how_to_run.txt b/libs/hwui/tests/microbench/how_to_run.txt
similarity index 100%
rename from libs/hwui/microbench/how_to_run.txt
rename to libs/hwui/tests/microbench/how_to_run.txt
diff --git a/libs/hwui/unit_tests/BakedOpStateTests.cpp b/libs/hwui/tests/unit/BakedOpStateTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/BakedOpStateTests.cpp
rename to libs/hwui/tests/unit/BakedOpStateTests.cpp
index 7ad2f9b..de14abf 100644
--- a/libs/hwui/unit_tests/BakedOpStateTests.cpp
+++ b/libs/hwui/tests/unit/BakedOpStateTests.cpp
@@ -18,7 +18,7 @@
#include <BakedOpState.h>
#include <RecordedOp.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/unit_tests/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/CanvasStateTests.cpp
rename to libs/hwui/tests/unit/CanvasStateTests.cpp
diff --git a/libs/hwui/unit_tests/ClipAreaTests.cpp b/libs/hwui/tests/unit/ClipAreaTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/ClipAreaTests.cpp
rename to libs/hwui/tests/unit/ClipAreaTests.cpp
diff --git a/libs/hwui/unit_tests/DamageAccumulatorTests.cpp b/libs/hwui/tests/unit/DamageAccumulatorTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/DamageAccumulatorTests.cpp
rename to libs/hwui/tests/unit/DamageAccumulatorTests.cpp
diff --git a/libs/hwui/unit_tests/DeviceInfoTests.cpp b/libs/hwui/tests/unit/DeviceInfoTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/DeviceInfoTests.cpp
rename to libs/hwui/tests/unit/DeviceInfoTests.cpp
diff --git a/libs/hwui/unit_tests/FatVectorTests.cpp b/libs/hwui/tests/unit/FatVectorTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/FatVectorTests.cpp
rename to libs/hwui/tests/unit/FatVectorTests.cpp
index c6ccf4d..64b0ba1 100644
--- a/libs/hwui/unit_tests/FatVectorTests.cpp
+++ b/libs/hwui/tests/unit/FatVectorTests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <utils/FatVector.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
rename to libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
index cc15cc6..8b0e91c 100644
--- a/libs/hwui/unit_tests/LayerUpdateQueueTests.cpp
+++ b/libs/hwui/tests/unit/LayerUpdateQueueTests.cpp
@@ -19,7 +19,7 @@
#include <LayerUpdateQueue.h>
#include <RenderNode.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/unit_tests/LinearAllocatorTests.cpp b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/LinearAllocatorTests.cpp
rename to libs/hwui/tests/unit/LinearAllocatorTests.cpp
index 0591db6..78d65dd 100644
--- a/libs/hwui/unit_tests/LinearAllocatorTests.cpp
+++ b/libs/hwui/tests/unit/LinearAllocatorTests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <utils/LinearAllocator.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
similarity index 98%
rename from libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
rename to libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
index de86aed..2187654 100644
--- a/libs/hwui/unit_tests/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <renderstate/OffscreenBufferPool.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
using namespace android;
using namespace android::uirenderer;
diff --git a/libs/hwui/unit_tests/OpReordererTests.cpp b/libs/hwui/tests/unit/OpReordererTests.cpp
similarity index 99%
rename from libs/hwui/unit_tests/OpReordererTests.cpp
rename to libs/hwui/tests/unit/OpReordererTests.cpp
index 2ce1d0a..98a430a 100644
--- a/libs/hwui/unit_tests/OpReordererTests.cpp
+++ b/libs/hwui/tests/unit/OpReordererTests.cpp
@@ -21,7 +21,7 @@
#include <OpReorderer.h>
#include <RecordedOp.h>
#include <RecordingCanvas.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
#include <unordered_map>
diff --git a/libs/hwui/unit_tests/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
similarity index 99%
rename from libs/hwui/unit_tests/RecordingCanvasTests.cpp
rename to libs/hwui/tests/unit/RecordingCanvasTests.cpp
index 81f0851..2449ce8 100644
--- a/libs/hwui/unit_tests/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -18,7 +18,7 @@
#include <RecordedOp.h>
#include <RecordingCanvas.h>
-#include <utils/TestUtils.h>
+#include <tests/common/TestUtils.h>
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/unit_tests/StringUtilsTests.cpp b/libs/hwui/tests/unit/StringUtilsTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/StringUtilsTests.cpp
rename to libs/hwui/tests/unit/StringUtilsTests.cpp
diff --git a/libs/hwui/unit_tests/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
similarity index 100%
rename from libs/hwui/unit_tests/VectorDrawableTests.cpp
rename to libs/hwui/tests/unit/VectorDrawableTests.cpp
diff --git a/libs/hwui/unit_tests/how_to_run.txt b/libs/hwui/tests/unit/how_to_run.txt
similarity index 100%
rename from libs/hwui/unit_tests/how_to_run.txt
rename to libs/hwui/tests/unit/how_to_run.txt
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index fa1714e..5e8bab1 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -20,6 +20,7 @@
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.util.Log;
@@ -116,21 +117,27 @@
*/
// TODO: UI Automator should provide such logic.
public void chooseActivity(String name) {
- // First select activity if it's not the default option.
- boolean gotIt = mDevice.wait(Until.hasObject(By.text(name)), mTimeout);
- // TODO: if the activity is indeed the default option, call above will timeout, which will
- // make the tests run slower. It might be better to change the logic to assume the default
- // first.
+ // First check if the activity is the default option.
+ String shareText = String.format("Share with %s", name);
+ boolean gotIt = mDevice.wait(Until.hasObject(By.text(shareText)), mTimeout);
+
if (gotIt) {
- Log.v(TAG, "Found activity " + name + ", it's not default action");
- UiObject activityChooser = getVisibleObject(name);
- click(activityChooser, "activity chooser");
+ Log.v(TAG, "Found activity " + name + ", it's the default action");
} else {
- String text = String.format("Share with %s", name);
- Log.v(TAG, "Didn't find activity " + name
- + ", assuming it's the default action and search for '" + text + "'");
- gotIt = mDevice.wait(Until.hasObject(By.text(text)), mTimeout);
- assertTrue("did not find text '" + text + "'", gotIt);
+ // Since it's not, need to find it in the scrollable list...
+ Log.v(TAG, "Activity " + name + " is not default action");
+ UiScrollable activitiesList = new UiScrollable(new UiSelector().scrollable(true));
+
+ UiObject activity;
+ try {
+ activitiesList.scrollForward();
+ activity = getVisibleObject(name);
+ } catch (UiObjectNotFoundException e) {
+ throw new IllegalStateException("didn't find activity '" + name
+ + "' on activities chooser", e);
+ }
+ // ... then select it.
+ click(activity, name);
}
// Then clicks the "Just Once" button.
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bfd8af9..5618e9b 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -21,7 +21,6 @@
<drawable name="ticker_background_color">#ff1d1d1d</drawable>
<drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
<color name="system_bar_background_opaque">#ff000000</color>
- <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black -->
<color name="system_bar_background_transparent">#00000000</color>
<color name="notification_panel_solid_background">#ff000000</color>
<drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d6a361c..002b9f5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1171,13 +1171,23 @@
<!-- Toggles fullscreen screenshots. DO NOT TRANSLATE -->
<string name="overview_fullscreen_thumbnails">Enable fullscreen screenshots</string>
<!-- Description for the toggle for fullscreen screenshots. DO NOT TRANSLATE -->
- <string name="overview_fullscreen_thumbnails_desc">Enable fullscreen screenshots in Overview</string>
+ <string name="overview_fullscreen_thumbnails_desc">Enable fullscreen screenshots in Overview. Restart required.</string>
+
+ <!-- Toggle to enable the Overview nav bar gesture. DO NOT TRANSLATE -->
+ <string name="overview_nav_bar_gesture">Enable navigation bar gesture</string>
+ <!-- Description for the toggle to enable the Overview nav bar gesture. DO NOT TRANSLATE -->
+ <string name="overview_nav_bar_gesture_desc">Enables the gesture to enter Overview by swiping up on the Nav bar</string>
<!-- Toggle to show the history view in Overview. DO NOT TRANSLATE -->
<string name="overview_show_history">Show History</string>
<!-- Description for the toggle to show the history view in Overview. DO NOT TRANSLATE -->
<string name="overview_show_history_desc">Enables the history view to see more recent tasks</string>
+ <!-- Toggle to set the initial scroll state to be paging or stack. DO NOT TRANSLATE -->
+ <string name="overview_initial_state_paging">Initialize to paging</string>
+ <!-- Description for the toggle to set the initial scroll state to be paging or stack. DO NOT TRANSLATE -->
+ <string name="overview_initial_state_paging_desc">Determines whether Overview will initially be in a stacked or paged state</string>
+
<!-- Category in the System UI Tuner settings, where new/experimental
settings are -->
<string name="experimental">Experimental</string>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index f398af3..8dcf8a7 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -93,11 +93,21 @@
android:summary="@string/overview_page_on_toggle_desc" />
<com.android.systemui.tuner.TunerSwitch
+ android:key="overview_initial_state_paging"
+ android:title="@string/overview_initial_state_paging"
+ android:summary="@string/overview_initial_state_paging_desc" />
+
+ <com.android.systemui.tuner.TunerSwitch
android:key="overview_fast_toggle"
android:title="@string/overview_fast_toggle_via_button"
android:summary="@string/overview_fast_toggle_via_button_desc" />
<com.android.systemui.tuner.TunerSwitch
+ android:key="overview_nav_bar_gesture"
+ android:title="@string/overview_nav_bar_gesture"
+ android:summary="@string/overview_nav_bar_gesture_desc" />
+
+ <com.android.systemui.tuner.TunerSwitch
android:key="overview_fullscreen_thumbnails"
android:title="@string/overview_fullscreen_thumbnails"
android:summary="@string/overview_fullscreen_thumbnails_desc" />
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 4cb8a3c..7f6cda0 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -32,7 +32,7 @@
/**
* Docks the top-most task and opens recents.
*/
- void dockTopTask(boolean draggingInRecents, Rect initialBounds);
+ void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds);
/**
* Called during a drag-from-navbar-in gesture.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index c98ecb5..b81c23a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -365,8 +365,8 @@
}
@Override
- public void dockTopTask(boolean draggingInRecents, Rect initialBounds) {
- mImpl.dockTopTask(draggingInRecents, initialBounds);
+ public void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
+ mImpl.dockTopTask(draggingInRecents, stackCreateMode,initialBounds);
if (draggingInRecents) {
mDraggingInRecentsCurrentUser = sSystemServicesProxy.getCurrentUser();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 063bb3e..384b86f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -425,10 +425,6 @@
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
- if (!launchState.launchedHasConfigurationChanged) {
- mRecentsView.disableLayersForOneFrame();
- }
-
// Notify that recents is now visible
SystemServicesProxy ssp = Recents.getSystemServices();
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, ssp, true));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index e8b8816..d778886 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -30,6 +30,7 @@
private static final String KEY_PAGE_ON_TOGGLE = "overview_page_on_toggle";
private static final String KEY_FULLSCREEN_THUMBNAILS = "overview_fullscreen_thumbnails";
private static final String KEY_SHOW_HISTORY = "overview_show_history";
+ private static final String KEY_INITIAL_STATE_PAGING = "overview_initial_state_paging";
public static class Static {
// Enables debug drawing for the transition thumbnail
@@ -54,6 +55,7 @@
private boolean mPageOnToggle;
private boolean mUseFullscreenThumbnails;
private boolean mShowHistory;
+ private boolean mInitialStatePaging;
/**
* We read the prefs once when we start the activity, then update them as the tuner changes
@@ -63,7 +65,7 @@
// Register all our flags, this will also call onTuningChanged() for each key, which will
// initialize the current state of each flag
TunerService.get(context).addTunable(this, KEY_FAST_TOGGLE, KEY_PAGE_ON_TOGGLE,
- KEY_FULLSCREEN_THUMBNAILS, KEY_SHOW_HISTORY);
+ KEY_FULLSCREEN_THUMBNAILS, KEY_SHOW_HISTORY, KEY_INITIAL_STATE_PAGING);
}
/**
@@ -94,6 +96,13 @@
return mShowHistory;
}
+ /**
+ * @return whether the initial stack state is paging.
+ */
+ public boolean isInitialStatePaging() {
+ return mInitialStatePaging;
+ }
+
@Override
public void onTuningChanged(String key, String newValue) {
switch (key) {
@@ -113,6 +122,10 @@
mShowHistory = (newValue != null) &&
(Integer.parseInt(newValue) != 0);
break;
+ case KEY_INITIAL_STATE_PAGING:
+ mInitialStatePaging = (newValue != null) &&
+ (Integer.parseInt(newValue) != 0);
+ break;
}
EventBus.getDefault().send(new DebugFlagsChangedEvent());
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 3efb0cc..2a4017a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -539,12 +539,11 @@
showRelativeAffiliatedTask(false);
}
- public void dockTopTask(boolean draggingInRecents, Rect initialBounds) {
+ public void dockTopTask(boolean draggingInRecents, int stackCreateMode, Rect initialBounds) {
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo topTask = ssp.getTopMostTask();
if (topTask != null && !SystemServicesProxy.isHomeStack(topTask.stackId)) {
- ssp.moveTaskToDockedStack(topTask.id,
- ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, initialBounds);
+ ssp.moveTaskToDockedStack(topTask.id, stackCreateMode, initialBounds);
showRecents(false /* triggeredFromAltTab */, draggingInRecents, false /* animate */,
true /* reloadTasks*/);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 2b20c07..5d17e2c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -115,7 +115,6 @@
/** Private constructor */
public SystemServicesProxy(Context context) {
- RecentsDebugFlags flags = Recents.getDebugFlags();
mAccm = AccessibilityManager.getInstance(context);
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mIam = ActivityManagerNative.getDefault();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 3bb89a3..63d09ee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -48,7 +48,8 @@
private static boolean DEBUG = false;
private static int MIN_NUM_TASKS = 5;
- private static int SESSION_BEGIN_TIME = 60 /* s/min */ * 60 /* min/hr */ * 6 /* hrs */;
+ private static int SESSION_BEGIN_TIME = 1000 /* ms/s */ * 60 /* s/min */ * 60 /* min/hr */ *
+ 6 /* hrs */;
/** The set of conditions to load tasks. */
public static class Options {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 530cd2d..e313fd2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -199,8 +199,8 @@
/** Task stack callbacks */
public interface TaskStackCallbacks {
/* Notifies when a task has been removed from the stack */
- void onStackTaskRemoved(TaskStack stack, Task removedTask, int removedTaskIndex,
- boolean wasFrontMostTask, Task newFrontMostTask);
+ void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
+ Task newFrontMostTask);
/* Notifies when a task has been removed from the history */
void onHistoryTaskRemoved(TaskStack stack, Task removedTask);
@@ -393,8 +393,7 @@
}
if (mCb != null) {
// Notify that a task has been removed
- mCb.onStackTaskRemoved(this, t, removedTaskIndex, wasFrontMostTask,
- newFrontMostTask);
+ mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask);
}
} else if (mHistoryTaskList.contains(t)) {
removeTaskImpl(mHistoryTaskList, t);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 0911578..a9f570e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents.views;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -27,6 +29,8 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewPropertyAnimator;
import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -55,6 +59,8 @@
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.stackdivider.WindowManagerProxy;
+import com.android.systemui.statusbar.FlingAnimationUtils;
import java.util.ArrayList;
import java.util.List;
@@ -94,8 +100,10 @@
Rect mSystemInsets = new Rect();
+ final FlingAnimationUtils mFlingAnimationUtils;
+
public RecentsView(Context context) {
- super(context);
+ this(context, null);
}
public RecentsView(Context context, AttributeSet attrs) {
@@ -118,6 +126,7 @@
com.android.internal.R.interpolator.fast_out_linear_in);
mHistoryTransitionDuration = res.getInteger(R.integer.recents_history_transition_duration);
mTouchHandler = new RecentsViewTouchHandler(this);
+ mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
LayoutInflater inflater = LayoutInflater.from(context);
mHistoryButton = inflater.inflate(R.layout.recents_history_button, this, false);
@@ -138,6 +147,8 @@
// If onRecentsHidden is not triggered, we need to the stack view again here
mTaskStackView.reset();
mTaskStackView.setStack(stack);
+ removeView(mTaskStackView);
+ addView(mTaskStackView);
} else {
mTaskStackView = new TaskStackView(getContext(), stack);
mTaskStackView.setCallbacks(this);
@@ -443,12 +454,6 @@
return super.verifyDrawable(who);
}
- public void disableLayersForOneFrame() {
- if (mTaskStackView != null) {
- mTaskStackView.disableLayersForOneFrame();
- }
- }
-
/**** TaskStackView.TaskStackCallbacks Implementation ****/
@Override
@@ -515,7 +520,22 @@
}
public final void onBusEvent(DraggingInRecentsEndedEvent event) {
- animate().translationY(0f);
+ ViewPropertyAnimator animator = animate();
+ if (event.velocity > ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity()) {
+ animator.translationY(getHeight());
+ animator.withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ WindowManagerProxy.getInstance().maximizeDockedStack();
+ }
+ });
+ mFlingAnimationUtils.apply(animator, getTranslationY(), getHeight(), event.velocity);
+ } else {
+ animator.translationY(0f);
+ animator.setListener(null);
+ mFlingAnimationUtils.apply(animator, getTranslationY(), 0, event.velocity);
+ }
+ animator.start();
}
public final void onBusEvent(ShowHistoryEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 6dc380c..ebb819c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -118,18 +118,21 @@
*/
public static class StackState {
- public static final StackState FREEFORM_ONLY = new StackState(1f);
- public static final StackState STACK_ONLY = new StackState(0f);
- public static final StackState SPLIT = new StackState(0.5f);
+ public static final StackState FREEFORM_ONLY = new StackState(1f, 0);
+ public static final StackState STACK_ONLY = new StackState(0f, 0);
+ public static final StackState SPLIT = new StackState(0.5f, 255);
public final float freeformHeightPct;
+ public final int freeformBackgroundAlpha;
/**
* @param freeformHeightPct the percentage of the stack height (not including paddings) to
* allocate to the freeform workspace
+ * @param freeformBackgroundAlpha the background alpha for the freeform workspace
*/
- StackState(float freeformHeightPct) {
+ StackState(float freeformHeightPct, int freeformBackgroundAlpha) {
this.freeformHeightPct = freeformHeightPct;
+ this.freeformBackgroundAlpha = freeformBackgroundAlpha;
}
/**
@@ -278,7 +281,6 @@
FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
public TaskStackLayoutAlgorithm(Context context, TaskStackView stackView) {
- SystemServicesProxy ssp = Recents.getSystemServices();
Resources res = context.getResources();
mStackView = stackView;
@@ -309,9 +311,6 @@
*/
public void setSystemInsets(Rect systemInsets) {
mSystemInsets.set(systemInsets);
- if (DEBUG) {
- Log.d(TAG, "setSystemInsets: " + systemInsets);
- }
}
/**
@@ -343,6 +342,7 @@
// The freeform height is the visible height (not including system insets) - padding above
// freeform and below stack - gap between the freeform and stack
+ mState = state;
mStackTopOffset = mFocusedPeekHeight + heightPadding;
mStackBottomOffset = mSystemInsets.bottom + heightPadding;
state.computeRects(mFreeformRect, mStackRect, taskStackBounds, widthPadding, heightPadding,
@@ -498,13 +498,31 @@
public float getDefaultFocusState() {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- if (debugFlags.isPageOnToggleEnabled() || launchState.launchedWithAltTab) {
+ if (launchState.launchedWithAltTab ||
+ (debugFlags.isPageOnToggleEnabled() && debugFlags.isInitialStatePaging())) {
return 1f;
}
return 0f;
}
/**
+ * Returns the task progress that would put the task just off the front of the stack.
+ */
+ public float getStackFrontTaskProgress(float stackScroll) {
+ float max = mUnfocusedRange.relativeMax +
+ mFocusState * (mFocusedRange.relativeMax - mUnfocusedRange.relativeMax);
+ return stackScroll + max;
+ }
+
+ /**
+ *
+ * Returns the current stack state.
+ */
+ public StackState getStackState() {
+ return mState;
+ }
+
+ /**
* Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
* stack scroll. Requires that update() is called first.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index d45fba2..cc5aaae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.views;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
@@ -23,8 +24,11 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.util.IntProperty;
import android.util.Log;
+import android.util.Property;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -90,6 +94,19 @@
private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
+ public static final Property<ColorDrawable, Integer> COLOR_DRAWABLE_ALPHA =
+ new IntProperty<ColorDrawable>("colorDrawableAlpha") {
+ @Override
+ public void setValue(ColorDrawable object, int alpha) {
+ object.setAlpha(alpha);
+ }
+
+ @Override
+ public Integer get(ColorDrawable object) {
+ return object.getAlpha();
+ }
+ };
+
/** The TaskView callbacks */
interface TaskStackViewCallbacks {
public void onTaskViewClicked(TaskStackView stackView, TaskView tv, TaskStack stack, Task t,
@@ -102,10 +119,11 @@
TaskStackViewTouchHandler mTouchHandler;
TaskStackViewCallbacks mCb;
ColorDrawable mFreeformWorkspaceBackground;
+ ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
ViewPool<TaskView, Task> mViewPool;
ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
DozeTrigger mUIDozeTrigger;
- int mFocusedTaskIndex = -1;
+ Task mFocusedTask;
// Optimizations
int mStackViewsAnimationDuration;
boolean mStackViewsDirty = true;
@@ -119,7 +137,6 @@
int[] mTmpVisibleRange = new int[2];
Rect mTmpRect = new Rect();
RectF mTmpTaskRect = new RectF();
- TaskViewTransform mTmpTransform = new TaskViewTransform();
TaskViewTransform mTmpStackBackTransform = new TaskViewTransform();
TaskViewTransform mTmpStackFrontTransform = new TaskViewTransform();
HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<>();
@@ -127,7 +144,6 @@
List<TaskView> mImmutableTaskViews = new ArrayList<>();
List<TaskView> mTmpTaskViews = new ArrayList<>();
LayoutInflater mInflater;
- boolean mLayersDisabled;
boolean mTouchExplorationEnabled;
Interpolator mFastOutSlowInInterpolator;
@@ -186,6 +202,7 @@
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
mFreeformWorkspaceBackground = new ColorDrawable(0x33000000);
+ mFreeformWorkspaceBackground.setCallback(this);
}
/** Sets the callbacks */
@@ -462,24 +479,14 @@
Log.d(TAG, "picking up from pool: " + task.key);
}
tv = mViewPool.pickUpViewFromPool(task, task);
- if (mLayersDisabled) {
- tv.disableLayersForOneFrame();
- }
} else {
// Reattach it in the right z order
- detachViewFromParent(tv);
- int insertIndex = -1;
int taskIndex = mStack.indexOfStackTask(task);
- taskViews = getTaskViews();
- taskViewCount = taskViews.size();
- for (int j = 0; j < taskViewCount; j++) {
- Task tvTask = taskViews.get(j).getTask();
- if (taskIndex <= mStack.indexOfStackTask(tvTask)) {
- insertIndex = j;
- break;
- }
+ int insertIndex = findTaskViewInsertIndex(task, taskIndex);
+ if (insertIndex != getTaskViews().indexOf(tv)){
+ detachViewFromParent(tv);
+ attachViewToParent(tv, insertIndex, tv.getLayoutParams());
}
- attachViewToParent(tv, insertIndex, tv.getLayoutParams());
}
// Animate the task into place
@@ -500,9 +507,6 @@
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
- if (mLayersDisabled) {
- tv.disableLayersForOneFrame();
- }
if (mStackViewsAnimationDuration > 0) {
// For items in the list, put them in start animating them from the
// approriate ends of the list where they are expected to appear
@@ -517,8 +521,9 @@
} else {
if (!hasStackFrontTransform) {
hasStackFrontTransform = true;
- mLayoutAlgorithm.getStackTransform(1f, 0f, mTmpStackFrontTransform,
- null);
+ mLayoutAlgorithm.getStackTransform(
+ mLayoutAlgorithm.getStackFrontTaskProgress(0f), 0f,
+ mTmpStackFrontTransform, null);
}
tv.updateViewPropertiesToTaskTransform(mTmpStackFrontTransform, 0, 0,
mFastOutSlowInInterpolator, mRequestUpdateClippingListener);
@@ -612,7 +617,6 @@
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp.hasFreeformWorkspaceSupport()) {
mTmpRect.set(mLayoutAlgorithm.mFreeformRect);
- mFreeformWorkspaceBackground.setAlpha(255);
mFreeformWorkspaceBackground.setBounds(mTmpRect);
}
@@ -642,7 +646,7 @@
* @return whether or not the stack will scroll as a part of this focus change
*/
private boolean setFocusedTask(int taskIndex, boolean scrollToTask, final boolean animated,
- final boolean requestViewFocus) {
+ final boolean requestViewFocus) {
// Find the next task to focus
int newFocusedTaskIndex = mStack.getStackTaskCount() > 0 ?
Math.max(0, Math.min(mStack.getStackTaskCount() - 1, taskIndex)) : -1;
@@ -650,16 +654,13 @@
mStack.getStackTasks().get(newFocusedTaskIndex) : null;
// Reset the last focused task state if changed
- if (mFocusedTaskIndex != -1) {
- Task focusedTask = mStack.getStackTasks().get(mFocusedTaskIndex);
- if (focusedTask != newFocusedTask) {
- resetFocusedTask(focusedTask);
- }
+ if (mFocusedTask != null) {
+ resetFocusedTask(mFocusedTask);
}
boolean willScroll = false;
- mFocusedTaskIndex = newFocusedTaskIndex;
- if (mFocusedTaskIndex != -1) {
+ mFocusedTask = newFocusedTask;
+ if (newFocusedTask != null) {
Runnable focusTaskRunnable = new Runnable() {
@Override
public void run() {
@@ -729,13 +730,11 @@
*/
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
boolean cancelWindowAnimations) {
- int newIndex = -1;
- if (mFocusedTaskIndex != -1) {
+ int newIndex = mStack.indexOfStackTask(mFocusedTask);
+ if (mFocusedTask != null) {
if (stackTasksOnly) {
List<Task> tasks = mStack.getStackTasks();
- newIndex = mFocusedTaskIndex;
- Task task = tasks.get(mFocusedTaskIndex);
- if (task.isFreeformTask()) {
+ if (mFocusedTask.isFreeformTask()) {
// Try and focus the front most stack task
TaskView tv = getFrontMostTaskView(stackTasksOnly);
if (tv != null) {
@@ -743,7 +742,7 @@
}
} else {
// Try the next task if it is a stack task
- int tmpNewIndex = mFocusedTaskIndex + (forward ? -1 : 1);
+ int tmpNewIndex = newIndex + (forward ? -1 : 1);
if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
Task t = tasks.get(tmpNewIndex);
if (!t.isFreeformTask()) {
@@ -755,7 +754,7 @@
// No restrictions, lets just move to the new task (looping forward/backwards if
// necessary)
int taskCount = mStack.getStackTaskCount();
- newIndex = (mFocusedTaskIndex + (forward ? -1 : 1) + taskCount) % taskCount;
+ newIndex = (newIndex + (forward ? -1 : 1) + taskCount) % taskCount;
}
} else {
// We don't have a focused task, so focus the first visible task view
@@ -784,17 +783,14 @@
tv.setFocusedState(false, false /* animated */, false /* requestViewFocus */);
}
}
- mFocusedTaskIndex = -1;
+ mFocusedTask = null;
}
/**
* Returns the focused task.
*/
Task getFocusedTask() {
- if (mFocusedTaskIndex != -1) {
- return mStack.getStackTasks().get(mFocusedTaskIndex);
- }
- return null;
+ return mFocusedTask;
}
@Override
@@ -819,12 +815,13 @@
super.onInitializeAccessibilityNodeInfo(info);
List<TaskView> taskViews = getTaskViews();
int taskViewCount = taskViews.size();
- if (taskViewCount > 1 && mFocusedTaskIndex != -1) {
+ if (taskViewCount > 1 && mFocusedTask != null) {
info.setScrollable(true);
- if (mFocusedTaskIndex > 0) {
+ int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask);
+ if (focusedTaskIndex > 0) {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
}
- if (mFocusedTaskIndex < mStack.getStackTaskCount() - 1) {
+ if (focusedTaskIndex < mStack.getStackTaskCount() - 1) {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
}
}
@@ -1027,6 +1024,11 @@
mStartEnterAnimationContext = null;
}
+ // Animate in the freeform workspace
+ animateFreeformWorkspaceBackgroundAlpha(
+ mLayoutAlgorithm.getStackState().freeformBackgroundAlpha, 150,
+ mFastOutSlowInInterpolator);
+
// Set the task focused state without requesting view focus, and leave the focus animations
// until after the enter-animation
RecentsConfiguration config = Recents.getConfiguration();
@@ -1088,11 +1090,11 @@
// requesting view focus in onFirstLayout(), actually request view focus and
// animate the focused state if we are alt-tabbing now, after the window enter
// animation is completed
- if (mFocusedTaskIndex != -1) {
+ if (mFocusedTask != null) {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
- setFocusedTask(mFocusedTaskIndex, false /* scrollToTask */,
- launchState.launchedWithAltTab);
+ setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
+ false /* scrollToTask */, launchState.launchedWithAltTab);
}
}
});
@@ -1106,6 +1108,11 @@
mStackScroller.stopBoundScrollAnimation();
// Animate all the task views out of view
ctx.offscreenTranslationY = mLayoutAlgorithm.mStackRect.bottom;
+ // Dismiss the freeform workspace background
+ int taskViewExitToHomeDuration = getResources().getInteger(
+ R.integer.recents_task_exit_to_home_duration);
+ animateFreeformWorkspaceBackgroundAlpha(0, taskViewExitToHomeDuration,
+ mFastOutSlowInInterpolator);
List<TaskView> taskViews = getTaskViews();
int taskViewCount = taskViews.size();
@@ -1146,8 +1153,6 @@
@Override
protected void dispatchDraw(Canvas canvas) {
- mLayersDisabled = false;
-
// Draw the freeform workspace background
SystemServicesProxy ssp = Recents.getSystemServices();
if (ssp.hasFreeformWorkspaceSupport()) {
@@ -1159,12 +1164,12 @@
super.dispatchDraw(canvas);
}
- public void disableLayersForOneFrame() {
- mLayersDisabled = true;
- List<TaskView> taskViews = getTaskViews();
- for (int i = 0; i < taskViews.size(); i++) {
- taskViews.get(i).disableLayersForOneFrame();
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ if (who == mFreeformWorkspaceBackground) {
+ return true;
}
+ return super.verifyDrawable(who);
}
/**
@@ -1182,9 +1187,9 @@
/**** TaskStackCallbacks Implementation ****/
@Override
- public void onStackTaskRemoved(TaskStack stack, Task removedTask, int removedTaskIndex,
- boolean wasFrontMostTask, Task newFrontMostTask) {
- if (mFocusedTaskIndex == removedTaskIndex) {
+ public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
+ Task newFrontMostTask) {
+ if (mFocusedTask == removedTask) {
resetFocusedTask(removedTask);
}
@@ -1313,19 +1318,8 @@
tv.setNoUserInteractionState();
// Find the index where this task should be placed in the stack
- int insertIndex = -1;
int taskIndex = mStack.indexOfStackTask(task);
- if (taskIndex != -1) {
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- Task tvTask = taskViews.get(i).getTask();
- if (taskIndex < mStack.indexOfStackTask(tvTask)) {
- insertIndex = i;
- break;
- }
- }
- }
+ int insertIndex = findTaskViewInsertIndex(task, taskIndex);
// Add/attach the view to the hierarchy
if (isNewView) {
@@ -1343,7 +1337,7 @@
tv.setCallbacks(this);
tv.setTouchEnabled(true);
tv.setClipViewInStack(true);
- if (mFocusedTaskIndex == taskIndex) {
+ if (mFocusedTask == task) {
tv.setFocusedState(true, false /* animated */, false /* requestViewFocus */);
}
}
@@ -1429,10 +1423,12 @@
}
public final void onBusEvent(DismissFocusedTaskViewEvent event) {
- if (mFocusedTaskIndex != -1) {
- Task t = mStack.getStackTasks().get(mFocusedTaskIndex);
- TaskView tv = getChildViewForTask(t);
- tv.dismissTask();
+ if (mFocusedTask != null) {
+ TaskView tv = getChildViewForTask(mFocusedTask);
+ if (tv != null) {
+ tv.dismissTask();
+ }
+ resetFocusedTask(mFocusedTask);
}
}
@@ -1574,4 +1570,50 @@
// Remove the task from the stack
mStack.removeTask(task);
}
+
+ /**
+ * Starts an alpha animation on the freeform workspace background.
+ */
+ private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha, int duration,
+ Interpolator interpolator) {
+ if (mFreeformWorkspaceBackground.getAlpha() == targetAlpha) {
+ return;
+ }
+
+ Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
+ mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
+ COLOR_DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
+ mFreeformWorkspaceBackgroundAnimator.setDuration(duration);
+ mFreeformWorkspaceBackgroundAnimator.setInterpolator(interpolator);
+ mFreeformWorkspaceBackgroundAnimator.start();
+ }
+
+ /**
+ * Returns the insert index for the task in the current set of task views. If the given task
+ * is already in the task view list, then this method returns the insert index assuming it
+ * is first removed at the previous index.
+ *
+ * @param task the task we are finding the index for
+ * @param taskIndex the index of the task in the stack
+ */
+ private int findTaskViewInsertIndex(Task task, int taskIndex) {
+ if (taskIndex != -1) {
+ List<TaskView> taskViews = getTaskViews();
+ boolean foundTaskView = false;
+ int taskViewCount = taskViews.size();
+ for (int i = 0; i < taskViewCount; i++) {
+ Task tvTask = taskViews.get(i).getTask();
+ if (tvTask == task) {
+ foundTaskView = true;
+ } else if (taskIndex < mStack.indexOfStackTask(tvTask)) {
+ if (foundTaskView) {
+ return i - 1;
+ } else {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 907ed2f..1a6f129 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -176,11 +176,11 @@
}
case MotionEvent.ACTION_POINTER_DOWN: {
final int index = ev.getActionIndex();
- mDownX = (int) ev.getX();
- mDownY = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(index);
+ mDownX = (int) ev.getX(index);
+ mDownY = (int) ev.getY(index);
mLastY = mDownY;
mDownScrollP = mScroller.getStackScroll();
- mActivePointerId = ev.getPointerId(index);
mVelocityTracker.addMovement(ev);
break;
}
@@ -221,6 +221,10 @@
// Select a new active pointer id and reset the motion state
final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
+ mDownX = (int) ev.getX(pointerIndex);
+ mDownY = (int) ev.getY(pointerIndex);
+ mLastY = mDownY;
+ mDownScrollP = mScroller.getStackScroll();
}
mVelocityTracker.addMovement(ev);
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 1baa1a3..813a1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -659,10 +659,6 @@
}
}
- public void disableLayersForOneFrame() {
- mHeaderView.disableLayersForOneFrame();
- }
-
/**** TaskCallbacks Implementation ****/
/** Binds this task view to the task */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index ec59f31..78a2c7f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -80,13 +80,10 @@
// Header dim, which is only used when task view hardware layers are not used
Paint mDimLayerPaint = new Paint();
- PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
Interpolator mFastOutSlowInInterpolator;
Interpolator mFastOutLinearInInterpolator;
- boolean mLayersDisabled;
-
public TaskViewHeader(Context context) {
this(context, null);
}
@@ -111,6 +108,7 @@
});
// Load the dismiss resources
+ mDimLayerPaint.setColor(Color.argb(0, 0, 0, 0));
mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
mDismissContentDescription =
@@ -173,21 +171,13 @@
canvas.restoreToCount(count);
}
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
/**
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
void setDimAlpha(int alpha) {
- mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0));
- mDimLayerPaint.setColorFilter(mDimColorFilter);
- if (!mLayersDisabled) {
- setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
- }
+ mDimLayerPaint.setColor(Color.argb(alpha, 0, 0, 0));
+ invalidate();
}
/** Returns the secondary color for a primary color. */
@@ -341,23 +331,11 @@
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
- if (mLayersDisabled) {
- mLayersDisabled = false;
- postOnAnimation(new Runnable() {
- @Override
- public void run() {
- mLayersDisabled = false;
- setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
- }
- });
- }
- }
- public void disableLayersForOneFrame() {
- mLayersDisabled = true;
-
- // Disable layer for a frame so we can draw our first frame faster.
- setLayerType(LAYER_TYPE_NONE, null);
+ // Draw the thumbnail with the rounded corners
+ canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
+ mCornerRadius,
+ mCornerRadius, mDimLayerPaint);
}
/** Notifies the associated TaskView has been focused. */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 98f3f0c..93264ff 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -74,7 +74,7 @@
private final Rect mTmpRect = new Rect();
private final Rect mLastResizeRect = new Rect();
- private final WindowManagerProxy mWindowManagerProxy = new WindowManagerProxy();
+ private final WindowManagerProxy mWindowManagerProxy = WindowManagerProxy.getInstance();
private Interpolator mFastOutSlowInInterpolator;
private final Interpolator mTouchResponseInterpolator =
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 0d3f803..58de5d5 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -37,6 +37,8 @@
private static final String TAG = "WindowManagerProxy";
+ private static final WindowManagerProxy sInstance = new WindowManagerProxy();
+
@GuardedBy("mResizeRect")
private final Rect mResizeRect = new Rect();
private final Rect mTmpRect = new Rect();
@@ -78,6 +80,13 @@
}
};
+ private WindowManagerProxy() {
+ }
+
+ public static WindowManagerProxy getInstance() {
+ return sInstance;
+ }
+
public void resizeDockedStack(Rect rect) {
synchronized (mResizeRect) {
mResizeRect.set(rect);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 1601b83..a3f404a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -146,7 +146,8 @@
mWarning = 0xffff0000;
} else {
mOpaque = context.getColor(R.color.system_bar_background_opaque);
- mSemiTransparent = context.getColor(R.color.system_bar_background_semi_transparent);
+ mSemiTransparent = context.getColor(
+ com.android.internal.R.color.system_bar_background_semi_transparent);
mTransparent = context.getColor(R.color.system_bar_background_transparent);
mWarning = context.getColor(com.android.internal.R.color.battery_saver_mode_color);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
index d91bfb9..a2616fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarGestureHelper.java
@@ -16,30 +16,29 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManager;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
-import android.os.SystemProperties;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
-import android.view.WindowManager;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.tuner.TunerService;
import static android.view.WindowManager.*;
/**
* Class to detect gestures on the navigation bar.
*/
-public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureListener {
+public class NavigationBarGestureHelper extends GestureDetector.SimpleOnGestureListener
+ implements TunerService.Tunable {
- private static final String DOCK_WINDOW_GESTURE_ENABLED_PROP = "persist.dock_gesture_enabled";
+ private static final String KEY_DOCK_WINDOW_GESTURE = "overview_nav_bar_gesture";
/**
* When dragging from the navigation bar, we drag in recents.
@@ -53,6 +52,7 @@
private RecentsComponent mRecentsComponent;
private Divider mDivider;
+ private Context mContext;
private boolean mIsVertical;
private boolean mIsRTL;
@@ -69,13 +69,14 @@
private int mDragMode;
public NavigationBarGestureHelper(Context context) {
+ mContext = context;
ViewConfiguration configuration = ViewConfiguration.get(context);
Resources r = context.getResources();
mScrollTouchSlop = r.getDimensionPixelSize(R.dimen.navigation_bar_min_swipe_distance);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
mTaskSwitcherDetector = new GestureDetector(context, this);
- mDockWindowEnabled = SystemProperties.getBoolean(DOCK_WINDOW_GESTURE_ENABLED_PROP, false);
+ TunerService.get(context).addTunable(this, KEY_DOCK_WINDOW_GESTURE);
}
public void setComponents(RecentsComponent recentsComponent, Divider divider) {
@@ -172,6 +173,7 @@
== DOCKED_INVALID) {
mDragMode = calculateDragMode();
Rect initialBounds = null;
+ int createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
if (mDragMode == DRAG_MODE_DIVIDER) {
initialBounds = new Rect();
mDivider.getView().calculateBoundsForPosition(mIsVertical
@@ -181,8 +183,12 @@
? DOCKED_TOP
: DOCKED_LEFT,
initialBounds);
+ } else if (mDragMode == DRAG_MODE_RECENTS && mTouchDownX
+ < mContext.getResources().getDisplayMetrics().widthPixels / 2) {
+ createMode = ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
}
- mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS, initialBounds);
+ mRecentsComponent.dockTopTask(mDragMode == DRAG_MODE_RECENTS, createMode,
+ initialBounds);
if (mDragMode == DRAG_MODE_DIVIDER) {
mDivider.getView().startDragging();
}
@@ -259,4 +265,14 @@
}
return true;
}
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ switch (key) {
+ case KEY_DOCK_WINDOW_GESTURE:
+ mDockWindowEnabled = (newValue != null) &&
+ (Integer.parseInt(newValue) != 0);
+ break;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 685c4e5..e51cf7ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1133,7 +1133,9 @@
@Override
public boolean onLongClick(View v) {
if (mRecents != null) {
- mRecents.dockTopTask(false /* draggingInRecents */, null /* initialBounds */);
+ mRecents.dockTopTask(false /* draggingInRecents */,
+ ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+ null /* initialBounds */);
return true;
}
return false;
@@ -2486,12 +2488,14 @@
// update status bar mode
final int sbMode = computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),
- View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT);
+ View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT,
+ View.STATUS_BAR_TRANSPARENT);
// update navigation bar mode
final int nbMode = mNavigationBarView == null ? -1 : computeBarMode(
oldVal, newVal, mNavigationBarView.getBarTransitions(),
- View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT);
+ View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
+ View.NAVIGATION_BAR_TRANSPARENT);
final boolean sbModeChanged = sbMode != -1;
final boolean nbModeChanged = nbMode != -1;
boolean checkBarModes = false;
@@ -2542,21 +2546,21 @@
}
private int computeBarMode(int oldVis, int newVis, BarTransitions transitions,
- int transientFlag, int translucentFlag) {
- final int oldMode = barMode(oldVis, transientFlag, translucentFlag);
- final int newMode = barMode(newVis, transientFlag, translucentFlag);
+ int transientFlag, int translucentFlag, int transparentFlag) {
+ final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag);
+ final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag);
if (oldMode == newMode) {
return -1; // no mode change
}
return newMode;
}
- private int barMode(int vis, int transientFlag, int translucentFlag) {
- int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_TRANSPARENT;
+ private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) {
+ int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag;
return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
: (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
: (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT
- : (vis & View.SYSTEM_UI_TRANSPARENT) != 0 ? MODE_TRANSPARENT
+ : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT
: (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
: MODE_OPAQUE;
}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a5cef1a..ede92fb 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -513,33 +513,35 @@
String[] uidPackageNames = getPackagesForUid(uid);
ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
- ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
- if (callbacks != null) {
- final int callbackCount = callbacks.size();
- for (int i = 0; i < callbackCount; i++) {
- Callback callback = callbacks.get(i);
- ArraySet<String> changedPackages = new ArraySet<>();
- Collections.addAll(changedPackages, uidPackageNames);
- callbackSpecs = new ArrayMap<>();
- callbackSpecs.put(callback, changedPackages);
- }
- }
-
- for (String uidPackageName : uidPackageNames) {
- callbacks = mPackageModeWatchers.get(uidPackageName);
+ synchronized (this) {
+ ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
if (callbacks != null) {
- if (callbackSpecs == null) {
- callbackSpecs = new ArrayMap<>();
- }
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
Callback callback = callbacks.get(i);
- ArraySet<String> changedPackages = callbackSpecs.get(callback);
- if (changedPackages == null) {
- changedPackages = new ArraySet<>();
- callbackSpecs.put(callback, changedPackages);
+ ArraySet<String> changedPackages = new ArraySet<>();
+ Collections.addAll(changedPackages, uidPackageNames);
+ callbackSpecs = new ArrayMap<>();
+ callbackSpecs.put(callback, changedPackages);
+ }
+ }
+
+ for (String uidPackageName : uidPackageNames) {
+ callbacks = mPackageModeWatchers.get(uidPackageName);
+ if (callbacks != null) {
+ if (callbackSpecs == null) {
+ callbackSpecs = new ArrayMap<>();
}
- changedPackages.add(uidPackageName);
+ final int callbackCount = callbacks.size();
+ for (int i = 0; i < callbackCount; i++) {
+ Callback callback = callbacks.get(i);
+ ArraySet<String> changedPackages = callbackSpecs.get(callback);
+ if (changedPackages == null) {
+ changedPackages = new ArraySet<>();
+ callbackSpecs.put(callback, changedPackages);
+ }
+ changedPackages.add(uidPackageName);
+ }
}
}
}
@@ -2051,7 +2053,7 @@
private static String[] getPackagesForUid(int uid) {
String[] packageNames = null;
try {
- packageNames= AppGlobals.getPackageManager().getPackagesForUid(uid);
+ packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
} catch (RemoteException e) {
/* ignore - local call */
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 6aa5263..033a4b8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -624,7 +624,13 @@
byte[] hash = credentialUtil.toHash(credential, userId);
if (Arrays.equals(hash, storedHash.hash)) {
unlockKeystore(credentialUtil.adjustForKeystore(credential), userId);
- unlockUser(userId, null);
+
+ // TODO: pass through a meaningful token from gatekeeper to
+ // unlock credential keys; for now pass through a stub value to
+ // indicate that we came from a user challenge.
+ final byte[] token = String.valueOf(userId).getBytes();
+ unlockUser(userId, token);
+
// migrate credential to GateKeeper
credentialUtil.setCredential(credential, null, userId);
if (!hasChallenge) {
@@ -677,7 +683,13 @@
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
// credential has matched
unlockKeystore(credential, userId);
- unlockUser(userId, null);
+
+ // TODO: pass through a meaningful token from gatekeeper to
+ // unlock credential keys; for now pass through a stub value to
+ // indicate that we came from a user challenge.
+ final byte[] token = String.valueOf(userId).getBytes();
+ unlockUser(userId, token);
+
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
if (LockPatternUtils.isSeparateWorkChallengeEnabled() && info.isManagedProfile()) {
TrustManager trustManager =
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index bd43a71..807c0d6 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -100,6 +100,7 @@
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.internal.widget.LockPatternUtils;
import com.android.server.NativeDaemonConnector.Command;
import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.pm.PackageManagerService;
@@ -435,6 +436,7 @@
private PackageManagerService mPms;
private final Callbacks mCallbacks;
+ private final LockPatternUtils mLockPatternUtils;
// Two connectors - mConnector & mCryptConnector
private final CountDownLatch mConnectedSignal = new CountDownLatch(2);
@@ -1429,6 +1431,7 @@
mContext = context;
mCallbacks = new Callbacks(FgThread.get().getLooper());
+ mLockPatternUtils = new LockPatternUtils(mContext);
// XXX: This will go away soon in favor of IMountServiceObserver
mPms = (PackageManagerService) ServiceManager.getService("package");
@@ -2721,6 +2724,12 @@
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
waitForReady();
+ // When a user has secure lock screen, require a challenge token to
+ // actually unlock. This check is mostly in place for emulation mode.
+ if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(token)) {
+ throw new IllegalStateException("Token required to unlock secure user " + userId);
+ }
+
final String encodedToken;
if (ArrayUtils.isEmpty(token)) {
encodedToken = "!";
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index e0a9ab4..ce3166d 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -133,6 +133,15 @@
public void onStartUser(int userHandle) {}
/**
+ * Called when an existing user is unlocked. This means the
+ * credential-encrypted storage for that user is now available, and
+ * encryption-aware component filtering is no longer in effect.
+ *
+ * @param userHandle The identifier of the user.
+ */
+ public void onUnlockUser(int userHandle) {}
+
+ /**
* Called when switching to a different foreground user, for system services that have
* special behavior for whichever user is currently in the foreground. This is called
* before any application processes are aware of the new user.
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 92e6814..ecc69e9 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -165,6 +165,19 @@
}
}
+ public void unlockUser(final int userHandle) {
+ final int serviceLen = mServices.size();
+ for (int i = 0; i < serviceLen; i++) {
+ final SystemService service = mServices.get(i);
+ try {
+ service.onUnlockUser(userHandle);
+ } catch (Exception ex) {
+ Slog.wtf(TAG, "Failure reporting unlock of user " + userHandle
+ + " to service " + service.getClass().getName(), ex);
+ }
+ }
+ }
+
public void switchUser(final int userHandle) {
final int serviceLen = mServices.size();
for (int i = 0; i < serviceLen; i++) {
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 0b67ad8..6f713cd 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -57,7 +57,6 @@
private static final boolean LOG = false;
// Enable launching of applications when entering the dock.
- private static final boolean ENABLE_LAUNCH_CAR_DOCK_APP = true;
private static final boolean ENABLE_LAUNCH_DESK_DOCK_APP = true;
final Object mLock = new Object();
@@ -76,6 +75,13 @@
private boolean mComputedNightMode;
private int mCarModeEnableFlags;
+ // flag set by resource, whether to enable Car dock launch when starting car mode.
+ private boolean mEnableCarDockLaunch = true;
+ // flag set by resource, whether to lock UI mode to the default one or not.
+ private boolean mUiModeLocked = false;
+ // flag set by resource, whether to night mode change for normal all or not.
+ private boolean mNightModeLocked = false;
+
int mCurUiMode = 0;
private int mSetUiMode = 0;
private boolean mHoldingConfiguration = false;
@@ -176,6 +182,10 @@
com.android.internal.R.integer.config_carDockKeepsScreenOn) == 1);
mDeskModeKeepsScreenOn = (res.getInteger(
com.android.internal.R.integer.config_deskDockKeepsScreenOn) == 1);
+ mEnableCarDockLaunch = res.getBoolean(
+ com.android.internal.R.bool.config_enableCarDockHomeLaunch);
+ mUiModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockUiMode);
+ mNightModeLocked = res.getBoolean(com.android.internal.R.bool.config_lockDayNightMode);
final PackageManager pm = context.getPackageManager();
mTelevision = pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION)
@@ -199,6 +209,10 @@
private final IBinder mService = new IUiModeManager.Stub() {
@Override
public void enableCarMode(int flags) {
+ if (isUiModeLocked()) {
+ Slog.e(TAG, "enableCarMode while UI mode is locked");
+ return;
+ }
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -214,6 +228,10 @@
@Override
public void disableCarMode(int flags) {
+ if (isUiModeLocked()) {
+ Slog.e(TAG, "disableCarMode while UI mode is locked");
+ return;
+ }
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
@@ -241,6 +259,13 @@
@Override
public void setNightMode(int mode) {
+ if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
+ != PackageManager.PERMISSION_GRANTED)) {
+ Slog.e(TAG,
+ "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
+ return;
+ }
switch (mode) {
case UiModeManager.MODE_NIGHT_NO:
case UiModeManager.MODE_NIGHT_YES:
@@ -273,6 +298,20 @@
}
@Override
+ public boolean isUiModeLocked() {
+ synchronized (mLock) {
+ return mUiModeLocked;
+ }
+ }
+
+ @Override
+ public boolean isNightModeLocked() {
+ synchronized (mLock) {
+ return mNightModeLocked;
+ }
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -293,10 +332,13 @@
pw.print(" mDockState="); pw.print(mDockState);
pw.print(" mLastBroadcastState="); pw.println(mLastBroadcastState);
pw.print(" mNightMode="); pw.print(mNightMode);
+ pw.print(" mNightModeLocked="); pw.print(mNightModeLocked);
pw.print(" mCarModeEnabled="); pw.print(mCarModeEnabled);
pw.print(" mComputedNightMode="); pw.print(mComputedNightMode);
- pw.print(" mCarModeEnableFlags="); pw.println(mCarModeEnableFlags);
+ pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags);
+ pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch);
pw.print(" mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
+ pw.print(" mUiModeLocked="); pw.print(mUiModeLocked);
pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
pw.print(" mHoldingConfiguration="); pw.print(mHoldingConfiguration);
pw.print(" mSystemReady="); pw.println(mSystemReady);
@@ -356,7 +398,9 @@
private void updateConfigurationLocked() {
int uiMode = mDefaultUiModeType;
- if (mTelevision) {
+ if (mUiModeLocked) {
+ // no-op, keeps default one
+ } else if (mTelevision) {
uiMode = Configuration.UI_MODE_TYPE_TELEVISION;
} else if (mWatch) {
uiMode = Configuration.UI_MODE_TYPE_WATCH;
@@ -460,7 +504,7 @@
} else {
String category = null;
if (mCarModeEnabled) {
- if (ENABLE_LAUNCH_CAR_DOCK_APP
+ if (mEnableCarDockLaunch
&& (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
category = Intent.CATEGORY_CAR_DOCK;
}
@@ -503,7 +547,7 @@
if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(action)) {
// Only launch car home when car mode is enabled and the caller
// has asked us to switch to it.
- if (ENABLE_LAUNCH_CAR_DOCK_APP
+ if (mEnableCarDockLaunch
&& (enableFlags & UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
category = Intent.CATEGORY_CAR_DOCK;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ef623eb..b769d39 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1487,6 +1487,7 @@
static final int APP_BOOST_DEACTIVATE_MSG = 58;
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 59;
static final int IDLE_UIDS_MSG = 60;
+ static final int SYSTEM_USER_UNLOCK_MSG = 61;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1989,6 +1990,10 @@
mSystemServiceManager.startUser(msg.arg1);
break;
}
+ case SYSTEM_USER_UNLOCK_MSG: {
+ mSystemServiceManager.unlockUser(msg.arg1);
+ break;
+ }
case SYSTEM_USER_CURRENT_MSG: {
mBatteryStatsService.noteEvent(
BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 3e0ae17..f6f82da 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -34,6 +34,7 @@
import static com.android.server.am.ActivityManagerService.REPORT_USER_SWITCH_MSG;
import static com.android.server.am.ActivityManagerService.SYSTEM_USER_CURRENT_MSG;
import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG;
+import static com.android.server.am.ActivityManagerService.SYSTEM_USER_UNLOCK_MSG;
import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG;
import android.annotation.NonNull;
@@ -81,8 +82,6 @@
import java.util.List;
import java.util.Set;
-import libcore.util.EmptyArray;
-
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
*/
@@ -147,7 +146,6 @@
// User 0 is the first and only user that runs at boot.
final UserState uss = new UserState(UserHandle.SYSTEM);
mStartedUsers.put(UserHandle.USER_SYSTEM, uss);
- updateUserUnlockedState(uss);
mUserLru.add(UserHandle.USER_SYSTEM);
updateStartedUserArrayLocked();
}
@@ -173,8 +171,8 @@
num--;
continue;
}
- if (oldUss.mState == UserState.STATE_STOPPING
- || oldUss.mState == UserState.STATE_SHUTDOWN) {
+ if (oldUss.state == UserState.STATE_STOPPING
+ || oldUss.state == UserState.STATE_SHUTDOWN) {
// This user is already stopping, doesn't count.
num--;
i++;
@@ -199,17 +197,65 @@
}
void finishUserBoot(UserState uss) {
+ finishUserBoot(uss, null);
+ }
+
+ void finishUserBoot(UserState uss, IIntentReceiver resultTo) {
+ final int userId = uss.mHandle.getIdentifier();
synchronized (mService) {
- if (uss.mState == UserState.STATE_BOOTING
- && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
- uss.mState = UserState.STATE_RUNNING;
- final int userId = uss.mHandle.getIdentifier();
- Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+ // Bail if we ended up with a stale user
+ if (mStartedUsers.get(userId) != uss) return;
+
+ // We always walk through all the user lifecycle states to send
+ // consistent developer events. We step into RUNNING_LOCKED here,
+ // but we might immediately step into RUNNING below if the user
+ // storage is already unlocked.
+ if (uss.state == UserState.STATE_BOOTING) {
+ uss.setState(UserState.STATE_RUNNING_LOCKED);
+
+ Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null);
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
- mService.broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null,
- new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
+ mService.broadcastIntentLocked(null, null, intent, null, resultTo, 0, null, null,
+ new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
+ AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
+ }
+
+ maybeUnlockUser(userId);
+ }
+ }
+
+ /**
+ * Consider stepping from {@link UserState#STATE_RUNNING_LOCKED} into
+ * {@link UserState#STATE_RUNNING}, which only occurs if the user storage is
+ * actually unlocked.
+ */
+ void finishUserUnlock(UserState uss) {
+ final int userId = uss.mHandle.getIdentifier();
+ synchronized (mService) {
+ // Bail if we ended up with a stale user
+ if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
+
+ // Only keep marching forward if user is actually unlocked
+ if (!isUserKeyUnlocked(userId)) return;
+
+ if (uss.state == UserState.STATE_RUNNING_LOCKED) {
+ uss.setState(UserState.STATE_RUNNING);
+
+ mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0));
+
+ final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
+ unlockedIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ mService.broadcastIntentLocked(null, null, unlockedIntent, null, null, 0, null,
+ null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ userId);
+
+ final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+ bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
+ mService.broadcastIntentLocked(null, null, bootIntent, null, null, 0, null, null,
+ new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
}
@@ -291,9 +337,9 @@
uss.mStopCallbacks.add(callback);
}
- if (uss.mState != UserState.STATE_STOPPING
- && uss.mState != UserState.STATE_SHUTDOWN) {
- uss.mState = UserState.STATE_STOPPING;
+ if (uss.state != UserState.STATE_STOPPING
+ && uss.state != UserState.STATE_SHUTDOWN) {
+ uss.setState(UserState.STATE_STOPPING);
updateStartedUserArrayLocked();
long ident = Binder.clearCallingIdentity();
@@ -321,11 +367,11 @@
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
// On to the next.
synchronized (mService) {
- if (uss.mState != UserState.STATE_STOPPING) {
+ if (uss.state != UserState.STATE_STOPPING) {
// Whoops, we are being started back up. Abort, abort!
return;
}
- uss.mState = UserState.STATE_SHUTDOWN;
+ uss.setState(UserState.STATE_SHUTDOWN);
}
mService.mBatteryStatsService.noteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
@@ -355,7 +401,7 @@
callbacks = new ArrayList<>(uss.mStopCallbacks);
if (mStartedUsers.get(userId) != uss) {
stopped = false;
- } else if (uss.mState != UserState.STATE_SHUTDOWN) {
+ } else if (uss.state != UserState.STATE_SHUTDOWN) {
stopped = false;
} else {
stopped = true;
@@ -438,8 +484,8 @@
Integer oldUserId = mUserLru.get(i);
UserState oldUss = mStartedUsers.get(oldUserId);
if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
- || oldUss.mState == UserState.STATE_STOPPING
- || oldUss.mState == UserState.STATE_SHUTDOWN) {
+ || oldUss.state == UserState.STATE_STOPPING
+ || oldUss.state == UserState.STATE_SHUTDOWN) {
continue;
}
UserInfo userInfo = getUserInfo(oldUserId);
@@ -482,18 +528,21 @@
return userManager;
}
- private void updateUserUnlockedState(UserState uss) {
- final IMountService mountService = IMountService.Stub
- .asInterface(ServiceManager.getService("mount"));
+ private IMountService getMountService() {
+ return IMountService.Stub.asInterface(ServiceManager.getService("mount"));
+ }
+
+ private boolean isUserKeyUnlocked(int userId) {
+ final IMountService mountService = getMountService();
if (mountService != null) {
try {
- uss.unlocked = mountService.isUserKeyUnlocked(uss.mHandle.getIdentifier());
+ return mountService.isUserKeyUnlocked(userId);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
} else {
- // System isn't fully booted yet, so guess based on property
- uss.unlocked = !StorageManager.isFileBasedEncryptionEnabled();
+ Slog.w(TAG, "Mount service not published; guessing locked state based on property");
+ return !StorageManager.isFileBasedEncryptionEnabled();
}
}
@@ -547,8 +596,6 @@
}
final UserState uss = mStartedUsers.get(userId);
- updateUserUnlockedState(uss);
-
final Integer userIdInt = userId;
mUserLru.remove(userIdInt);
mUserLru.add(userIdInt);
@@ -572,22 +619,22 @@
// Make sure user is in the started state. If it is currently
// stopping, we need to knock that off.
- if (uss.mState == UserState.STATE_STOPPING) {
+ if (uss.state == UserState.STATE_STOPPING) {
// If we are stopping, we haven't sent ACTION_SHUTDOWN,
// so we can just fairly silently bring the user back from
// the almost-dead.
- uss.mState = UserState.STATE_RUNNING;
+ uss.setState(uss.lastState);
updateStartedUserArrayLocked();
needStart = true;
- } else if (uss.mState == UserState.STATE_SHUTDOWN) {
+ } else if (uss.state == UserState.STATE_SHUTDOWN) {
// This means ACTION_SHUTDOWN has been sent, so we will
// need to treat this as a new boot of the user.
- uss.mState = UserState.STATE_BOOTING;
+ uss.setState(UserState.STATE_BOOTING);
updateStartedUserArrayLocked();
needStart = true;
}
- if (uss.mState == UserState.STATE_BOOTING) {
+ if (uss.state == UserState.STATE_BOOTING) {
// Let user manager propagate user restrictions to other services.
getUserManager().onBeforeStartUser(userId);
@@ -697,35 +744,40 @@
}
}
+ /**
+ * Attempt to unlock user without a credential token. This typically
+ * succeeds when the device doesn't have credential-encrypted storage, or
+ * when the the credential-encrypted storage isn't tied to a user-provided
+ * PIN or pattern.
+ */
+ boolean maybeUnlockUser(final int userId) {
+ // Try unlocking storage using empty token
+ return unlockUserCleared(userId, null);
+ }
+
boolean unlockUserCleared(final int userId, byte[] token) {
synchronized (mService) {
+ // Bail if already running unlocked
final UserState uss = mStartedUsers.get(userId);
- if (uss.unlocked) {
- // Bail early when already unlocked
- return true;
+ if (uss.state == UserState.STATE_RUNNING) return true;
+ }
+
+ if (!isUserKeyUnlocked(userId)) {
+ final UserInfo userInfo = getUserInfo(userId);
+ final IMountService mountService = getMountService();
+ try {
+ mountService.unlockUserKey(userId, userInfo.serialNumber, token);
+ } catch (RemoteException | RuntimeException e) {
+ Slog.w(TAG, "Failed to unlock: " + e.getMessage());
+ return false;
}
}
- final UserInfo userInfo = getUserInfo(userId);
- final IMountService mountService = IMountService.Stub
- .asInterface(ServiceManager.getService("mount"));
- try {
- mountService.unlockUserKey(userId, userInfo.serialNumber, token);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to unlock: " + e.getMessage());
- return false;
- }
-
synchronized (mService) {
final UserState uss = mStartedUsers.get(userId);
- updateUserUnlockedState(uss);
+ finishUserUnlock(uss);
}
- final Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
- mService.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, userId);
-
return true;
}
@@ -1045,8 +1097,8 @@
for (int i = 0; i < mStartedUsers.size(); i++) {
UserState uss = mStartedUsers.valueAt(i);
// This list does not include stopping users.
- if (uss.mState != UserState.STATE_STOPPING
- && uss.mState != UserState.STATE_SHUTDOWN) {
+ if (uss.state != UserState.STATE_STOPPING
+ && uss.state != UserState.STATE_SHUTDOWN) {
num++;
}
}
@@ -1054,8 +1106,8 @@
num = 0;
for (int i = 0; i < mStartedUsers.size(); i++) {
UserState uss = mStartedUsers.valueAt(i);
- if (uss.mState != UserState.STATE_STOPPING
- && uss.mState != UserState.STATE_SHUTDOWN) {
+ if (uss.state != UserState.STATE_STOPPING
+ && uss.state != UserState.STATE_SHUTDOWN) {
mStartedUserArray[num] = mStartedUsers.keyAt(i);
num++;
}
@@ -1065,17 +1117,7 @@
void sendBootCompletedLocked(IIntentReceiver resultTo) {
for (int i = 0; i < mStartedUsers.size(); i++) {
UserState uss = mStartedUsers.valueAt(i);
- if (uss.mState == UserState.STATE_BOOTING) {
- uss.mState = UserState.STATE_RUNNING;
- final int userId = mStartedUsers.keyAt(i);
- Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
- mService.broadcastIntentLocked(null, null, intent, null,
- resultTo, 0, null, null,
- new String[] {android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
- }
+ finishUserBoot(uss, resultTo);
}
}
@@ -1117,14 +1159,33 @@
if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
return true;
}
- if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0 && state.unlocked) {
- return false;
+
+ final boolean unlocked;
+ switch (state.state) {
+ case UserState.STATE_STOPPING:
+ case UserState.STATE_SHUTDOWN:
+ default:
+ return false;
+
+ case UserState.STATE_BOOTING:
+ case UserState.STATE_RUNNING_LOCKED:
+ unlocked = false;
+ break;
+
+ case UserState.STATE_RUNNING:
+ unlocked = true;
+ break;
}
- if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0 && !state.unlocked) {
- return false;
+
+ if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) {
+ return !unlocked;
}
- return state.mState != UserState.STATE_STOPPING
- && state.mState != UserState.STATE_SHUTDOWN;
+ if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0) {
+ return unlocked;
+ }
+
+ // One way or another, we're running!
+ return true;
}
UserInfo getCurrentUser() {
diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java
index b5b5c1d..7b18a17 100644
--- a/services/core/java/com/android/server/am/UserState.java
+++ b/services/core/java/com/android/server/am/UserState.java
@@ -19,28 +19,37 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
import android.app.IStopUserCallback;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.Slog;
public final class UserState {
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "UserState" : TAG_AM;
+
// User is first coming up.
public final static int STATE_BOOTING = 0;
+ // User is in the locked running state.
+ public final static int STATE_RUNNING_LOCKED = 1;
// User is in the normal running state.
- public final static int STATE_RUNNING = 1;
+ public final static int STATE_RUNNING = 2;
// User is in the initial process of being stopped.
- public final static int STATE_STOPPING = 2;
+ public final static int STATE_STOPPING = 3;
// User is in the final phase of stopping, sending Intent.ACTION_SHUTDOWN.
- public final static int STATE_SHUTDOWN = 3;
+ public final static int STATE_SHUTDOWN = 4;
public final UserHandle mHandle;
public final ArrayList<IStopUserCallback> mStopCallbacks
= new ArrayList<IStopUserCallback>();
- public int mState = STATE_BOOTING;
+ public int state = STATE_BOOTING;
+ public int lastState = STATE_BOOTING;
public boolean switching;
public boolean initializing;
- public boolean unlocked;
/**
* The last time that a provider was reported to usage stats as being brought to important
@@ -52,22 +61,32 @@
mHandle = handle;
}
- void dump(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("mState=");
- switch (mState) {
- case STATE_BOOTING: pw.print("BOOTING"); break;
- case STATE_RUNNING: pw.print("RUNNING"); break;
- case STATE_STOPPING: pw.print("STOPPING"); break;
- case STATE_SHUTDOWN: pw.print("SHUTDOWN"); break;
- default: pw.print(mState); break;
+ public void setState(int newState) {
+ if (DEBUG_MU) {
+ Slog.i(TAG, "User " + mHandle.getIdentifier() + " state changed from "
+ + stateToString(state) + " to " + stateToString(newState));
}
+ lastState = state;
+ state = newState;
+ }
+
+ private static String stateToString(int state) {
+ switch (state) {
+ case STATE_BOOTING: return "BOOTING";
+ case STATE_RUNNING_LOCKED: return "RUNNING_LOCKED";
+ case STATE_RUNNING: return "RUNNING";
+ case STATE_STOPPING: return "STOPPING";
+ case STATE_SHUTDOWN: return "SHUTDOWN";
+ default: return Integer.toString(state);
+ }
+ }
+
+ void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix);
+ pw.print("state="); pw.print(stateToString(state));
+ pw.print(" lastState="); pw.print(stateToString(lastState));
if (switching) pw.print(" SWITCHING");
if (initializing) pw.print(" INITIALIZING");
- if (unlocked) {
- pw.print(" UNLOCKED");
- } else {
- pw.print(" LOCKED");
- }
pw.println();
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e0b7370..c2666b8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -17,6 +17,19 @@
package com.android.server.notification;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CLICK;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_CANCEL_ALL;
+import static android.service.notification.NotificationAssistantService.REASON_DELEGATE_ERROR;
+import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_CHANGED;
+import static android.service.notification.NotificationAssistantService.REASON_USER_STOPPED;
+import static android.service.notification.NotificationAssistantService.REASON_PACKAGE_BANNED;
+import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationAssistantService.REASON_APP_CANCEL_ALL;
+import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL;
+import static android.service.notification.NotificationAssistantService.REASON_LISTENER_CANCEL_ALL;
+import static android.service.notification.NotificationAssistantService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationAssistantService.REASON_GROUP_OPTIMIZATION;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_LIGHTS;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_PEEK;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
@@ -281,19 +294,6 @@
private static final int MY_UID = Process.myUid();
private static final int MY_PID = Process.myPid();
- private static final int REASON_DELEGATE_CLICK = 1;
- private static final int REASON_DELEGATE_CANCEL = 2;
- private static final int REASON_DELEGATE_CANCEL_ALL = 3;
- private static final int REASON_DELEGATE_ERROR = 4;
- private static final int REASON_PACKAGE_CHANGED = 5;
- private static final int REASON_USER_STOPPED = 6;
- private static final int REASON_PACKAGE_BANNED = 7;
- private static final int REASON_NOMAN_CANCEL = 8;
- private static final int REASON_NOMAN_CANCEL_ALL = 9;
- private static final int REASON_LISTENER_CANCEL = 10;
- private static final int REASON_LISTENER_CANCEL_ALL = 11;
- private static final int REASON_GROUP_SUMMARY_CANCELED = 12;
- private static final int REASON_GROUP_OPTIMIZATION = 13;
private static class Archive {
final int mBufferSize;
@@ -1176,7 +1176,7 @@
cancelNotification(Binder.getCallingUid(), Binder.getCallingPid(), pkg, tag, id, 0,
Binder.getCallingUid() == Process.SYSTEM_UID
? 0 : Notification.FLAG_FOREGROUND_SERVICE, false, userId,
- REASON_NOMAN_CANCEL, null);
+ REASON_APP_CANCEL, null);
}
@Override
@@ -1190,7 +1190,7 @@
// running foreground services.
cancelAllNotificationsInt(Binder.getCallingUid(), Binder.getCallingPid(),
pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId,
- REASON_NOMAN_CANCEL_ALL, null);
+ REASON_APP_CANCEL_ALL, null);
}
@Override
@@ -2879,8 +2879,8 @@
case REASON_LISTENER_CANCEL_ALL:
mUsageStats.registerDismissedByUser(r);
break;
- case REASON_NOMAN_CANCEL:
- case REASON_NOMAN_CANCEL_ALL:
+ case REASON_APP_CANCEL:
+ case REASON_APP_CANCEL_ALL:
mUsageStats.registerRemovedByApp(r);
break;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0fde27f..8ef8276 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8397,9 +8397,9 @@
}
}
if ((p.info.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
- ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(p.info.name);
- if (appOpPerms != null) {
- appOpPerms.remove(pkg.packageName);
+ ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(p.info.name);
+ if (appOpPkgs != null) {
+ appOpPkgs.remove(pkg.packageName);
}
}
}
@@ -8413,10 +8413,10 @@
String perm = pkg.requestedPermissions.get(i);
BasePermission bp = mSettings.mPermissions.get(perm);
if (bp != null && (bp.protectionLevel&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) {
- ArraySet<String> appOpPerms = mAppOpPermissionPackages.get(perm);
- if (appOpPerms != null) {
- appOpPerms.remove(pkg.packageName);
- if (appOpPerms.isEmpty()) {
+ ArraySet<String> appOpPkgs = mAppOpPermissionPackages.get(perm);
+ if (appOpPkgs != null) {
+ appOpPkgs.remove(pkg.packageName);
+ if (appOpPkgs.isEmpty()) {
mAppOpPermissionPackages.remove(perm);
}
}
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index 051b7fb..0c80ffa 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -47,6 +47,7 @@
private final int mTransientFlag;
private final int mUnhideFlag;
private final int mTranslucentFlag;
+ private final int mTransparentFlag;
private final int mStatusBarManagerId;
private final int mTranslucentWmFlag;
protected final Handler mHandler;
@@ -63,13 +64,14 @@
private boolean mNoAnimationOnNextShow;
public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag,
- int statusBarManagerId, int translucentWmFlag) {
+ int statusBarManagerId, int translucentWmFlag, int transparentFlag) {
mTag = "BarController." + tag;
mTransientFlag = transientFlag;
mUnhideFlag = unhideFlag;
mTranslucentFlag = translucentFlag;
mStatusBarManagerId = statusBarManagerId;
mTranslucentWmFlag = translucentWmFlag;
+ mTransparentFlag = transparentFlag;
mHandler = new Handler();
}
@@ -126,13 +128,13 @@
vis &= ~mTranslucentFlag;
}
if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
- vis |= View.SYSTEM_UI_TRANSPARENT;
+ vis |= mTransparentFlag;
} else {
- vis &= ~View.SYSTEM_UI_TRANSPARENT;
+ vis &= ~mTransparentFlag;
}
} else {
vis = (vis & ~mTranslucentFlag) | (oldVis & mTranslucentFlag);
- vis = (vis & ~View.SYSTEM_UI_TRANSPARENT) | (oldVis & View.SYSTEM_UI_TRANSPARENT);
+ vis = (vis & ~mTransparentFlag) | (oldVis & mTransparentFlag);
}
}
return vis;
@@ -247,7 +249,7 @@
}
}
if (mShowTransparent) {
- vis |= View.SYSTEM_UI_TRANSPARENT;
+ vis |= mTransparentFlag;
if (mSetUnHideFlagWhenNextTransparent) {
vis |= mUnhideFlag;
mSetUnHideFlagWhenNextTransparent = false;
@@ -258,7 +260,7 @@
vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile
}
if ((vis & mTranslucentFlag) != 0 || (oldVis & mTranslucentFlag) != 0 ||
- ((vis | oldVis) & View.SYSTEM_UI_TRANSPARENT) != 0) {
+ ((vis | oldVis) & mTransparentFlag) != 0) {
mLastTranslucent = SystemClock.uptimeMillis();
}
return vis;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 9a7d153..fe427d3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -158,8 +158,7 @@
static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
// Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
- // No longer recommended for desk docks; still useful in car docks.
- static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
+ // No longer recommended for desk docks;
static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
static final int SHORT_PRESS_POWER_NOTHING = 0;
@@ -210,7 +209,8 @@
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.STATUS_BAR_TRANSLUCENT
| View.NAVIGATION_BAR_TRANSLUCENT
- | View.SYSTEM_UI_TRANSPARENT;
+ | View.STATUS_BAR_TRANSPARENT
+ | View.NAVIGATION_BAR_TRANSPARENT;
private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -316,6 +316,10 @@
int[] mNavigationBarHeightForRotation = new int[4];
int[] mNavigationBarWidthForRotation = new int[4];
+ // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
+ // This is for car dock and this is updated from resource.
+ private boolean mEnableCarDockHomeCapture = true;
+
boolean mBootMessageNeedsHiding;
KeyguardServiceDelegate mKeyguardDelegate;
final Runnable mWindowManagerDrawCallback = new Runnable() {
@@ -623,6 +627,8 @@
private final LogDecelerateInterpolator mLogDecelerateInterpolator
= new LogDecelerateInterpolator(100, 0);
+ private boolean mForceWindowDrawsStatusBarBackground;
+
private static final int MSG_ENABLE_POINTER_LOCATION = 1;
private static final int MSG_DISABLE_POINTER_LOCATION = 2;
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -803,7 +809,8 @@
View.NAVIGATION_BAR_UNHIDE,
View.NAVIGATION_BAR_TRANSLUCENT,
StatusBarManager.WINDOW_NAVIGATION_BAR,
- WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
+ View.NAVIGATION_BAR_TRANSPARENT);
private ImmersiveModeConfirmation mImmersiveModeConfirmation;
@@ -1398,6 +1405,8 @@
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ mEnableCarDockHomeCapture = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableCarDockHomeLaunch);
mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -1582,6 +1591,8 @@
mScreenshotChordEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableScreenshotChord);
+ mForceWindowDrawsStatusBarBackground = mContext.getResources().getBoolean(
+ R.bool.config_forceWindowDrawsStatusBarBackground);
mGlobalKeyManager = new GlobalKeyManager(mContext);
@@ -2044,10 +2055,14 @@
attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
- if (ActivityManager.isHighEndGfx()
- && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
- attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ if (ActivityManager.isHighEndGfx()) {
+ if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
+ attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ }
+ if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ || mForceWindowDrawsStatusBarBackground) {
+ attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ }
}
}
@@ -3604,7 +3619,7 @@
final int sysui = mLastSystemUiFlags;
boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
boolean navTranslucent = (sysui
- & (View.NAVIGATION_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
+ & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0;
boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
boolean navAllowedHidden = immersive || immersiveSticky;
@@ -3672,7 +3687,7 @@
boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
boolean statusBarTranslucent = (sysui
- & (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
+ & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
if (!isKeyguardShowing) {
statusBarTranslucent &= areTranslucentBarsAllowed();
}
@@ -4003,7 +4018,8 @@
&& (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0
&& (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
&& (fl & WindowManager.LayoutParams.
- FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
+ FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+ && !mForceWindowDrawsStatusBarBackground) {
// Ensure policy decor includes status bar
dcf.top = mStableTop;
}
@@ -6404,7 +6420,7 @@
* true:
* <ul>
* <li>The device is not in either car mode or desk mode
- * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
+ * <li>The device is in car mode but mEnableCarDockHomeCapture is false
* <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
* <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
* <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
@@ -6418,7 +6434,7 @@
// is, when in car mode you should be taken to car home regardless
// of whether we are actually in a car dock.
if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
- if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
+ if (mEnableCarDockHomeCapture) {
intent = mCarDockIntent;
}
} else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
@@ -6728,10 +6744,7 @@
final boolean freeformStackVisible =
mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID);
final boolean forceShowSystemBars = dockedStackVisible || freeformStackVisible;
- // TODO(multi-window): Update to force opaque independently for status bar and nav bar.
- // This will require refactoring the code to have separate vis flag for each bar so it can
- // be adjusted independently.
- final boolean forceOpaqueSystemBars = forceShowSystemBars;
+ final boolean forceOpaqueSystemBars = forceShowSystemBars && !mForceStatusBarFromKeyguard;
// apply translucent bar vis flags
WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
@@ -6761,6 +6774,11 @@
| View.SYSTEM_UI_TRANSPARENT);
}
+ if (mForceWindowDrawsStatusBarBackground) {
+ vis |= View.STATUS_BAR_TRANSPARENT;
+ vis &= ~View.STATUS_BAR_TRANSLUCENT;
+ }
+
// update status bar
boolean immersiveSticky =
(vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
@@ -6938,6 +6956,7 @@
pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
pw.print(" mDockMode="); pw.print(mDockMode);
+ pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture);
pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
index b935f5a..9d353c6 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -111,7 +111,8 @@
View.STATUS_BAR_UNHIDE,
View.STATUS_BAR_TRANSLUCENT,
StatusBarManager.WINDOW_STATUS_BAR,
- WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+ View.STATUS_BAR_TRANSPARENT);
}
public AppTransitionListener getAppTransitionListener() {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 22f1d63..e4f6c56 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -252,7 +252,7 @@
}
int boundsChange = BOUNDS_CHANGE_NONE;
- if (mBounds.left != bounds.left || mBounds.right != bounds.right) {
+ if (mBounds.left != bounds.left || mBounds.top != bounds.top) {
boundsChange |= BOUNDS_CHANGE_POSITION;
}
if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4736c60..f25f1e3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2517,7 +2517,7 @@
}
void repositionChild(Session session, IWindow client,
- int top, int left, int right, int bottom,
+ int left, int top, int right, int bottom,
long deferTransactionUntilFrame, Rect outFrame) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
long origId = Binder.clearCallingIdentity();
@@ -2538,23 +2538,24 @@
win.mAttrs.y = top;
win.mAttrs.width = right - left;
win.mAttrs.height = bottom - top;
-
win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
- win.mWinAnimator.computeShownFrameLocked();
-
if (SHOW_TRANSACTIONS) {
Slog.i(TAG, ">>> OPEN TRANSACTION repositionChild");
}
SurfaceControl.openTransaction();
+ win.applyGravityAndUpdateFrame();
+ win.mWinAnimator.computeShownFrameLocked();
+
+ win.mWinAnimator.setSurfaceBoundariesLocked(false);
+
if (deferTransactionUntilFrame > 0) {
win.mWinAnimator.mSurfaceController.deferTransactionUntil(
win.mAttachedWindow.mWinAnimator.mSurfaceController.getHandle(),
deferTransactionUntilFrame);
}
- win.mWinAnimator.setSurfaceBoundariesLocked(false);
SurfaceControl.closeTransaction();
if (SHOW_TRANSACTIONS) {
@@ -2588,6 +2589,7 @@
if (win == null) {
return 0;
}
+
WindowStateAnimator winAnimator = win.mWinAnimator;
if (viewVisibility != View.GONE) {
win.setRequestedSize(requestedWidth, requestedHeight);
@@ -10193,7 +10195,7 @@
public void setReplacingWindow(IBinder token, boolean animate) {
synchronized (mWindowMap) {
AppWindowToken appWindowToken = findAppWindowToken(token);
- if (appWindowToken == null) {
+ if (appWindowToken == null || !appWindowToken.isVisible()) {
Slog.w(TAG, "Attempted to set replacing window on non-existing app token " + token);
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index cfa2bb3..5e38492 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -72,6 +72,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
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_KEYGUARD;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -618,39 +619,6 @@
final int pw = mContainingFrame.width();
final int ph = mContainingFrame.height();
- int w,h;
- if ((mAttrs.flags & FLAG_SCALED) != 0) {
- if (mAttrs.width < 0) {
- w = pw;
- } else if (mEnforceSizeCompat) {
- w = (int)(mAttrs.width * mGlobalScale + .5f);
- } else {
- w = mAttrs.width;
- }
- if (mAttrs.height < 0) {
- h = ph;
- } else if (mEnforceSizeCompat) {
- h = (int)(mAttrs.height * mGlobalScale + .5f);
- } else {
- h = mAttrs.height;
- }
- } else {
- if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) {
- w = pw;
- } else if (mEnforceSizeCompat) {
- w = (int)(mRequestedWidth * mGlobalScale + .5f);
- } else {
- w = mRequestedWidth;
- }
- if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
- h = ph;
- } else if (mEnforceSizeCompat) {
- h = (int)(mRequestedHeight * mGlobalScale + .5f);
- } else {
- h = mRequestedHeight;
- }
- }
-
if (!mParentFrame.equals(pf)) {
//Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
// + " to " + pf);
@@ -676,28 +644,7 @@
final int fw = mFrame.width();
final int fh = mFrame.height();
- float x, y;
- if (mEnforceSizeCompat) {
- x = mAttrs.x * mGlobalScale;
- y = mAttrs.y * mGlobalScale;
- } else {
- x = mAttrs.x;
- y = mAttrs.y;
- }
-
- if (nonFullscreenTask) {
- // Make sure window fits in containing frame since it is in a non-fullscreen stack as
- // required by {@link Gravity#apply} call.
- w = Math.min(w, pw);
- h = Math.min(h, ph);
- }
-
- Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
- (int) (x + mAttrs.horizontalMargin * pw),
- (int) (y + mAttrs.verticalMargin * ph), mFrame);
-
- // Now make sure the window fits in the overall display frame.
- Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ applyGravityAndUpdateFrame();
// Calculate the outsets before the content frame gets shrinked to the window frame.
if (hasOutsets) {
@@ -2229,4 +2176,69 @@
rect.bottom = rect.top + (int)((rect.bottom - rect.top) / mVScale);
}
}
+
+ void applyGravityAndUpdateFrame() {
+ final int pw = mContainingFrame.width();
+ final int ph = mContainingFrame.height();
+ final Task task = getTask();
+ final boolean nonFullscreenTask = task != null && !task.isFullscreen();
+
+ float x, y;
+ int w,h;
+
+ if ((mAttrs.flags & FLAG_SCALED) != 0) {
+ if (mAttrs.width < 0) {
+ w = pw;
+ } else if (mEnforceSizeCompat) {
+ w = (int)(mAttrs.width * mGlobalScale + .5f);
+ } else {
+ w = mAttrs.width;
+ }
+ if (mAttrs.height < 0) {
+ h = ph;
+ } else if (mEnforceSizeCompat) {
+ h = (int)(mAttrs.height * mGlobalScale + .5f);
+ } else {
+ h = mAttrs.height;
+ }
+ } else {
+ if (mAttrs.width == MATCH_PARENT) {
+ w = pw;
+ } else if (mEnforceSizeCompat) {
+ w = (int)(mRequestedWidth * mGlobalScale + .5f);
+ } else {
+ w = mRequestedWidth;
+ }
+ if (mAttrs.height == MATCH_PARENT) {
+ h = ph;
+ } else if (mEnforceSizeCompat) {
+ h = (int)(mRequestedHeight * mGlobalScale + .5f);
+ } else {
+ h = mRequestedHeight;
+ }
+ }
+
+ if (mEnforceSizeCompat) {
+ x = mAttrs.x * mGlobalScale;
+ y = mAttrs.y * mGlobalScale;
+ } else {
+ x = mAttrs.x;
+ y = mAttrs.y;
+ }
+
+ if (nonFullscreenTask) {
+ // Make sure window fits in containing frame since it is in a non-fullscreen stack as
+ // required by {@link Gravity#apply} call.
+ w = Math.min(w, pw);
+ h = Math.min(h, ph);
+ }
+
+ // Set mFrame
+ Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
+ (int) (x + mAttrs.horizontalMargin * pw),
+ (int) (y + mAttrs.verticalMargin * ph), mFrame);
+
+ // Now make sure the window fits in the overall display frame.
+ Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ }
}