summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt5
-rw-r--r--core/java/android/app/Notification.java10
-rw-r--r--core/java/android/app/slice/Slice.java19
-rw-r--r--core/java/android/privacy/internal/longitudinalreporting/LongitudinalReportingEncoder.java13
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java3
-rw-r--r--location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java4
-rw-r--r--packages/SystemUI/Android.mk3
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res/layout/car_facet_button.xml1
-rw-r--r--packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml62
-rw-r--r--packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml61
-rw-r--r--packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml62
-rw-r--r--packages/SystemUI/res/layout/car_status_bar_header.xml19
-rw-r--r--packages/SystemUI/res/layout/car_top_navigation_bar.xml38
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_footer.xml3
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_row.xml13
-rw-r--r--packages/SystemUI/res/values/attrs_car.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/OverviewProxyService.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java205
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java82
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java35
-rw-r--r--packages/SystemUI/tests/Android.mk2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java12
-rw-r--r--services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java17
-rw-r--r--services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java46
-rw-r--r--services/core/java/com/android/server/net/watchlist/PrivacyUtils.java4
-rw-r--r--services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java106
-rw-r--r--services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java29
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java17
-rw-r--r--services/core/java/com/android/server/wm/AlertWindowNotification.java5
-rw-r--r--telephony/java/android/telephony/MbmsDownloadSession.java4
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java16
-rw-r--r--telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java6
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java2
48 files changed, 962 insertions, 231 deletions
diff --git a/api/current.txt b/api/current.txt
index 8c6207fc5286..85f238c1113d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7206,8 +7206,9 @@ package android.app.slice {
field public static final java.lang.String HINT_ACTIONS = "actions";
field public static final java.lang.String HINT_ERROR = "error";
field public static final java.lang.String HINT_HORIZONTAL = "horizontal";
- field public static final java.lang.String HINT_KEY_WORDS = "key_words";
+ field public static final java.lang.String HINT_KEYWORDS = "keywords";
field public static final java.lang.String HINT_LARGE = "large";
+ field public static final java.lang.String HINT_LAST_UPDATED = "last_updated";
field public static final java.lang.String HINT_LIST = "list";
field public static final java.lang.String HINT_LIST_ITEM = "list_item";
field public static final java.lang.String HINT_NO_TINT = "no_tint";
@@ -7217,10 +7218,12 @@ package android.app.slice {
field public static final java.lang.String HINT_SHORTCUT = "shortcut";
field public static final java.lang.String HINT_SUMMARY = "summary";
field public static final java.lang.String HINT_TITLE = "title";
+ field public static final java.lang.String HINT_TTL = "ttl";
field public static final java.lang.String SUBTYPE_COLOR = "color";
field public static final java.lang.String SUBTYPE_CONTENT_DESCRIPTION = "content_description";
field public static final java.lang.String SUBTYPE_MAX = "max";
field public static final java.lang.String SUBTYPE_MESSAGE = "message";
+ field public static final java.lang.String SUBTYPE_MILLIS = "millis";
field public static final java.lang.String SUBTYPE_PRIORITY = "priority";
field public static final java.lang.String SUBTYPE_RANGE = "range";
field public static final deprecated java.lang.String SUBTYPE_SLIDER = "slider";
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d3c1e99f1523..4326ee3e75e3 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1219,11 +1219,11 @@ public class Notification implements Parcelable
public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
/**
- * This is set on the notification shown by the activity manager about all apps
- * running in the background. It indicates that the notification should be shown
- * only if any of the given apps do not already have a {@link #FLAG_FOREGROUND_SERVICE}
- * notification currently visible to the user. This is a string array of all
- * package names of the apps.
+ * This is set on the notifications shown by system_server about apps running foreground
+ * services. It indicates that the notification should be shown
+ * only if any of the given apps do not already have a properly tagged
+ * {@link #FLAG_FOREGROUND_SERVICE} notification currently visible to the user.
+ * This is a string array of all package names of the apps.
* @hide
*/
public static final String EXTRA_FOREGROUND_APPS = "android.foregroundApps";
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 61679cb4d631..95bb1f682701 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -66,8 +66,10 @@ public final class Slice implements Parcelable {
HINT_HORIZONTAL,
HINT_PARTIAL,
HINT_SEE_MORE,
- HINT_KEY_WORDS,
+ HINT_KEYWORDS,
HINT_ERROR,
+ HINT_TTL,
+ HINT_LAST_UPDATED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SliceHint {}
@@ -168,12 +170,20 @@ public final class Slice implements Parcelable {
* related to the parent slice.
* Expected to be on an item of format {@link SliceItem#FORMAT_SLICE}.
*/
- public static final String HINT_KEY_WORDS = "key_words";
+ public static final String HINT_KEYWORDS = "keywords";
/**
* A hint to indicate that this slice represents an error.
*/
public static final String HINT_ERROR = "error";
/**
+ * Hint indicating an item representing a time-to-live for the content.
+ */
+ public static final String HINT_TTL = "ttl";
+ /**
+ * Hint indicating an item representing when the content was created or last updated.
+ */
+ public static final String HINT_LAST_UPDATED = "last_updated";
+ /**
* Key to retrieve an extra added to an intent when a control is changed.
*/
public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
@@ -243,6 +253,11 @@ public final class Slice implements Parcelable {
* Expected to be on an item of format {@link SliceItem#FORMAT_TEXT}.
*/
public static final String SUBTYPE_CONTENT_DESCRIPTION = "content_description";
+ /**
+ * Subtype to tag an item as representing a time in milliseconds since midnight,
+ * January 1, 1970 UTC.
+ */
+ public static final String SUBTYPE_MILLIS = "millis";
private final SliceItem[] mItems;
private final @SliceHint String[] mHints;
diff --git a/core/java/android/privacy/internal/longitudinalreporting/LongitudinalReportingEncoder.java b/core/java/android/privacy/internal/longitudinalreporting/LongitudinalReportingEncoder.java
index 219868d663d2..dd97f1ef6a02 100644
--- a/core/java/android/privacy/internal/longitudinalreporting/LongitudinalReportingEncoder.java
+++ b/core/java/android/privacy/internal/longitudinalreporting/LongitudinalReportingEncoder.java
@@ -19,6 +19,7 @@ package android.privacy.internal.longitudinalreporting;
import android.privacy.DifferentialPrivacyEncoder;
import android.privacy.internal.rappor.RapporConfig;
import android.privacy.internal.rappor.RapporEncoder;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -48,6 +49,9 @@ import com.android.internal.annotations.VisibleForTesting;
*/
public class LongitudinalReportingEncoder implements DifferentialPrivacyEncoder {
+ private static final String TAG = "LongitudinalEncoder";
+ private static final boolean DEBUG = false;
+
// Suffix that will be added to Rappor's encoder id. There's a (relatively) small risk some
// other Rappor encoder may re-use the same encoder id.
private static final String PRR1_ENCODER_ID = "prr1_encoder_id";
@@ -121,11 +125,18 @@ public class LongitudinalReportingEncoder implements DifferentialPrivacyEncoder
@Override
public byte[] encodeBoolean(boolean original) {
+ if (DEBUG) {
+ Log.d(TAG, "encodeBoolean, encoderId:" + mConfig.getEncoderId() + ", original: "
+ + original);
+ }
if (mFakeValue != null) {
// Use the fake value generated in PRR.
original = mFakeValue.booleanValue();
+ if (DEBUG) Log.d(TAG, "Use fake value: " + original);
}
- return mIRREncoder.encodeBoolean(original);
+ byte[] result = mIRREncoder.encodeBoolean(original);
+ if (DEBUG) Log.d(TAG, "result: " + ((result[0] & 0x1) != 0));
+ return result;
}
@Override
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 51dd92961f54..957c784087af 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -1008,6 +1008,9 @@ public class LockPatternView extends View {
mDrawingProfilingStarted = false;
}
}
+ if (mFadePattern) {
+ clearPattern();
+ }
}
private void cancelLineAnimations() {
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 98e67c21c1a1..3643ca4a02f7 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -224,7 +224,9 @@ public class GnssMetrics {
s.append("GNSS_KPI_END").append("\n");
GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
if (stats != null) {
- s.append("Power Metrics").append('\n');
+ s.append("Power Metrics").append("\n");
+ s.append(" Time on battery (min): "
+ + stats.getLoggingDurationMs() / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
long[] t = stats.getTimeInGpsSignalQualityLevel();
if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) {
s.append(" Amount of time (while on battery) Top 4 Avg CN0 > " +
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 68293d964601..df2115147fb2 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -56,7 +56,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
SystemUI-tags \
SystemUI-proto
-LOCAL_JAVA_LIBRARIES := telephony-common
+LOCAL_JAVA_LIBRARIES := telephony-common \
+ android.car
LOCAL_PACKAGE_NAME := SystemUI
LOCAL_PRIVATE_PLATFORM_APIS := true
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3d49e5c37cf8..3488168b651b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -205,6 +205,9 @@
<!-- Listen app op changes -->
<uses-permission android:name="android.permission.WATCH_APPOPS" />
+ <!-- to read and change hvac values in a car -->
+ <uses-permission android:name="android.car.permission.ADJUST_CAR_CLIMATE" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
diff --git a/packages/SystemUI/res/layout/car_facet_button.xml b/packages/SystemUI/res/layout/car_facet_button.xml
index f432d366e926..ad8604935628 100644
--- a/packages/SystemUI/res/layout/car_facet_button.xml
+++ b/packages/SystemUI/res/layout/car_facet_button.xml
@@ -42,6 +42,7 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:animateLayoutChanges="true"
+ android:src="@drawable/car_ic_arrow"
android:background="@android:color/transparent"
android:scaleType="fitCenter">
</com.android.keyguard.AlphaOptimizedImageButton>
diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
new file mode 100644
index 000000000000..a65ff1693797
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:background="@drawable/system_bar_background">
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:id="@+id/nav_buttons"
+ android:orientation="vertical"
+ android:gravity="top"
+ android:paddingTop="30dp"
+ android:layout_weight="1"
+ android:background="@drawable/system_bar_background"
+ android:animateLayoutChanges="true">
+
+ <com.android.systemui.statusbar.car.CarNavigationButton
+ android:id="@+id/home"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ android:src="@drawable/car_ic_overview"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingTop="30dp"
+ android:paddingBottom="30dp"
+ />
+
+ <com.android.systemui.statusbar.car.CarNavigationButton
+ android:id="@+id/hvac"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+ systemui:broadcast="true"
+ android:src="@drawable/car_ic_hvac"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingTop="30dp"
+ android:paddingBottom="30dp"
+ />
+ </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
new file mode 100644
index 000000000000..b0488ae6382b
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="@drawable/system_bar_background">
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:orientation="horizontal"
+ android:id="@+id/nav_buttons"
+ android:gravity="left"
+ android:paddingLeft="30dp"
+ android:layout_weight="1"
+ android:animateLayoutChanges="true">
+
+ <com.android.systemui.statusbar.car.CarNavigationButton
+ android:id="@+id/home"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ android:src="@drawable/car_ic_overview"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingLeft="30dp"
+ android:paddingRight="30dp"
+ />
+
+ <com.android.systemui.statusbar.car.CarNavigationButton
+ android:id="@+id/hvac"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+ systemui:broadcast="true"
+ android:src="@drawable/car_ic_hvac"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingLeft="30dp"
+ android:paddingRight="30dp"
+ />
+ </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
+
diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
new file mode 100644
index 000000000000..a65ff1693797
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:orientation="vertical"
+ android:background="@drawable/system_bar_background">
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:id="@+id/nav_buttons"
+ android:orientation="vertical"
+ android:gravity="top"
+ android:paddingTop="30dp"
+ android:layout_weight="1"
+ android:background="@drawable/system_bar_background"
+ android:animateLayoutChanges="true">
+
+ <com.android.systemui.statusbar.car.CarNavigationButton
+ android:id="@+id/home"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+ android:src="@drawable/car_ic_overview"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingTop="30dp"
+ android:paddingBottom="30dp"
+ />
+
+ <com.android.systemui.statusbar.car.CarNavigationButton
+ android:id="@+id/hvac"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+ systemui:broadcast="true"
+ android:src="@drawable/car_ic_hvac"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingTop="30dp"
+ android:paddingBottom="30dp"
+ />
+ </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/SystemUI/res/layout/car_status_bar_header.xml b/packages/SystemUI/res/layout/car_status_bar_header.xml
index 158907e03541..f2ef30180bc0 100644
--- a/packages/SystemUI/res/layout/car_status_bar_header.xml
+++ b/packages/SystemUI/res/layout/car_status_bar_header.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<!-- Extends RelativeLayout -->
+<!-- Extends LinearLayout -->
<com.android.systemui.qs.car.CarStatusBarHeader
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
@@ -23,22 +23,21 @@
android:paddingStart="8dp"
android:paddingEnd="8dp" >
- <include
- layout="@layout/system_icons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true" />
+ <include layout="@layout/system_icons"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical|end"
+ android:layout_weight="1"
+ />
<com.android.systemui.statusbar.policy.Clock
android:id="@+id/clock"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
android:singleLine="true"
android:paddingStart="@dimen/status_bar_clock_starting_padding"
android:paddingEnd="@dimen/status_bar_clock_end_padding"
- systemui:showDark="false" />
+ android:gravity="center_vertical|end"
+ />
</com.android.systemui.qs.car.CarStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/car_top_navigation_bar.xml b/packages/SystemUI/res/layout/car_top_navigation_bar.xml
new file mode 100644
index 000000000000..e16014bb8945
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_top_navigation_bar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+** Copyright 2018, 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="@drawable/system_bar_background">
+
+ <com.android.systemui.statusbar.policy.Clock
+ android:id="@+id/clock"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:singleLine="true"
+ android:paddingStart="@dimen/status_bar_clock_starting_padding"
+ android:paddingEnd="@dimen/status_bar_clock_end_padding"
+ android:gravity="center_vertical"
+ />
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
+
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index aa0d4a05f6cc..22f1618f5474 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -44,7 +44,6 @@
android:focusable="true"
android:contentDescription="@string/accessibility_clear_all"
android:text="@string/clear_all_notifications_text"
- android:textColor="?attr/wallpaperTextColor"
- android:textAllCaps="true"/>
+ android:textColor="?attr/wallpaperTextColor"/>
</FrameLayout>
</com.android.systemui.statusbar.FooterView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 2e7ab7fe8904..f15ca9e972c2 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -55,19 +55,6 @@
android:paddingStart="8dp"
/>
- <!-- TODO: remove -->
- <ImageButton
- android:id="@+id/helper"
- android:layout_width="48dp"
- android:layout_height="@*android:dimen/notification_header_height"
- android:layout_gravity="top|end"
- android:layout_marginEnd="6dp"
- android:src="@drawable/ic_dnd"
- android:tint="#FF0000"
- android:background="@drawable/ripple_drawable"
- android:visibility="visible"
- />
-
<ViewStub
android:layout="@layout/notification_children_container"
android:id="@+id/child_container_stub"
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
index b1097c39363c..5e4bd79bcc04 100644
--- a/packages/SystemUI/res/values/attrs_car.xml
+++ b/packages/SystemUI/res/values/attrs_car.xml
@@ -27,6 +27,13 @@
<attr name="categories" format="string"/>
<!-- package names that will be added as extras to the fired intents -->
<attr name="packages" format="string" />
+ <!-- Alpha value to used when in selected state. Defaults 1f -->
+ <attr name="selectedAlpha" format="float" />
+ <!-- Alpha value to used when in un-selected state. Defaults 0.7f -->
+ <attr name="unselectedAlpha" format="float" />
+ <!-- Render a "more" icon. Defaults true -->
+ <attr name="useMoreIcon" format="boolean" />
+
</declare-styleable>
@@ -39,4 +46,11 @@
<!-- start the intent as a broad cast instead of an activity if true-->
<attr name="broadcast" format="boolean"/>
</declare-styleable>
+
+ <!-- Custom attributes to configure hvac values -->
+ <declare-styleable name="TemperatureView">
+ <attr name="hvacAreaId" format="integer"/>
+ <attr name="hvacPropertyId" format="integer"/>
+ <attr name="hvacTempFormat" format="string"/>
+ </declare-styleable>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 2983df6ec937..816c598daf4f 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -50,6 +50,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
/**
@@ -249,6 +250,10 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mConnectionCallbacks.remove(listener);
}
+ public boolean shouldShowSwipeUpUI() {
+ return getProxy() != null && ((mInteractionFlags & FLAG_DISABLE_SWIPE_UP) == 0);
+ }
+
public IOverviewProxy getProxy() {
return mOverviewProxy;
}
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index 245d240017e1..9459ce1ba827 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -21,6 +21,8 @@ import android.util.ArrayMap;
import com.android.systemui.Dependency.DependencyProvider;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.statusbar.NotificationEntryManager;
+import com.android.systemui.statusbar.car.CarFacetButtonController;
+import com.android.systemui.statusbar.car.hvac.HvacController;
/**
* Class factory to provide car specific SystemUI components.
@@ -32,5 +34,7 @@ public class CarSystemUIFactory extends SystemUIFactory {
super.injectDependencies(providers, context);
providers.put(NotificationEntryManager.class,
() -> new CarNotificationEntryManager(context));
+ providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context));
+ providers.put(HvacController.class, () -> new HvacController(context));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
index 6797bb9dbe82..ec183769c763 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
@@ -19,7 +19,7 @@ import android.graphics.Rect;
import android.support.annotation.IdRes;
import android.util.AttributeSet;
import android.view.View;
-import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
@@ -30,7 +30,7 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher;
* A view that forms the header of the notification panel. This view will ensure that any
* status icons that are displayed are tinted accordingly to the current theme.
*/
-public class CarStatusBarHeader extends RelativeLayout {
+public class CarStatusBarHeader extends LinearLayout {
public CarStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 05a5a8ea3484..03b263d2ae95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -183,7 +183,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private AboveShelfChangedListener mAboveShelfChangedListener;
private HeadsUpManager mHeadsUpManager;
private Consumer<Boolean> mHeadsUpAnimatingAwayListener;
- private View mHelperButton;
private boolean mChildIsExpanding;
private boolean mJustClicked;
@@ -401,8 +400,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
updateLimits();
updateIconVisibilities();
updateShelfIconColor();
-
- showBlockingHelperButton(mEntry.userSentiment == USER_SENTIMENT_NEGATIVE);
updateRippleAllowed();
}
@@ -1426,10 +1423,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
requestLayout();
}
- public void showBlockingHelperButton(boolean show) {
- mHelperButton.setVisibility(show ? View.VISIBLE : View.GONE);
- }
-
public void showAppOpsIcons(ArraySet<Integer> activeOps) {
if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() != null) {
mChildrenContainer.getHeaderView().showAppOpsIcons(activeOps);
@@ -1459,11 +1452,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
- mHelperButton = findViewById(R.id.helper);
- mHelperButton.setOnClickListener(view -> {
- doLongClickCallback();
- });
-
for (NotificationContentView l : mLayouts) {
l.setExpandClickListener(mExpandClickListener);
l.setContainingNotification(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 775faee7fbc3..402d9fddc825 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -641,9 +641,14 @@ public class NotificationData {
// this is a foreground-service disclosure for a user that does not need to show one
return true;
}
- if (mFsc.isSystemAlertNotification(sbn) && !mFsc.isSystemAlertWarningNeeded(
- sbn.getUserId(), sbn.getPackageName())) {
- return true;
+ if (mFsc.isSystemAlertNotification(sbn)) {
+ final String[] apps = sbn.getNotification().extras.getStringArray(
+ Notification.EXTRA_FOREGROUND_APPS);
+ if (apps != null && apps.length >= 1) {
+ if (!mFsc.isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
+ return true;
+ }
+ }
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index a2f336eb6398..82ad74e26f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -165,6 +165,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
mIsForeground =
(mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
mIsForBlockingHelper = isForBlockingHelper;
+ mAppUid = mSbn.getUid();
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -173,9 +174,9 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
} else {
// Special behavior for the Default channel if no other channels have been defined.
mIsSingleDefaultChannel = mNumNotificationChannels == 1
- && mSingleNotificationChannel.getId()
- .equals(NotificationChannel.DEFAULT_CHANNEL_ID)
- && numTotalChannels <= 1;
+ && mSingleNotificationChannel.getId().equals(
+ NotificationChannel.DEFAULT_CHANNEL_ID)
+ && numTotalChannels == 1;
}
try {
@@ -210,7 +211,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
if (info != null) {
- mAppUid = mSbn.getUid();
mAppName = String.valueOf(mPm.getApplicationLabel(info));
pkgicon = mPm.getApplicationIcon(info);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index b1e08b81b6e0..fd3a9d5e2bd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -350,9 +350,6 @@ public class NotificationViewHierarchyManager {
}
}
- row.showBlockingHelperButton(entry.userSentiment ==
- NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE);
-
row.showAppOpsIcons(entry.mActiveAppOps);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 53101a5bd61f..5f3e2e358306 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -3,6 +3,7 @@ package com.android.systemui.statusbar.car;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -10,6 +11,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
/**
@@ -21,9 +23,6 @@ import com.android.systemui.R;
* other music apps installed.
*/
public class CarFacetButton extends LinearLayout {
- private static final float SELECTED_ALPHA = 1f;
- private static final float UNSELECTED_ALPHA = 0.7f;
-
private static final String FACET_FILTER_DELIMITER = ";";
/**
* Extra information to be sent to a helper to make the decision of what app to launch when
@@ -42,6 +41,10 @@ public class CarFacetButton extends LinearLayout {
private String[] mFacetCategories;
/** App packages that are allowed to be used with this widget */
private String[] mFacetPackages;
+ private int mIconResourceId;
+ private boolean mUseMoreIcon = true;
+ private float mSelectedAlpha = 1f;
+ private float mUnselectedAlpha = 1f;
public CarFacetButton(Context context, AttributeSet attrs) {
@@ -53,6 +56,10 @@ public class CarFacetButton extends LinearLayout {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
setupIntents(typedArray);
setupIcons(typedArray);
+ CarFacetButtonController carFacetButtonController = Dependency.get(
+ CarFacetButtonController.class);
+ carFacetButtonController.addFacetButton(this);
+
}
/**
@@ -96,21 +103,25 @@ public class CarFacetButton extends LinearLayout {
private void setupIcons(TypedArray styledAttributes) {
+ mSelectedAlpha = styledAttributes.getFloat(
+ R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha);
+ mUnselectedAlpha = styledAttributes.getFloat(
+ R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha);
mIcon = findViewById(R.id.car_nav_button_icon);
mIcon.setScaleType(ImageView.ScaleType.CENTER);
mIcon.setClickable(false);
- mIcon.setAlpha(UNSELECTED_ALPHA);
- int iconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
- if (iconResourceId == 0) {
+ mIcon.setAlpha(mUnselectedAlpha);
+ mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
+ if (mIconResourceId == 0) {
throw new RuntimeException("specified icon resource was not found and is required");
}
- mIcon.setImageResource(iconResourceId);
+ mIcon.setImageResource(mIconResourceId);
mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
mMoreIcon.setClickable(false);
- mMoreIcon.setImageDrawable(getContext().getDrawable(R.drawable.car_ic_arrow));
- mMoreIcon.setAlpha(UNSELECTED_ALPHA);
+ mMoreIcon.setAlpha(mSelectedAlpha);
mMoreIcon.setVisibility(GONE);
+ mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true);
}
/**
@@ -145,17 +156,27 @@ public class CarFacetButton extends LinearLayout {
/**
* Updates the visual state to let the user know if it's been selected.
* @param selected true if should update the alpha of the icon to selected, false otherwise
- * @param showMoreIcon true if the "more icon" should be shown, false otherwise
+ * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this
+ * is ignored if the attribute useMoreIcon is set to false
*/
public void setSelected(boolean selected, boolean showMoreIcon) {
mSelected = selected;
if (selected) {
- mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
- mMoreIcon.setAlpha(SELECTED_ALPHA);
- mIcon.setAlpha(SELECTED_ALPHA);
+ if (mUseMoreIcon) {
+ mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
+ }
+ mIcon.setAlpha(mSelectedAlpha);
} else {
mMoreIcon.setVisibility(GONE);
- mIcon.setAlpha(UNSELECTED_ALPHA);
+ mIcon.setAlpha(mUnselectedAlpha);
+ }
+ }
+
+ public void setIcon(Drawable d) {
+ if (d != null) {
+ mIcon.setImageDrawable(d);
+ } else {
+ mIcon.setImageResource(mIconResourceId);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
index e8c9a5e5693a..284113624cc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -5,8 +5,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.view.View;
-import android.view.ViewGroup;
import java.util.HashMap;
import java.util.List;
@@ -29,39 +27,25 @@ public class CarFacetButtonController {
}
/**
- * Goes through the supplied CarNavigationBarView and keeps track of all the CarFacetButtons
- * such that it can select and unselect them based on running task chages
- * @param bar that may contain CarFacetButtons
+ * Add facet button to this controller. The expected use is for the facet button
+ * to get a reference to this controller via {@link com.android.systemui.Dependency}
+ * and self add.
+ * @param facetButton
*/
- public void addCarNavigationBar(CarNavigationBarView bar) {
- findFacets(bar);
- }
-
- private void findFacets(ViewGroup root) {
- final int childCount = root.getChildCount();
-
- for (int i = 0; i < childCount; ++i) {
- final View v = root.getChildAt(i);
- if (v instanceof CarFacetButton) {
- CarFacetButton facetButton = (CarFacetButton) v;
- String[] categories = facetButton.getCategories();
- for (int j = 0; j < categories.length; j++) {
- String category = categories[j];
- mButtonsByCategory.put(category, facetButton);
- }
+ public void addFacetButton(CarFacetButton facetButton) {
+ String[] categories = facetButton.getCategories();
+ for (int j = 0; j < categories.length; j++) {
+ String category = categories[j];
+ mButtonsByCategory.put(category, facetButton);
+ }
- String[] facetPackages = facetButton.getFacetPackages();
- for (int j = 0; j < facetPackages.length; j++) {
- String facetPackage = facetPackages[j];
- mButtonsByPackage.put(facetPackage, facetButton);
- }
- } else if (v instanceof ViewGroup) {
- findFacets((ViewGroup) v);
- }
+ String[] facetPackages = facetButton.getFacetPackages();
+ for (int j = 0; j < facetPackages.length; j++) {
+ String facetPackage = facetPackages[j];
+ mButtonsByPackage.put(facetPackage, facetButton);
}
}
-
/**
* This will unselect the currently selected CarFacetButton and determine which one should be
* selected next. It does this by reading the properties on the CarFacetButton and seeing if
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 1d9ef616d98d..e73b1736f33a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -22,6 +22,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
+import android.widget.TextView;
import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.R;
@@ -36,9 +37,11 @@ class CarNavigationBarView extends LinearLayout {
private LinearLayout mNavButtons;
private AlphaOptimizedImageButton mNotificationsButton;
private CarStatusBar mCarStatusBar;
+ private Context mContext;
public CarNavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mContext = context;
}
@Override
@@ -46,7 +49,9 @@ class CarNavigationBarView extends LinearLayout {
mNavButtons = findViewById(R.id.nav_buttons);
mNotificationsButton = findViewById(R.id.notifications);
- mNotificationsButton.setOnClickListener(this::onNotificationsClick);
+ if (mNotificationsButton != null) {
+ mNotificationsButton.setOnClickListener(this::onNotificationsClick);
+ }
}
void setStatusBar(CarStatusBar carStatusBar) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index c15a01330534..a95d0a4dc7b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -17,13 +17,9 @@
package com.android.systemui.statusbar.car;
import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.UserHandle;
+import android.os.SystemProperties;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
@@ -45,8 +41,8 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.car.hvac.HvacController;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -60,6 +56,8 @@ import java.util.Map;
public class CarStatusBar extends StatusBar implements
CarBatteryController.BatteryViewHandler {
private static final String TAG = "CarStatusBar";
+ public static final boolean ENABLE_HVAC_CONNECTION
+ = !SystemProperties.getBoolean("android.car.hvac.demo", true);
private TaskStackListenerImpl mTaskStackListener;
@@ -93,6 +91,11 @@ public class CarStatusBar extends StatusBar implements
createBatteryController();
mCarBatteryController.startListening();
+
+ if (ENABLE_HVAC_CONNECTION) {
+ Log.d(TAG, "Connecting to HVAC service");
+ Dependency.get(HvacController.class).connectToCarService();
+ }
}
@Override
@@ -164,7 +167,7 @@ public class CarStatusBar extends StatusBar implements
@Override
protected void createNavigationBar() {
- mCarFacetButtonController = new CarFacetButtonController(mContext);
+ mCarFacetButtonController = Dependency.get(CarFacetButtonController.class);
if (mNavigationBarView != null) {
return;
}
@@ -225,7 +228,6 @@ public class CarStatusBar extends StatusBar implements
lp.windowAnimations = 0;
- mCarFacetButtonController.addCarNavigationBar(mNavigationBarView);
mWindowManager.addView(mNavigationBarWindow, lp);
}
@@ -243,7 +245,6 @@ public class CarStatusBar extends StatusBar implements
throw new RuntimeException("Unable to build left nav bar due to missing layout");
}
mLeftNavigationBarView.setStatusBar(this);
- mCarFacetButtonController.addCarNavigationBar(mLeftNavigationBarView);
WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
widthForSides, LayoutParams.MATCH_PARENT,
@@ -275,7 +276,6 @@ public class CarStatusBar extends StatusBar implements
throw new RuntimeException("Unable to build right nav bar due to missing layout");
}
mRightNavigationBarView.setStatusBar(this);
- mCarFacetButtonController.addCarNavigationBar(mRightNavigationBarView);
WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
widthForSides, LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
new file mode 100644
index 000000000000..23bf88796da3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.hvac;
+
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.hvac.CarHvacManager;
+import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Manages the connection to the Car service and delegates value changes to the registered
+ * {@link TemperatureView}s
+ */
+public class HvacController {
+
+ public static final String TAG = "HvacController";
+ public final static int BIND_TO_HVAC_RETRY_DELAY = 5000;
+
+ private Context mContext;
+ private Handler mHandler;
+ private Car mCar;
+ private CarHvacManager mHvacManager;
+ private HashMap<HvacKey, TemperatureView> mTempComponents = new HashMap<>();
+
+ public HvacController(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Create connection to the Car service. Note: call backs from the Car service
+ * ({@link CarHvacManager}) will happen on the same thread this method was called from.
+ */
+ public void connectToCarService() {
+ mHandler = new Handler();
+ mCar = Car.createCar(mContext, mServiceConnection, mHandler);
+ if (mCar != null) {
+ // note: this connect call handles the retries
+ mCar.connect();
+ }
+ }
+
+ /**
+ * Registers callbacks and initializes components upon connection.
+ */
+ private ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ try {
+ service.linkToDeath(mRestart, 0);
+ mHvacManager = (CarHvacManager) mCar.getCarManager(Car.HVAC_SERVICE);
+ mHvacManager.registerCallback(mHardwareCallback);
+ initComponents();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to correctly connect to HVAC", e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ destroyHvacManager();
+ }
+ };
+
+ private void destroyHvacManager() {
+ if (mHvacManager != null) {
+ mHvacManager.unregisterCallback(mHardwareCallback);
+ mHvacManager = null;
+ }
+ }
+
+ /**
+ * If the connection to car service goes away then restart it.
+ */
+ private final IBinder.DeathRecipient mRestart = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ Log.d(TAG, "Death of HVAC triggering a restart");
+ if (mCar != null) {
+ mCar.disconnect();
+ }
+ destroyHvacManager();
+ mHandler.postDelayed(() -> mCar.connect(), BIND_TO_HVAC_RETRY_DELAY);
+ }
+ };
+
+ /**
+ * Add component to list and initialize it if the connection is up.
+ * @param temperatureView
+ */
+ public void addHvacTextView(TemperatureView temperatureView) {
+ mTempComponents.put(
+ new HvacKey(temperatureView.getPropertyId(), temperatureView.getAreaId()),
+ temperatureView);
+ initComponent(temperatureView);
+ }
+
+ private void initComponents() {
+ Iterator<Map.Entry<HvacKey, TemperatureView>> iterator =
+ mTempComponents.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry<HvacKey, TemperatureView> next = iterator.next();
+ initComponent(next.getValue());
+ }
+ }
+
+
+ private void initComponent(TemperatureView view) {
+ int id = view.getPropertyId();
+ int zone = view.getAreaId();
+ try {
+ if (mHvacManager == null || !mHvacManager.isPropertyAvailable(id, zone)) {
+ view.setTemp(Float.NaN);
+ return;
+ }
+ view.setTemp(mHvacManager.getFloatProperty(id, zone));
+ } catch (CarNotConnectedException e) {
+ view.setTemp(Float.NaN);
+ Log.e(TAG, "Failed to get value from hvac service", e);
+ }
+ }
+
+ /**
+ * Callback for getting changes from {@link CarHvacManager} and setting the UI elements to
+ * match.
+ */
+ private final CarHvacEventCallback mHardwareCallback = new CarHvacEventCallback() {
+ @Override
+ public void onChangeEvent(final CarPropertyValue val) {
+ try {
+ int areaId = val.getAreaId();
+ int propertyId = val.getPropertyId();
+ TemperatureView temperatureView = mTempComponents.get(
+ new HvacKey(propertyId, areaId));
+ if (temperatureView != null) {
+ float value = (float) val.getValue();
+ temperatureView.setTemp(value);
+ } // else the data is not of interest
+ } catch (Exception e) {
+ // catch all so we don't take down the sysui if a new data type is
+ // introduced.
+ Log.e(TAG, "Failed handling hvac change event", e);
+ }
+ }
+
+ @Override
+ public void onErrorEvent(final int propertyId, final int zone) {
+ Log.d(TAG, "HVAC error event, propertyId: " + propertyId +
+ " zone: " + zone);
+ }
+ };
+
+ /**
+ * Key for storing {@link TemperatureView}s in a hash map
+ */
+ private static class HvacKey {
+
+ int mPropertyId;
+ int mAreaId;
+
+ public HvacKey(int propertyId, int areaId) {
+ mPropertyId = propertyId;
+ mAreaId = areaId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ HvacKey hvacKey = (HvacKey) o;
+ return mPropertyId == hvacKey.mPropertyId &&
+ mAreaId == hvacKey.mAreaId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPropertyId, mAreaId);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java
new file mode 100644
index 000000000000..4049ec3aa385
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.hvac;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+
+/**
+ * Simple text display of HVAC properties, It is designed to show temperature and is configured in
+ * the XML.
+ * XML properties:
+ * hvacPropertyId - Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385)
+ * hvacAreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1)
+ * hvacTempFormat - Example: "%.1f\u00B0" (1 decimal and the degree symbol)
+ *
+ * Note: It registers itself with {@link HvacController}
+ */
+public class TemperatureView extends TextView {
+
+ private final int mAreaId;
+ private final int mPropertyId;
+ private final String mTempFormat;
+
+ public TemperatureView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TemperatureView);
+ mAreaId = typedArray.getInt(R.styleable.TemperatureView_hvacAreaId,-1);
+ mPropertyId = typedArray.getInt(R.styleable.TemperatureView_hvacPropertyId, -1);
+ String format = typedArray.getString(R.styleable.TemperatureView_hvacTempFormat);
+ mTempFormat = (format == null) ? "%.1f\u00B0" : format;
+
+ // register with controller
+ HvacController hvacController = Dependency.get(HvacController.class);
+ hvacController.addHvacTextView(this);
+ }
+
+ /**
+ * Formats the float for display
+ * @param temp - The current temp or NaN
+ */
+ public void setTemp(float temp) {
+ if (Float.isNaN(temp)) {
+ setText("--");
+ return;
+ }
+ setText(String.format(mTempFormat, temp));
+ }
+
+ /**
+ * @return propertiyId Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385)
+ */
+ public int getPropertyId() {
+ return mPropertyId;
+ }
+
+ /**
+ * @return hvac AreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1)
+ */
+ public int getAreaId() {
+ return mAreaId;
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index b4cb088621fd..84582b0278f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -79,7 +79,6 @@ import java.io.PrintWriter;
import java.util.function.Consumer;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
@@ -385,17 +384,13 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
}
public boolean isQuickStepSwipeUpEnabled() {
- return mOverviewProxyService.getProxy() != null
- && isOverviewEnabled()
- && ((mOverviewProxyService.getInteractionFlags()
- & FLAG_DISABLE_SWIPE_UP) == 0);
+ return mOverviewProxyService.shouldShowSwipeUpUI() && isOverviewEnabled();
}
public boolean isQuickScrubEnabled() {
return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true)
&& mOverviewProxyService.getProxy() != null && isOverviewEnabled()
- && ((mOverviewProxyService.getInteractionFlags()
- & FLAG_DISABLE_QUICK_SCRUB) == 0);
+ && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
}
private void updateCarModeIcons(Context ctx) {
@@ -468,7 +463,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
private KeyButtonDrawable chooseNavigationIconDrawable(Context ctx, @DrawableRes int iconLight,
@DrawableRes int iconDark, @DrawableRes int quickStepIconLight,
@DrawableRes int quickStepIconDark) {
- final boolean quickStepEnabled = isQuickStepSwipeUpEnabled() || isQuickScrubEnabled();
+ final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
return quickStepEnabled
? getDrawable(ctx, quickStepIconLight, quickStepIconDark)
: getDrawable(ctx, iconLight, iconDark);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index c326feeb3d52..33c3ee9b7cba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -363,16 +363,16 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
zenDescription = mContext.getString(R.string.interruption_level_priority);
}
- if (DndTile.isVisible(mContext) && !DndTile.isCombinedIcon(mContext)
- && audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
- volumeVisible = true;
- volumeIconId = R.drawable.stat_sys_ringer_silent;
- volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
- } else if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
+ if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
volumeVisible = true;
volumeIconId = R.drawable.stat_sys_ringer_vibrate;
volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
+ } else if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
+ audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
+ volumeVisible = true;
+ volumeIconId = R.drawable.stat_sys_ringer_silent;
+ volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
}
if (zenVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index cc7943b85bc1..8e32a0b44c28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -26,9 +26,12 @@ import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.SystemProperties;
import android.view.DisplayListCanvas;
import android.view.RenderNodeAnimator;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.animation.Interpolator;
import com.android.systemui.Interpolators;
@@ -56,14 +59,17 @@ public class KeyButtonRipple extends Drawable {
private float mGlowAlpha = 0f;
private float mGlowScale = 1f;
private boolean mPressed;
+ private boolean mVisible;
private boolean mDrawingHardwareGlow;
private int mMaxWidth;
private boolean mLastDark;
private boolean mDark;
+ private boolean mDelayTouchFeedback;
private final Interpolator mInterpolator = new LogInterpolator();
private boolean mSupportHardware;
private final View mTargetView;
+ private final Handler mHandler = new Handler();
private final HashSet<Animator> mRunningAnimations = new HashSet<>();
private final ArrayList<Animator> mTmpArray = new ArrayList<>();
@@ -77,6 +83,10 @@ public class KeyButtonRipple extends Drawable {
mDark = darkIntensity >= 0.5f;
}
+ public void setDelayTouchFeedback(boolean delay) {
+ mDelayTouchFeedback = delay;
+ }
+
private Paint getRipplePaint() {
if (mRipplePaint == null) {
mRipplePaint = new Paint();
@@ -211,7 +221,16 @@ public class KeyButtonRipple extends Drawable {
}
}
+ /**
+ * Abort the ripple while it is delayed and before shown used only when setShouldDelayStartTouch
+ * is enabled.
+ */
+ public void abortDelayedRipple() {
+ mHandler.removeCallbacksAndMessages(null);
+ }
+
private void cancelAnimations() {
+ mVisible = false;
mTmpArray.addAll(mRunningAnimations);
int size = mTmpArray.size();
for (int i = 0; i < size; i++) {
@@ -220,11 +239,21 @@ public class KeyButtonRipple extends Drawable {
}
mTmpArray.clear();
mRunningAnimations.clear();
+ mHandler.removeCallbacksAndMessages(null);
}
private void setPressedSoftware(boolean pressed) {
if (pressed) {
- enterSoftware();
+ if (mDelayTouchFeedback) {
+ if (mRunningAnimations.isEmpty()) {
+ mHandler.removeCallbacksAndMessages(null);
+ mHandler.postDelayed(this::enterSoftware, ViewConfiguration.getTapTimeout());
+ } else if (mVisible) {
+ enterSoftware();
+ }
+ } else {
+ enterSoftware();
+ }
} else {
exitSoftware();
}
@@ -232,6 +261,7 @@ public class KeyButtonRipple extends Drawable {
private void enterSoftware() {
cancelAnimations();
+ mVisible = true;
mGlowAlpha = getMaxGlowAlpha();
ObjectAnimator scaleAnimator = ObjectAnimator.ofFloat(this, "glowScale",
0f, GLOW_MAX_SCALE_FACTOR);
@@ -240,6 +270,12 @@ public class KeyButtonRipple extends Drawable {
scaleAnimator.addListener(mAnimatorListener);
scaleAnimator.start();
mRunningAnimations.add(scaleAnimator);
+
+ // With the delay, it could eventually animate the enter animation with no pressed state,
+ // then immediately show the exit animation. If this is skipped there will be no ripple.
+ if (mDelayTouchFeedback && !mPressed) {
+ exitSoftware();
+ }
}
private void exitSoftware() {
@@ -253,7 +289,16 @@ public class KeyButtonRipple extends Drawable {
private void setPressedHardware(boolean pressed) {
if (pressed) {
- enterHardware();
+ if (mDelayTouchFeedback) {
+ if (mRunningAnimations.isEmpty()) {
+ mHandler.removeCallbacksAndMessages(null);
+ mHandler.postDelayed(this::enterHardware, ViewConfiguration.getTapTimeout());
+ } else if (mVisible) {
+ enterHardware();
+ }
+ } else {
+ enterHardware();
+ }
} else {
exitHardware();
}
@@ -302,6 +347,7 @@ public class KeyButtonRipple extends Drawable {
private void enterHardware() {
cancelAnimations();
+ mVisible = true;
mDrawingHardwareGlow = true;
setExtendStart(CanvasProperty.createFloat(getExtendSize() / 2));
final RenderNodeAnimator startAnim = new RenderNodeAnimator(getExtendStart(),
@@ -343,6 +389,12 @@ public class KeyButtonRipple extends Drawable {
mRunningAnimations.add(endAnim);
invalidateSelf();
+
+ // With the delay, it could eventually animate the enter animation with no pressed state,
+ // then immediately show the exit animation. If this is skipped there will be no ripple.
+ if (mDelayTouchFeedback && !mPressed) {
+ exitHardware();
+ }
}
private void exitHardware() {
@@ -366,6 +418,7 @@ public class KeyButtonRipple extends Drawable {
public void onAnimationEnd(Animator animation) {
mRunningAnimations.remove(animation);
if (mRunningAnimations.isEmpty() && !mPressed) {
+ mVisible = false;
mDrawingHardwareGlow = false;
invalidateSelf();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index e5fefd34ffb7..5d7e9383930a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -65,7 +65,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
private int mTouchSlop;
private int mTouchDownX;
private int mTouchDownY;
- private boolean mIsPressed;
private boolean mSupportsLongpress = true;
private AudioManager mAudioManager;
private boolean mGestureAborted;
@@ -78,7 +77,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
- if (mIsPressed) {
+ if (isPressed()) {
// Log.d("KeyButtonView", "longpressed: " + this);
if (isLongClickable()) {
// Just an old-fashioned ImageView
@@ -89,12 +88,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
mLongClicked = true;
}
-
- // Only when quick step is enabled, ripple will not be shown on touch down, then
- // show the ripple on touch up or on long press
- if (mLongClicked && mOverviewProxyService.getProxy() != null) {
- setPressed(true);
- }
}
}
};
@@ -214,9 +207,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
mGestureAborted = false;
}
if (mGestureAborted) {
- if (mIsPressed) {
- setPressed(false);
- }
+ setPressed(false);
return false;
}
@@ -224,6 +215,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
case MotionEvent.ACTION_DOWN:
mDownTime = SystemClock.uptimeMillis();
mLongClicked = false;
+ setPressed(true);
// Use raw X and Y to detect gestures in case a parent changes the x and y values
mTouchDownX = (int) ev.getRawX();
@@ -234,10 +226,8 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
// Provide the same haptic feedback that the system offers for virtual keys.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
- mIsPressed = true;
if (!isProxyConnected) {
playSoundEffect(SoundEffectConstants.CLICK);
- setPressed(mIsPressed);
}
removeCallbacks(mCheckLongPress);
postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
@@ -250,10 +240,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
if (exceededTouchSlopX || exceededTouchSlopY) {
// When quick step is enabled, prevent animating the ripple triggered by
// setPressed and decide to run it on touch up
- mIsPressed = false;
- if (!isProxyConnected) {
- setPressed(mIsPressed);
- }
+ setPressed(false);
removeCallbacks(mCheckLongPress);
}
break;
@@ -265,12 +252,11 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
removeCallbacks(mCheckLongPress);
break;
case MotionEvent.ACTION_UP:
- final boolean doIt = mIsPressed && !mLongClicked;
+ final boolean doIt = isPressed() && !mLongClicked;
+ setPressed(false);
final boolean doHapticFeedback = (SystemClock.uptimeMillis() - mDownTime) > 150;
if (isProxyConnected) {
if (doIt) {
- // Animate the ripple in on touch up with setPressed and then out later
- setPressed(true);
if (doHapticFeedback) {
mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
}
@@ -281,7 +267,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
// and it feels weird to sometimes get a release haptic and other times not.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);
}
- setPressed(false);
if (mCode != 0) {
if (doIt) {
// If there was a pending remote recents animation, then we need to
@@ -311,12 +296,6 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
}
- @Override
- public void setPressed(boolean pressed) {
- mIsPressed = pressed;
- super.setPressed(pressed);
- }
-
public void sendEvent(int action, int flags) {
sendEvent(action, flags, SystemClock.uptimeMillis());
}
@@ -339,6 +318,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
@Override
public void abortCurrentGesture() {
setPressed(false);
+ mRipple.abortDelayedRipple();
mGestureAborted = true;
}
@@ -357,6 +337,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
@Override
public void setDelayTouchFeedback(boolean shouldDelay) {
+ mRipple.setDelayTouchFeedback(shouldDelay);
}
@Override
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 107ce1eecf2f..a6b09ced2d81 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -75,7 +75,7 @@ LOCAL_JAVA_LIBRARIES := \
android.test.runner \
telephony-common \
android.test.base \
-
+ android.car
LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
index 2000bff7e99a..c43702119e91 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
@@ -226,12 +226,21 @@ public class NotificationDataTest extends SysuiTestCase {
public void testSuppressSystemAlertNotification() {
when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
+ StatusBarNotification sbn = mRow.getEntry().notification;
+ Bundle bundle = new Bundle();
+ bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {"something"});
+ sbn.getNotification().extras = bundle;
assertTrue(mNotificationData.shouldFilterOut(mRow.getEntry().notification));
}
@Test
public void testDoNotSuppressSystemAlertNotification() {
+ StatusBarNotification sbn = mRow.getEntry().notification;
+ Bundle bundle = new Bundle();
+ bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {"something"});
+ sbn.getNotification().extras = bundle;
+
when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
@@ -249,6 +258,22 @@ public class NotificationDataTest extends SysuiTestCase {
}
@Test
+ public void testDoNotSuppressMalformedSystemAlertNotification() {
+ when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
+
+ // missing extra
+ assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry().notification));
+
+ StatusBarNotification sbn = mRow.getEntry().notification;
+ Bundle bundle = new Bundle();
+ bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {});
+ sbn.getNotification().extras = bundle;
+
+ // extra missing values
+ assertFalse(mNotificationData.shouldFilterOut(mRow.getEntry().notification));
+ }
+
+ @Test
public void testShouldFilterHiddenNotifications() {
// setup
when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 7dda8b268b3e..c2cb5b9940eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -218,6 +218,18 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@Test
+ public void testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist()
+ throws Exception {
+ // Package has one channel by default.
+ when(mMockINotificationManager.getNumNotificationChannelsForPackage(
+ eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, null);
+ final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
+ assertEquals(VISIBLE, textView.getVisibility());
+ }
+
+ @Test
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null,
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
index 6907c58f13b0..29b1339e8022 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
@@ -171,7 +171,7 @@ public class NetworkWatchlistService extends INetworkWatchlistManager.Stub {
Slog.w(TAG, "Only shell is allowed to call network watchlist shell commands");
return;
}
- (new NetworkWatchlistShellCommand(mContext)).exec(this, in, out, err, args, callback,
+ (new NetworkWatchlistShellCommand(this, mContext)).exec(this, in, out, err, args, callback,
resultReceiver);
}
@@ -262,6 +262,21 @@ public class NetworkWatchlistService extends INetworkWatchlistManager.Stub {
mNetworkWatchlistHandler.reportWatchlistIfNecessary();
}
+ /**
+ * Force generate watchlist report for testing.
+ *
+ * @param lastReportTime Watchlist report will cotain all records before this time.
+ * @return True if operation success.
+ */
+ public boolean forceReportWatchlistForTest(long lastReportTime) {
+ if (mConfig.isConfigSecure()) {
+ // Should not force generate report under production config.
+ return false;
+ }
+ mNetworkWatchlistHandler.forceReportWatchlistForTest(lastReportTime);
+ return true;
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
index 9533823df808..17c5868a53f7 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
@@ -19,9 +19,11 @@ package com.android.server.net.watchlist;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkWatchlistManager;
+import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ShellCommand;
+import android.provider.Settings;
import java.io.FileInputStream;
import java.io.IOException;
@@ -34,10 +36,12 @@ import java.io.PrintWriter;
*/
class NetworkWatchlistShellCommand extends ShellCommand {
- final NetworkWatchlistManager mNetworkWatchlistManager;
+ final Context mContext;
+ final NetworkWatchlistService mService;
- NetworkWatchlistShellCommand(Context context) {
- mNetworkWatchlistManager = new NetworkWatchlistManager(context);
+ NetworkWatchlistShellCommand(NetworkWatchlistService service, Context context) {
+ mContext = context;
+ mService = service;
}
@Override
@@ -51,11 +55,13 @@ class NetworkWatchlistShellCommand extends ShellCommand {
switch(cmd) {
case "set-test-config":
return runSetTestConfig();
+ case "force-generate-report":
+ return runForceGenerateReport();
default:
return handleDefaultCommands(cmd);
}
- } catch (RemoteException e) {
- pw.println("Remote exception: " + e);
+ } catch (Exception e) {
+ pw.println("Exception: " + e);
}
return -1;
}
@@ -73,22 +79,44 @@ class NetworkWatchlistShellCommand extends ShellCommand {
WatchlistConfig.getInstance().setTestMode(fileStream);
}
pw.println("Success!");
- } catch (RuntimeException | IOException ex) {
+ } catch (Exception ex) {
pw.println("Error: " + ex.toString());
return -1;
}
return 0;
}
+ private int runForceGenerateReport() throws RemoteException {
+ final PrintWriter pw = getOutPrintWriter();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ // Reset last report time
+ if (!WatchlistConfig.getInstance().isConfigSecure()) {
+ pw.println("Error: Cannot force generate report under production config");
+ return -1;
+ }
+ Settings.Global.putLong(mContext.getContentResolver(),
+ Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME, 0L);
+ mService.forceReportWatchlistForTest(System.currentTimeMillis());
+ pw.println("Success!");
+ } catch (Exception ex) {
+ pw.println("Error: " + ex);
+ return -1;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return 0;
+ }
+
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
pw.println("Network watchlist manager commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println("");
pw.println(" set-test-config your_watchlist_config.xml");
- pw.println();
- Intent.printIntentArgsHelp(pw , "");
+ pw.println(" Set network watchlist test config file.");
+ pw.println(" force-generate-report");
+ pw.println(" Force generate watchlist test report.");
}
}
diff --git a/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java b/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java
index c1231fa342e7..408a9ed31d18 100644
--- a/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java
+++ b/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java
@@ -19,6 +19,7 @@ package com.android.server.net.watchlist;
import android.privacy.DifferentialPrivacyEncoder;
import android.privacy.internal.longitudinalreporting.LongitudinalReportingConfig;
import android.privacy.internal.longitudinalreporting.LongitudinalReportingEncoder;
+import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -32,6 +33,7 @@ import java.util.Map;
class PrivacyUtils {
private static final String TAG = "PrivacyUtils";
+ private static final boolean DEBUG = NetworkWatchlistService.DEBUG;
/**
* Parameters used for encoding watchlist reports.
@@ -84,6 +86,7 @@ class PrivacyUtils {
@VisibleForTesting
static Map<String, Boolean> createDpEncodedReportMap(boolean isSecure, byte[] userSecret,
List<String> appDigestList, WatchlistReportDbHelper.AggregatedResult aggregatedResult) {
+ if (DEBUG) Slog.i(TAG, "createDpEncodedReportMap start");
final int appDigestListSize = appDigestList.size();
final HashMap<String, Boolean> resultMap = new HashMap<>(appDigestListSize);
for (int i = 0; i < appDigestListSize; i++) {
@@ -93,6 +96,7 @@ class PrivacyUtils {
? createSecureDPEncoder(userSecret, appDigest)
: createInsecureDPEncoderForTest(appDigest);
final boolean visitedWatchlist = aggregatedResult.appDigestList.contains(appDigest);
+ if (DEBUG) Slog.i(TAG, appDigest + ": " + visitedWatchlist);
// Get the least significant bit of first byte, and set result to True if it is 1
boolean encodedVisitedWatchlist = ((int) encoder.encodeBoolean(visitedWatchlist)[0]
& 0x1) == 0x1;
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index e8b39c04a830..b331b9c0d9ae 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -43,6 +43,7 @@ import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -61,6 +62,8 @@ class WatchlistLoggingHandler extends Handler {
static final int LOG_WATCHLIST_EVENT_MSG = 1;
@VisibleForTesting
static final int REPORT_RECORDS_IF_NECESSARY_MSG = 2;
+ @VisibleForTesting
+ static final int FORCE_REPORT_RECORDS_NOW_FOR_TEST_MSG = 3;
private static final long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);
private static final String DROPBOX_TAG = "network_watchlist_report";
@@ -110,7 +113,15 @@ class WatchlistLoggingHandler extends Handler {
break;
}
case REPORT_RECORDS_IF_NECESSARY_MSG:
- tryAggregateRecords();
+ tryAggregateRecords(getLastMidnightTime());
+ break;
+ case FORCE_REPORT_RECORDS_NOW_FOR_TEST_MSG:
+ if (msg.obj instanceof Long) {
+ long lastRecordTime = (Long) msg.obj;
+ tryAggregateRecords(lastRecordTime);
+ } else {
+ Slog.e(TAG, "Msg.obj needs to be a Long object.");
+ }
break;
default: {
Slog.d(TAG, "WatchlistLoggingHandler received an unknown of message.");
@@ -146,6 +157,12 @@ class WatchlistLoggingHandler extends Handler {
sendMessage(msg);
}
+ public void forceReportWatchlistForTest(long lastReportTime) {
+ final Message msg = obtainMessage(FORCE_REPORT_RECORDS_NOW_FOR_TEST_MSG);
+ msg.obj = lastReportTime;
+ sendMessage(msg);
+ }
+
/**
* Insert network traffic event to watchlist async queue processor.
*/
@@ -177,8 +194,14 @@ class WatchlistLoggingHandler extends Handler {
}
private boolean insertRecord(int uid, String cncHost, long timestamp) {
+ if (DEBUG) {
+ Slog.i(TAG, "trying to insert record with host: " + cncHost + ", uid: " + uid);
+ }
if (!mConfig.isConfigSecure() && !isPackageTestOnly(uid)) {
// Skip package if config is not secure and package is not TestOnly app.
+ if (DEBUG) {
+ Slog.i(TAG, "uid: " + uid + " is not test only package");
+ }
return true;
}
final byte[] digest = getDigestFromUid(uid);
@@ -187,50 +210,56 @@ class WatchlistLoggingHandler extends Handler {
return false;
}
final boolean result = mDbHelper.insertNewRecord(digest, cncHost, timestamp);
- tryAggregateRecords();
return result;
}
- private boolean shouldReportNetworkWatchlist() {
+ private boolean shouldReportNetworkWatchlist(long lastRecordTime) {
final long lastReportTime = Settings.Global.getLong(mResolver,
Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME, 0L);
- final long currentTimestamp = System.currentTimeMillis();
- if (currentTimestamp < lastReportTime) {
+ if (lastRecordTime < lastReportTime) {
Slog.i(TAG, "Last report time is larger than current time, reset report");
- mDbHelper.cleanup();
+ mDbHelper.cleanup(lastReportTime);
return false;
}
- return currentTimestamp >= lastReportTime + ONE_DAY_MS;
+ return lastRecordTime >= lastReportTime + ONE_DAY_MS;
}
- private void tryAggregateRecords() {
- // Check if it's necessary to generate watchlist report now.
- if (!shouldReportNetworkWatchlist()) {
- Slog.i(TAG, "No need to aggregate record yet.");
- return;
- }
- Slog.i(TAG, "Start aggregating watchlist records.");
- if (mDropBoxManager != null && mDropBoxManager.isTagEnabled(DROPBOX_TAG)) {
- Settings.Global.putLong(mResolver,
- Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
- System.currentTimeMillis());
- final WatchlistReportDbHelper.AggregatedResult aggregatedResult =
- mDbHelper.getAggregatedRecords();
- if (aggregatedResult == null) {
- Slog.i(TAG, "Cannot get result from database");
+ private void tryAggregateRecords(long lastRecordTime) {
+ long startTime = System.currentTimeMillis();
+ try {
+ // Check if it's necessary to generate watchlist report now.
+ if (!shouldReportNetworkWatchlist(lastRecordTime)) {
+ Slog.i(TAG, "No need to aggregate record yet.");
return;
}
- // Get all digests for watchlist report, it should include all installed
- // application digests and previously recorded app digests.
- final List<String> digestsForReport = getAllDigestsForReport(aggregatedResult);
- final byte[] secretKey = mSettings.getPrivacySecretKey();
- final byte[] encodedResult = ReportEncoder.encodeWatchlistReport(mConfig,
- secretKey, digestsForReport, aggregatedResult);
- if (encodedResult != null) {
- addEncodedReportToDropBox(encodedResult);
+ Slog.i(TAG, "Start aggregating watchlist records.");
+ if (mDropBoxManager != null && mDropBoxManager.isTagEnabled(DROPBOX_TAG)) {
+ Settings.Global.putLong(mResolver,
+ Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
+ lastRecordTime);
+ final WatchlistReportDbHelper.AggregatedResult aggregatedResult =
+ mDbHelper.getAggregatedRecords(lastRecordTime);
+ if (aggregatedResult == null) {
+ Slog.i(TAG, "Cannot get result from database");
+ return;
+ }
+ // Get all digests for watchlist report, it should include all installed
+ // application digests and previously recorded app digests.
+ final List<String> digestsForReport = getAllDigestsForReport(aggregatedResult);
+ final byte[] secretKey = mSettings.getPrivacySecretKey();
+ final byte[] encodedResult = ReportEncoder.encodeWatchlistReport(mConfig,
+ secretKey, digestsForReport, aggregatedResult);
+ if (encodedResult != null) {
+ addEncodedReportToDropBox(encodedResult);
+ }
+ } else {
+ Slog.w(TAG, "Network Watchlist dropbox tag is not enabled");
}
+ mDbHelper.cleanup(lastRecordTime);
+ } finally {
+ long endTime = System.currentTimeMillis();
+ Slog.i(TAG, "Milliseconds spent on tryAggregateRecords(): " + (endTime - startTime));
}
- mDbHelper.cleanup();
}
/**
@@ -379,4 +408,19 @@ class WatchlistLoggingHandler extends Handler {
}
return subDomainList.toArray(new String[0]);
}
+
+ static long getLastMidnightTime() {
+ return getMidnightTimestamp(0);
+ }
+
+ static long getMidnightTimestamp(int daysBefore) {
+ java.util.Calendar date = new GregorianCalendar();
+ // reset hour, minutes, seconds and millis
+ date.set(java.util.Calendar.HOUR_OF_DAY, 0);
+ date.set(java.util.Calendar.MINUTE, 0);
+ date.set(java.util.Calendar.SECOND, 0);
+ date.set(java.util.Calendar.MILLISECOND, 0);
+ date.add(java.util.Calendar.DAY_OF_MONTH, -daysBefore);
+ return date.getTimeInMillis();
+ }
}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
index 4b577bb9c919..632ab81b131e 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
@@ -141,11 +141,10 @@ class WatchlistReportDbHelper extends SQLiteOpenHelper {
}
/**
- * Aggregate all records before most recent local midnight in database, and return a
+ * Aggregate all records in database before input timestamp, and return a
* rappor encoded result.
*/
- public AggregatedResult getAggregatedRecords() {
- final long lastMidnightTime = getLastMidnightTime();
+ public AggregatedResult getAggregatedRecords(long untilTimestamp) {
final String selectStatement = WhiteListReportContract.TIMESTAMP + " < ?";
final SQLiteDatabase db = getReadableDatabase();
@@ -153,7 +152,7 @@ class WatchlistReportDbHelper extends SQLiteOpenHelper {
try {
c = db.query(true /* distinct */,
WhiteListReportContract.TABLE, DIGEST_DOMAIN_PROJECTION, selectStatement,
- new String[]{"" + lastMidnightTime}, null, null,
+ new String[]{Long.toString(untilTimestamp)}, null, null,
null, null);
if (c == null) {
return null;
@@ -181,29 +180,13 @@ class WatchlistReportDbHelper extends SQLiteOpenHelper {
}
/**
- * Remove all the records before most recent local midnight.
+ * Remove all the records before input timestamp.
*
* @return True if success.
*/
- public boolean cleanup() {
+ public boolean cleanup(long untilTimestamp) {
final SQLiteDatabase db = getWritableDatabase();
- final long midnightTime = getLastMidnightTime();
- final String clause = WhiteListReportContract.TIMESTAMP + "< " + midnightTime;
+ final String clause = WhiteListReportContract.TIMESTAMP + "< " + untilTimestamp;
return db.delete(WhiteListReportContract.TABLE, clause, null) != 0;
}
-
- static long getLastMidnightTime() {
- return getMidnightTimestamp(0);
- }
-
- static long getMidnightTimestamp(int daysBefore) {
- java.util.Calendar date = new GregorianCalendar();
- // reset hour, minutes, seconds and millis
- date.set(java.util.Calendar.HOUR_OF_DAY, 0);
- date.set(java.util.Calendar.MINUTE, 0);
- date.set(java.util.Calendar.SECOND, 0);
- date.set(java.util.Calendar.MILLISECOND, 0);
- date.add(java.util.Calendar.DAY_OF_MONTH, -daysBefore);
- return date.getTimeInMillis();
- }
} \ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 775fdaa8d7ca..e08ec556c68f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -808,7 +808,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
final String[] getStaticOverlayPaths(List<PackageParser.Package> overlayPackages,
- String targetPath) {
+ String targetPath, Object installLock) {
if (overlayPackages == null || overlayPackages.isEmpty()) {
return null;
}
@@ -828,7 +828,16 @@ public class PackageManagerService extends IPackageManager.Stub
//
// OverlayManagerService will update each of them with a correct gid from its
// target package app id.
- synchronized (mInstallLock) {
+ if (installLock != null) {
+ synchronized (installLock) {
+ mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
+ UserHandle.getSharedAppGid(
+ UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
+ }
+ } else {
+ // We can call mInstaller without holding mInstallLock because mInstallLock
+ // is held before running parallel parsing.
+ // Moreover holding mInstallLock on each parsing thread causes dead-lock.
mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
UserHandle.getSharedAppGid(
UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
@@ -853,7 +862,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
// It is safe to keep overlayPackages without holding mPackages because static overlay
// packages can't be uninstalled or disabled.
- return getStaticOverlayPaths(overlayPackages, targetPath);
+ return getStaticOverlayPaths(overlayPackages, targetPath, mInstallLock);
}
@Override public final String[] getOverlayApks(String targetPackageName) {
@@ -890,7 +899,7 @@ public class PackageManagerService extends IPackageManager.Stub
return mOverlayPackages == null ? null :
getStaticOverlayPaths(
getStaticOverlayPackages(mOverlayPackages, targetPackageName),
- targetPath);
+ targetPath, null);
}
}
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 9b787deb8298..9177d253e464 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -37,6 +37,8 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
+
import com.android.internal.R;
import com.android.server.policy.IconUtilities;
@@ -109,6 +111,8 @@ class AlertWindowNotification {
final String message = context.getString(R.string.alert_windows_notification_message,
appName);
+ Bundle extras = new Bundle();
+ extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[] {mPackageName});
final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
.setOngoing(true)
.setContentTitle(
@@ -118,6 +122,7 @@ class AlertWindowNotification {
.setColor(context.getColor(R.color.system_notification_accent_color))
.setStyle(new Notification.BigTextStyle().bigText(message))
.setLocalOnly(true)
+ .addExtras(extras)
.setContentIntent(getContentIntent(context, mPackageName));
if (aInfo != null) {
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index 9dc07c1659db..da04a0d1075c 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -920,11 +920,11 @@ public class MbmsDownloadSession implements AutoCloseable {
try {
if (!token.createNewFile()) {
throw new RuntimeException("Failed to create download token for request "
- + request);
+ + request + ". Token location is " + token.getPath());
}
} catch (IOException e) {
throw new RuntimeException("Failed to create download token for request " + request
- + " due to IOException " + e);
+ + " due to IOException " + e + ". Attempted to write to " + token.getPath());
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index da5bd84f9083..15e06321206a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7752,11 +7752,25 @@ public class TelephonyManager {
*/
public static final int INDICATION_FILTER_DATA_CALL_DORMANCY_CHANGED = 0x4;
+ /**
+ * The indication for link capacity estimate update.
+ * @hide
+ */
+ public static final int INDICATION_FILTER_LINK_CAPACITY_ESTIMATE = 0x8;
+
+ /**
+ * The indication for physical channel config update.
+ * @hide
+ */
+ public static final int INDICATION_FILTER_PHYSICAL_CHANNEL_CONFIG = 0x10;
+
/** @hide */
@IntDef(flag = true, prefix = { "INDICATION_FILTER_" }, value = {
INDICATION_FILTER_SIGNAL_STRENGTH,
INDICATION_FILTER_FULL_NETWORK_STATE,
- INDICATION_FILTER_DATA_CALL_DORMANCY_CHANGED
+ INDICATION_FILTER_DATA_CALL_DORMANCY_CHANGED,
+ INDICATION_FILTER_LINK_CAPACITY_ESTIMATE,
+ INDICATION_FILTER_PHYSICAL_CHANNEL_CONFIG
})
@Retention(RetentionPolicy.SOURCE)
public @interface IndicationFilters{}
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
index b0c00c6284a6..fe7533f57b12 100644
--- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
+++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
@@ -297,7 +297,9 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
for (Uri tempFileUri : tempFiles) {
if (verifyTempFilePath(context, request.getFileServiceId(), tempFileUri)) {
File tempFile = new File(tempFileUri.getSchemeSpecificPart());
- tempFile.delete();
+ if (!tempFile.delete()) {
+ Log.w(LOG_TAG, "Failed to delete temp file at " + tempFile.getPath());
+ }
}
}
}
@@ -474,6 +476,8 @@ public class MbmsDownloadReceiver extends BroadcastReceiver {
if (!MbmsUtils.isContainedIn(
MbmsUtils.getEmbmsTempFileDirForService(context, serviceId), tempFile)) {
+ Log.w(LOG_TAG, "File at " + path + " is not contained in the temp file root," +
+ " which is " + MbmsUtils.getEmbmsTempFileDirForService(context, serviceId));
return false;
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index ee7084ad86c0..d25fd3fdf60c 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -419,6 +419,8 @@ cat include/telephony/ril.h | \
int RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING = 145;
int RIL_REQUEST_START_KEEPALIVE = 146;
int RIL_REQUEST_STOP_KEEPALIVE = 147;
+ int RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA = 148;
+ int RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA = 149;
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;