summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java3
-rw-r--r--packages/EasterEgg/AndroidManifest.xml11
-rw-r--r--packages/EasterEgg/res/drawable/food_cookie.xml35
-rw-r--r--packages/EasterEgg/res/values/strings.xml3
-rw-r--r--packages/EasterEgg/res/xml/filepaths.xml19
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/Cat.java3
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoLand.java8
-rw-r--r--packages/EasterEgg/src/com/android/egg/neko/NekoService.java28
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java49
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java33
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java97
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java71
-rw-r--r--packages/SystemUI/AndroidManifest.xml13
-rw-r--r--packages/SystemUI/res/color/qs_detail_progress_track.xml2
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_no_sim.xml16
-rw-r--r--packages/SystemUI/res/layout/car_fullscreen_user_pod.xml3
-rw-r--r--packages/SystemUI/res/layout/car_qs_footer.xml30
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml4
-rw-r--r--packages/SystemUI/res/values-h600dp/dimens_car.xml20
-rw-r--r--packages/SystemUI/res/values-ldrtl/config.xml2
-rw-r--r--packages/SystemUI/res/values/attrs.xml1
-rw-r--r--packages/SystemUI/res/values/colors.xml5
-rw-r--r--packages/SystemUI/res/values/colors_car.xml12
-rw-r--r--packages/SystemUI/res/values/dimens_car.xml17
-rw-r--r--packages/SystemUI/res/values/ids.xml1
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/CellTileView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLogger.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java177
-rw-r--r--packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml20
88 files changed, 1170 insertions, 261 deletions
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index a61881f2f0df..95ec83dd9e14 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -181,7 +181,8 @@ public class CaptivePortalLoginActivity extends Activity {
}
private void done(boolean success) {
- if (DBG) logd(String.format("Result success %b for %s", success, mUrl.toString()));
+ if (DBG) logd(String.format("Result success %b for %s", success,
+ mUrl != null ? mUrl.toString() : "null"));
if (success) {
// Trigger re-evaluation upon success http response code
CarrierActionUtils.applyCarrierAction(
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
index 14861c261f0d..172490dc9178 100644
--- a/packages/EasterEgg/AndroidManifest.xml
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -84,5 +84,16 @@ Copyright (C) 2016 The Android Open Source Project
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
+
+ <!-- FileProvider for sending pictures -->
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.android.egg.fileprovider"
+ android:grantUriPermissions="true"
+ android:exported="false">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/filepaths" />
+ </provider>
</application>
</manifest>
diff --git a/packages/EasterEgg/res/drawable/food_cookie.xml b/packages/EasterEgg/res/drawable/food_cookie.xml
new file mode 100644
index 000000000000..74dd134355e2
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_cookie.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <group>
+ <path
+ android:fillColor="#55FFFFFF"
+ android:fillType="evenOdd"
+ android:pathData="M5.71 18.29A8.99 8.99 0 0 0 22 13c0-3-1.46-5.65-3.71-7.29A8.99 8.99 0 0 0 2 11c0 3 1.46 5.65 3.71 7.29z"/>
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:fillType="evenOdd"
+ android:pathData="M7.25 19.18A8.5 8.5 0 0 0 19.19 7.24 9 9 0 0 1 7.24 19.19z"/>
+ <path
+ android:fillColor="#55FFFFFF"
+ android:pathData="M10.5 3a0.5 0.5 0 1 1 1 0v2.05a0.5 0.5 0 1 1-1 0V3zm3.1 0.42a0.5 0.5 0 0 1 0.93 0.39l-0.8 1.88A0.5 0.5 0 1 1 12.8 5.3l0.8-1.88zm2.7 1.57a0.5 0.5 0 1 1 0.71 0.7l-1.45 1.46a0.5 0.5 0 0 1-0.7-0.71l1.44-1.45zm1.9 2.5a0.5 0.5 0 0 1 0.38 0.92l-1.9 0.77a0.5 0.5 0 0 1-0.37-0.93l1.9-0.77zM19 10.5a0.5 0.5 0 1 1 0 1h-2.05a0.5 0.5 0 0 1 0-1H19zm-0.42 3.1a0.5 0.5 0 0 1-0.39 0.93l-1.88-0.8a0.5 0.5 0 1 1 0.39-0.92l1.88 0.8zm-1.57 2.7a0.5 0.5 0 1 1-0.7 0.71l-1.46-1.45a0.5 0.5 0 0 1 0.71-0.7l1.45 1.44zm-2.5 1.9a0.5 0.5 0 1 1-0.92 0.38l-0.77-1.9a0.5 0.5 0 0 1 0.93-0.37l0.77 1.9zM11.5 19a0.5 0.5 0 1 1-1 0v-2.05a0.5 0.5 0 0 1 1 0V19zm-3.1-0.42a0.5 0.5 0 0 1-0.93-0.39l0.8-1.88A0.5 0.5 0 0 1 9.2 16.7l-0.8 1.88zm-2.7-1.57a0.5 0.5 0 1 1-0.71-0.7l1.45-1.46a0.5 0.5 0 0 1 0.7 0.71L5.7 17.01zm-1.9-2.48a0.5 0.5 0 0 1-0.38-0.92l1.88-0.8a0.5 0.5 0 0 1 0.4 0.92l-1.9 0.8zM3 11.5a0.5 0.5 0 1 1 0-1h2.05a0.5 0.5 0 1 1 0 1H3zm0.42-3.1A0.5 0.5 0 0 1 3.8 7.46l1.88 0.8A0.5 0.5 0 1 1 5.3 9.2L3.42 8.4zm1.57-2.7a0.5 0.5 0 1 1 0.7-0.71l1.46 1.45a0.5 0.5 0 0 1-0.71 0.7L4.99 5.7zm2.5-1.9A0.5 0.5 0 0 1 8.4 3.41l0.77 1.9a0.5 0.5 0 0 1-0.93 0.37L7.48 3.8z"/>
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
index 8478a438a0e4..61e38342872e 100644
--- a/packages/EasterEgg/res/values/strings.xml
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -17,6 +17,7 @@ Copyright (C) 2016 The Android Open Source Project
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<string name="app_name" translatable="false">Android Easter Egg</string>
<string name="notification_name" translatable="false">Android Neko</string>
+ <string name="notification_channel_name" translatable="false">New cats</string>
<string name="default_tile_name" translatable="false">\????</string>
<string name="notification_title" translatable="false">A cat is here.</string>
<string name="default_cat_name" translatable="false">Cat #%s</string>
@@ -34,7 +35,7 @@ Copyright (C) 2016 The Android Open Source Project
<item>@drawable/food_bits</item>
<item>@drawable/food_sysuituna</item>
<item>@drawable/food_chicken</item>
- <item>@drawable/food_donut</item>
+ <item>@drawable/food_cookie</item>
</array>
<integer-array name="food_intervals">
<item>0</item>
diff --git a/packages/EasterEgg/res/xml/filepaths.xml b/packages/EasterEgg/res/xml/filepaths.xml
new file mode 100644
index 000000000000..2130025e9265
--- /dev/null
+++ b/packages/EasterEgg/res/xml/filepaths.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<paths>
+ <external-path name="cats" path="Pictures/Cats" />
+</paths> \ No newline at end of file
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
index a4df372ef835..dd1bd07f3298 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/Cat.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
@@ -31,6 +31,8 @@ import java.util.concurrent.ThreadLocalRandom;
import com.android.egg.R;
import com.android.internal.logging.MetricsLogger;
+import static com.android.egg.neko.NekoLand.CHAN_ID;
+
public class Cat extends Drawable {
public static final long[] PURR = {0, 40, 20, 40, 20, 40, 20, 40, 20, 40, 20, 40};
@@ -218,6 +220,7 @@ public class Cat extends Drawable {
.setContentText(getName())
.setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
.setAutoCancel(true)
+ .setChannel(CHAN_ID)
.setVibrate(PURR)
.addExtras(extras);
}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
index 689e38142988..d2e37d8779d1 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
@@ -31,6 +31,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore.Images;
+import android.support.v4.content.FileProvider;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@@ -56,6 +57,8 @@ import java.util.Comparator;
import java.util.List;
public class NekoLand extends Activity implements PrefsListener {
+ public static String CHAN_ID = "EGG";
+
public static boolean DEBUG = false;
public static boolean DEBUG_NOTIFICATIONS = false;
@@ -289,10 +292,13 @@ public class NekoLand extends Activity implements PrefsListener {
new String[] {png.toString()},
new String[] {"image/png"},
null);
- Uri uri = Uri.fromFile(png);
+ Log.v("Neko", "cat file: " + png);
+ Uri uri = FileProvider.getUriForFile(this, "com.android.egg.fileprovider", png);
+ Log.v("Neko", "cat uri: " + uri);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.putExtra(Intent.EXTRA_SUBJECT, cat.getName());
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.setType("image/png");
startActivity(Intent.createChooser(intent, null));
cat.logShare(this);
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
index 808ec361fb4f..42506e61d2ec 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
@@ -15,15 +15,15 @@
package com.android.egg.neko;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import java.util.List;
@@ -33,6 +33,9 @@ import com.android.egg.R;
import java.util.Random;
+import static com.android.egg.neko.Cat.PURR;
+import static com.android.egg.neko.NekoLand.CHAN_ID;
+
public class NekoService extends JobService {
private static final String TAG = "NekoService";
@@ -40,6 +43,7 @@ public class NekoService extends JobService {
public static int JOB_ID = 42;
public static int CAT_NOTIFICATION = 1;
+ public static int DEBUG_NOTIFICATION = 1234;
public static float CAT_CAPTURE_PROB = 1.0f; // generous
@@ -50,6 +54,18 @@ public class NekoService extends JobService {
public static float INTERVAL_JITTER_FRAC = 0.25f;
+ private static void setupNotificationChannels(Context context) {
+ NotificationManager noman = context.getSystemService(NotificationManager.class);
+ NotificationChannel eggChan = new NotificationChannel(CHAN_ID,
+ context.getString(R.string.notification_channel_name),
+ NotificationManager.IMPORTANCE_DEFAULT);
+ eggChan.setSound(Uri.EMPTY, Notification.AUDIO_ATTRIBUTES_DEFAULT); // cats are quiet
+ eggChan.setVibrationPattern(PURR); // not totally quiet though
+ eggChan.setBlockableSystem(true); // unlike a real cat, you can push this one off your lap
+ eggChan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); // cats sit in the window
+ noman.createNotificationChannel(eggChan);
+ }
+
@Override
public boolean onStartJob(JobParameters params) {
Log.v(TAG, "Starting job: " + String.valueOf(params));
@@ -64,8 +80,9 @@ public class NekoService extends JobService {
final Notification.Builder builder
= cat.buildNotification(this)
.setContentTitle("DEBUG")
+ .setChannel(NekoLand.CHAN_ID)
.setContentText("Ran job: " + params);
- noman.notify(1, builder.build());
+ noman.notify(DEBUG_NOTIFICATION, builder.build());
}
final PrefState prefs = new PrefState(this);
@@ -111,6 +128,8 @@ public class NekoService extends JobService {
}
public static void registerJob(Context context, long intervalMinutes) {
+ setupNotificationChannels(context);
+
JobScheduler jss = context.getSystemService(JobScheduler.class);
jss.cancel(JOB_ID);
long interval = intervalMinutes * MINUTES;
@@ -126,12 +145,13 @@ public class NekoService extends JobService {
if (NekoLand.DEBUG_NOTIFICATIONS) {
NotificationManager noman = context.getSystemService(NotificationManager.class);
- noman.notify(500, new Notification.Builder(context)
+ noman.notify(DEBUG_NOTIFICATION, new Notification.Builder(context)
.setSmallIcon(R.drawable.stat_icon)
.setContentTitle(String.format("Job scheduled in %d min", (interval / MINUTES)))
.setContentText(String.valueOf(jobInfo))
.setPriority(Notification.PRIORITY_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
+ .setChannel(NekoLand.CHAN_ID)
.setShowWhen(true)
.build());
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index bf1bf34dc220..40c2b1f3b771 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -339,26 +339,35 @@ public class ApplicationsState {
synchronized (mEntriesMap) {
AppEntry entry = mEntriesMap.get(userId).get(packageName);
if (entry != null && (entry.info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
- mBackgroundHandler.post(() -> {
- try {
- final StorageStats stats = mStats.queryStatsForPackage(
- entry.info.storageUuid, packageName, UserHandle.of(userId));
- final PackageStats legacy = new PackageStats(packageName, userId);
- legacy.codeSize = stats.getCodeBytes();
- legacy.dataSize = stats.getDataBytes();
- legacy.cacheSize = stats.getCacheBytes();
- try {
- mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacy, true);
- } catch (RemoteException ignored) {
- }
- } catch (NameNotFoundException | IOException e) {
- Log.w(TAG, "Failed to query stats: " + e);
- try {
- mBackgroundHandler.mStatsObserver.onGetStatsCompleted(null, false);
- } catch (RemoteException ignored) {
- }
- }
- });
+ mBackgroundHandler.post(
+ () -> {
+ try {
+ final StorageStats stats =
+ mStats.queryStatsForPackage(
+ entry.info.storageUuid,
+ packageName,
+ UserHandle.of(userId));
+ final long cacheQuota =
+ mStats.getCacheQuotaBytes(
+ entry.info.storageUuid.toString(), entry.info.uid);
+ final PackageStats legacy = new PackageStats(packageName, userId);
+ legacy.codeSize = stats.getCodeBytes();
+ legacy.dataSize = stats.getDataBytes();
+ legacy.cacheSize = Math.min(stats.getCacheBytes(), cacheQuota);
+ try {
+ mBackgroundHandler.mStatsObserver.onGetStatsCompleted(
+ legacy, true);
+ } catch (RemoteException ignored) {
+ }
+ } catch (NameNotFoundException | IOException e) {
+ Log.w(TAG, "Failed to query stats: " + e);
+ try {
+ mBackgroundHandler.mStatsObserver.onGetStatsCompleted(
+ null, false);
+ } catch (RemoteException ignored) {
+ }
+ }
+ });
}
if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 109446d8ed4a..2873fb68ce5b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -335,8 +335,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
public int getProfileConnectionState(LocalBluetoothProfile profile) {
- if (mProfileConnectionState == null ||
- mProfileConnectionState.get(profile) == null) {
+ if (mProfileConnectionState.get(profile) == null) {
// If cache is empty make the binder call to get the state
int state = profile.getConnectionStatus(mDevice);
mProfileConnectionState.put(profile, state);
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index fc0a444915c3..713e9675cccd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -428,15 +428,6 @@ public class TileUtils {
if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) {
int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW);
remoteViews = new RemoteViews(applicationInfo.packageName, layoutId);
- if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
- String uriString = metaData.getString(
- META_DATA_PREFERENCE_SUMMARY_URI);
- String overrideSummary = getTextFromUri(context, uriString, providerMap,
- META_DATA_PREFERENCE_SUMMARY);
- if (overrideSummary != null) {
- remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
- }
- }
}
}
} catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
@@ -543,6 +534,30 @@ public class TileUtils {
}
}
+ public static void updateTileUsingSummaryUri(Context context, Tile tile) {
+ if (tile == null || tile.metaData == null ||
+ !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
+ return;
+ }
+
+ final Map<String, IContentProvider> providerMap = new HashMap<>();
+
+ final String uriString = tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI);
+ final Bundle bundle = getBundleFromUri(context, uriString, providerMap);
+ final String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY);
+ final String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE);
+ if (overrideSummary != null) {
+ tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
+ }
+ if (overrideTitle != null) {
+ tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle);
+ }
+ }
+
+ private static String getString(Bundle bundle, String key) {
+ return bundle == null ? null : bundle.getString(key);
+ }
+
private static IContentProvider getProviderFromUri(Context context, Uri uri,
Map<String, IContentProvider> providerMap) {
if (uri == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java
index cb15a795fe9b..abc9b022b90b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java
@@ -57,7 +57,7 @@ class TimestampedScoredNetwork implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeParcelable(mScore, flags);
+ mScore.writeToParcel(dest, flags);
dest.writeLong(mUpdatedTimestampMillis);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 3e90435b21d7..88035e4fc600 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -22,10 +22,12 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.RuntimeEnvironment.application;
@@ -64,9 +66,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.internal.ShadowExtractor;
import java.util.ArrayList;
import java.util.Collections;
@@ -75,8 +74,7 @@ import java.util.Map;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
- sdk = TestConfig.SDK_VERSION,
- shadows = {TileUtilsTest.TileUtilsShadowRemoteViews.class})
+ sdk = TestConfig.SDK_VERSION)
public class TileUtilsTest {
@Mock
@@ -421,24 +419,12 @@ public class TileUtilsTest {
}
@Test
- public void getTilesForIntent_summaryUriSpecified_shouldOverrideRemoteViewSummary()
+ public void updateTileUsingSummaryUri_summaryUriSpecified_shouldOverrideRemoteViewSummary()
throws RemoteException {
- Intent intent = new Intent();
- Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
- List<Tile> outTiles = new ArrayList<>();
- List<ResolveInfo> info = new ArrayList<>();
- ResolveInfo resolveInfo = newInfo(true, null /* category */, null,
- null, URI_GET_SUMMARY);
- resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
- R.layout.user_preference);
- info.add(resolveInfo);
-
- when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
- .thenReturn(info);
-
// Mock the content provider interaction.
Bundle bundle = new Bundle();
- bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text");
+ String expectedSummary = "new summary text";
+ bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, expectedSummary);
when(mIContentProvider.call(anyString(),
eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
any())).thenReturn(bundle);
@@ -447,57 +433,12 @@ public class TileUtilsTest {
when(mContentResolver.acquireUnstableProvider(any(Uri.class)))
.thenReturn(mIContentProvider);
- TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
- null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */, true /* forceTintExternalIcon */);
-
- assertThat(outTiles.size()).isEqualTo(1);
- Tile tile = outTiles.get(0);
- assertThat(tile.remoteViews).isNotNull();
- assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
- // Make sure the summary TextView got a new text string.
- TileUtilsShadowRemoteViews shadowRemoteViews =
- (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews);
- assertThat(shadowRemoteViews.overrideViewId).isEqualTo(android.R.id.summary);
- assertThat(shadowRemoteViews.overrideText).isEqualTo("new summary text");
- }
-
- @Test
- public void getTilesForIntent_providerUnavailable_shouldNotOverrideRemoteViewSummary()
- throws RemoteException {
- Intent intent = new Intent();
- Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
- List<Tile> outTiles = new ArrayList<>();
- List<ResolveInfo> info = new ArrayList<>();
- ResolveInfo resolveInfo = newInfo(true, null /* category */, null,
- null, URI_GET_SUMMARY);
- resolveInfo.activityInfo.metaData.putInt("com.android.settings.custom_view",
- R.layout.user_preference);
- info.add(resolveInfo);
-
- when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
- .thenReturn(info);
-
- // Mock the content provider interaction.
- Bundle bundle = new Bundle();
- bundle.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY, "new summary text");
- when(mIContentProvider.call(anyString(),
- eq(TileUtils.getMethodFromUri(Uri.parse(URI_GET_SUMMARY))), eq(URI_GET_SUMMARY),
- any())).thenReturn(bundle);
-
- TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
- null /* defaultCategory */, outTiles, false /* usePriority */,
- false /* checkCategory */, true /* forceTintExternalIcon */);
-
- assertThat(outTiles.size()).isEqualTo(1);
- Tile tile = outTiles.get(0);
- assertThat(tile.remoteViews).isNotNull();
- assertThat(tile.remoteViews.getLayoutId()).isEqualTo(R.layout.user_preference);
- // Make sure the summary TextView didn't get any text view updates.
- TileUtilsShadowRemoteViews shadowRemoteViews =
- (TileUtilsShadowRemoteViews) ShadowExtractor.extract(tile.remoteViews);
- assertThat(shadowRemoteViews.overrideViewId).isNull();
- assertThat(shadowRemoteViews.overrideText).isNull();
+ Tile tile = new Tile();
+ tile.metaData = new Bundle();
+ tile.metaData.putString(TileUtils.META_DATA_PREFERENCE_SUMMARY_URI, URI_GET_SUMMARY);
+ tile.remoteViews = mock(RemoteViews.class);
+ TileUtils.updateTileUsingSummaryUri(mContext, tile);
+ verify(tile.remoteViews, times(1)).setTextViewText(anyInt(), eq(expectedSummary));
}
public static ResolveInfo newInfo(boolean systemApp, String category) {
@@ -558,16 +499,4 @@ public class TileUtilsTest {
}
}
- @Implements(RemoteViews.class)
- public static class TileUtilsShadowRemoteViews {
-
- private Integer overrideViewId;
- private CharSequence overrideText;
-
- @Implementation
- public void setTextViewText(int viewId, CharSequence text) {
- overrideViewId = viewId;
- overrideText = text;
- }
- }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
new file mode 100644
index 000000000000..b2d9d67bd104
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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.settingslib.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.NetworkKey;
+import android.net.ScoredNetwork;
+import android.net.WifiKey;
+import android.os.Parcel;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.TestConfig;
+import java.util.Date;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class TimestampedScoredNetworkTest {
+ private TimestampedScoredNetwork impl;
+
+ private ScoredNetwork createTestScoredNetwork(String ssid) {
+ return new ScoredNetwork(
+ new NetworkKey(new WifiKey("\"" + ssid + "\"", "00:00:00:00:00:00")), null);
+ }
+
+ @Before
+ public void setUp() {
+ impl = new TimestampedScoredNetwork(createTestScoredNetwork("test"),
+ 0 /* updatedTimestampMillis */);
+ }
+
+ @Test
+ public void testUpdate() {
+ long time = new Date().getTime();
+ ScoredNetwork updated = createTestScoredNetwork("updated");
+ impl.update(updated, time);
+
+ assertThat(impl.getScore()).isEqualTo(updated);
+ assertThat(impl.getUpdatedTimestampMillis()).isEqualTo(time);
+ }
+
+ @Test
+ public void testParcel() {
+ Parcel parcel = Parcel.obtain();
+ impl.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ TimestampedScoredNetwork fromParcel = TimestampedScoredNetwork.CREATOR.createFromParcel(parcel);
+
+ assertThat(fromParcel.getScore()).isEqualTo(impl.getScore());
+ assertThat(fromParcel.getUpdatedTimestampMillis()).isEqualTo(impl.getUpdatedTimestampMillis());
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 75e919990f01..87971cb41f96 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -318,15 +318,20 @@
android:exported="false">
</activity>
+ <!-- Springboard for launching the share activity -->
+ <receiver android:name=".screenshot.GlobalScreenshot$ShareReceiver"
+ android:process=":screenshot"
+ android:exported="false" />
+
<!-- Callback for dismissing screenshot notification after a share target is picked -->
<receiver android:name=".screenshot.GlobalScreenshot$TargetChosenReceiver"
- android:process=":screenshot"
- android:exported="false" />
+ android:process=":screenshot"
+ android:exported="false" />
<!-- Callback for deleting screenshot notification -->
<receiver android:name=".screenshot.GlobalScreenshot$DeleteScreenshotReceiver"
- android:process=":screenshot"
- android:exported="false" />
+ android:process=":screenshot"
+ android:exported="false" />
<!-- started from UsbDeviceSettingsManager -->
<activity android:name=".usb.UsbConfirmActivity"
diff --git a/packages/SystemUI/res/color/qs_detail_progress_track.xml b/packages/SystemUI/res/color/qs_detail_progress_track.xml
index c56382e6047f..d86119fc01fe 100644
--- a/packages/SystemUI/res/color/qs_detail_progress_track.xml
+++ b/packages/SystemUI/res/color/qs_detail_progress_track.xml
@@ -16,5 +16,5 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- I really don't want to define this, but the View that uses this asset uses both the
light and dark accent colors. -->
- <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
+ <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_dark" />
</selector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index 69869fe9c9be..5dcd9f78301b 100644
--- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2014 The Android Open Source Project
+Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -16,10 +16,14 @@ Copyright (C) 2014 The Android Open Source Project
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportWidth="18.4"
+ android:viewportHeight="18.4">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-7.0,0.0L7.7,5.3L19.0,16.7L19.0,5.0zM3.7,3.9L2.4,5.2L5.0,7.8L5.0,19.0c0.0,1.1 0.9,2.0 2.0,2.0l10.0,0.0c0.4,0.0 0.7,-0.1 1.0,-0.3l1.9,1.9l1.3,-1.3L3.7,3.9z"/>
+ <group
+ android:translateX="0.7"
+ android:translateY="1.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M13.91,11.84L5.14,3.08l1.81,-1.81h5.41c0.85,0 1.54,0.69 1.54,1.54l0.01,9.03zM15.06,14.95L2.54,2.44c-0.28,-0.28 -0.71,-0.28 -0.99,0s-0.28,0.71 0,0.98l1.53,1.53v8.67c0,0.85 0.69,1.54 1.54,1.54h7.74c0.27,0 0.52,-0.07 0.74,-0.2l0.96,0.96c0.28,0.28 0.71,0.28 0.99,0 0.28,-0.26 0.28,-0.69 0.01,-0.97z"/>
+ </group>
</vector>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index dde2db2f484f..2f16516a6fea 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -30,7 +30,8 @@
<TextView android:id="@+id/user_name"
android:layout_width="@dimen/car_fullscreen_user_pod_width"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_above_text"
+ android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
+ android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
android:textSize="@dimen/car_fullscreen_user_pod_text_size"
android:textColor="@color/qs_user_detail_name"
android:ellipsize="end"
diff --git a/packages/SystemUI/res/layout/car_qs_footer.xml b/packages/SystemUI/res/layout/car_qs_footer.xml
index 96f34fca58f5..044090be9f5d 100644
--- a/packages/SystemUI/res/layout/car_qs_footer.xml
+++ b/packages/SystemUI/res/layout/car_qs_footer.xml
@@ -18,23 +18,24 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/qs_footer"
android:layout_width="match_parent"
- android:layout_height="@dimen/qs_footer_height"
+ android:layout_height="@dimen/car_qs_footer_height"
android:baselineAligned="false"
android:clickable="false"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingBottom="16dp"
- android:paddingTop="16dp"
- android:paddingEnd="32dp"
- android:paddingStart="32dp"
+ android:paddingBottom="@dimen/car_qs_footer_padding_bottom"
+ android:paddingTop="@dimen/car_qs_footer_padding_top"
+ android:paddingEnd="@dimen/car_qs_footer_padding_end"
+ android:paddingStart="@dimen/car_qs_footer_padding_start"
android:gravity="center_vertical">
<com.android.systemui.statusbar.phone.MultiUserSwitch
android:id="@+id/multi_user_switch"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="@dimen/car_qs_footer_icon_width"
+ android:layout_height="@dimen/car_qs_footer_icon_height"
+ android:layout_marginRight="@dimen/car_qs_footer_user_switch_margin_right"
android:background="@drawable/ripple_drawable"
android:focusable="true">
@@ -43,15 +44,24 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:scaleType="centerInside"/>
+ android:scaleType="fitCenter"/>
</com.android.systemui.statusbar.phone.MultiUserSwitch>
+ <TextView android:id="@+id/user_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/car_qs_footer_user_name_text_size"
+ android:textColor="@color/car_qs_footer_user_name_color"
+ android:gravity="start|center_vertical"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/multi_user_switch" />
+
<com.android.systemui.statusbar.phone.SettingsButton
android:id="@+id/settings_button"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="@dimen/car_qs_footer_icon_width"
+ android:layout_height="@dimen/car_qs_footer_icon_height"
android:background="@drawable/ripple_drawable"
android:contentDescription="@string/accessibility_quick_settings_settings"
android:scaleType="centerCrop"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index bbd315ee8776..6df1657ba947 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -62,7 +62,9 @@
android:layout_height="wrap_content"
android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
android:layout_marginStart="2dp"
- android:layout_marginEnd="2dp"/>
+ android:layout_marginEnd="2dp"
+ android:ellipsize="end"
+ android:maxLines="1"/>
</LinearLayout>
<!-- Channel Info Block -->
diff --git a/packages/SystemUI/res/values-h600dp/dimens_car.xml b/packages/SystemUI/res/values-h600dp/dimens_car.xml
new file mode 100644
index 000000000000..c3e62c8ec9c8
--- /dev/null
+++ b/packages/SystemUI/res/values-h600dp/dimens_car.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+ <dimen name="car_body2_size">32sp</dimen> <!-- B2 -->
+</resources>
diff --git a/packages/SystemUI/res/values-ldrtl/config.xml b/packages/SystemUI/res/values-ldrtl/config.xml
index 40604c16be9b..884c95f57f51 100644
--- a/packages/SystemUI/res/values-ldrtl/config.xml
+++ b/packages/SystemUI/res/values-ldrtl/config.xml
@@ -17,5 +17,5 @@
<resources>
<!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
when the PIP menu is shown with settings. -->
- <string translatable="false" name="pip_settings_bounds">"778 54 1258 324"</string>
+ <string translatable="false" name="pip_settings_bounds">"778 756 1258 1026"</string>
</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 745d6015d0ff..a923f0b8c332 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -34,6 +34,7 @@
<attr name="recentItemLayout" format="reference" />
<!-- Style for the "Clear all" button. -->
<attr name="clearAllStyle" format="reference" />
+ <attr name="clearAllBackgroundColor" format="reference" />
</declare-styleable>
<declare-styleable name="DeadZone">
<attr name="minSize" format="dimension" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f72f3794e808..f244d88b8573 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -60,6 +60,11 @@
<!-- The background color for the freeform workspace. -->
<color name="recents_freeform_workspace_bg_color">#33FFFFFF</color>
+ <!-- The background color for clear all button on light backgrounds if not transparent. -->
+ <color name="recents_clear_all_button_bg_light_color">#CCFFFFFF</color>
+ <!-- The background color for clear all button on dark backgrounds if not transparent. -->
+ <color name="recents_clear_all_button_bg_dark_color">#CC000000</color>
+
<color name="keyguard_affordance">#ffffffff</color>
<!-- The color of the legacy notification background -->
diff --git a/packages/SystemUI/res/values/colors_car.xml b/packages/SystemUI/res/values/colors_car.xml
index 1b8c2fa68244..710b3e03ccf7 100644
--- a/packages/SystemUI/res/values/colors_car.xml
+++ b/packages/SystemUI/res/values/colors_car.xml
@@ -20,8 +20,12 @@
<color name="car_qs_background_primary">#263238</color> <!-- Blue Gray 900 -->
<color name="car_user_switcher_progress_bgcolor">#00000000</color> <!-- Transparent -->
<color name="car_user_switcher_progress_fgcolor">#80CBC4</color> <!-- Teal 200 -->
- <color name="car_user_switcher_no_user_image_bgcolor">#FAFAFA</color> <!-- Grey 50 -->
- <color name="car_user_switcher_no_user_image_fgcolor">#212121</color> <!-- Grey 900 -->
- <color name="car_start_driving_background">#FAFAFA</color> <!-- Grey 50 -->
- <color name="car_start_driving_text">#212121</color> <!-- Grey 900 -->
+ <color name="car_user_switcher_no_user_image_bgcolor">@color/car_grey_50</color>
+ <color name="car_user_switcher_no_user_image_fgcolor">@color/car_grey_900</color>
+ <color name="car_start_driving_background">@color/car_grey_50</color>
+ <color name="car_start_driving_text">@color/car_grey_900</color>
+ <color name="car_qs_footer_user_name_color">@color/car_grey_50</color>
+
+ <color name="car_grey_50">#FAFAFA</color>
+ <color name="car_grey_900">#212121</color>
</resources>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 5f56c4ea6f2d..8853587dba47 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -18,7 +18,8 @@
<resources>
<dimen name="car_margin">148dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_above_text">24dp</dimen>
+ <dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
+ <dimen name="car_fullscreen_user_pod_margin_name_bottom">64dp</dimen>
<dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
<dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
<dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
@@ -37,5 +38,17 @@
<dimen name="car_start_driving_corner_radius">16dp</dimen>
<dimen name="car_start_driving_padding_side">30dp</dimen>
<dimen name="car_start_driving_height">80dp</dimen>
- <dimen name="car_start_driving_text_size">32sp</dimen> <!-- B2 -->
+ <dimen name="car_start_driving_text_size">@dimen/car_body2_size</dimen>
+
+ <dimen name="car_qs_footer_height">112dp</dimen>
+ <dimen name="car_qs_footer_padding_bottom">16dp</dimen>
+ <dimen name="car_qs_footer_padding_top">16dp</dimen>
+ <dimen name="car_qs_footer_padding_end">46dp</dimen>
+ <dimen name="car_qs_footer_padding_start">46dp</dimen>
+ <dimen name="car_qs_footer_icon_width">56dp</dimen>
+ <dimen name="car_qs_footer_icon_height">56dp</dimen>
+ <dimen name="car_qs_footer_user_switch_margin_right">46dp</dimen>
+ <dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen>
+
+ <dimen name="car_body2_size">26sp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index b27deddb4dd0..2148c8047476 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -59,6 +59,7 @@
<item type="id" name="transformation_start_y_tag"/>
<item type="id" name="transformation_start_scale_x_tag"/>
<item type="id" name="transformation_start_scale_y_tag"/>
+ <item type="id" name="continuous_clipping_tag"/>
<!-- Whether the icon is from a notification for which targetSdk < L -->
<item type="id" name="icon_is_pre_L"/>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2199fffa4bbe..90c5977e2a67 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -34,11 +34,13 @@
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowDisablePreview">true</item>
<item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
+ <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_dark_color</item>
<item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
<item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item>
</style>
<style name="RecentsTheme.Wallpaper.Light">
+ <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_light_color</item>
<item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
<item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c596398cf804..d95402cdb5dc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -50,6 +50,7 @@ import android.media.AudioManager;
import android.os.BatteryManager;
import android.os.CancellationSignal;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IRemoteCallback;
import android.os.Message;
import android.os.RemoteException;
@@ -58,6 +59,8 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -67,8 +70,6 @@ import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
-import com.google.android.collect.Lists;
-
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
@@ -77,6 +78,8 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
+import com.google.android.collect.Lists;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -217,6 +220,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private UserManager mUserManager;
private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
private LockPatternUtils mLockPatternUtils;
+ private final IDreamManager mDreamManager;
+ private boolean mIsDreaming;
/**
* Short delay before restarting fingerprint authentication after a successful try
@@ -458,6 +463,26 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
updateFingerprintListeningState();
}
+ /**
+ * @return a cached version of DreamManager.isDreaming()
+ */
+ public boolean isDreaming() {
+ return mIsDreaming;
+ }
+
+ /**
+ * If the device is dreaming, awakens the device
+ */
+ public void awakenFromDream() {
+ if (mIsDreaming && mDreamManager != null) {
+ try {
+ mDreamManager.awaken();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to awaken from dream");
+ }
+ }
+ }
+
private void onFingerprintAuthenticated(int userId) {
Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
mUserFingerprintAuthenticated.put(userId, true);
@@ -1037,11 +1062,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private void handleDreamingStateChanged(int dreamStart) {
final int count = mCallbacks.size();
- boolean showingDream = dreamStart == 1;
+ mIsDreaming = dreamStart == 1;
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
- cb.onDreamingStateChanged(showingDream);
+ cb.onDreamingStateChanged(mIsDreaming);
}
}
}
@@ -1146,6 +1171,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
mLockPatternUtils = new LockPatternUtils(context);
mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
+ mDreamManager = IDreamManager.Stub.asInterface(
+ ServiceManager.getService(DreamService.DREAM_SERVICE));
+
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
}
@@ -1183,7 +1211,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private boolean shouldListenForFingerprint() {
return (mKeyguardIsVisible || !mDeviceInteractive ||
(mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
- shouldListenForFingerprintAssistant())
+ shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
&& !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
&& !mKeyguardGoingAway;
}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index fd2447bd47b4..2b31967cea4f 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.policy.IconLogger;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -150,7 +151,9 @@ public class BatteryMeterView extends LinearLayout implements
public void onTuningChanged(String key, String newValue) {
if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
ArraySet<String> icons = StatusBarIconController.getIconBlacklist(newValue);
- setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
+ boolean hidden = icons.contains(mSlotBattery);
+ Dependency.get(IconLogger.class).onIconVisibility(mSlotBattery, !hidden);
+ setVisibility(hidden ? View.GONE : View.VISIBLE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 49253ec536cd..a9a915b23a0c 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -42,6 +42,7 @@ import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -66,6 +67,8 @@ import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotControllerImpl;
+import com.android.systemui.statusbar.policy.IconLogger;
+import com.android.systemui.statusbar.policy.IconLoggerImpl;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.LocationController;
@@ -294,9 +297,13 @@ public class Dependency extends SystemUI {
mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
-
mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext));
+ mProviders.put(IconLogger.class, () -> new IconLoggerImpl(mContext,
+ getDependency(BG_LOOPER), getDependency(MetricsLogger.class)));
+
+ mProviders.put(LightBarController.class, () -> new LightBarController(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 33d5617c0397..4cbbbd6c2e90 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -14,6 +14,8 @@
package com.android.systemui.globalactions;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+
import com.android.internal.R;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
@@ -310,7 +312,10 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
- mItems.add(getLockdownAction());
+ if (Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0) {
+ mItems.add(getLockdownAction());
+ }
} else if (GLOBAL_ACTION_KEY_VOICEASSIST.equals(actionKey)) {
mItems.add(getVoiceAssistAction());
} else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) {
@@ -575,7 +580,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn
@Override
public void onPress() {
- new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
+ new LockPatternUtils(mContext)
+ .requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN,
+ UserHandle.USER_ALL);
try {
WindowManagerGlobal.getWindowManagerService().lockNow(null);
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 3d8f9ffe79d7..5f2609380085 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -44,7 +44,10 @@ public class CellTileView extends SignalTileView {
}
protected void updateIcon(ImageView iv, State state) {
- if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
+ if (!(state.icon instanceof SignalIcon)) {
+ super.updateIcon(iv, state);
+ return;
+ } else if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) {
mSignalDrawable.setLevel(((SignalIcon) state.icon).getState());
iv.setImageDrawable(mSignalDrawable);
iv.setTag(R.id.qs_icon_tag, state.icon);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index d42b87bcef28..142aab2626a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -22,6 +22,7 @@ import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
+import android.widget.TextView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -44,6 +45,7 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
private UserInfoController mUserInfoController;
private MultiUserSwitch mMultiUserSwitch;
+ private TextView mUserName;
private ImageView mMultiUserAvatar;
private UserGridView mUserGridView;
@@ -56,6 +58,7 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
super.onFinishInflate();
mMultiUserSwitch = findViewById(R.id.multi_user_switch);
mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+ mUserName = findViewById(R.id.user_name);
mUserInfoController = Dependency.get(UserInfoController.class);
@@ -89,6 +92,7 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
@Override
public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
mMultiUserAvatar.setImageDrawable(picture);
+ mUserName.setText(name);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 6c95a8013108..5a3081cd6664 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -18,6 +18,7 @@ package com.android.systemui.qs.customize;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
+import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
@@ -35,6 +36,8 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.widget.LinearLayout;
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
@@ -48,7 +51,9 @@ import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSContainerImpl;
import com.android.systemui.qs.QSDetailClipper;
import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
@@ -67,6 +72,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
private final QSDetailClipper mClipper;
+ private final LightBarController mLightBarController;
private boolean isShown;
private QSTileHost mHost;
@@ -80,6 +86,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private int mX;
private int mY;
private boolean mOpening;
+ private boolean mIsShowingNavBackdrop;
public QSCustomizer(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -114,6 +121,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
+ mLightBarController = Dependency.get(LightBarController.class);
updateNavBackDrop(getResources().getConfiguration());
}
@@ -125,11 +133,16 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
private void updateNavBackDrop(Configuration newConfig) {
View navBackdrop = findViewById(R.id.nav_bar_background);
+ mIsShowingNavBackdrop = newConfig.smallestScreenWidthDp >= 600
+ || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
if (navBackdrop != null) {
- boolean shouldShow = newConfig.smallestScreenWidthDp >= 600
- || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
- navBackdrop.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
+ navBackdrop.setVisibility(mIsShowingNavBackdrop ? View.VISIBLE : View.GONE);
}
+ updateNavColors();
+ }
+
+ private void updateNavColors() {
+ mLightBarController.setQsCustomizing(mIsShowingNavBackdrop && isShown);
}
public void setHost(QSTileHost host) {
@@ -161,6 +174,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
announceForAccessibility(mContext.getString(
R.string.accessibility_desc_quick_settings_edit));
Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ updateNavColors();
}
}
@@ -176,6 +190,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
mNotifQsContainer.setCustomizerAnimating(false);
mNotifQsContainer.setCustomizerShowing(true);
Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ updateNavColors();
}
}
@@ -201,6 +216,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
announceForAccessibility(mContext.getString(
R.string.accessibility_desc_quick_settings));
Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ updateNavColors();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 017365f6c64d..176112baa2a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -31,6 +31,7 @@ import android.provider.Settings;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
+import android.text.format.DateUtils;
import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
@@ -51,6 +52,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
public static final String PREFIX = "custom(";
+ private static final long CUSTOM_STALE_TIMEOUT = DateUtils.HOUR_IN_MILLIS;
+
private static final boolean DEBUG = false;
// We don't want to thrash binding and unbinding if the user opens and closes the panel a lot.
@@ -83,6 +86,11 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
mUser = ActivityManager.getCurrentUser();
}
+ @Override
+ protected long getStaleTimeout() {
+ return CUSTOM_STALE_TIMEOUT + DateUtils.MINUTE_IN_MILLIS * mHost.indexOf(getTileSpec());
+ }
+
private void setTileIcon() {
try {
PackageManager pm = mContext.getPackageManager();
@@ -186,7 +194,7 @@ public class CustomTile extends QSTileImpl<State> implements TileChangeListener
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (mListening == listening) return;
mListening = listening;
try {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 672f2c2df06e..576a447447b5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -17,12 +17,12 @@ package com.android.systemui.qs.tileimpl;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_CLICK;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_LONG_PRESS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_SECONDARY_CLICK;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CONTEXT;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_POSITION;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_VALUE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-import android.R.attr;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -32,10 +32,12 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.service.quicksettings.Tile;
+import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.Utils;
@@ -45,6 +47,7 @@ import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.PagedTileLayout.TilePage;
import com.android.systemui.qs.QSHost;
import java.util.ArrayList;
@@ -60,14 +63,18 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
protected final String TAG = "Tile." + getClass().getSimpleName();
protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG);
+ private static final long DEFAULT_STALE_TIMEOUT = 10 * DateUtils.MINUTE_IN_MILLIS;
+
protected final QSHost mHost;
protected final Context mContext;
- protected final H mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+ // @NonFinalForTesting
+ protected H mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
private final ArraySet<Object> mListeners = new ArraySet<>();
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ private final Object mStaleListener = new Object();
protected TState mState = newTileState();
private TState mTmpState = newTileState();
private boolean mAnnounceNextStateChange;
@@ -93,6 +100,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
protected QSTileImpl(QSHost host) {
mHost = host;
mContext = host.getContext();
+ handleStale(); // Tile was just created, must be stale.
}
/**
@@ -104,6 +112,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
if (mListeners.add(listener) && mListeners.size() == 1) {
if (DEBUG) Log.d(TAG, "setListening " + true);
mHandler.obtainMessage(H.SET_LISTENING, 1, 0).sendToTarget();
+ refreshState(); // Ensure we get at least one refresh after listening.
}
} else {
if (mListeners.remove(listener) && mListeners.size() == 0) {
@@ -113,6 +122,15 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
}
}
+ protected long getStaleTimeout() {
+ return DEFAULT_STALE_TIMEOUT;
+ }
+
+ @VisibleForTesting
+ protected void handleStale() {
+ setListening(mStaleListener, true);
+ }
+
public String getTileSpec() {
return mTileSpec;
}
@@ -180,9 +198,19 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
logMaker.addTaggedData(FIELD_QS_VALUE, ((BooleanState) mState).value ? 1 : 0);
}
return logMaker.setSubtype(getMetricsCategory())
+ .addTaggedData(FIELD_CONTEXT, isFullQs())
.addTaggedData(FIELD_QS_POSITION, mHost.indexOf(mTileSpec));
}
+ private int isFullQs() {
+ for (Object listener : mListeners) {
+ if (TilePage.class.equals(listener.getClass())) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
public void showDetail(boolean show) {
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0).sendToTarget();
}
@@ -261,6 +289,9 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
if (changed) {
handleStateChanged();
}
+ mHandler.removeMessages(H.STALE);
+ mHandler.sendEmptyMessageDelayed(H.STALE, getStaleTimeout());
+ setListening(mStaleListener, false);
}
private void handleStateChanged() {
@@ -314,11 +345,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
handleRefreshState(null);
}
- protected abstract void setListening(boolean listening);
+ protected abstract void handleSetListening(boolean listening);
protected void handleDestroy() {
if (mListeners.size() != 0) {
- setListening(false);
+ handleSetListening(false);
}
mCallbacks.clear();
}
@@ -368,8 +399,10 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
private static final int REMOVE_CALLBACKS = 12;
private static final int REMOVE_CALLBACK = 13;
private static final int SET_LISTENING = 14;
+ private static final int STALE = 15;
- private H(Looper looper) {
+ @VisibleForTesting
+ protected H(Looper looper) {
super(looper);
}
@@ -424,8 +457,11 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
name = "handleClearState";
handleClearState();
} else if (msg.what == SET_LISTENING) {
- name = "setListening";
- setListening(msg.arg1 != 0);
+ name = "handleSetListening";
+ handleSetListening(msg.arg1 != 0);
+ } else if (msg.what == STALE) {
+ name = "handleStale";
+ handleStale();
} else {
throw new IllegalArgumentException("Unknown msg: " + msg.what);
}
@@ -439,15 +475,22 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
public static class DrawableIcon extends Icon {
protected final Drawable mDrawable;
+ protected final Drawable mInvisibleDrawable;
public DrawableIcon(Drawable drawable) {
mDrawable = drawable;
+ mInvisibleDrawable = drawable.getConstantState().newDrawable();
}
@Override
public Drawable getDrawable(Context context) {
return mDrawable;
}
+
+ @Override
+ public Drawable getInvisibleDrawable(Context context) {
+ return mInvisibleDrawable;
+ }
}
public static class DrawableIconWithRes extends DrawableIcon {
@@ -503,7 +546,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile {
}
}
- protected class AnimationIcon extends ResourceIcon {
+ protected static class AnimationIcon extends ResourceIcon {
private final int mAnimatedResId;
public AnimationIcon(int resId, int staticResId) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 2e7012e95e29..bef1aff571f3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -110,7 +110,7 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> {
}
}
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (mListening == listening) return;
mListening = listening;
if (listening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 3f419a81d36e..95504edf2e10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -55,7 +55,7 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mBatteryController.addCallback(this);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index bc6233d45a67..774f0b3dfbb4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -76,7 +76,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mController.addCallback(mCallback);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 2fc9fc7b09b0..fb396b9ddb07 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -91,9 +91,9 @@ public class CastTile extends QSTileImpl<BooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (mController == null) return;
- if (DEBUG) Log.d(TAG, "setListening " + listening);
+ if (DEBUG) Log.d(TAG, "handleSetListening " + listening);
if (listening) {
mController.addCallback(mCallback);
mKeyguard.addCallback(mCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 0e0f949ce42f..2e389ba151bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -92,7 +92,7 @@ public class CellularTile extends QSTileImpl<SignalState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mController.addCallback(mSignalCallback);
} else {
@@ -112,6 +112,9 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
protected void handleClick() {
+ if (getState().state == Tile.STATE_UNAVAILABLE) {
+ return;
+ }
if (mDataController.isMobileDataEnabled()) {
if (mKeyguardMonitor.isSecure() && !mKeyguardMonitor.canSkipBouncer()) {
mActivityStarter.postQSRunnableDismissingKeyguard(this::showDisableDialog);
@@ -183,9 +186,14 @@ public class CellularTile extends QSTileImpl<SignalState> {
state.value = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
- state.icon = new SignalIcon(cb.mobileSignalIconId);
- if (cb.airplaneModeEnabled) {
- state.state = Tile.STATE_INACTIVE;
+ if (cb.noSim) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_sim);
+ } else {
+ state.icon = new SignalIcon(cb.mobileSignalIconId);
+ }
+
+ if (cb.airplaneModeEnabled | cb.noSim) {
+ state.state = Tile.STATE_UNAVAILABLE;
} else {
state.state = Tile.STATE_ACTIVE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 40fe4844955b..b93f1c208c11 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -63,7 +63,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
mSetting.setListening(listening);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 8b62beb861ba..a1026967633f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -45,7 +45,7 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mDataSaverController.addCallback(this);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 5938749d14d2..9e265e2295c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -232,7 +232,7 @@ public class DndTile extends QSTileImpl<BooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (mListening == listening) return;
mListening = listening;
if (mListening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index e6ac90872403..f2ead1cbca94 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -54,7 +54,7 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mFlashlightController.addCallback(this);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index c17573d9189a..910b6b174062 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -74,7 +74,7 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (mListening == listening) return;
mListening = listening;
if (listening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 00cfbfa1eac7..4f4004c6efdc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -76,7 +76,7 @@ public class IntentTile extends QSTileImpl<State> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 5e663342905e..c35f5917d6cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -55,7 +55,7 @@ public class LocationTile extends QSTileImpl<BooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mController.addCallback(mCallback);
mKeyguard.addCallback(mCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 6500740761ce..b3ff4e5b890c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -51,7 +51,7 @@ public class NfcTile extends QSTileImpl<BooleanState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
mListening = listening;
if (mListening) {
mContext.registerReceiver(mNfcReceiver,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 2a127695a53e..4c2036141daf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -95,7 +95,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState>
}
@Override
- protected void setListening(boolean listening) {
+ protected void handleSetListening(boolean listening) {
mIsListening = listening;
if (listening) {
mController.setListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index fb937bd09bc2..1e00894483ac 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -62,7 +62,7 @@ public class RotationLockTile extends QSTileImpl<BooleanState> {
return new BooleanState();
}
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (mController == null) return;
if (listening) {
mController.addCallback(mCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index d6043f4fff1f..bde1c98d023c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -69,7 +69,7 @@ public class UserTile extends QSTileImpl<State> implements UserInfoController.On
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mUserInfoController.addCallback(this);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 136cf216f653..33b15121b47e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -75,7 +75,7 @@ public class WifiTile extends QSTileImpl<SignalState> {
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mController.addCallback(mSignalCallback);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 38821f6aa081..5f7d6fb41311 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -48,7 +48,7 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements
}
@Override
- public void setListening(boolean listening) {
+ public void handleSetListening(boolean listening) {
if (listening) {
mProfileController.addCallback(this);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f8448661d799..f5455568f799 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -65,6 +65,7 @@ import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
@@ -119,6 +120,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
private boolean mFinishedOnStartup;
private boolean mIgnoreAltTabRelease;
private boolean mIsVisible;
+ private boolean mRecentsStartRequested;
private Configuration mLastConfig;
// Top level views
@@ -416,6 +418,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
launchState.launchedFromHome = false;
onEnterAnimationComplete();
}
+ mRecentsStartRequested = false;
}
@Override
@@ -449,7 +452,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
* Reloads the stack views upon launching Recents.
*/
private void reloadStackView() {
-
// If the Recents component has preloaded a load plan, then use that to prevent
// reconstructing the task stack
RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -572,7 +574,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
- if (!isChangingConfigurations()) {
+ // When recents starts again before onStop, do not reset launch flags so entrance animation
+ // can run
+ if (!isChangingConfigurations() && !mRecentsStartRequested) {
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
// through SystemUI, we need to reset the config launch flags to ensure that we do not
// wait on the system to send a signal that was never queued.
@@ -718,6 +722,10 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
}
+ public final void onBusEvent(RecentsActivityStartingEvent event) {
+ mRecentsStartRequested = true;
+ }
+
public final void onBusEvent(UserInteractionEvent event) {
// Stop the fast-toggle dozer
mIterateTrigger.stopDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 71f06cbf6e64..c44cd7287625 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -205,6 +205,10 @@ public class RecentsView extends FrameLayout {
mStackButtonShadowDistance.x, mStackButtonShadowDistance.y,
mStackButtonShadowColor);
}
+ if (Recents.getConfiguration().isLowRamDevice) {
+ int bgColor = Utils.getColorAttr(mContext, R.attr.clearAllBackgroundColor);
+ mStackActionButton.setBackgroundColor(bgColor);
+ }
}
// Let's also require dark status and nav bars if the text is dark
@@ -955,8 +959,8 @@ public class RecentsView extends FrameLayout {
int left, top;
if (Recents.getConfiguration().isLowRamDevice) {
Rect windowRect = Recents.getSystemServices().getWindowRect();
- left = (windowRect.width() - mSystemInsets.left - mSystemInsets.right
- - mStackActionButton.getMeasuredWidth()) / 2;
+ int spaceLeft = windowRect.width() - mSystemInsets.left - mSystemInsets.right;
+ left = (spaceLeft - mStackActionButton.getMeasuredWidth()) / 2 + mSystemInsets.left;
top = windowRect.height() - (mStackActionButton.getMeasuredHeight()
+ mSystemInsets.bottom + mStackActionButton.getPaddingBottom() / 2);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index a633a3ebda07..8899e307bb16 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -2396,10 +2396,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
private void updateStackActionButtonVisibility() {
+ if (Recents.getConfiguration().isLowRamDevice) {
+ return;
+ }
+
// Always show the button in grid layout.
if (useGridLayout() ||
(mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
- mStack.getTaskCount() > 0 && !Recents.getConfiguration().isLowRamDevice)) {
+ mStack.getTaskCount() > 0)) {
EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
} else {
EventBus.getDefault().send(new HideStackActionButtonEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
index 52fa7b5c7186..17e6b9e3c195 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
@@ -126,7 +126,6 @@ public class TaskStackLowRamLayoutAlgorithm {
return transformOut;
}
boolean visible = true;
- int x = mPaddingLeftRight;
int y;
if (taskCount > 1) {
y = getTaskTopFromIndex(taskIndex) - percentageToScroll(stackScroll);
@@ -255,7 +254,7 @@ public class TaskStackLowRamLayoutAlgorithm {
transformOut.dimAlpha = 0f;
transformOut.viewOutlineAlpha = 1f;
transformOut.rect.set(getTaskRect());
- transformOut.rect.offset(mPaddingLeftRight, y);
+ transformOut.rect.offset(mPaddingLeftRight + mSystemInsets.left, y);
Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
transformOut.visible = visible;
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index a35310fc7d59..991c3c83cbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -16,11 +16,16 @@
package com.android.systemui.screenshot;
+import static com.android.systemui.screenshot.GlobalScreenshot.SHARING_INTENT;
+import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.admin.DevicePolicyManager;
import android.app.Notification;
import android.app.Notification.BigPictureStyle;
@@ -48,6 +53,7 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
@@ -277,14 +283,13 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- // Create a share action for the notification
- PendingIntent chooseAction = PendingIntent.getBroadcast(context, 0,
- new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Intent chooserIntent = Intent.createChooser(sharingIntent, null,
- chooseAction.getIntentSender())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
- PendingIntent shareAction = PendingIntent.getActivity(context, 0, chooserIntent,
+ // Create a share action for the notification. Note, we proxy the call to ShareReceiver
+ // because RemoteViews currently forces an activity options on the PendingIntent being
+ // launched, and since we don't want to trigger the share sheet in this case, we will
+ // start the chooser activitiy directly in ShareReceiver.
+ PendingIntent shareAction = PendingIntent.getBroadcast(context, 0,
+ new Intent(context, GlobalScreenshot.ShareReceiver.class)
+ .putExtra(SHARING_INTENT, sharingIntent),
PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
R.drawable.ic_screenshot_share,
@@ -292,7 +297,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
mNotificationBuilder.addAction(shareActionBuilder.build());
// Create a delete action for the notification
- PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
+ PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
.putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
@@ -403,6 +408,7 @@ class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
class GlobalScreenshot {
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
+ static final String SHARING_INTENT = "android:screenshot_sharing_intent";
private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
private static final int SCREENSHOT_DROP_IN_DURATION = 430;
@@ -897,6 +903,30 @@ class GlobalScreenshot {
}
/**
+ * Receiver to proxy the share intent.
+ */
+ public static class ShareReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_SCREENSHOT);
+ } catch (RemoteException e) {
+ }
+
+ Intent sharingIntent = intent.getParcelableExtra(SHARING_INTENT);
+ PendingIntent chooseAction = PendingIntent.getBroadcast(context, 0,
+ new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Intent chooserIntent = Intent.createChooser(sharingIntent, null,
+ chooseAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+ ActivityOptions opts = ActivityOptions.makeBasic();
+ opts.setDisallowEnterPictureInPictureWhileLaunching(true);
+ context.startActivityAsUser(chooserIntent, opts.toBundle(), UserHandle.CURRENT);
+ }
+ }
+
+ /**
* Removes the notification for a screenshot after a share target is chosen.
*/
public static class TargetChosenReceiver extends BroadcastReceiver {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 1ffb3b5387a3..3b23a0c0db89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -126,7 +126,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
if (info != null) {
- mAppUid = info.uid;
+ mAppUid = sbn.getUid();
mAppName = String.valueOf(pm.getApplicationLabel(info));
pkgicon = pm.getApplicationIcon(info);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 5eefe9ae0736..5557dde7a5d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -22,10 +22,12 @@ import static com.android.systemui.statusbar.phone.NotificationIconContainer.OVE
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.systemui.Interpolators;
@@ -53,6 +55,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
SystemProperties.getBoolean("debug.icon_opening_animations", true);
private static final boolean ICON_ANMATIONS_WHILE_SCROLLING
= SystemProperties.getBoolean("debug.icon_scroll_animations", true);
+ private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private ViewInvertHelper mViewInvertHelper;
private boolean mDark;
private NotificationIconContainer mShelfIcons;
@@ -305,6 +308,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
mShelfIcons.calculateIconTranslations();
mShelfIcons.applyIconStates();
+ for (int i = 0; i < mHostLayout.getChildCount(); i++) {
+ View child = mHostLayout.getChildAt(i);
+ if (!(child instanceof ExpandableNotificationRow)
+ || child.getVisibility() == GONE) {
+ continue;
+ }
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ updateIconClipAmount(row);
+ updateContinuousClipping(row);
+ }
boolean hideBackground = numViewsInShelf < 1.0f;
setHideBackground(hideBackground || backgroundForceHidden);
if (mNotGoneIndex == -1) {
@@ -312,6 +325,43 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
}
+ private void updateIconClipAmount(ExpandableNotificationRow row) {
+ float maxTop = row.getTranslationY();
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ float shelfIconPosition = getTranslationY() + icon.getTop() + icon.getTranslationY();
+ if (shelfIconPosition < maxTop) {
+ int top = (int) (maxTop - shelfIconPosition);
+ Rect clipRect = new Rect(0, top, icon.getWidth(), Math.max(top, icon.getHeight()));
+ icon.setClipBounds(clipRect);
+ } else {
+ icon.setClipBounds(null);
+ }
+ }
+
+ private void updateContinuousClipping(final ExpandableNotificationRow row) {
+ StatusBarIconView icon = row.getEntry().expandedIcon;
+ boolean needsContinuousClipping = ViewState.isAnimatingY(icon);
+ boolean isContinuousClipping = icon.getTag(TAG_CONTINUOUS_CLIPPING) != null;
+ if (needsContinuousClipping && !isContinuousClipping) {
+ ViewTreeObserver.OnPreDrawListener predrawListener =
+ new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ boolean animatingY = ViewState.isAnimatingY(icon);
+ if (!animatingY || !icon.isAttachedToWindow()) {
+ icon.getViewTreeObserver().removeOnPreDrawListener(this);
+ icon.setTag(TAG_CONTINUOUS_CLIPPING, null);
+ return true;
+ }
+ updateIconClipAmount(row);
+ return true;
+ }
+ };
+ icon.getViewTreeObserver().addOnPreDrawListener(predrawListener);
+ icon.setTag(TAG_CONTINUOUS_CLIPPING, predrawListener);
+ }
+ }
+
private void updateNotificationClipHeight(ExpandableNotificationRow row,
float notificationClipEnd) {
float viewEnd = row.getTranslationY() + row.getActualHeight();
@@ -330,6 +380,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
}
+ @Override
+ public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+ int outlineTranslation) {
+ if (!mHasItemsInStableShelf) {
+ shadowIntensity = 0.0f;
+ }
+ super.setFakeShadowIntensity(shadowIntensity, outlineAlpha, shadowYEnd, outlineTranslation);
+ }
+
/**
* @return the icon amount how much this notification is in the shelf;
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 25f3e25f2051..759d2cf2f8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.phone.SignalDrawable;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.policy.IconLogger;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -65,6 +66,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController
private static final String SLOT_MOBILE = "mobile";
private static final String SLOT_WIFI = "wifi";
private static final String SLOT_ETHERNET = "ethernet";
+ private static final String SLOT_VPN = "vpn";
private final NetworkController mNetworkController;
private final SecurityController mSecurityController;
@@ -117,6 +119,8 @@ public class SignalClusterView extends LinearLayout implements NetworkController
private boolean mActivityEnabled;
private boolean mForceBlockWifi;
+ private final IconLogger mIconLogger = Dependency.get(IconLogger.class);
+
public SignalClusterView(Context context) {
this(context, null);
}
@@ -447,14 +451,15 @@ public class SignalClusterView extends LinearLayout implements NetworkController
private void apply() {
if (mWifiGroup == null) return;
- mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
if (mVpnVisible) {
if (mLastVpnIconId != mVpnIconId) {
setIconForView(mVpn, mVpnIconId);
mLastVpnIconId = mVpnIconId;
}
+ mIconLogger.onIconShown(SLOT_VPN);
mVpn.setVisibility(View.VISIBLE);
} else {
+ mIconLogger.onIconHidden(SLOT_VPN);
mVpn.setVisibility(View.GONE);
}
if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
@@ -466,8 +471,10 @@ public class SignalClusterView extends LinearLayout implements NetworkController
mLastEthernetIconId = mEthernetIconId;
}
mEthernetGroup.setContentDescription(mEthernetDescription);
+ mIconLogger.onIconShown(SLOT_ETHERNET);
mEthernetGroup.setVisibility(View.VISIBLE);
} else {
+ mIconLogger.onIconHidden(SLOT_ETHERNET);
mEthernetGroup.setVisibility(View.GONE);
}
@@ -481,9 +488,11 @@ public class SignalClusterView extends LinearLayout implements NetworkController
setIconForView(mWifiDark, mWifiStrengthId);
mLastWifiStrengthId = mWifiStrengthId;
}
+ mIconLogger.onIconShown(SLOT_WIFI);
mWifiGroup.setContentDescription(mWifiDescription);
mWifiGroup.setVisibility(View.VISIBLE);
} else {
+ mIconLogger.onIconHidden(SLOT_WIFI);
mWifiGroup.setVisibility(View.GONE);
}
@@ -505,6 +514,11 @@ public class SignalClusterView extends LinearLayout implements NetworkController
}
}
}
+ if (anyMobileVisible) {
+ mIconLogger.onIconShown(SLOT_MOBILE);
+ } else {
+ mIconLogger.onIconHidden(SLOT_MOBILE);
+ }
if (mIsAirplaneMode) {
if (mLastAirplaneIconId != mAirplaneIconId) {
@@ -512,8 +526,10 @@ public class SignalClusterView extends LinearLayout implements NetworkController
mLastAirplaneIconId = mAirplaneIconId;
}
mAirplane.setContentDescription(mAirplaneContentDescription);
+ mIconLogger.onIconShown(SLOT_AIRPLANE);
mAirplane.setVisibility(View.VISIBLE);
} else {
+ mIconLogger.onIconHidden(SLOT_AIRPLANE);
mAirplane.setVisibility(View.GONE);
}
@@ -529,7 +545,13 @@ public class SignalClusterView extends LinearLayout implements NetworkController
mWifiSignalSpacer.setVisibility(View.GONE);
}
- mNoSimsCombo.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
+ if (mNoSimsVisible) {
+ mIconLogger.onIconShown(SLOT_MOBILE);
+ mNoSimsCombo.setVisibility(View.VISIBLE);
+ } else {
+ mIconLogger.onIconHidden(SLOT_MOBILE);
+ mNoSimsCombo.setVisibility(View.GONE);
+ }
boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
|| anyMobileVisible || mVpnVisible || mEthernetVisible;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index fcc982ea3fb0..b95b8a392c86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -114,7 +114,6 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mIcon = mView.findViewById(com.android.internal.R.id.icon);
mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
- mExpandButton.setLabeledBy(mRow);
mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
mColor = resolveColor(mExpandButton);
mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index f379a4636623..1f44abea755a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -41,8 +41,6 @@ public class BarTransitions {
private static final boolean DEBUG = false;
private static final boolean DEBUG_COLORS = false;
- public static final boolean HIGH_END = ActivityManager.isHighEndGfx();
-
public static final int MODE_OPAQUE = 0;
public static final int MODE_SEMI_TRANSPARENT = 1;
public static final int MODE_TRANSLUCENT = 2;
@@ -66,9 +64,7 @@ public class BarTransitions {
mTag = "BarTransitions." + view.getClass().getSimpleName();
mView = view;
mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
- if (HIGH_END) {
- mView.setBackground(mBarBackground);
- }
+ mView.setBackground(mBarBackground);
}
public int getMode() {
@@ -89,7 +85,7 @@ public class BarTransitions {
public boolean isAlwaysOpaque() {
// Low-end devices do not support translucent modes, fallback to opaque
- return !HIGH_END || mAlwaysOpaque;
+ return mAlwaysOpaque;
}
public void transitionTo(int mode, boolean animate) {
@@ -109,9 +105,7 @@ public class BarTransitions {
}
protected void onTransition(int oldMode, int newMode, boolean animate) {
- if (HIGH_END) {
- applyModeBackground(oldMode, newMode, animate);
- }
+ applyModeBackground(oldMode, newMode, animate);
}
protected void applyModeBackground(int oldMode, int newMode, boolean animate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 8c923cbcde0b..2c3f452e8274 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -161,10 +161,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
showNotificationIconArea(animate);
}
}
- if (!BarTransitions.HIGH_END) {
- int mask = DISABLE_NOTIFICATION_ICONS | DISABLE_SYSTEM_INFO;
- getView().setVisibility((mDisabled1 & mask) == mask ? View.GONE : View.VISIBLE);
- }
}
protected int adjustDisableFlags(int state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 316d229e4f1a..00cb5329d2e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -85,6 +85,11 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
public static final int MODE_DISMISS_BOUNCER = 6;
/**
+ * Mode in which fingerprint wakes and unlocks the device from a dream.
+ */
+ public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 7;
+
+ /**
* How much faster we collapse the lockscreen when authenticating with fingerprint.
*/
private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
@@ -230,16 +235,19 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
}
Trace.endSection();
break;
+ case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
case MODE_WAKE_AND_UNLOCK_PULSING:
case MODE_WAKE_AND_UNLOCK:
if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
true /* allowEnterAnimation */);
- } else {
+ } else if (mMode == MODE_WAKE_AND_UNLOCK){
Trace.beginSection("MODE_WAKE_AND_UNLOCK");
-
mDozeScrimController.abortDoze();
+ } else {
+ Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
+ mUpdateMonitor.awakenFromDream();
}
mStatusBarWindowManager.setStatusBarFocusable(false);
mKeyguardViewMediator.onWakeAndUnlocking();
@@ -299,6 +307,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
private int calculateMode() {
boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
+ boolean deviceDreaming = mUpdateMonitor.isDreaming();
if (!mUpdateMonitor.isDeviceInteractive()) {
if (!mStatusBarKeyguardViewManager.isShowing()) {
@@ -311,6 +320,9 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback {
return MODE_SHOW_BOUNCER;
}
}
+ if (unlockingAllowed && deviceDreaming) {
+ return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
+ }
if (mStatusBarKeyguardViewManager.isShowing()) {
if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
return MODE_DISMISS_BOUNCER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index fd95cc4adc1d..165ed78996b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -27,6 +27,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.widget.LockPatternUtils;
@@ -247,12 +248,16 @@ public class KeyguardBouncer {
removeView();
mHandler.removeCallbacks(mRemoveViewRunnable);
mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
- mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
+ mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
mKeyguardView.setLockPatternUtils(mLockPatternUtils);
mKeyguardView.setViewMediatorCallback(mCallback);
mContainer.addView(mRoot, mContainer.getChildCount());
mRoot.setVisibility(View.INVISIBLE);
- mRoot.dispatchApplyWindowInsets(mRoot.getRootWindowInsets());
+
+ final WindowInsets rootInsets = mRoot.getRootWindowInsets();
+ if (rootInsets != null) {
+ mRoot.dispatchApplyWindowInsets(rootInsets);
+ }
}
protected void removeView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 917a56fbc99d..533771a31d0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -72,6 +72,7 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private final Rect mLastFullscreenBounds = new Rect();
private final Rect mLastDockedBounds = new Rect();
+ private boolean mQsCustomizing;
public LightBarController(Context ctx) {
mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
@@ -129,7 +130,8 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
mHasLightNavigationBar = isLight(vis, navigationBarMode,
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
mNavigationLight = mHasLightNavigationBar
- && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim);
+ && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim)
+ && !mQsCustomizing;
if (mNavigationLight != last) {
updateNavigation();
}
@@ -146,6 +148,12 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
mLastNavigationBarMode);
}
+ public void setQsCustomizing(boolean customizing) {
+ if (mQsCustomizing == customizing) return;
+ mQsCustomizing = customizing;
+ reevaluate();
+ }
+
public void setScrimAlpha(float alpha) {
mScrimAlpha = alpha;
boolean belowThresholdBefore = mScrimAlphaBelowThreshold;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index d3a6280212cd..b0ac6ecae5bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -127,11 +127,6 @@ public class LightBarTransitionsController implements Dumpable, Callbacks {
}
public void setIconsDark(boolean dark, boolean animate) {
- if (!BarTransitions.HIGH_END) {
- setIconTintInternal(0.0f);
- mNextDarkIntensity = 0.0f;
- return;
- }
if (!animate) {
setIconTintInternal(dark ? 1.0f : 0.0f);
mNextDarkIntensity = dark ? 1.0f : 0.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 004a6043ff94..1452e0c7a0b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -87,7 +87,8 @@ public class NearestTouchFrame extends FrameLayout {
if (mTouchingChild != null) {
event.offsetLocation(mTouchingChild.getWidth() / 2 - event.getX(),
mTouchingChild.getHeight() / 2 - event.getY());
- return mTouchingChild.dispatchTouchEvent(event);
+ return mTouchingChild.getVisibility() == VISIBLE
+ && mTouchingChild.dispatchTouchEvent(event);
}
}
return super.onTouchEvent(event);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 0575e21d6623..00ba1f293b8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -300,6 +300,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// Should match the values in PhoneWindowManager
public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
+ static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
private static final String BANNER_ACTION_CANCEL =
"com.android.systemui.statusbar.banner_action_cancel";
@@ -1124,7 +1125,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
});
- mLightBarController = new LightBarController(context);
+ mLightBarController = Dependency.get(LightBarController.class);
if (mNavigationBar != null) {
mNavigationBar.setLightBarController(mLightBarController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 70b92ade1bbc..68f8e065a429 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -20,12 +20,8 @@ import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.UserHandle;
-import android.text.TextUtils;
import android.util.ArraySet;
-import android.view.Gravity;
-import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageView;
import android.widget.LinearLayout;
import com.android.internal.statusbar.StatusBarIcon;
@@ -38,6 +34,7 @@ import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.IconLogger;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -61,6 +58,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
private final ArraySet<String> mIconBlacklist = new ArraySet<>();
+ private final IconLogger mIconLogger = Dependency.get(IconLogger.class);
public StatusBarIconControllerImpl(Context context) {
super(context.getResources().getStringArray(
@@ -122,6 +120,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
int viewIndex = getViewIndex(index);
boolean blocked = mIconBlacklist.contains(slot);
+ mIconLogger.onIconVisibility(getSlot(index), icon.visible);
mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, icon));
}
@@ -174,6 +173,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
if (getIcon(index) == null) {
return;
}
+ mIconLogger.onIconHidden(getSlot(index));
super.removeIcon(index);
int viewIndex = getViewIndex(index);
mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
@@ -196,6 +196,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
private void handleSet(int index, StatusBarIcon icon) {
int viewIndex = getViewIndex(index);
+ mIconLogger.onIconVisibility(getSlot(index), icon.visible);
mIconGroups.forEach(l -> l.onSetIcon(viewIndex, icon));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 1411a544c346..f9c2130e4e81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -159,6 +159,11 @@ public class UnlockMethodCache {
public void onScreenTurnedOff() {
update(false /* updateAlways */);
}
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ update(false /* updateAlways */);
+ }
};
public boolean isTrustManaged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index f0af77de6a22..4c92d01eae4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -24,7 +24,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.os.Bundle;
@@ -193,8 +192,9 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
}
private void updateClockVisibility() {
- int visibility = (mClockVisibleByPolicy && mClockVisibleByUser)
- ? View.VISIBLE : View.GONE;
+ boolean visible = mClockVisibleByPolicy && mClockVisibleByUser;
+ Dependency.get(IconLogger.class).onIconVisibility("clock", visible);
+ int visibility = visible ? View.VISIBLE : View.GONE;
setVisibility(visibility);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLogger.java
new file mode 100644
index 000000000000..710e1df61404
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLogger.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+public interface IconLogger {
+
+ void onIconShown(String tag);
+ void onIconHidden(String tag);
+
+ default void onIconVisibility(String tag, boolean visible) {
+ if (visible) {
+ onIconShown(tag);
+ } else {
+ onIconHidden(tag);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
new file mode 100644
index 000000000000..0c201c3d8660
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NUM_STATUS_ICONS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.STATUS_BAR_ICONS_CHANGED;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
+
+import android.content.Context;
+import android.metrics.LogMaker;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.VisibleForTesting;
+import android.util.ArraySet;
+
+import com.android.internal.logging.MetricsLogger;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class IconLoggerImpl implements IconLogger {
+
+ // Minimum ms between log statements.
+ // NonFinalForTesting
+ @VisibleForTesting
+ protected static long MIN_LOG_INTERVAL = 1000;
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final MetricsLogger mLogger;
+ private final ArraySet<String> mIcons = new ArraySet<>();
+ private final List<String> mIconIndex;
+ private long mLastLog = System.currentTimeMillis();
+
+ public IconLoggerImpl(Context context, Looper bgLooper, MetricsLogger logger) {
+ mContext = context;
+ mHandler = new Handler(bgLooper);
+ mLogger = logger;
+ String[] icons = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_statusBarIcons);
+ mIconIndex = Arrays.asList(icons);
+ doLog();
+ }
+
+ @Override
+ public void onIconShown(String tag) {
+ synchronized (mIcons) {
+ if (mIcons.contains(tag)) return;
+ mIcons.add(tag);
+ }
+ if (!mHandler.hasCallbacks(mLog)) {
+ mHandler.postDelayed(mLog, MIN_LOG_INTERVAL);
+ }
+ }
+
+ @Override
+ public void onIconHidden(String tag) {
+ synchronized (mIcons) {
+ if (!mIcons.contains(tag)) return;
+ mIcons.remove(tag);
+ }
+ if (!mHandler.hasCallbacks(mLog)) {
+ mHandler.postDelayed(mLog, MIN_LOG_INTERVAL);
+ }
+ }
+
+ private void doLog() {
+ long time = System.currentTimeMillis();
+ long timeSinceLastLog = time - mLastLog;
+ mLastLog = time;
+
+ ArraySet<String> icons;
+ synchronized (mIcons) {
+ icons = new ArraySet<>(mIcons);
+ }
+ mLogger.write(new LogMaker(STATUS_BAR_ICONS_CHANGED)
+ .setType(TYPE_ACTION)
+ .setLatency(timeSinceLastLog)
+ .addTaggedData(FIELD_NUM_STATUS_ICONS, icons.size())
+ .addTaggedData(FIELD_STATUS_ICONS, getBitField(icons)));
+ }
+
+ private int getBitField(ArraySet<String> icons) {
+ int iconsVisible = 0;
+ for (String icon : icons) {
+ int index = mIconIndex.indexOf(icon);
+ if (index >= 0) {
+ iconsVisible |= (1 << index);
+ }
+ }
+ return iconsVisible;
+ }
+
+ private final Runnable mLog = this::doLog;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 34a03bf36c47..652f8bb646d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -182,6 +182,7 @@ public class MobileSignalController extends SignalController<
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_TD_SCDMA, TelephonyIcons.THREE_G);
if (!mConfig.showAtLeast3G) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4e592dbed322..75532d9e09be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -23,14 +23,12 @@ import android.animation.PropertyValuesHolder;
import android.animation.TimeAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.ColorInt;
import android.annotation.FloatRange;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
@@ -1083,6 +1081,20 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public ExpandableView getChildAtPosition(float touchX, float touchY) {
+ return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
+
+ }
+
+ /**
+ * Get the child at a certain screen location.
+ *
+ * @param touchX the x coordinate
+ * @param touchY the y coordinate
+ * @param requireMinHeight Whether a minimum height is required for a child to be returned.
+ * @return the child at the given location.
+ */
+ private ExpandableView getChildAtPosition(float touchX, float touchY,
+ boolean requireMinHeight) {
// find the view under the pointer, accounting for GONE views
final int count = getChildCount();
for (int childIdx = 0; childIdx < count; childIdx++) {
@@ -1101,7 +1113,7 @@ public class NotificationStackScrollLayout extends ViewGroup
int left = 0;
int right = getWidth();
- if (bottom - top >= mMinInteractionHeight
+ if ((bottom - top >= mMinInteractionHeight || !requireMinHeight)
&& touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
if (slidingChild instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
@@ -3220,7 +3232,7 @@ public class NotificationStackScrollLayout extends ViewGroup
case MotionEvent.ACTION_DOWN: {
final int y = (int) ev.getY();
mScrolledToTopOnFirstDown = isScrolledToTop();
- if (getChildAtPosition(ev.getX(), y) == null) {
+ if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) {
setIsBeingDragged(false);
recycleVelocityTracker();
break;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 66d00dd6c5c6..65d969932ef5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -54,6 +54,7 @@ public abstract class SysuiTestCase {
@Before
public void SysuiSetup() throws Exception {
System.setProperty("dexmaker.share_classloader", "true");
+ mContext.setTheme(R.style.Theme_SystemUI);
SystemUIFactory.createFromConfig(mContext);
mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 0500a546856d..004ff29f7eac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -21,13 +21,19 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_VALUE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static java.lang.Thread.sleep;
+
import android.content.Intent;
import android.metrics.LogMaker;
import android.support.test.filters.SmallTest;
@@ -66,10 +72,10 @@ public class QSTileImplTest extends SysuiTestCase {
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
mHost = mock(QSTileHost.class);
when(mHost.indexOf(spec)).thenReturn(POSITION);
- mTestableLooper.runWithLooper(() -> {
- mTile = new TileImpl(mHost);
- mTile.setTileSpec(spec);
- });
+
+ mTile = spy(new TileImpl(mHost));
+ mTile.mHandler = mTile.new H(mTestableLooper.getLooper());
+ mTile.setTileSpec(spec);
}
@Test
@@ -94,12 +100,38 @@ public class QSTileImplTest extends SysuiTestCase {
public void testPopulate() {
LogMaker maker = mock(LogMaker.class);
when(maker.setSubtype(anyInt())).thenReturn(maker);
+ when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
mTile.getState().value = true;
mTile.populate(maker);
verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
}
+ @Test
+ public void testStaleTimeout() throws InterruptedException {
+ when(mTile.getStaleTimeout()).thenReturn(5l);
+ clearInvocations(mTile);
+
+ mTile.handleRefreshState(null);
+ mTestableLooper.processAllMessages();
+ verify(mTile, never()).handleStale();
+
+ sleep(10);
+ mTestableLooper.processAllMessages();
+ verify(mTile).handleStale();
+ }
+
+ @Test
+ public void testStaleListening() {
+ mTile.handleStale();
+ mTestableLooper.processAllMessages();
+ verify(mTile).handleSetListening(eq(true));
+
+ mTile.handleRefreshState(null);
+ mTestableLooper.processAllMessages();
+ verify(mTile).handleSetListening(eq(false));
+ }
+
private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
private final int mCategory;
@@ -164,7 +196,7 @@ public class QSTileImplTest extends SysuiTestCase {
}
@Override
- protected void setListening(boolean listening) {
+ protected void handleSetListening(boolean listening) {
}
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 b6827eaa13bb..88fa659cd0e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -121,7 +121,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mDefaultNotificationChannel = new NotificationChannel(
NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
NotificationManager.IMPORTANCE_LOW);
- mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, 0, 0,
+ mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
index 54a96cd76715..83a2883c3099 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -184,7 +184,9 @@ public class NotificationInflaterTest extends SysuiTestCase {
countDownLatch.await();
}
+ /* Cancelling requires us to be on the UI thread otherwise we might have a race */
@Test
+ @UiThreadTest
public void testSupersedesExistingTask() throws Exception {
mNotificationInflater.inflateNotificationViews();
mNotificationInflater.setIsLowPriority(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
new file mode 100644
index 000000000000..40512205a8f8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.UiThreadTest;
+import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KeyguardBouncerTest extends SysuiTestCase {
+
+ @UiThreadTest
+ @Test
+ public void inflateDetached() {
+ final ViewGroup container = new FrameLayout(getContext());
+ final KeyguardBouncer bouncer = new KeyguardBouncer(getContext(),
+ mock(ViewMediatorCallback.class), mock(LockPatternUtils.class), container, mock(
+ DismissCallbackRegistry.class));
+
+ // Detached bouncer should still be able to be inflated
+ bouncer.inflateView();
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
index ed1491d31294..500d62012803 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
@@ -71,6 +71,24 @@ public class NearestTouchFrameTest extends SysuiTestCase {
}
@Test
+ public void testInvisibleViews() {
+ View left = mockViewAt(0, 0, 10, 10);
+ View right = mockViewAt(20, 0, 10, 10);
+ when(left.getVisibility()).thenReturn(View.INVISIBLE);
+
+ mNearestTouchFrame.addView(left);
+ mNearestTouchFrame.addView(right);
+ mNearestTouchFrame.onMeasure(0, 0);
+
+ MotionEvent ev = MotionEvent.obtain(0, 0, 0,
+ 12 /* x */, 5 /* y */, 0);
+ mNearestTouchFrame.onTouchEvent(ev);
+ verify(left, never()).onTouchEvent(eq(ev));
+ verify(right, never()).onTouchEvent(eq(ev));
+ ev.recycle();
+ }
+
+ @Test
public void testHorizontalSelection_Left() {
View left = mockViewAt(0, 0, 10, 10);
View right = mockViewAt(20, 0, 10, 10);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
index a915cb20534a..b22a6468f5fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
@@ -27,7 +27,6 @@ import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import android.util.Log;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
@@ -145,7 +144,6 @@ public class ExtensionControllerImplTest extends SysuiTestCase {
@Test
@RunWithLooper
public void testSortOrder() {
- Log.d("TestTest", "Config " + mContext.getResources().getConfiguration().uiMode);
Object def = new Object();
Object uiMode = new Object();
Object tuner = new Object();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java
new file mode 100644
index 000000000000..ec994a1a5650
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NUM_STATUS_ICONS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
+ .NOTIFICATION_SINCE_CREATE_MILLIS;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import static java.lang.Thread.sleep;
+
+import android.metrics.LogMaker;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.MessageHandler;
+import android.testing.TestableLooper.RunWithLooper;
+import android.util.Log;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatcher;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class IconLoggerImplTest extends SysuiTestCase {
+
+ private MetricsLogger mMetricsLogger;
+ private IconLoggerImpl mIconLogger;
+ private TestableLooper mTestableLooper;
+ private MessageHandler mMessageHandler;
+
+ @Before
+ public void setup() {
+ IconLoggerImpl.MIN_LOG_INTERVAL = 5; // Low interval for testing
+ mMetricsLogger = mock(MetricsLogger.class);
+ mTestableLooper = TestableLooper.get(this);
+ mMessageHandler = mock(MessageHandler.class);
+ mTestableLooper.setMessageHandler(mMessageHandler);
+ String[] iconArray = new String[] {
+ "test_icon_1",
+ "test_icon_2",
+ };
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.array.config_statusBarIcons, iconArray);
+ mIconLogger = new IconLoggerImpl(mContext, mTestableLooper.getLooper(), mMetricsLogger);
+ when(mMessageHandler.onMessageHandled(any())).thenReturn(true);
+ clearInvocations(mMetricsLogger);
+ }
+
+ @Test
+ public void testIconShown() throws InterruptedException {
+ // Should only get one message, for the same icon shown twice.
+ mIconLogger.onIconShown("test_icon_2");
+ mIconLogger.onIconShown("test_icon_2");
+
+ // There should be some delay before execute.
+ mTestableLooper.processAllMessages();
+ verify(mMessageHandler, never()).onMessageHandled(any());
+
+ sleep(10);
+ mTestableLooper.processAllMessages();
+ verify(mMessageHandler, times(1)).onMessageHandled(any());
+ }
+
+ @Test
+ public void testIconHidden() throws InterruptedException {
+ // Add the icon so that it can be removed.
+ mIconLogger.onIconShown("test_icon_2");
+ sleep(10);
+ mTestableLooper.processAllMessages();
+ clearInvocations(mMessageHandler);
+
+ // Should only get one message, for the same icon shown twice.
+ mIconLogger.onIconHidden("test_icon_2");
+ mIconLogger.onIconHidden("test_icon_2");
+
+ // There should be some delay before execute.
+ mTestableLooper.processAllMessages();
+ verify(mMessageHandler, never()).onMessageHandled(any());
+
+ sleep(10);
+ mTestableLooper.processAllMessages();
+ verify(mMessageHandler, times(1)).onMessageHandled(any());
+ }
+
+ @Test
+ public void testLog() throws InterruptedException {
+ mIconLogger.onIconShown("test_icon_2");
+ sleep(10);
+ mTestableLooper.processAllMessages();
+
+ verify(mMetricsLogger).write(argThat(maker -> {
+ if (IconLoggerImpl.MIN_LOG_INTERVAL >
+ (long) maker.getTaggedData(NOTIFICATION_SINCE_CREATE_MILLIS)) {
+ Log.e("IconLoggerImplTest", "Invalid latency "
+ + maker.getTaggedData(NOTIFICATION_SINCE_CREATE_MILLIS));
+ return false;
+ }
+ if (1 != (int) maker.getTaggedData(FIELD_NUM_STATUS_ICONS)) {
+ Log.e("IconLoggerImplTest", "Invalid icon count "
+ + maker.getTaggedData(FIELD_NUM_STATUS_ICONS));
+ return false;
+ }
+ return true;
+ }));
+ }
+
+ @Test
+ public void testBitField() throws InterruptedException {
+ mIconLogger.onIconShown("test_icon_2");
+ sleep(10);
+ mTestableLooper.processAllMessages();
+
+ verify(mMetricsLogger).write(argThat(maker -> {
+ if ((1 << 1) != (int) maker.getTaggedData(FIELD_STATUS_ICONS)) {
+ Log.e("IconLoggerImplTest", "Invalid bitfield " + Integer.toHexString(
+ (Integer) maker.getTaggedData(FIELD_NUM_STATUS_ICONS)));
+ return false;
+ }
+ return true;
+ }));
+
+ mIconLogger.onIconShown("test_icon_1");
+ sleep(10);
+ mTestableLooper.processAllMessages();
+
+ verify(mMetricsLogger).write(argThat(maker -> {
+ if ((1 << 1 | 1 << 0) != (int) maker.getTaggedData(FIELD_STATUS_ICONS)) {
+ Log.e("IconLoggerImplTest", "Invalid bitfield " + Integer.toHexString(
+ (Integer) maker.getTaggedData(FIELD_NUM_STATUS_ICONS)));
+ return false;
+ }
+ return true;
+ }));
+
+ mIconLogger.onIconHidden("test_icon_2");
+ sleep(10);
+ mTestableLooper.processAllMessages();
+
+ verify(mMetricsLogger).write(argThat(maker -> {
+ if ((1 << 0) != (int) maker.getTaggedData(FIELD_STATUS_ICONS)) {
+ Log.e("IconLoggerImplTest", "Invalid bitfield " + Integer.toHexString(
+ (Integer) maker.getTaggedData(FIELD_STATUS_ICONS)));
+ return false;
+ }
+ return true;
+ }));
+ }
+}
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml b/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml
new file mode 100644
index 000000000000..c56382e6047f
--- /dev/null
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- I really don't want to define this, but the View that uses this asset uses both the
+ light and dark accent colors. -->
+ <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
+</selector>