Merge "Reset statsd and correctly record the dump reason when system server restarts/crashes." into pi-dev
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 93875cd..e5bde0d 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -151,7 +151,8 @@
}
// ================================================================================
-Section::Section(int i, const int64_t timeoutMs) : id(i), timeoutMs(timeoutMs) {}
+Section::Section(int i, int64_t timeoutMs, bool deviceSpecific)
+ : id(i), timeoutMs(timeoutMs), deviceSpecific(deviceSpecific) {}
Section::~Section() {}
@@ -236,8 +237,9 @@
// ================================================================================
static inline bool isSysfs(const char* filename) { return strncmp(filename, "/sys/", 5) == 0; }
-FileSection::FileSection(int id, const char* filename, const int64_t timeoutMs)
- : Section(id, timeoutMs), mFilename(filename) {
+FileSection::FileSection(int id, const char* filename, const bool deviceSpecific,
+ const int64_t timeoutMs)
+ : Section(id, timeoutMs, deviceSpecific), mFilename(filename) {
name = filename;
mIsSysfs = isSysfs(filename);
}
@@ -250,7 +252,7 @@
unique_fd fd(open(mFilename, O_RDONLY | O_CLOEXEC));
if (fd.get() == -1) {
ALOGW("FileSection '%s' failed to open file", this->name.string());
- return -errno;
+ return this->deviceSpecific ? NO_ERROR : -errno;
}
FdBuffer buffer;
@@ -902,11 +904,16 @@
// Read from the pipe concurrently to avoid blocking the child.
FdBuffer buffer;
err = buffer.readFully(dumpPipe.readFd().get());
+ // Wait on the child to avoid it becoming a zombie process.
+ status_t cStatus = wait_child(child);
if (err != NO_ERROR) {
ALOGW("TombstoneSection '%s' failed to read stack dump: %d", this->name.string(), err);
dumpPipe.readFd().reset();
break;
}
+ if (cStatus != NO_ERROR) {
+ ALOGE("TombstoneSection '%s' child had an issue: %s\n", this->name.string(), strerror(-cStatus));
+ }
auto dump = std::make_unique<char[]>(buffer.size());
auto iterator = buffer.data();
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 20ecdb1..577892e 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -40,9 +40,10 @@
public:
const int id;
const int64_t timeoutMs; // each section must have a timeout
+ const bool deviceSpecific;
String8 name;
- Section(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+ Section(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS, bool deviceSpecific = false);
virtual ~Section();
virtual status_t Execute(ReportRequestSet* requests) const = 0;
@@ -75,7 +76,8 @@
*/
class FileSection : public Section {
public:
- FileSection(int id, const char* filename, const int64_t timeoutMs = 5000 /* 5 seconds */);
+ FileSection(int id, const char* filename, bool deviceSpecific = false,
+ int64_t timeoutMs = 5000 /* 5 seconds */);
virtual ~FileSection();
virtual status_t Execute(ReportRequestSet* requests) const;
@@ -105,7 +107,7 @@
*/
class WorkerThreadSection : public Section {
public:
- WorkerThreadSection(int id, const int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
+ WorkerThreadSection(int id, int64_t timeoutMs = REMOTE_CALL_TIMEOUT_MS);
virtual ~WorkerThreadSection();
virtual status_t Execute(ReportRequestSet* requests) const;
@@ -118,7 +120,7 @@
*/
class CommandSection : public Section {
public:
- CommandSection(int id, const int64_t timeoutMs, const char* command, ...);
+ CommandSection(int id, int64_t timeoutMs, const char* command, ...);
CommandSection(int id, const char* command, ...);
@@ -168,7 +170,7 @@
*/
class TombstoneSection : public WorkerThreadSection {
public:
- TombstoneSection(int id, const char* type, const int64_t timeoutMs = 30000 /* 30 seconds */);
+ TombstoneSection(int id, const char* type, int64_t timeoutMs = 30000 /* 30 seconds */);
virtual ~TombstoneSection();
virtual status_t BlockingCall(int pipeWriteFd) const;
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index 33f5206..3c338b3 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -143,8 +143,16 @@
EXPECT_THAT(GetCapturedStdout(), StrEq("\xa\vatadtsetmai"));
}
+TEST_F(SectionTest, FileSectionNotExist) {
+ FileSection fs1(NOOP_PARSER, "notexist", false, QUICK_TIMEOUT_MS);
+ ASSERT_EQ(NAME_NOT_FOUND, fs1.Execute(&requests));
+
+ FileSection fs2(NOOP_PARSER, "notexist", true, QUICK_TIMEOUT_MS);
+ ASSERT_EQ(NO_ERROR, fs2.Execute(&requests));
+}
+
TEST_F(SectionTest, FileSectionTimeout) {
- FileSection fs(TIMEOUT_PARSER, tf.path, QUICK_TIMEOUT_MS);
+ FileSection fs(TIMEOUT_PARSER, tf.path, false, QUICK_TIMEOUT_MS);
ASSERT_EQ(NO_ERROR, fs.Execute(&requests));
ASSERT_TRUE(requests.sectionStats(TIMEOUT_PARSER)->timed_out());
}
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index d557913..763d49b 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "statslog.h"
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp
index c8e406f..8d73699 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.cpp
+++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "anomaly/AlarmTracker.h"
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index 3f69a2c..ee9e9c0 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include <android/os/IIncidentManager.h>
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 5ff8082..df08181 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "MetricProducer.h"
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 9ca4daa..bf0f720 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define DEBUG true // STOPSHIP if true
+#define DEBUG false // STOPSHIP if true
#include "Log.h"
#include "MetricsManager.h"
#include "statslog.h"
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 1c18f67..6e4b2c8 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#define DEBUG true
+#define DEBUG false
#include "Log.h"
#include "IncidentdReporter.h"
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 1abb94c..7bc997d 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -211,6 +211,7 @@
Landroid/app/ApplicationPackageManager;->mPM:Landroid/content/pm/IPackageManager;
Landroid/app/ApplicationPackageManager;->shouldShowRequestPermissionRationale(Ljava/lang/String;)Z
Landroid/app/AppOpsManager$OpEntry;->getDuration()I
+Landroid/app/AppOpsManager$OpEntry;->getMode()I
Landroid/app/AppOpsManager$OpEntry;->getRejectTime()J
Landroid/app/AppOpsManager;->checkOp(IILjava/lang/String;)I
Landroid/app/AppOpsManager;->checkOpNoThrow(IILjava/lang/String;)I
@@ -285,6 +286,7 @@
Landroid/app/DownloadManager;->setAccessFilename(Z)V
Landroid/app/Fragment;->mChildFragmentManager:Landroid/app/FragmentManagerImpl;
Landroid/app/Fragment;->mWho:Ljava/lang/String;
+Landroid/app/FragmentManagerImpl;->loadAnimator(Landroid/app/Fragment;IZI)Landroid/animation/Animator;
Landroid/app/FragmentManagerImpl;->mAdded:Ljava/util/ArrayList;
Landroid/app/FragmentManagerImpl;->mStateSaved:Z
Landroid/app/FragmentManagerImpl;->noteStateNotSaved()V
@@ -302,6 +304,7 @@
Landroid/app/IActivityManager;->getConfiguration()Landroid/content/res/Configuration;
Landroid/app/IActivityManager;->getIntentSender(ILjava/lang/String;Landroid/os/IBinder;Ljava/lang/String;I[Landroid/content/Intent;[Ljava/lang/String;ILandroid/os/Bundle;I)Landroid/content/IIntentSender;
Landroid/app/IActivityManager;->getLaunchedFromPackage(Landroid/os/IBinder;)Ljava/lang/String;
+Landroid/app/IActivityManager;->getPackageProcessState(Ljava/lang/String;Ljava/lang/String;)I
Landroid/app/IActivityManager;->getProviderMimeType(Landroid/net/Uri;I)Ljava/lang/String;
Landroid/app/IActivityManager;->getTaskForActivity(Landroid/os/IBinder;Z)I
Landroid/app/IActivityManager;->moveActivityTaskToBack(Landroid/os/IBinder;Z)Z
@@ -695,6 +698,7 @@
Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
+Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -767,6 +771,7 @@
Landroid/content/pm/PackageInstaller$SessionParams;->sizeBytes:J
Landroid/content/pm/PackageItemInfo;->setForceSafeLabels(Z)V
Landroid/content/pm/PackageManager;->buildRequestPermissionsIntent([Ljava/lang/String;)Landroid/content/Intent;
+Landroid/content/pm/PackageManager;->deletePackage(Ljava/lang/String;Landroid/content/pm/IPackageDeleteObserver;I)V
Landroid/content/pm/PackageManager;->freeStorage(JLandroid/content/IntentSender;)V
Landroid/content/pm/PackageManager;->freeStorage(Ljava/lang/String;JLandroid/content/IntentSender;)V
Landroid/content/pm/PackageManager;->freeStorageAndNotify(JLandroid/content/pm/IPackageDataObserver;)V
@@ -843,6 +848,7 @@
Landroid/content/pm/Signature;->getPublicKey()Ljava/security/PublicKey;
Landroid/content/pm/UserInfo;-><init>(ILjava/lang/String;I)V
Landroid/content/pm/UserInfo;->FLAG_PRIMARY:I
+Landroid/content/pm/UserInfo;->getUserHandle()Landroid/os/UserHandle;
Landroid/content/pm/UserInfo;->id:I
Landroid/content/pm/UserInfo;->isPrimary()Z
Landroid/content/pm/UserInfo;->serialNumber:I
@@ -961,6 +967,7 @@
Landroid/database/AbstractCursor;->mExtras:Landroid/os/Bundle;
Landroid/database/AbstractCursor;->mNotifyUri:Landroid/net/Uri;
Landroid/database/AbstractWindowedCursor;->clearOrCreateWindow(Ljava/lang/String;)V
+Landroid/database/AbstractWindowedCursor;->closeWindow()V
Landroid/database/CursorWindow;->mWindowPtr:J
Landroid/database/CursorWindow;->sCursorWindowSize:I
Landroid/database/CursorWindow;->sWindowToPidMap:Landroid/util/LongSparseArray;
@@ -969,6 +976,7 @@
Landroid/database/sqlite/SQLiteCustomFunction;->name:Ljava/lang/String;
Landroid/database/sqlite/SQLiteCustomFunction;->numArgs:I
Landroid/database/sqlite/SQLiteDatabase;->CONFLICT_VALUES:[Ljava/lang/String;
+Landroid/database/sqlite/SQLiteDatabase;->getThreadSession()Landroid/database/sqlite/SQLiteSession;
Landroid/database/sqlite/SQLiteDatabase;->mConfigurationLocked:Landroid/database/sqlite/SQLiteDatabaseConfiguration;
Landroid/database/sqlite/SQLiteDatabase;->mConnectionPoolLocked:Landroid/database/sqlite/SQLiteConnectionPool;
Landroid/database/sqlite/SQLiteDatabase;->reopenReadWrite()V
@@ -977,6 +985,7 @@
Landroid/database/sqlite/SQLiteDebug$PagerStats;->memoryUsed:I
Landroid/database/sqlite/SQLiteDebug$PagerStats;->pageCacheOverflow:I
Landroid/database/sqlite/SQLiteOpenHelper;->mName:Ljava/lang/String;
+Landroid/database/sqlite/SQLiteSession;->beginTransaction(ILandroid/database/sqlite/SQLiteTransactionListener;ILandroid/os/CancellationSignal;)V
Landroid/database/sqlite/SQLiteStatement;-><init>(Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;[Ljava/lang/Object;)V
Landroid/ddm/DdmHandleAppName;->getAppName()Ljava/lang/String;
Landroid/ddm/DdmHandleAppName;->setAppName(Ljava/lang/String;I)V
@@ -1044,6 +1053,7 @@
Landroid/graphics/drawable/GradientDrawable;->getOpticalInsets()Landroid/graphics/Insets;
Landroid/graphics/drawable/GradientDrawable;->mGradientState:Landroid/graphics/drawable/GradientDrawable$GradientState;
Landroid/graphics/drawable/GradientDrawable;->mPadding:Landroid/graphics/Rect;
+Landroid/graphics/drawable/Icon;->createWithResource(Landroid/content/res/Resources;I)Landroid/graphics/drawable/Icon;
Landroid/graphics/drawable/Icon;->getBitmap()Landroid/graphics/Bitmap;
Landroid/graphics/drawable/Icon;->getDataBytes()[B
Landroid/graphics/drawable/Icon;->getDataLength()I
@@ -1227,6 +1237,7 @@
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->data:[B
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionConfig;->keyphrases:[Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseRecognitionExtra;
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;-><init>(IIZIIIZLandroid/media/AudioFormat;[B)V
+Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->captureSession:I
Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;->data:[B
Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->data:[B
Landroid/hardware/soundtrigger/SoundTrigger$SoundModel;->uuid:Ljava/util/UUID;
@@ -1774,6 +1785,7 @@
Landroid/os/HwParcel;-><init>(Z)V
Landroid/os/HwRemoteBinder;-><init>()V
Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/os/IDeviceIdleController;->getAppIdTempWhitelist()[I
Landroid/os/IPermissionController$Stub$Proxy;->checkPermission(Ljava/lang/String;II)Z
Landroid/os/IPermissionController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IPermissionController;
Landroid/os/IPowerManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1829,6 +1841,7 @@
Landroid/os/Process;->getTotalMemory()J
Landroid/os/Process;->getUidForPid(I)I
Landroid/os/Process;->isIsolated(I)Z
+Landroid/os/Process;->parseProcLine([BII[I[Ljava/lang/String;[J[F)Z
Landroid/os/Process;->readProcFile(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z
Landroid/os/Process;->readProcLines(Ljava/lang/String;[Ljava/lang/String;[J)V
Landroid/os/Process;->setArgV0(Ljava/lang/String;)V
@@ -1868,6 +1881,7 @@
Landroid/os/storage/StorageVolume;->getPathFile()Ljava/io/File;
Landroid/os/storage/StorageVolume;->getUserLabel()Ljava/lang/String;
Landroid/os/storage/StorageVolume;->mPath:Ljava/io/File;
+Landroid/os/storage/StorageVolume;->mRemovable:Z
Landroid/os/storage/VolumeInfo;->buildStorageVolume(Landroid/content/Context;IZ)Landroid/os/storage/StorageVolume;
Landroid/os/storage/VolumeInfo;->getDisk()Landroid/os/storage/DiskInfo;
Landroid/os/storage/VolumeInfo;->getEnvironmentForState(I)Ljava/lang/String;
@@ -1885,6 +1899,7 @@
Landroid/os/StrictMode;->enterCriticalSpan(Ljava/lang/String;)Landroid/os/StrictMode$Span;
Landroid/os/StrictMode;->getThreadPolicyMask()I
Landroid/os/StrictMode;->onBinderStrictModePolicyChange(I)V
+Landroid/os/StrictMode;->sLastVmViolationTime:Ljava/util/HashMap;
Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
Landroid/os/SystemProperties;-><init>()V
Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V
@@ -2376,6 +2391,8 @@
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_MODERATE:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_NONE_OR_UNKNOWN:I
Landroid/telephony/SignalStrength;->SIGNAL_STRENGTH_POOR:I
+Landroid/telephony/SmsManager;->deleteMessageFromIcc(I)Z
+Landroid/telephony/SmsManager;->getAllMessagesFromIcc()Ljava/util/ArrayList;
Landroid/telephony/SmsManager;->sendMultipartTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/util/ArrayList;Ljava/util/ArrayList;Ljava/util/ArrayList;IZI)V
Landroid/telephony/SmsManager;->sendTextMessage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;IZI)V
Landroid/telephony/SmsMessage;->getSubId()I
@@ -2402,6 +2419,7 @@
Landroid/telephony/TelephonyManager;->getITelephony()Lcom/android/internal/telephony/ITelephony;
Landroid/telephony/TelephonyManager;->getLine1Number(I)Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getMultiSimConfiguration()Landroid/telephony/TelephonyManager$MultiSimVariants;
+Landroid/telephony/TelephonyManager;->getNai(I)Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getNetworkClass(I)I
Landroid/telephony/TelephonyManager;->getNetworkCountryIso(I)Ljava/lang/String;
Landroid/telephony/TelephonyManager;->getNetworkOperator(I)Ljava/lang/String;
@@ -2629,6 +2647,7 @@
Landroid/view/IWindowManager;->getAnimationScale(I)F
Landroid/view/IWindowManager;->hasNavigationBar()Z
Landroid/view/IWindowManager;->setAnimationScale(IF)V
+Landroid/view/IWindowManager;->setAnimationScales([F)V
Landroid/view/IWindowManager;->setShelfHeight(ZI)V
Landroid/view/IWindowManager;->setStrictModeVisualIndicatorPreference(Ljava/lang/String;)V
Landroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
@@ -2884,6 +2903,7 @@
Landroid/view/ViewTreeObserver$InternalInsetsInfo;->TOUCHABLE_INSETS_REGION:I
Landroid/view/ViewTreeObserver;->addOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
Landroid/view/ViewTreeObserver;->removeOnComputeInternalInsetsListener(Landroid/view/ViewTreeObserver$OnComputeInternalInsetsListener;)V
+Landroid/view/Window;->addPrivateFlags(I)V
Landroid/view/Window;->mAppName:Ljava/lang/String;
Landroid/view/Window;->mAppToken:Landroid/os/IBinder;
Landroid/view/Window;->mCallback:Landroid/view/Window$Callback;
@@ -3196,6 +3216,7 @@
Landroid/widget/TextView;->mSingleLine:Z
Landroid/widget/TextView;->mText:Ljava/lang/CharSequence;
Landroid/widget/TextView;->mTextPaint:Landroid/text/TextPaint;
+Landroid/widget/TextView;->mTextSelectHandleLeftRes:I
Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;Landroid/widget/TextView$BufferType;ZI)V
Landroid/widget/Toast$TN;->mNextView:Landroid/view/View;
Landroid/widget/Toast$TN;->mParams:Landroid/view/WindowManager$LayoutParams;
@@ -3301,9 +3322,13 @@
Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
+Lcom/android/internal/content/PackageMonitor;->onPackageRemoved(Ljava/lang/String;I)V
+Lcom/android/internal/content/PackageMonitor;->register(Landroid/content/Context;Landroid/os/Looper;Z)V
Lcom/android/internal/content/ReferrerIntent;-><init>(Landroid/content/Intent;Ljava/lang/String;)V
Lcom/android/internal/content/ReferrerIntent;->mReferrer:Ljava/lang/String;
Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
+Lcom/android/internal/logging/MetricsLogger;-><init>()V
+Lcom/android/internal/logging/MetricsLogger;->write(Landroid/metrics/LogMaker;)V
Lcom/android/internal/os/BatterySipper;-><init>(Lcom/android/internal/os/BatterySipper$DrainType;Landroid/os/BatteryStats$Uid;D)V
Lcom/android/internal/os/BatterySipper;->add(Lcom/android/internal/os/BatterySipper;)V
Lcom/android/internal/os/BatterySipper;->drainType:Lcom/android/internal/os/BatterySipper$DrainType;
@@ -3676,6 +3701,7 @@
Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
+Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
Ldalvik/system/BaseDexClassLoader;->addDexPath(Ljava/lang/String;)V
Ldalvik/system/BaseDexClassLoader;->getLdLibraryPath()Ljava/lang/String;
Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList;
@@ -3701,6 +3727,7 @@
Ldalvik/system/DexPathList$NativeLibraryElement;->path:Ljava/io/File;
Ldalvik/system/DexPathList;-><init>(Ljava/lang/ClassLoader;Ljava/lang/String;Ljava/lang/String;Ljava/io/File;)V
Ldalvik/system/DexPathList;->addDexPath(Ljava/lang/String;Ljava/io/File;)V
+Ldalvik/system/DexPathList;->addNativePath(Ljava/util/Collection;)V
Ldalvik/system/DexPathList;->definingContext:Ljava/lang/ClassLoader;
Ldalvik/system/DexPathList;->dexElements:[Ldalvik/system/DexPathList$Element;
Ldalvik/system/DexPathList;->loadDexFile(Ljava/io/File;Ljava/io/File;Ljava/lang/ClassLoader;[Ldalvik/system/DexPathList$Element;)Ldalvik/system/DexFile;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 037a87b..3f66747 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2683,7 +2683,7 @@
// TODO(lifecycler): Can't switch to use #handleLaunchActivity() because it will try to
// call #reportSizeConfigurations(), but the server might not know anything about the
// activity if it was launched from LocalAcvitivyManager.
- return performLaunchActivity(r);
+ return performLaunchActivity(r, null /* customIntent */);
}
public final Activity getActivity(IBinder token) {
@@ -2768,7 +2768,7 @@
}
/** Core implementation of activity launch. */
- private Activity performLaunchActivity(ActivityClientRecord r) {
+ private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
@@ -2838,6 +2838,9 @@
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
+ if (customIntent != null) {
+ activity.mIntent = customIntent;
+ }
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
@@ -2982,7 +2985,7 @@
*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions) {
+ PendingTransactionActions pendingActions, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
@@ -3005,7 +3008,7 @@
}
WindowManagerGlobal.initialize();
- final Activity a = performLaunchActivity(r);
+ final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
@@ -4699,6 +4702,8 @@
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
PendingTransactionActions pendingActions, boolean startsNotResumed,
Configuration overrideConfig, String reason) {
+ // Preserve last used intent, it may be set from Activity#setIntent().
+ final Intent customIntent = r.activity.mIntent;
// Need to ensure state is saved.
if (!r.paused) {
performPauseActivity(r, false, reason, null /* pendingActions */);
@@ -4731,7 +4736,7 @@
r.startsNotResumed = startsNotResumed;
r.overrideConfig = overrideConfig;
- handleLaunchActivity(r, pendingActions);
+ handleLaunchActivity(r, pendingActions, customIntent);
}
@Override
@@ -5333,8 +5338,8 @@
}
}
}
- final List<String> oldPaths =
- sPackageManager.getPreviousCodePaths(packageName);
+ final ArrayList<String> oldPaths = new ArrayList<>();
+ LoadedApk.makePaths(this, pkgInfo.getApplicationInfo(), oldPaths);
pkgInfo.updateApplicationInfo(aInfo, oldPaths);
} catch (RemoteException e) {
}
@@ -5512,6 +5517,7 @@
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
+ VMRuntime.setProcessPackageName(data.appInfo.packageName);
if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 796e406..07048f9 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -338,7 +338,9 @@
/** @hide Any app start foreground service. */
public static final int OP_START_FOREGROUND = 76;
/** @hide */
- public static final int _NUM_OP = 77;
+ public static final int OP_BLUETOOTH_SCAN = 77;
+ /** @hide */
+ public static final int _NUM_OP = 78;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -580,6 +582,8 @@
/** @hide */
@SystemApi @TestApi
public static final String OPSTR_START_FOREGROUND = "android:start_foreground";
+ /** @hide */
+ public static final String OPSTR_BLUETOOTH_SCAN = "android:bluetooth_scan";
// Warning: If an permission is added here it also has to be added to
// com.android.packageinstaller.permission.utils.EventLogger
@@ -717,6 +721,7 @@
OP_ACCEPT_HANDOVER, // ACCEPT_HANDOVER
OP_MANAGE_IPSEC_TUNNELS, // MANAGE_IPSEC_HANDOVERS
OP_START_FOREGROUND, // START_FOREGROUND
+ OP_COARSE_LOCATION, // BLUETOOTH_SCAN
};
/**
@@ -800,6 +805,7 @@
OPSTR_ACCEPT_HANDOVER,
OPSTR_MANAGE_IPSEC_TUNNELS,
OPSTR_START_FOREGROUND,
+ OPSTR_BLUETOOTH_SCAN,
};
/**
@@ -884,6 +890,7 @@
"ACCEPT_HANDOVER",
"MANAGE_IPSEC_TUNNELS",
"START_FOREGROUND",
+ "BLUETOOTH_SCAN",
};
/**
@@ -968,6 +975,7 @@
Manifest.permission.ACCEPT_HANDOVER,
null, // no permission for OP_MANAGE_IPSEC_TUNNELS
Manifest.permission.FOREGROUND_SERVICE,
+ null, // no permission for OP_BLUETOOTH_SCAN
};
/**
@@ -1053,6 +1061,7 @@
null, // ACCEPT_HANDOVER
null, // MANAGE_IPSEC_TUNNELS
null, // START_FOREGROUND
+ null, // maybe should be UserManager.DISALLOW_SHARE_LOCATION, //BLUETOOTH_SCAN
};
/**
@@ -1137,6 +1146,7 @@
false, // ACCEPT_HANDOVER
false, // MANAGE_IPSEC_HANDOVERS
false, // START_FOREGROUND
+ true, // BLUETOOTH_SCAN
};
/**
@@ -1220,6 +1230,7 @@
AppOpsManager.MODE_ALLOWED, // ACCEPT_HANDOVER
AppOpsManager.MODE_ERRORED, // MANAGE_IPSEC_TUNNELS
AppOpsManager.MODE_ALLOWED, // OP_START_FOREGROUND
+ AppOpsManager.MODE_ALLOWED, // OP_BLUETOOTH_SCAN
};
/**
@@ -1307,6 +1318,7 @@
false, // ACCEPT_HANDOVER
false, // MANAGE_IPSEC_TUNNELS
false, // START_FOREGROUND
+ false, // BLUETOOTH_SCAN
};
/**
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index 7257044..0ed50f2 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -25,6 +25,8 @@
import dalvik.system.PathClassLoader;
+import java.util.Collection;
+
/** @hide */
public class ApplicationLoaders {
public static ApplicationLoaders getDefault() {
@@ -121,6 +123,17 @@
baseDexClassLoader.addDexPath(dexPath);
}
+ /**
+ * @hide
+ */
+ void addNative(ClassLoader classLoader, Collection<String> libPaths) {
+ if (!(classLoader instanceof PathClassLoader)) {
+ throw new IllegalStateException("class loader is not a PathClassLoader");
+ }
+ final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
+ baseDexClassLoader.addNativePath(libPaths);
+ }
+
private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<>();
private static final ApplicationLoaders gApplicationLoaders = new ApplicationLoaders();
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index ea0d703..d9c7cf3 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -18,6 +18,7 @@
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.TransactionExecutor;
+import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -140,7 +141,7 @@
/** Perform activity launch. */
public abstract Activity handleLaunchActivity(ActivityThread.ActivityClientRecord r,
- PendingTransactionActions pendingActions);
+ PendingTransactionActions pendingActions, Intent customIntent);
/** Perform activity start. */
public abstract void handleStartActivity(ActivityThread.ActivityClientRecord r,
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index fc7d9a5..8c0cd23 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -90,6 +90,7 @@
public final class LoadedApk {
static final String TAG = "LoadedApk";
static final boolean DEBUG = false;
+ private static final String PROPERTY_NAME_APPEND_NATIVE = "pi.append_native_lib_paths";
private final ActivityThread mActivityThread;
final String mPackageName;
@@ -723,6 +724,10 @@
needToSetupJitProfiles = true;
}
+ if (!libPaths.isEmpty() && SystemProperties.getBoolean(PROPERTY_NAME_APPEND_NATIVE, true)) {
+ ApplicationLoaders.getDefault().addNative(mClassLoader, libPaths);
+ }
+
if (addedPaths != null && addedPaths.size() > 0) {
final String add = TextUtils.join(File.pathSeparator, addedPaths);
ApplicationLoaders.getDefault().addPath(mClassLoader, add);
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 7be82bf..6bae359 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -75,7 +75,7 @@
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client);
- client.handleLaunchActivity(r, pendingActions);
+ client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 5c803a5..43a2b4c 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -173,7 +173,8 @@
log("Transitioning to state: " + state);
switch (state) {
case ON_CREATE:
- mTransactionHandler.handleLaunchActivity(r, mPendingActions);
+ mTransactionHandler.handleLaunchActivity(r, mPendingActions,
+ null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 6b1222f..0269b6c 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -96,7 +96,8 @@
encryptionAware = directBootAware = orig.directBootAware;
}
- @Override public CharSequence loadLabel(PackageManager pm) {
+ /** @hide */
+ @Override public CharSequence loadUnsafeLabel(PackageManager pm) {
if (nonLocalizedLabel != null) {
return nonLocalizedLabel;
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2be33e9..c988fa9 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -644,8 +644,6 @@
boolean isPackageDeviceAdminOnAnyUser(String packageName);
- List<String> getPreviousCodePaths(in String packageName);
-
int getInstallReason(String packageName, int userId);
ParceledListSlice getSharedLibraries(in String packageName, int flags, int userId);
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 53ffd55..07fbfb5 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -43,6 +43,8 @@
*/
public class PackageItemInfo {
private static final float MAX_LABEL_SIZE_PX = 500f;
+ /** The maximum length of a safe label, in characters */
+ private static final int MAX_SAFE_LABEL_LENGTH = 50000;
private static volatile boolean sForceSafeLabels = false;
@@ -187,7 +189,8 @@
// If the label contains new line characters it may push the UI
// down to hide a part of it. Labels shouldn't have new line
// characters, so just truncate at the first time one is seen.
- final int labelLength = labelStr.length();
+ final int labelLength = Math.min(labelStr.length(), MAX_SAFE_LABEL_LENGTH);
+ final StringBuffer sb = new StringBuffer(labelLength);
int offset = 0;
while (offset < labelLength) {
final int codePoint = labelStr.codePointAt(offset);
@@ -199,14 +202,19 @@
break;
}
// replace all non-break space to " " in order to be trimmed
+ final int charCount = Character.charCount(codePoint);
if (type == Character.SPACE_SEPARATOR) {
- labelStr = labelStr.substring(0, offset) + " " + labelStr.substring(offset +
- Character.charCount(codePoint));
+ sb.append(' ');
+ } else {
+ sb.append(labelStr.charAt(offset));
+ if (charCount == 2) {
+ sb.append(labelStr.charAt(offset + 1));
+ }
}
- offset += Character.charCount(codePoint);
+ offset += charCount;
}
- labelStr = labelStr.trim();
+ labelStr = sb.toString().trim();
if (labelStr.isEmpty()) {
return packageName;
}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 19b5c45..193e56e 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1905,6 +1905,10 @@
* Return whether the screen has a wide color gamut and wide color gamut rendering
* is supported by this device.
*
+ * When true, it implies the screen is colorspace aware but not
+ * necessarily color-managed. The final colors may still be changed by the
+ * screen depending on user settings.
+ *
* @return true if the screen has a wide color gamut and wide color gamut rendering
* is supported, false otherwise
*/
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c58cde0..7adea6a8 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -128,6 +128,14 @@
private final ArrayList<WeakReference<Theme>> mThemeRefs = new ArrayList<>();
/**
+ * To avoid leaking WeakReferences to garbage collected Themes on the
+ * mThemeRefs list, we flush the list of stale references any time the
+ * mThemeRefNextFlushSize is reached.
+ */
+ private static final int MIN_THEME_REFS_FLUSH_SIZE = 32;
+ private int mThemeRefsNextFlushSize = MIN_THEME_REFS_FLUSH_SIZE;
+
+ /**
* Returns the most appropriate default theme for the specified target SDK version.
* <ul>
* <li>Below API 11: Gingerbread
@@ -1770,6 +1778,13 @@
theme.setImpl(mResourcesImpl.newThemeImpl());
synchronized (mThemeRefs) {
mThemeRefs.add(new WeakReference<>(theme));
+
+ // Clean up references to garbage collected themes
+ if (mThemeRefs.size() > mThemeRefsNextFlushSize) {
+ mThemeRefs.removeIf(ref -> ref.get() == null);
+ mThemeRefsNextFlushSize = Math.max(MIN_THEME_REFS_FLUSH_SIZE,
+ 2 * mThemeRefs.size());
+ }
}
return theme;
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9b20ed2..11afd21 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -157,8 +157,9 @@
public static final String DISALLOW_CONFIG_LOCALE = "no_config_locale";
/**
- * Specifies if a user is disallowed from installing applications.
- * The default value is <code>false</code>.
+ * Specifies if a user is disallowed from installing applications. This user restriction also
+ * prevents device owners and profile owners installing apps. The default value is
+ * {@code false}.
*
* <p>Key for user restrictions.
* <p>Type: Boolean
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 9e3e386..5c99f6c 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -312,7 +312,7 @@
* {@link android.Manifest.permission#WRITE_MEDIA_STORAGE}.
*/
public File getInternalPathForUser(int userId) {
- if (type == TYPE_PUBLIC && !isVisible()) {
+ if (type == TYPE_PUBLIC) {
// TODO: plumb through cleaner path from vold
return new File(path.replace("/storage/", "/mnt/media_rw/"));
} else {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5deee11..ed8b005 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1580,6 +1580,20 @@
*/
public Transaction destroy(SurfaceControl sc) {
sc.checkNotReleased();
+
+ /**
+ * Perhaps it's safer to transfer the close guard to the Transaction
+ * but then we have a whole wonky scenario regarding merging, multiple
+ * close-guards per transaction etc...the whole scenario is kind of wonky
+ * and it seems really we'd like to just be able to call release here
+ * but the WindowManager has some code that looks like
+ * --- destroyInTransaction(a)
+ * --- reparentChildrenInTransaction(a)
+ * so we need to ensure the SC remains valid until the transaction
+ * is applied.
+ */
+ sc.mCloseGuard.close();
+
nativeDestroy(mNativeObject, sc.mNativeObject);
return this;
}
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index da47bcb..24f531d 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -114,9 +114,10 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @StringDef({WIDGET_TYPE_TEXTVIEW, WIDGET_TYPE_WEBVIEW, WIDGET_TYPE_EDITTEXT,
- WIDGET_TYPE_EDIT_WEBVIEW, WIDGET_TYPE_CUSTOM_TEXTVIEW, WIDGET_TYPE_CUSTOM_EDITTEXT,
- WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW, WIDGET_TYPE_UNKNOWN})
+ @StringDef({WIDGET_TYPE_TEXTVIEW, WIDGET_TYPE_EDITTEXT, WIDGET_TYPE_UNSELECTABLE_TEXTVIEW,
+ WIDGET_TYPE_WEBVIEW, WIDGET_TYPE_EDIT_WEBVIEW, WIDGET_TYPE_CUSTOM_TEXTVIEW,
+ WIDGET_TYPE_CUSTOM_EDITTEXT, WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW,
+ WIDGET_TYPE_UNKNOWN})
@interface WidgetType {}
/** The widget involved in the text classification session is a standard
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 4db3607..a22f345 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -104,8 +104,16 @@
sReceiverInfo.set(ri);
}
ri.addView(this);
+ // The view may not be added to the view hierarchy immediately right after setTime()
+ // is called which means it won't get any update from intents before being added.
+ // In such case, the view might show the incorrect relative time after being added to the
+ // view hierarchy until the next update intent comes.
+ // So we update the time here if mShowRelativeTime is enabled to prevent this case.
+ if (mShowRelativeTime) {
+ update();
+ }
}
-
+
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index a075705..b591163 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -85,6 +85,14 @@
protected abstract Uri buildNotificationUri(String docId);
+ /**
+ * Callback indicating that the given document has been modified. This gives
+ * the provider a hook to invalidate cached data, such as {@code sdcardfs}.
+ */
+ protected void onDocIdChanged(String docId) {
+ // Default is no-op
+ }
+
@Override
public boolean onCreate() {
throw new UnsupportedOperationException(
@@ -185,6 +193,7 @@
throw new IllegalStateException("Failed to mkdir " + file);
}
childId = getDocIdForFile(file);
+ onDocIdChanged(childId);
addFolderToMediaStore(getFileForDocId(childId, true));
} else {
try {
@@ -192,6 +201,7 @@
throw new IllegalStateException("Failed to touch " + file);
}
childId = getDocIdForFile(file);
+ onDocIdChanged(childId);
} catch (IOException e) {
throw new IllegalStateException("Failed to touch " + file + ": " + e);
}
@@ -227,16 +237,20 @@
final File before = getFileForDocId(docId);
final File after = FileUtils.buildUniqueFile(before.getParentFile(), displayName);
- final File visibleFileBefore = getFileForDocId(docId, true);
if (!before.renameTo(after)) {
throw new IllegalStateException("Failed to rename to " + after);
}
final String afterDocId = getDocIdForFile(after);
- moveInMediaStore(visibleFileBefore, getFileForDocId(afterDocId, true));
+ onDocIdChanged(docId);
+ onDocIdChanged(afterDocId);
+
+ final File beforeVisibleFile = getFileForDocId(docId, true);
+ final File afterVisibleFile = getFileForDocId(afterDocId, true);
+ moveInMediaStore(beforeVisibleFile, afterVisibleFile);
if (!TextUtils.equals(docId, afterDocId)) {
- scanFile(after);
+ scanFile(afterVisibleFile);
return afterDocId;
} else {
return null;
@@ -259,6 +273,8 @@
}
final String docId = getDocIdForFile(after);
+ onDocIdChanged(sourceDocumentId);
+ onDocIdChanged(docId);
moveInMediaStore(visibleFileBefore, getFileForDocId(docId, true));
return docId;
@@ -308,6 +324,7 @@
throw new IllegalStateException("Failed to delete " + file);
}
+ onDocIdChanged(docId);
removeFromMediaStore(visibleFile, isDirectory);
}
@@ -418,7 +435,10 @@
try {
// When finished writing, kick off media scanner
return ParcelFileDescriptor.open(
- file, pfdMode, mHandler, (IOException e) -> scanFile(visibleFile));
+ file, pfdMode, mHandler, (IOException e) -> {
+ onDocIdChanged(documentId);
+ scanFile(visibleFile);
+ });
} catch (IOException e) {
throw new FileNotFoundException("Failed to open for writing: " + e);
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index a1e6fd8..c388148 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -282,7 +282,10 @@
}
}
- private static void createNativeLibrarySubdir(File path) throws IOException {
+ /**
+ * @hide
+ */
+ public static void createNativeLibrarySubdir(File path) throws IOException {
if (!path.isDirectory()) {
path.delete();
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 98afebc..c4d08c7 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -56,8 +56,6 @@
private static final boolean USE_NATIVE_PARSING = true;
private static final boolean SANITY_CHECK_NATIVE = false;
- /** Path to {@code /proc/net/dev}. */
- private final File mStatsIfaceDev;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
@@ -133,47 +131,16 @@
@VisibleForTesting
public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
- mStatsIfaceDev = new File(procRoot, "net/dev");
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
mUseBpfStats = useBpfStats;
}
- @VisibleForTesting
- public NetworkStats readNetworkStatsIfaceDev() throws IOException {
- final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-
+ public NetworkStats readBpfNetworkStatsDev() throws IOException {
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
-
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(mStatsIfaceDev));
-
- // skip first two header lines
- reader.readLine();
- reader.readLine();
-
- // parse remaining lines
- String line;
- while ((line = reader.readLine()) != null) {
- String[] values = line.trim().split("\\:?\\s+");
- entry.iface = values[0];
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.rxBytes = Long.parseLong(values[1]);
- entry.rxPackets = Long.parseLong(values[2]);
- entry.txBytes = Long.parseLong(values[9]);
- entry.txPackets = Long.parseLong(values[10]);
- stats.addValues(entry);
- }
- } catch (NullPointerException|NumberFormatException e) {
- throw new ProtocolException("problem parsing stats", e);
- } finally {
- IoUtils.closeQuietly(reader);
- StrictMode.setThreadPolicy(savedPolicy);
+ if (nativeReadNetworkStatsDev(stats) != 0) {
+ throw new IOException("Failed to parse bpf iface stats");
}
return stats;
}
@@ -188,9 +155,9 @@
*/
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
- // Return the stats get from /proc/net/dev if switched to bpf module.
+ // Return xt_bpf stats if switched to bpf module.
if (mUseBpfStats)
- return readNetworkStatsIfaceDev();
+ return readBpfNetworkStatsDev();
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
@@ -244,9 +211,9 @@
*/
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
- // Return the stats get from /proc/net/dev if qtaguid module is replaced.
+ // Return xt_bpf stats if qtaguid module is replaced.
if (mUseBpfStats)
- return readNetworkStatsIfaceDev();
+ return readBpfNetworkStatsDev();
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
@@ -408,4 +375,7 @@
@VisibleForTesting
public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path,
int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);
+
+ @VisibleForTesting
+ public static native int nativeReadNetworkStatsDev(NetworkStats stats);
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index cc95df7..2db5739 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -308,10 +308,8 @@
public void onDraw(Canvas c) {
super.onDraw(c);
- // When we are resizing, we need the fallback background to cover the area where we have our
- // system bar background views as the navigation bar will be hidden during resizing.
- mBackgroundFallback.draw(isResizing() ? this : mContentRoot, mContentRoot, c,
- mWindow.mContentParent);
+ mBackgroundFallback.draw(this, mContentRoot, c, mWindow.mContentParent,
+ mStatusColorViewState.view, mNavigationColorViewState.view);
}
@Override
diff --git a/core/java/com/android/internal/widget/BackgroundFallback.java b/core/java/com/android/internal/widget/BackgroundFallback.java
index 309f80c..2b05f1e 100644
--- a/core/java/com/android/internal/widget/BackgroundFallback.java
+++ b/core/java/com/android/internal/widget/BackgroundFallback.java
@@ -46,8 +46,11 @@
* @param root The view group containing the content.
* @param c The canvas to draw the background onto.
* @param content The view where the actual app content is contained in.
+ * @param coveringView1 A potentially opaque view drawn atop the content
+ * @param coveringView2 A potentially opaque view drawn atop the content
*/
- public void draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content) {
+ public void draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content,
+ View coveringView1, View coveringView2) {
if (!hasFallback()) {
return;
}
@@ -55,6 +58,10 @@
// Draw the fallback in the padding.
final int width = boundsView.getWidth();
final int height = boundsView.getHeight();
+
+ final int rootOffsetX = root.getLeft();
+ final int rootOffsetY = root.getTop();
+
int left = width;
int top = height;
int right = 0;
@@ -71,17 +78,58 @@
((ViewGroup) child).getChildCount() == 0) {
continue;
}
- } else if (child.getVisibility() != View.VISIBLE || childBg == null ||
- childBg.getOpacity() != PixelFormat.OPAQUE) {
+ } else if (child.getVisibility() != View.VISIBLE || !isOpaque(childBg)) {
// Potentially translucent or invisible children don't count, and we assume
// the content view will cover the whole area if we're in a background
// fallback situation.
continue;
}
- left = Math.min(left, child.getLeft());
- top = Math.min(top, child.getTop());
- right = Math.max(right, child.getRight());
- bottom = Math.max(bottom, child.getBottom());
+ left = Math.min(left, rootOffsetX + child.getLeft());
+ top = Math.min(top, rootOffsetY + child.getTop());
+ right = Math.max(right, rootOffsetX + child.getRight());
+ bottom = Math.max(bottom, rootOffsetY + child.getBottom());
+ }
+
+ // If one of the bar backgrounds is a solid color and covers the entire padding on a side
+ // we can drop that padding.
+ boolean eachBarCoversTopInY = true;
+ for (int i = 0; i < 2; i++) {
+ View v = (i == 0) ? coveringView1 : coveringView2;
+ if (v == null || v.getVisibility() != View.VISIBLE
+ || v.getAlpha() != 1f || !isOpaque(v.getBackground())) {
+ eachBarCoversTopInY = false;
+ continue;
+ }
+
+ // Bar covers entire left padding
+ if (v.getTop() <= 0 && v.getBottom() >= height
+ && v.getLeft() <= 0 && v.getRight() >= left) {
+ left = 0;
+ }
+ // Bar covers entire right padding
+ if (v.getTop() <= 0 && v.getBottom() >= height
+ && v.getLeft() <= right && v.getRight() >= width) {
+ right = width;
+ }
+ // Bar covers entire top padding
+ if (v.getTop() <= 0 && v.getBottom() >= top
+ && v.getLeft() <= 0 && v.getRight() >= width) {
+ top = 0;
+ }
+ // Bar covers entire bottom padding
+ if (v.getTop() <= bottom && v.getBottom() >= height
+ && v.getLeft() <= 0 && v.getRight() >= width) {
+ bottom = height;
+ }
+
+ eachBarCoversTopInY &= v.getTop() <= 0 && v.getBottom() >= top;
+ }
+
+ // Special case: Sometimes, both covering views together may cover the top inset, but
+ // neither does on its own.
+ if (eachBarCoversTopInY && (viewsCoverEntireWidth(coveringView1, coveringView2, width)
+ || viewsCoverEntireWidth(coveringView2, coveringView1, width))) {
+ top = 0;
}
if (left >= right || top >= bottom) {
@@ -106,4 +154,24 @@
mBackgroundFallback.draw(c);
}
}
+
+ private boolean isOpaque(Drawable childBg) {
+ return childBg != null && childBg.getOpacity() == PixelFormat.OPAQUE;
+ }
+
+ /**
+ * Returns true if {@code view1} starts before or on {@code 0} and extends at least
+ * up to {@code view2}, and that view extends at least to {@code width}.
+ *
+ * @param view1 the first view to check if it covers the width
+ * @param view2 the second view to check if it covers the width
+ * @param width the width to check for
+ * @return returns true if both views together cover the entire width (and view1 is to the left
+ * of view2)
+ */
+ private boolean viewsCoverEntireWidth(View view1, View view2, int width) {
+ return view1.getLeft() <= 0
+ && view1.getRight() >= view2.getLeft()
+ && view2.getRight() >= width;
+ }
}
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index 1e7c11e..e143498 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -28,8 +28,6 @@
import android.widget.RemoteViews;
import android.widget.TextView;
-import com.android.internal.R;
-
/**
* A TextView that can float around an image on the end.
*
@@ -44,9 +42,7 @@
/** Resolved layout direction */
private int mResolvedDirection = LAYOUT_DIRECTION_UNDEFINED;
private int mMaxLinesForHeight = -1;
- private boolean mFirstMeasure = true;
private int mLayoutMaxLines = -1;
- private boolean mBlockLayouts;
private int mImageEndMargin;
public ImageFloatingTextView(Context context) {
@@ -122,30 +118,31 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int height = MeasureSpec.getSize(heightMeasureSpec);
- // Lets calculate how many lines the given measurement allows us.
- int availableHeight = height - mPaddingTop - mPaddingBottom;
- int maxLines = availableHeight / getLineHeight();
- maxLines = Math.max(1, maxLines);
- if (getMaxLines() > 0) {
- maxLines = Math.min(getMaxLines(), maxLines);
- }
- if (maxLines != mMaxLinesForHeight) {
- mMaxLinesForHeight = maxLines;
- if (getLayout() != null && mMaxLinesForHeight != mLayoutMaxLines) {
- // Invalidate layout.
- mBlockLayouts = true;
- setHint(getHint());
- mBlockLayouts = false;
- }
+ int availableHeight = MeasureSpec.getSize(heightMeasureSpec) - mPaddingTop - mPaddingBottom;
+ if (getLayout() != null && getLayout().getHeight() != availableHeight) {
+ // We've been measured before and the new size is different than before, lets make sure
+ // we reset the maximum lines, otherwise we may be cut short
+ mMaxLinesForHeight = -1;
+ nullLayouts();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- public void requestLayout() {
- if (!mBlockLayouts) {
- super.requestLayout();
+ Layout layout = getLayout();
+ if (layout.getHeight() > availableHeight) {
+ // With the existing layout, not all of our lines fit on the screen, let's find the
+ // first one that fits and ellipsize at that one.
+ int maxLines = layout.getLineCount() - 1;
+ while (maxLines > 1 && layout.getLineBottom(maxLines - 1) > availableHeight) {
+ maxLines--;
+ }
+ if (getMaxLines() > 0) {
+ maxLines = Math.min(getMaxLines(), maxLines);
+ }
+ // Only if the number of lines is different from the current layout, we recreate it.
+ if (maxLines != mLayoutMaxLines) {
+ mMaxLinesForHeight = maxLines;
+ nullLayouts();
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
}
}
@@ -157,7 +154,8 @@
mResolvedDirection = layoutDirection;
if (mIndentLines > 0) {
// Invalidate layout.
- setHint(getHint());
+ nullLayouts();
+ requestLayout();
}
}
}
@@ -175,7 +173,8 @@
if (mIndentLines != lines) {
mIndentLines = lines;
// Invalidate layout.
- setHint(getHint());
+ nullLayouts();
+ requestLayout();
return true;
}
return false;
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 4104b6ca9d..15b2718 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -276,9 +276,16 @@
boolean hasNormal = false;
for (int i = mMessageContainer.getChildCount() - 1; i >= 0; i--) {
View child = mMessageContainer.getChildAt(i);
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
if (child instanceof MessagingLinearLayout.MessagingChild) {
int type = ((MessagingLinearLayout.MessagingChild) child).getMeasuredType();
- if (type == MEASURED_TOO_SMALL) {
+ boolean tooSmall = type == MEASURED_TOO_SMALL;
+ final MessagingLinearLayout.LayoutParams lp =
+ (MessagingLinearLayout.LayoutParams) child.getLayoutParams();
+ tooSmall |= lp.hide;
+ if (tooSmall) {
if (hasNormal) {
return MEASURED_SHORTENED;
} else {
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 99d9839..c15b7ee 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -205,37 +205,8 @@
return 0;
}
-static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
- jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
- jboolean useBpfStats) {
- ScopedUtfChars path8(env, path);
- if (path8.c_str() == NULL) {
- return -1;
- }
-
- std::vector<std::string> limitIfaces;
- if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
- int num = env->GetArrayLength(limitIfacesObj);
- for (int i = 0; i < num; i++) {
- jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
- ScopedUtfChars string8(env, string);
- if (string8.c_str() != NULL) {
- limitIfaces.push_back(std::string(string8.c_str()));
- }
- }
- }
- std::vector<stats_line> lines;
-
-
- if (useBpfStats) {
- if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
- return -1;
- } else {
- if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
- limitUid, path8.c_str()) < 0)
- return -1;
- }
-
+static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats,
+ std::vector<stats_line>& lines) {
int size = lines.size();
bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
@@ -308,14 +279,58 @@
env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
}
-
return 0;
}
+static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path,
+ jint limitUid, jobjectArray limitIfacesObj, jint limitTag,
+ jboolean useBpfStats) {
+ ScopedUtfChars path8(env, path);
+ if (path8.c_str() == NULL) {
+ return -1;
+ }
+
+ std::vector<std::string> limitIfaces;
+ if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
+ int num = env->GetArrayLength(limitIfacesObj);
+ for (int i = 0; i < num; i++) {
+ jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
+ ScopedUtfChars string8(env, string);
+ if (string8.c_str() != NULL) {
+ limitIfaces.push_back(std::string(string8.c_str()));
+ }
+ }
+ }
+ std::vector<stats_line> lines;
+
+
+ if (useBpfStats) {
+ if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0)
+ return -1;
+ } else {
+ if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag,
+ limitUid, path8.c_str()) < 0)
+ return -1;
+ }
+
+ return statsLinesToNetworkStats(env, clazz, stats, lines);
+}
+
+static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) {
+ std::vector<stats_line> lines;
+
+ if (parseBpfNetworkStatsDev(&lines) < 0)
+ return -1;
+
+ return statsLinesToNetworkStats(env, clazz, stats, lines);
+}
+
static const JNINativeMethod gMethods[] = {
{ "nativeReadNetworkStatsDetail",
"(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",
- (void*) readNetworkStatsDetail }
+ (void*) readNetworkStatsDetail },
+ { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I",
+ (void*) readNetworkStatsDev },
};
int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) {
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 503bd21..64e1239 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -161,6 +161,7 @@
optional CpuFreqProto cpu_freq = 2004 [
(section).type = SECTION_FILE,
+ (section).device_specific = true,
(section).args = "/sys/devices/system/cpu/cpufreq/all_time_in_state"
];
@@ -170,7 +171,8 @@
];
optional BatteryTypeProto battery_type = 2006 [
- (section).type = SECTION_NONE, // disabled since the path is device specific!
+ (section).type = SECTION_FILE,
+ (section).device_specific = true,
(section).args = "/sys/class/power_supply/bms/battery_type"
];
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index d1861d9..26eb4e7 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -24,7 +24,7 @@
>
<include layout="@layout/notification_template_header" />
- <LinearLayout
+ <com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_action_list_margin_target"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -34,7 +34,7 @@
android:clipToPadding="false"
android:orientation="vertical">
- <LinearLayout
+ <com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_main_column"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -62,7 +62,7 @@
android:visibility="gone"
android:textAlignment="viewStart"
/>
- </LinearLayout>
+ </com.android.internal.widget.RemeasuringLinearLayout>
<ViewStub android:layout="@layout/notification_material_reply_text"
android:id="@+id/notification_material_reply_container"
@@ -75,6 +75,6 @@
android:layout_marginEnd="@dimen/notification_content_margin_end"
android:layout_marginTop="@dimen/notification_content_margin" />
<include layout="@layout/notification_material_action_list" />
- </LinearLayout>
+ </com.android.internal.widget.RemeasuringLinearLayout>
<include layout="@layout/notification_template_right_icon" />
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index 08f8f57..0717d96 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -36,6 +36,7 @@
android:id="@+id/message_name"
style="@style/Widget.Material.Notification.MessagingName"
android:layout_width="wrap_content"
+ android:textAlignment="viewStart"
/>
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/group_message_container"
diff --git a/core/res/res/layout/notification_template_messaging_text_message.xml b/core/res/res/layout/notification_template_messaging_text_message.xml
index e728e69..3611186 100644
--- a/core/res/res/layout/notification_template_messaging_text_message.xml
+++ b/core/res/res/layout/notification_template_messaging_text_message.xml
@@ -17,5 +17,6 @@
<com.android.internal.widget.MessagingTextMessage
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/message_text"
+ android:textAlignment="viewStart"
style="@style/Widget.Material.Notification.MessagingText"
/>
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 9ef58ab..1750dac 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -16,7 +16,11 @@
package android.app.activity;
+import static android.content.Intent.ACTION_EDIT;
+import static android.content.Intent.ACTION_VIEW;
+
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import android.app.Activity;
import android.app.ActivityThread;
@@ -27,6 +31,7 @@
import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.StopActivityItem;
import android.content.Intent;
+import android.os.IBinder;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
@@ -94,6 +99,36 @@
});
}
+ /** Verify that custom intent set via Activity#setIntent() is preserved on relaunch. */
+ @Test
+ public void testCustomIntentPreservedOnRelaunch() throws Exception {
+ final Intent initIntent = new Intent();
+ initIntent.setAction(ACTION_VIEW);
+ final Activity activity = mActivityTestRule.launchActivity(initIntent);
+ IBinder token = activity.getActivityToken();
+
+ final ActivityThread activityThread = activity.getActivityThread();
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // Recreate and check that intent is still the same.
+ activity.recreate();
+
+ final Activity newActivity = activityThread.getActivity(token);
+ assertTrue("Original intent must be preserved after recreate",
+ initIntent.filterEquals(newActivity.getIntent()));
+
+ // Set custom intent, recreate and check if it is preserved.
+ final Intent customIntent = new Intent();
+ customIntent.setAction(ACTION_EDIT);
+ newActivity.setIntent(customIntent);
+
+ activity.recreate();
+
+ final Activity lastActivity = activityThread.getActivity(token);
+ assertTrue("Custom intent must be preserved after recreate",
+ customIntent.filterEquals(lastActivity.getIntent()));
+ });
+ }
+
private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
null, 0, new MergedConfiguration(), false /* preserveWindow */);
diff --git a/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java b/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
new file mode 100644
index 0000000..e21143d
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/widget/BackgroundFallbackTest.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import static android.view.View.VISIBLE;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.test.InstrumentationRegistry;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+public class BackgroundFallbackTest {
+
+ private static final int NAVBAR_BOTTOM = 0;
+ private static final int NAVBAR_LEFT = 1;
+ private static final int NAVBAR_RIGHT = 2;
+
+ private static final int SCREEN_HEIGHT = 2000;
+ private static final int SCREEN_WIDTH = 1000;
+ private static final int STATUS_HEIGHT = 100;
+ private static final int NAV_SIZE = 200;
+
+ private static final boolean INSET_CONTENT_VIEWS = true;
+ private static final boolean DONT_INSET_CONTENT_VIEWS = false;
+
+ BackgroundFallback mFallback;
+ Drawable mDrawableMock;
+
+ ViewGroup mStatusBarView;
+ ViewGroup mNavigationBarView;
+
+ ViewGroup mDecorViewMock;
+ ViewGroup mContentRootMock;
+ ViewGroup mContentContainerMock;
+ ViewGroup mContentMock;
+
+ int mLastTop = 0;
+
+ @Before
+ public void setUp() throws Exception {
+ mFallback = new BackgroundFallback();
+ mDrawableMock = mock(Drawable.class);
+
+ mFallback.setDrawable(mDrawableMock);
+
+ }
+
+ @Test
+ public void hasFallback_withDrawable_true() {
+ mFallback.setDrawable(mDrawableMock);
+ assertThat(mFallback.hasFallback(), is(true));
+ }
+
+ @Test
+ public void hasFallback_withoutDrawable_false() {
+ mFallback.setDrawable(null);
+ assertThat(mFallback.hasFallback(), is(false));
+ }
+
+ @Test
+ public void draw_portrait_noFallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_BOTTOM);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_portrait_translucentBars_fallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_BOTTOM);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyFallbackTop(STATUS_HEIGHT);
+ verifyFallbackBottom(NAV_SIZE);
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_landscape_translucentBars_fallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_RIGHT);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyFallbackTop(STATUS_HEIGHT);
+ verifyFallbackRight(NAV_SIZE);
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_seascape_translucentBars_fallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_LEFT);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyFallbackTop(STATUS_HEIGHT);
+ verifyFallbackLeft(NAV_SIZE);
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_landscape_noFallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_RIGHT);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_seascape_noFallback() {
+ setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_LEFT);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ @Test
+ public void draw_seascape_translucentBars_noInsets_noFallback() {
+ setUpViewHierarchy(DONT_INSET_CONTENT_VIEWS, NAVBAR_LEFT);
+ setTranslucent(mStatusBarView);
+ setTranslucent(mNavigationBarView);
+
+ mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock,
+ mStatusBarView, mNavigationBarView);
+
+ verifyNoMoreInteractions(mDrawableMock);
+ }
+
+ private void verifyFallbackTop(int size) {
+ verify(mDrawableMock).setBounds(0, 0, SCREEN_WIDTH, size);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ mLastTop = size;
+ }
+
+ private void verifyFallbackLeft(int size) {
+ verify(mDrawableMock).setBounds(0, mLastTop, size, SCREEN_HEIGHT);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ }
+
+ private void verifyFallbackRight(int size) {
+ verify(mDrawableMock).setBounds(SCREEN_WIDTH - size, mLastTop, SCREEN_WIDTH, SCREEN_HEIGHT);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ }
+
+ private void verifyFallbackBottom(int size) {
+ verify(mDrawableMock).setBounds(0, SCREEN_HEIGHT - size, SCREEN_WIDTH, SCREEN_HEIGHT);
+ verify(mDrawableMock, atLeastOnce()).draw(any());
+ }
+
+ private void setUpViewHierarchy(boolean insetContentViews, int navBarPosition) {
+ int insetLeft = 0;
+ int insetTop = 0;
+ int insetRight = 0;
+ int insetBottom = 0;
+
+ mStatusBarView = mockView(0, 0, SCREEN_WIDTH, STATUS_HEIGHT,
+ new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetTop = STATUS_HEIGHT;
+ }
+
+ switch (navBarPosition) {
+ case NAVBAR_BOTTOM:
+ mNavigationBarView = mockView(0, SCREEN_HEIGHT - NAV_SIZE, SCREEN_WIDTH,
+ SCREEN_HEIGHT, new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetBottom = NAV_SIZE;
+ }
+ break;
+ case NAVBAR_LEFT:
+ mNavigationBarView = mockView(0, 0, NAV_SIZE, SCREEN_HEIGHT,
+ new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetLeft = NAV_SIZE;
+ }
+ break;
+ case NAVBAR_RIGHT:
+ mNavigationBarView = mockView(SCREEN_WIDTH - NAV_SIZE, 0, SCREEN_WIDTH,
+ SCREEN_HEIGHT, new ColorDrawable(Color.BLACK), VISIBLE, emptyList());
+ if (insetContentViews) {
+ insetRight = NAV_SIZE;
+ }
+ break;
+ }
+
+ mContentMock = mockView(0, 0, SCREEN_WIDTH - insetLeft - insetRight,
+ SCREEN_HEIGHT - insetTop - insetBottom, null, VISIBLE, emptyList());
+ mContentContainerMock = mockView(0, 0, SCREEN_WIDTH - insetLeft - insetRight,
+ SCREEN_HEIGHT - insetTop - insetBottom, null, VISIBLE, asList(mContentMock));
+ mContentRootMock = mockView(insetLeft, insetTop, SCREEN_WIDTH - insetRight,
+ SCREEN_HEIGHT - insetBottom, null, VISIBLE, asList(mContentContainerMock));
+
+ mDecorViewMock = mockView(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null, VISIBLE,
+ asList(mContentRootMock, mStatusBarView, mNavigationBarView));
+ }
+
+ private void setTranslucent(ViewGroup bar) {
+ bar.setBackground(new ColorDrawable(Color.TRANSPARENT));
+ }
+
+ private ViewGroup mockView(int left, int top, int right, int bottom, Drawable background,
+ int visibility, List<ViewGroup> children) {
+ final ViewGroup v = new FrameLayout(InstrumentationRegistry.getTargetContext());
+
+ v.layout(left, top, right, bottom);
+ v.setBackground(background);
+ v.setVisibility(visibility);
+
+ for (ViewGroup c : children) {
+ v.addView(c);
+ }
+
+ return v;
+ }
+}
\ No newline at end of file
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
index a7f4d4d..fd33133 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.cpp
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -57,7 +57,8 @@
int pxOffset = -(scrollPx % (mItemSpacing + mItemHeight));
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- mListView->stagingProperties().getWidth(), mListView->stagingProperties().getHeight()));
+ mListView->stagingProperties().getWidth(), mListView->stagingProperties().getHeight(),
+ mListView.get()));
for (size_t ci = 0; ci < mListItems.size(); ci++) {
// update item position
auto listItem = mListItems[(ci + itemIndexOffset) % mListItems.size()];
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 1bfa046..2752ae9 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -250,7 +250,8 @@
static void recordNode(RenderNode& node, std::function<void(Canvas&)> contentCallback) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- node.stagingProperties().getWidth(), node.stagingProperties().getHeight()));
+ node.stagingProperties().getWidth(), node.stagingProperties().getHeight(),
+ &node));
contentCallback(*canvas.get());
node.setStagingDisplayList(canvas->finishRecording());
}
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index 38999cb..f0a5e9d 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -44,7 +44,8 @@
std::unique_ptr<Canvas> canvas(
Canvas::create_recording_canvas(container->stagingProperties().getWidth(),
- container->stagingProperties().getHeight()));
+ container->stagingProperties().getHeight(),
+ container.get()));
Paint paint;
paint.setAntiAlias(true);
diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp
index 003d8e9..a64e844 100644
--- a/libs/hwui/tests/common/scenes/TvApp.cpp
+++ b/libs/hwui/tests/common/scenes/TvApp.cpp
@@ -194,7 +194,8 @@
// re-recording card's canvas, not necessary but to add some burden to CPU
std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas(
- card->stagingProperties().getWidth(), card->stagingProperties().getHeight()));
+ card->stagingProperties().getWidth(), card->stagingProperties().getHeight(),
+ card.get()));
sp<RenderNode> image = mImages[ci];
sp<RenderNode> infoArea = mInfoAreas[ci];
cardcanvas->drawRenderNode(infoArea.get());
@@ -205,14 +206,16 @@
sp<RenderNode> overlay = mOverlays[ci];
std::unique_ptr<Canvas> canvas(
Canvas::create_recording_canvas(overlay->stagingProperties().getWidth(),
- overlay->stagingProperties().getHeight()));
+ overlay->stagingProperties().getHeight(),
+ overlay.get()));
canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver);
overlay->setStagingDisplayList(canvas->finishRecording());
cardcanvas->drawRenderNode(overlay.get());
} else {
// re-recording image node's canvas, animating ColorFilter
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
- image->stagingProperties().getWidth(), image->stagingProperties().getHeight()));
+ image->stagingProperties().getWidth(), image->stagingProperties().getHeight(),
+ image.get()));
SkPaint paint;
sk_sp<SkColorFilter> filter(
SkColorFilter::MakeModeFilter((curFrame % 150) << 24, SkBlendMode::kSrcATop));
diff --git a/libs/incident/proto/android/section.proto b/libs/incident/proto/android/section.proto
index b3ed393..e8280ed 100644
--- a/libs/incident/proto/android/section.proto
+++ b/libs/incident/proto/android/section.proto
@@ -51,6 +51,7 @@
message SectionFlags {
optional SectionType type = 1 [default = SECTION_NONE];
optional string args = 2;
+ optional bool device_specific = 3 [default = false];
}
extend google.protobuf.FieldOptions {
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 2a82fc9..0a720a5 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -38,6 +38,9 @@
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
@@ -360,14 +363,19 @@
@Override
protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
+ return getFileForDocId(docId, visible, true);
+ }
+
+ private File getFileForDocId(String docId, boolean visible, boolean mustExist)
+ throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
- return buildFile(root, docId, visible);
+ return buildFile(root, docId, visible, mustExist);
}
private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
throws FileNotFoundException {
RootInfo root = getRootFromDocId(docId);
- return Pair.create(root, buildFile(root, docId, visible));
+ return Pair.create(root, buildFile(root, docId, visible, true));
}
private RootInfo getRootFromDocId(String docId) throws FileNotFoundException {
@@ -385,7 +393,7 @@
return root;
}
- private File buildFile(RootInfo root, String docId, boolean visible)
+ private File buildFile(RootInfo root, String docId, boolean visible, boolean mustExist)
throws FileNotFoundException {
final int splitIndex = docId.indexOf(':', 1);
final String path = docId.substring(splitIndex + 1);
@@ -398,7 +406,7 @@
target.mkdirs();
}
target = new File(target, path);
- if (!target.exists()) {
+ if (mustExist && !target.exists()) {
throw new FileNotFoundException("Missing file for " + docId + " at " + target);
}
return target;
@@ -410,6 +418,19 @@
}
@Override
+ protected void onDocIdChanged(String docId) {
+ try {
+ // Touch the visible path to ensure that any sdcardfs caches have
+ // been updated to reflect underlying changes on disk.
+ final File visiblePath = getFileForDocId(docId, true, false);
+ if (visiblePath != null) {
+ Os.access(visiblePath.getAbsolutePath(), OsConstants.F_OK);
+ }
+ } catch (FileNotFoundException | ErrnoException ignored) {
+ }
+ }
+
+ @Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
synchronized (mRootsLock) {
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index cfcecbc..59e5cfb 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -250,19 +250,6 @@
<item>Best Effort (Adaptive Bit Rate)</item>
</string-array>
- <!-- TODO: Enable for translation per b/73007419 -->
- <!-- Summaries for Bluetooth Audio Active Device status. [CHAR LIMIT=50]-->
- <string-array name="bluetooth_audio_active_device_summaries" translatable="false" >
- <!-- Status message when the device is not Active. -->
- <item></item>
- <!-- Status message when the device is Active for Media and Phone. -->
- <item>, active</item>
- <!-- Status message when the device is Active for Media only. -->
- <item>, active(media)</item>
- <!-- Status message when the device is Active for Phone only. -->
- <item>, active(phone)</item>
- </string-array>
-
<!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
<string-array name="select_logd_size_titles">
<item>Off</item>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 50c9b5c..a46c3e6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -566,7 +566,7 @@
<!-- UI debug setting: Trigger Bluetooth Audio LDAC Playback Quality Selection -->
<string name="bluetooth_select_a2dp_codec_ldac_playback_quality">Bluetooth Audio LDAC Codec: Playback Quality</string>
<!-- UI debug setting: Select Bluetooth Audio LDAC Codec: LDAC Playback Quality -->
- <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Trigger Bluetooth Audio LDAC Codec\u000ASelection: Playback Quality</string>
+ <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title">Trigger Bluetooth Audio LDAC\u000ACodec Selection: Playback Quality</string>
<!-- [CHAR LIMIT=NONE] Label for displaying Bluetooth Audio Codec Parameters while streaming -->
<string name="bluetooth_select_a2dp_codec_streaming_label">Streaming: <xliff:g id="streaming_parameter">%1$s</xliff:g></string>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index 3193101..87983b9 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -20,39 +20,54 @@
<!-- This is a view that shows general status information in Keyguard. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/res-auto"
android:id="@+id/presentation"
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+ <!-- This is mostly keyguard_status_view.xml with minor modifications -->
<com.android.keyguard.KeyguardStatusView
android:id="@+id/clock"
android:orientation="vertical"
- android:layout_width="wrap_content"
+ android:layout_width="410dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:orientation="vertical"
- android:focusable="true">
- <TextClock
- android:id="@+id/clock_view"
- android:layout_width="wrap_content"
+ android:orientation="vertical">
+ <RelativeLayout
+ android:id="@+id/keyguard_clock_container"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:textColor="?attr/wallpaperTextColor"
- android:singleLine="true"
- style="@style/widget_big_thin"
- android:format12Hour="@string/keyguard_widget_12_hours_format"
- android:format24Hour="@string/keyguard_widget_24_hours_format"
- android:baselineAligned="true" />
-
- <include layout="@layout/keyguard_status_area" />
+ android:layout_gravity="center_horizontal|top">
+ <TextClock
+ android:id="@+id/clock_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_alignParentTop="true"
+ android:letterSpacing="0.03"
+ android:textColor="?attr/wallpaperTextColor"
+ android:singleLine="true"
+ style="@style/widget_big_thin"
+ android:format12Hour="@string/keyguard_widget_12_hours_format"
+ android:format24Hour="@string/keyguard_widget_24_hours_format" />
+ <View
+ android:id="@+id/clock_separator"
+ android:layout_width="@dimen/widget_separator_width"
+ android:layout_height="@dimen/widget_separator_thickness"
+ android:layout_below="@id/clock_view"
+ android:background="#f00"
+ android:layout_centerHorizontal="true" />
+ <include layout="@layout/keyguard_status_area"
+ android:id="@+id/keyguard_status_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/clock_separator" />
+ </RelativeLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="10dip"
+ android:layout_marginTop="@dimen/widget_vertical_padding"
android:layout_gravity="center_horizontal"
android:src="@drawable/kg_security_lock_normal" />
</LinearLayout>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 712b6e5..d628ca8 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -77,7 +77,7 @@
<dimen name="password_char_padding">8dp</dimen>
<!-- The vertical margin between the date and the owner info. -->
- <dimen name="date_owner_info_margin">2dp</dimen>
+ <dimen name="date_owner_info_margin">4dp</dimen>
<!-- The translation for disappearing security views after having solved them. -->
<dimen name="disappear_y_translation">-32dp</dimen>
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 5a0e767..1be3375 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -16,6 +16,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/menu_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
diff --git a/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml b/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml
deleted file mode 100644
index eff9b36..0000000
--- a/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
- Copyright 2018, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Extends Framelayout -->
-<com.android.systemui.statusbar.DndSuppressingNotificationsView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/hidden_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone">
- <TextView
- android:id="@+id/hidden_notifications"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="64dp"
- android:paddingTop="28dp"
- android:gravity="top|center_horizontal"
- android:textColor="?attr/wallpaperTextColor"
- android:textSize="16sp"
- android:text="@string/dnd_suppressing_shade_text"/>
-</com.android.systemui.statusbar.DndSuppressingNotificationsView>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1b4b15e..f1f80c7 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1064,7 +1064,7 @@
<string name="manage_notifications_text">Manage notifications</string>
<!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
- <string name="dnd_suppressing_shade_text">Notifications hidden by Do Not Disturb</string>
+ <string name="dnd_suppressing_shade_text">Do Not Disturb is hiding notifications</string>
<!-- Media projection permission dialog action text. [CHAR LIMIT=60] -->
<string name="media_projection_action_text">Start now</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index c73da3c..c9b14dc 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -320,7 +320,7 @@
<item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
<item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
<item name="android:colorError">@*android:color/error_color_material_light</item>
- <item name="android:colorControlHighlight">@*android:color/primary_text_material_light</item>
+ <item name="android:colorControlHighlight">#40000000</item>
<item name="passwordStyle">@style/PasswordTheme.Light</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index c31cea2..33cac3b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -145,17 +145,13 @@
}
private void showSlice() {
- if (mPulsing) {
+ if (mPulsing || mSlice == null) {
mTitle.setVisibility(GONE);
mRow.setVisibility(GONE);
mContentChangeListener.accept(getLayoutTransition() != null);
return;
}
- if (mSlice == null) {
- return;
- }
-
ListContent lc = new ListContent(getContext(), mSlice);
mHasHeader = lc.hasHeader();
List<SliceItem> subItems = lc.getRowItems();
@@ -170,18 +166,6 @@
SliceItem mainTitle = header.getTitleItem();
CharSequence title = mainTitle != null ? mainTitle.getText() : null;
mTitle.setText(title);
-
- // Check if we're already ellipsizing the text.
- // We're going to figure out the best possible line break if not.
- Layout layout = mTitle.getLayout();
- if (layout != null){
- final int lineCount = layout.getLineCount();
- if (lineCount > 0) {
- if (layout.getEllipsisCount(lineCount - 1) == 0) {
- mTitle.setText(findBestLineBreak(title));
- }
- }
- }
}
mClickActions.clear();
@@ -385,6 +369,27 @@
mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size);
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ // Find best ellipsis strategy for the title.
+ // Done on onMeasure since TextView#getLayout needs a measure pass to calculate its bounds.
+ Layout layout = mTitle.getLayout();
+ if (layout != null) {
+ final int lineCount = layout.getLineCount();
+ if (lineCount > 0) {
+ if (layout.getEllipsisCount(lineCount - 1) == 0) {
+ CharSequence title = mTitle.getText();
+ CharSequence bestLineBreak = findBestLineBreak(title);
+ if (!TextUtils.equals(title, bestLineBreak)) {
+ mTitle.setText(bestLineBreak);
+ }
+ }
+ }
+ }
+ }
+
public static class Row extends LinearLayout {
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 727b62b..454528e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -164,7 +164,9 @@
protected void onFinishInflate() {
super.onFinishInflate();
mLogoutView = findViewById(R.id.logout);
- mLogoutView.setOnClickListener(this::onLogoutClicked);
+ if (mLogoutView != null) {
+ mLogoutView.setOnClickListener(this::onLogoutClicked);
+ }
mClockView = findViewById(R.id.clock_view);
mClockView.setShowCurrentUserTime(true);
@@ -296,6 +298,9 @@
}
public int getLogoutButtonHeight() {
+ if (mLogoutView == null) {
+ return 0;
+ }
return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
}
@@ -304,6 +309,9 @@
}
private void updateLogoutView() {
+ if (mLogoutView == null) {
+ return;
+ }
mLogoutView.setVisibility(shouldShowLogout() ? VISIBLE : GONE);
// Logout button will stay in language of user 0 if we don't set that manually.
mLogoutView.setText(mContext.getResources().getString(
@@ -390,7 +398,9 @@
private void updateDark() {
boolean dark = mDarkAmount == 1;
- mLogoutView.setAlpha(dark ? 0 : 1);
+ if (mLogoutView != null) {
+ mLogoutView.setAlpha(dark ? 0 : 1);
+ }
if (mOwnerInfo != null) {
boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
mOwnerInfo.setVisibility(hasText && mDarkAmount != 1 ? VISIBLE : GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
index 282a8f1..9307c22 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
@@ -66,6 +66,7 @@
public static final String TAG_OPS = "OverviewProxyService";
public static final boolean DEBUG_OVERVIEW_PROXY = false;
private static final long BACKOFF_MILLIS = 5000;
+ private static final long DEFERRED_CALLBACK_MILLIS = 5000;
private final Context mContext;
private final Handler mHandler;
@@ -162,6 +163,12 @@
}
};
+ private final Runnable mDeferredConnectionCallback = () -> {
+ Log.w(TAG_OPS, "Binder supposed established connection but actual connection to service "
+ + "timed out, trying again");
+ internalConnectToCurrentUser();
+ };
+
private final BroadcastReceiver mLauncherStateChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -181,22 +188,33 @@
private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- if (service != null) {
- mConnectionBackoffAttempts = 0;
- mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
- // Listen for launcher's death
- try {
- service.linkToDeath(mOverviewServiceDeathRcpt, 0);
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Lost connection to launcher service", e);
- }
- try {
- mOverviewProxy.onBind(mSysUiProxy);
- } catch (RemoteException e) {
- Log.e(TAG_OPS, "Failed to call onBind()", e);
- }
- notifyConnectionChanged();
+ mHandler.removeCallbacks(mDeferredConnectionCallback);
+ mConnectionBackoffAttempts = 0;
+ mOverviewProxy = IOverviewProxy.Stub.asInterface(service);
+ // Listen for launcher's death
+ try {
+ service.linkToDeath(mOverviewServiceDeathRcpt, 0);
+ } catch (RemoteException e) {
+ Log.e(TAG_OPS, "Lost connection to launcher service", e);
}
+ try {
+ mOverviewProxy.onBind(mSysUiProxy);
+ } catch (RemoteException e) {
+ Log.e(TAG_OPS, "Failed to call onBind()", e);
+ }
+ notifyConnectionChanged();
+ }
+
+ @Override
+ public void onNullBinding(ComponentName name) {
+ Log.w(TAG_OPS, "Null binding of '" + name + "', try reconnecting");
+ internalConnectToCurrentUser();
+ }
+
+ @Override
+ public void onBindingDied(ComponentName name) {
+ Log.w(TAG_OPS, "Binding died of '" + name + "', try reconnecting");
+ internalConnectToCurrentUser();
}
@Override
@@ -262,6 +280,9 @@
// If user has not setup yet or already connected, do not try to connect
if (!mDeviceProvisionedController.isCurrentUserSetup() || !isEnabled()) {
+ Log.v(TAG_OPS, "Cannot attempt connection, is setup "
+ + mDeviceProvisionedController.isCurrentUserSetup() + ", is enabled "
+ + isEnabled());
return;
}
mHandler.removeCallbacks(mConnectionRunnable);
@@ -275,11 +296,16 @@
} catch (SecurityException e) {
Log.e(TAG_OPS, "Unable to bind because of security error", e);
}
- if (!bound) {
+ if (bound) {
+ // Ensure that connection has been established even if it thinks it is bound
+ mHandler.postDelayed(mDeferredConnectionCallback, DEFERRED_CALLBACK_MILLIS);
+ } else {
// Retry after exponential backoff timeout
final long timeoutMs = (long) Math.scalb(BACKOFF_MILLIS, mConnectionBackoffAttempts);
mHandler.postDelayed(mConnectionRunnable, timeoutMs);
mConnectionBackoffAttempts++;
+ Log.w(TAG_OPS, "Failed to connect on attempt " + mConnectionBackoffAttempts
+ + " will try again in " + timeoutMs + "ms");
}
}
@@ -351,6 +377,10 @@
pw.print(" isCurrentUserSetup="); pw.println(mDeviceProvisionedController
.isCurrentUserSetup());
pw.print(" isConnected="); pw.println(mOverviewProxy != null);
+ pw.print(" mRecentsComponentName="); pw.println(mRecentsComponentName);
+ pw.print(" mIsEnabled="); pw.println(isEnabled());
+ pw.print(" mInteractionFlags="); pw.println(mInteractionFlags);
+ pw.print(" mQuickStepIntent="); pw.println(mQuickStepIntent);
}
public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index f595d77..a7163bb 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -94,6 +94,8 @@
String OVERVIEW_OPENED_FROM_HOME_COUNT = "OverviewOpenedFromHomeCount";
String HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING = "HasSeenRecentsSwipeUpOnboarding";
String HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING = "HasSeenRecentsQuickScrubOnboarding";
+ String HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE =
+ "HasDismissedRecentsQuickScrubOnboardingOnce";
String SEEN_RINGER_GUIDANCE_COUNT = "RingerGuidanceCount";
String QS_TILE_SPECS_REVEALED = "QsTileSpecsRevealed";
String QS_HAS_TURNED_OFF_MOBILE_DATA = "QsHasTurnedOffMobileData";
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 087d481..ea3f95e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -344,8 +344,8 @@
} else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
mItems.add(getSettingsAction());
} else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
- if (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0
+ if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0, getCurrentUser().id) != 0
&& shouldDisplayLockdown()) {
mItems.add(getLockdownAction());
mHasLockdownButton = true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 441d29b..5adeec3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -67,6 +67,10 @@
private static final long EDIT_ID = 10000;
private static final long DIVIDER_ID = 20000;
+ private static final int ACTION_NONE = 0;
+ private static final int ACTION_ADD = 1;
+ private static final int ACTION_MOVE = 2;
+
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -82,7 +86,7 @@
private List<TileInfo> mAllTiles;
private Holder mCurrentDrag;
- private boolean mAccessibilityMoving;
+ private int mAccessibilityAction = ACTION_NONE;
private int mAccessibilityFromIndex;
private QSTileHost mHost;
@@ -172,7 +176,7 @@
@Override
public int getItemViewType(int position) {
- if (mAccessibilityMoving && position == mEditIndex - 1) {
+ if (mAccessibilityAction == ACTION_ADD && position == mEditIndex - 1) {
return TYPE_ACCESSIBLE_DROP;
}
if (position == mTileDividerIndex) {
@@ -266,18 +270,18 @@
if (position > mEditIndex) {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_add_tile_label, info.state.label);
- } else if (mAccessibilityMoving) {
+ } else if (mAccessibilityAction != ACTION_NONE) {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_position_label, position + 1);
} else {
info.state.contentDescription = mContext.getString(
R.string.accessibility_qs_edit_tile_label, position + 1, info.state.label);
}
- holder.mTileView.onStateChanged(info.state);
+ holder.mTileView.handleStateChanged(info.state);
holder.mTileView.setShowAppLabel(position > mEditIndex && !info.isSystem);
if (mAccessibilityManager.isTouchExplorationEnabled()) {
- final boolean selectable = !mAccessibilityMoving || position < mEditIndex;
+ final boolean selectable = mAccessibilityAction == ACTION_NONE || position < mEditIndex;
holder.mTileView.setClickable(selectable);
holder.mTileView.setFocusable(selectable);
holder.mTileView.setImportantForAccessibility(selectable
@@ -288,13 +292,13 @@
@Override
public void onClick(View v) {
int position = holder.getAdapterPosition();
- if (mAccessibilityMoving) {
+ if (mAccessibilityAction != ACTION_NONE) {
selectPosition(position, v);
} else {
if (position < mEditIndex && canRemoveTiles()) {
showAccessibilityDialog(position, v);
} else {
- startAccessibleDrag(position);
+ startAccessibleAdd(position);
}
}
}
@@ -302,21 +306,21 @@
}
}
}
-
+
private boolean canRemoveTiles() {
return mCurrentSpecs.size() > MIN_NUM_TILES;
}
private void selectPosition(int position, View v) {
- // Remove the placeholder.
- mAccessibilityMoving = false;
- mTiles.remove(mEditIndex--);
- notifyItemRemoved(mEditIndex - 1);
- // Don't remove items when the last position is selected.
- if (position == mEditIndex) position--;
-
+ if (mAccessibilityAction == ACTION_ADD) {
+ // Remove the placeholder.
+ mTiles.remove(mEditIndex--);
+ notifyItemRemoved(mEditIndex);
+ // Don't remove items when the last position is selected.
+ if (position == mEditIndex - 1) position--;
+ }
+ mAccessibilityAction = ACTION_NONE;
move(mAccessibilityFromIndex, position, v);
-
notifyDataSetChanged();
}
@@ -331,7 +335,7 @@
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
- startAccessibleDrag(position);
+ startAccessibleMove(position);
} else {
move(position, info.isSystem ? mEditIndex : mTileDividerIndex, v);
notifyItemChanged(mTileDividerIndex);
@@ -345,12 +349,18 @@
dialog.show();
}
- private void startAccessibleDrag(int position) {
- mAccessibilityMoving = true;
- mNeedsFocus = true;
+ private void startAccessibleAdd(int position) {
mAccessibilityFromIndex = position;
+ mAccessibilityAction = ACTION_ADD;
// Add placeholder for last slot.
mTiles.add(mEditIndex++, null);
+ mNeedsFocus = true;
+ notifyDataSetChanged();
+ }
+
+ private void startAccessibleMove(int position) {
+ mAccessibilityFromIndex = position;
+ mAccessibilityAction = ACTION_MOVE;
notifyDataSetChanged();
}
@@ -365,30 +375,26 @@
CharSequence fromLabel = mTiles.get(from).state.label;
move(from, to, mTiles);
updateDividerLocations();
- CharSequence announcement;
if (to >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_REMOVE,
from);
- announcement = mContext.getString(R.string.accessibility_qs_edit_tile_removed,
- fromLabel);
} else if (from >= mEditIndex) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_ADD,
to);
- announcement = mContext.getString(R.string.accessibility_qs_edit_tile_added,
- fromLabel, (to + 1));
+ v.announceForAccessibility(mContext.getString(R.string.accessibility_qs_edit_tile_added,
+ fromLabel, (to + 1)));
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_MOVE_SPEC,
strip(mTiles.get(to)));
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_QS_EDIT_MOVE,
to);
- announcement = mContext.getString(R.string.accessibility_qs_edit_tile_moved,
- fromLabel, (to + 1));
+ v.announceForAccessibility(mContext.getString(R.string.accessibility_qs_edit_tile_moved,
+ fromLabel, (to + 1)));
}
- v.announceForAccessibility(announcement);
saveSpecs(mHost);
return true;
}
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 63be4b7..c7191f8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -45,8 +45,8 @@
* Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the
* nearest hour and add on the AM/PM indicator.
*/
- private static final String HOUR_MINUTE_DATE_TIME_PATTERN = "h a";
- private static final String APPROXIMATE_HOUR_DATE_TIME_PATTERN = "h:m a";
+ private static final String PATTERN_HOUR = "h a";
+ private static final String PATTERN_HOUR_MINUTE = "h:mm a";
private ColorDisplayController mController;
@@ -142,9 +142,7 @@
// Choose between just showing the hour or also showing the minutes (based on the
// user-selected toggle time). This helps reduce how much space the label takes.
toggleTimeFormat = DateTimeFormatter.ofPattern(
- toggleTime.getMinute() == 0
- ? HOUR_MINUTE_DATE_TIME_PATTERN
- : APPROXIMATE_HOUR_DATE_TIME_PATTERN);
+ toggleTime.getMinute() == 0 ? PATTERN_HOUR : PATTERN_HOUR_MINUTE);
return mContext.getString(toggleTimeStringRes, toggleTime.format(toggleTimeFormat));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index ffa1444..31933d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
@@ -66,7 +67,7 @@
private static final String TAG = "RecentsOnboarding";
private static final boolean RESET_PREFS_FOR_DEBUG = false;
- private static final boolean ONBOARDING_ENABLED = false;
+ private static final boolean ONBOARDING_ENABLED = true;
private static final long SHOW_DELAY_MS = 500;
private static final long SHOW_HIDE_DURATION_MS = 300;
// Show swipe-up tips after opening overview from home this number of times.
@@ -76,9 +77,6 @@
// After explicitly dismissing, show again after launching this number of apps for swipe-up
// tips.
private static final int SWIPE_UP_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 5;
- // After explicitly dismissing, show again after launching this number of apps for QuickScrub
- // tips.
- private static final int QUICK_SCRUB_SHOW_ON_APP_LAUNCH_AFTER_DISMISS = 10;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -99,7 +97,7 @@
private boolean mHasDismissedSwipeUpTip;
private boolean mHasDismissedQuickScrubTip;
private int mNumAppsLaunchedSinceSwipeUpTipDismiss;
- private int mNumAppsLaunchedSinceQuickScrubTipDismiss;
+ private int mOverviewOpenedCountSinceQuickScrubTipDismiss;
private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
@Override
@@ -145,10 +143,9 @@
} else {
if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
if (mHasDismissedQuickScrubTip) {
- mNumAppsLaunchedSinceQuickScrubTipDismiss++;
- if (mNumAppsLaunchedSinceQuickScrubTipDismiss
- == QUICK_SCRUB_SHOW_ON_APP_LAUNCH_AFTER_DISMISS) {
- mNumAppsLaunchedSinceQuickScrubTipDismiss = 0;
+ if (mOverviewOpenedCountSinceQuickScrubTipDismiss
+ == QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+ mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
show(R.string.recents_quick_scrub_onboarding);
}
} else {
@@ -166,14 +163,19 @@
new OverviewProxyService.OverviewProxyListener() {
@Override
public void onOverviewShown(boolean fromHome) {
- boolean alreadySeenRecentsOnboarding = hasSeenSwipeUpOnboarding();
- if (!alreadySeenRecentsOnboarding && !fromHome) {
+ if (!hasSeenSwipeUpOnboarding() && !fromHome) {
setHasSeenSwipeUpOnboarding(true);
}
if (fromHome) {
setOpenedOverviewFromHomeCount(getOpenedOverviewFromHomeCount() + 1);
}
setOpenedOverviewCount(getOpenedOverviewCount() + 1);
+
+ if (getOpenedOverviewCount() >= QUICK_SCRUB_SHOW_ON_OVERVIEW_OPENED_COUNT) {
+ if (mHasDismissedQuickScrubTip) {
+ mOverviewOpenedCountSinceQuickScrubTipDismiss++;
+ }
+ }
}
@Override
@@ -191,7 +193,11 @@
public void onViewAttachedToWindow(View view) {
if (view == mLayout) {
mLayoutAttachedToWindow = true;
- mHasDismissedSwipeUpTip = false;
+ if (view.getTag().equals(R.string.recents_swipe_up_onboarding)) {
+ mHasDismissedSwipeUpTip = false;
+ } else {
+ mHasDismissedQuickScrubTip = false;
+ }
}
}
@@ -199,6 +205,17 @@
public void onViewDetachedFromWindow(View view) {
if (view == mLayout) {
mLayoutAttachedToWindow = false;
+ if (view.getTag().equals(R.string.recents_quick_scrub_onboarding)) {
+ mHasDismissedQuickScrubTip = true;
+ if (hasDismissedQuickScrubOnboardingOnce()) {
+ // If user dismisses the quick scrub tip twice, we consider user has seen it
+ // and do not show it again.
+ setHasSeenQuickScrubOnboarding(true);
+ } else {
+ setHasDismissedQuickScrubOnboardingOnce(true);
+ }
+ mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
+ }
}
}
};
@@ -228,15 +245,6 @@
if (v.getTag().equals(R.string.recents_swipe_up_onboarding)) {
mHasDismissedSwipeUpTip = true;
mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- } else {
- if (mHasDismissedQuickScrubTip) {
- // If user dismisses the quick scrub tip twice, we consider user has seen it
- // and do not show it again.
- setHasSeenQuickScrubOnboarding(true);
- } else {
- mHasDismissedQuickScrubTip = true;
- }
- mNumAppsLaunchedSinceQuickScrubTipDismiss = 0;
}
});
@@ -252,6 +260,7 @@
if (RESET_PREFS_FOR_DEBUG) {
setHasSeenSwipeUpOnboarding(false);
setHasSeenQuickScrubOnboarding(false);
+ setHasDismissedQuickScrubOnboardingOnce(false);
setOpenedOverviewCount(0);
setOpenedOverviewFromHomeCount(0);
}
@@ -289,7 +298,7 @@
mHasDismissedSwipeUpTip = false;
mHasDismissedQuickScrubTip = false;
mNumAppsLaunchedSinceSwipeUpTipDismiss = 0;
- mNumAppsLaunchedSinceQuickScrubTipDismiss = 0;
+ mOverviewOpenedCountSinceQuickScrubTipDismiss = 0;
hide(false);
}
@@ -303,11 +312,15 @@
if (!shouldShow()) {
return;
}
+ if (mLayoutAttachedToWindow) {
+ hide(false);
+ }
mDismissView.setTag(stringRes);
+ mLayout.setTag(stringRes);
mTextView.setText(stringRes);
// Only show in portrait.
int orientation = mContext.getResources().getConfiguration().orientation;
- if (!mLayoutAttachedToWindow && orientation == Configuration.ORIENTATION_PORTRAIT) {
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
mLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mWindowManager.addView(mLayout, getWindowLayoutParams());
@@ -348,11 +361,11 @@
.withLayer()
.setDuration(SHOW_HIDE_DURATION_MS)
.setInterpolator(new AccelerateInterpolator())
- .withEndAction(() -> mWindowManager.removeView(mLayout))
+ .withEndAction(() -> mWindowManager.removeViewImmediate(mLayout))
.start();
} else {
mLayout.animate().cancel();
- mWindowManager.removeView(mLayout);
+ mWindowManager.removeViewImmediate(mLayout);
}
}
}
@@ -400,6 +413,16 @@
}
}
+ private boolean hasDismissedQuickScrubOnboardingOnce() {
+ return Prefs.getBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE, false);
+ }
+
+ private void setHasDismissedQuickScrubOnboardingOnce(
+ boolean hasDismissedQuickScrubOnboardingOnce) {
+ Prefs.putBoolean(mContext, HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE,
+ hasDismissedQuickScrubOnboardingOnce);
+ }
+
private int getOpenedOverviewFromHomeCount() {
return Prefs.getInt(mContext, OVERVIEW_OPENED_FROM_HOME_COUNT, 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 79fea9f..c8ee8735 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -376,15 +376,15 @@
public Rect getNonMinimizedSplitScreenSecondaryBounds() {
calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
+ mOtherTaskRect.bottom -= mStableInsets.bottom;
switch (mDockSide) {
case WindowManager.DOCKED_LEFT:
+ mOtherTaskRect.top += mStableInsets.top;
mOtherTaskRect.right -= mStableInsets.right;
break;
case WindowManager.DOCKED_RIGHT:
- mOtherTaskRect.left -= mStableInsets.left;
- break;
- case WindowManager.DOCKED_TOP:
- mOtherTaskRect.bottom -= mStableInsets.bottom;
+ mOtherTaskRect.top += mStableInsets.top;
+ mOtherTaskRect.left += mStableInsets.left;
break;
}
return mOtherTaskRect;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java
deleted file mode 100644
index db3a02d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.annotation.ColorInt;
-import android.annotation.DrawableRes;
-import android.annotation.IntegerRes;
-import android.annotation.StringRes;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.graphics.drawable.Icon;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.systemui.R;
-import com.android.systemui.statusbar.stack.ExpandableViewState;
-import com.android.systemui.statusbar.stack.StackScrollState;
-
-public class DndSuppressingNotificationsView extends StackScrollerDecorView {
-
- private TextView mText;
- private @StringRes int mTextId = R.string.dnd_suppressing_shade_text;
-
- public DndSuppressingNotificationsView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- mText.setText(mTextId);
- }
-
- @Override
- protected View findContentView() {
- return findViewById(R.id.hidden_container);
- }
-
- @Override
- protected View findSecondaryView() {
- return null;
- }
-
- public void setColor(@ColorInt int color) {
- mText.setTextColor(color);
- }
-
- public void setOnContentClickListener(OnClickListener listener) {
- mText.setOnClickListener(listener);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mText = findViewById(R.id.hidden_notifications);
- }
-
- @Override
- public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
- return new DndSuppressingViewState();
- }
-
- public class DndSuppressingViewState extends ExpandableViewState {
- @Override
- public void applyToView(View view) {
- super.applyToView(view);
- if (view instanceof DndSuppressingNotificationsView) {
- DndSuppressingNotificationsView dndView = (DndSuppressingNotificationsView) view;
- boolean visible = this.clipTopAmount <= mText.getPaddingTop() * 0.6f;
- dndView.performVisibilityAnimation(visible && !dndView.willBeGone());
- }
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3efeb6e..27fa48a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1635,6 +1635,7 @@
mTranslateableViews.get(i).setTranslationX(0);
}
invalidateOutline();
+ getEntry().expandedIcon.setScrollX(0);
}
mMenuRow.resetMenu();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b442bb4..419e262 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,6 +16,11 @@
package com.android.systemui.statusbar;
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
@@ -52,6 +57,7 @@
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -68,6 +74,7 @@
private final Environment mEnvironment;
private HeadsUpManager mHeadsUpManager;
+ final ZenModeController mZen = Dependency.get(ZenModeController.class);
final ForegroundServiceController mFsc = Dependency.get(ForegroundServiceController.class);
public static final class Entry {
@@ -474,6 +481,10 @@
}
protected boolean isExemptFromDndVisualSuppression(Entry entry) {
+ if (isNotificationBlockedByPolicy(entry.notification.getNotification())) {
+ return false;
+ }
+
if ((entry.notification.getNotification().flags
& Notification.FLAG_FOREGROUND_SERVICE) != 0) {
return true;
@@ -487,6 +498,26 @@
return false;
}
+ /**
+ * Categories that are explicitly called out on DND settings screens are always blocked, if
+ * DND has flagged them, even if they are foreground or system notifications that might
+ * otherwise visually bypass DND.
+ */
+ protected boolean isNotificationBlockedByPolicy(Notification n) {
+ if (isCategory(CATEGORY_CALL, n)
+ || isCategory(CATEGORY_MESSAGE, n)
+ || isCategory(CATEGORY_ALARM, n)
+ || isCategory(CATEGORY_EVENT, n)
+ || isCategory(CATEGORY_REMINDER, n)) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isCategory(String category, Notification n) {
+ return Objects.equals(n.category, category);
+ }
+
public int getImportance(String key) {
if (mRankingMap != null) {
getRanking(key, mTmpRanking);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index bf94c1f..c3b4fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -191,6 +191,7 @@
}
private void updateState(WifiIconState state) {
+ setContentDescription(state.contentDescription);
if (mState.resId != state.resId && state.resId >= 0) {
NeutralGoodDrawable drawable = NeutralGoodDrawable
.create(mLightContext, mDarkContext, state.resId);
@@ -212,6 +213,7 @@
}
private void initViewState() {
+ setContentDescription(mState.contentDescription);
if (mState.resId >= 0) {
NeutralGoodDrawable drawable = NeutralGoodDrawable.create(
mLightContext, mDarkContext, mState.resId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 5768fa2..fc76f78e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -38,6 +38,8 @@
import androidx.car.widget.PagedListView;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import com.android.internal.util.UserIcons;
import com.android.settingslib.users.UserManagerHelper;
import com.android.systemui.R;
@@ -193,7 +195,10 @@
@Override
public void onBindViewHolder(UserAdapterViewHolder holder, int position) {
UserRecord userRecord = mUsers.get(position);
- holder.mUserAvatarImageView.setImageBitmap(getUserRecordIcon(userRecord));
+ RoundedBitmapDrawable circleIcon = RoundedBitmapDrawableFactory.create(mRes,
+ getUserRecordIcon(userRecord));
+ circleIcon.setCircular(true);
+ holder.mUserAvatarImageView.setImageDrawable(circleIcon);
holder.mUserNameTextView.setText(userRecord.mInfo.name);
holder.mView.setOnClickListener(v -> {
if (userRecord == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index fc8ceb6..8ede224 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -530,6 +530,7 @@
protected void reset() {
mTransformedView = null;
+ mTransformInfo = null;
mSameAsAny = false;
mTransformationEndX = UNDEFINED;
mTransformationEndY = UNDEFINED;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 7284ee8..2161655 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -14,8 +14,12 @@
package com.android.systemui.statusbar.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.view.View;
+import com.android.systemui.Interpolators;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -26,6 +30,8 @@
* multiples of the same nav bar icon appearing.
*/
public class ButtonDispatcher {
+ private final static int FADE_DURATION_IN = 150;
+ private final static int FADE_DURATION_OUT = 100;
private final ArrayList<View> mViews = new ArrayList<>();
@@ -36,13 +42,24 @@
private View.OnLongClickListener mLongClickListener;
private View.OnHoverListener mOnHoverListener;
private Boolean mLongClickable;
- private Integer mAlpha;
+ private Float mAlpha;
private Float mDarkIntensity;
private Integer mVisibility = -1;
private Boolean mDelayTouchFeedback;
private KeyButtonDrawable mImageDrawable;
private View mCurrentView;
private boolean mVertical;
+ private ValueAnimator mFadeAnimator;
+
+ private final ValueAnimator.AnimatorUpdateListener mAlphaListener = animation ->
+ setAlpha((float) animation.getAnimatedValue());
+
+ private final AnimatorListenerAdapter mFadeListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setVisibility(getAlpha() == 1 ? View.VISIBLE : View.INVISIBLE);
+ }
+ };
public ButtonDispatcher(int id) {
mId = id;
@@ -64,19 +81,22 @@
if (mAlpha != null) {
view.setAlpha(mAlpha);
}
- if (mDarkIntensity != null) {
- ((ButtonInterface) view).setDarkIntensity(mDarkIntensity);
- }
- if (mVisibility != null) {
+ if (mVisibility != null && mVisibility != -1) {
view.setVisibility(mVisibility);
}
- if (mImageDrawable != null) {
- ((ButtonInterface) view).setImageDrawable(mImageDrawable);
+ if (view instanceof ButtonInterface) {
+ final ButtonInterface button = (ButtonInterface) view;
+ if (mDarkIntensity != null) {
+ button.setDarkIntensity(mDarkIntensity);
+ }
+ if (mImageDrawable != null) {
+ button.setImageDrawable(mImageDrawable);
+ }
+ if (mDelayTouchFeedback != null) {
+ button.setDelayTouchFeedback(mDelayTouchFeedback);
+ }
+ button.setVertical(mVertical);
}
- if (mDelayTouchFeedback != null) {
- ((ButtonInterface) view).setDelayTouchFeedback(mDelayTouchFeedback);
- }
- ((ButtonInterface) view).setVertical(mVertical);
}
public int getId() {
@@ -99,7 +119,9 @@
mImageDrawable = drawable;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).setImageDrawable(mImageDrawable);
+ }
}
}
@@ -116,11 +138,13 @@
// This seems to be an instantaneous thing, so not going to persist it.
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).abortCurrentGesture();
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).abortCurrentGesture();
+ }
}
}
- public void setAlpha(int alpha) {
+ public void setAlpha(float alpha) {
mAlpha = alpha;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
@@ -132,7 +156,9 @@
mDarkIntensity = darkIntensity;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).setDarkIntensity(darkIntensity);
+ }
}
}
@@ -140,7 +166,9 @@
mDelayTouchFeedback = delay;
final int N = mViews.size();
for (int i = 0; i < N; i++) {
- ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay);
+ if (mViews.get(i) instanceof ButtonInterface) {
+ ((ButtonInterface) mViews.get(i)).setDelayTouchFeedback(delay);
+ }
}
}
@@ -192,6 +220,19 @@
}
}
+ public void animateFade(boolean in) {
+ if (mFadeAnimator != null) {
+ mFadeAnimator.cancel();
+ }
+ mFadeAnimator = ValueAnimator.ofFloat(getAlpha(), in ? 1 : 0);
+ mFadeAnimator.setDuration(in? FADE_DURATION_IN : FADE_DURATION_OUT);
+ mFadeAnimator.setInterpolator(in ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ mFadeAnimator.addListener(mFadeListener);
+ mFadeAnimator.addUpdateListener(mAlphaListener);
+ mFadeAnimator.start();
+ setVisibility(View.VISIBLE);
+ }
+
public ArrayList<View> getViews() {
return mViews;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 91cf8f0..4885c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -168,10 +168,10 @@
}
}
- public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDisatchers) {
- mButtonDispatchers = buttonDisatchers;
- for (int i = 0; i < buttonDisatchers.size(); i++) {
- initiallyFill(buttonDisatchers.valueAt(i));
+ public void setButtonDispatchers(SparseArray<ButtonDispatcher> buttonDispatchers) {
+ mButtonDispatchers = buttonDispatchers;
+ for (int i = 0; i < buttonDispatchers.size(); i++) {
+ initiallyFill(buttonDispatchers.valueAt(i));
}
}
@@ -220,7 +220,8 @@
// and will only happen once.
if (parent.getChildAt(i).getId() == buttonDispatcher.getId()) {
buttonDispatcher.addView(parent.getChildAt(i));
- } else if (parent.getChildAt(i) instanceof ViewGroup) {
+ }
+ if (parent.getChildAt(i) instanceof ViewGroup) {
addAll(buttonDispatcher, (ViewGroup) parent.getChildAt(i));
}
}
@@ -411,7 +412,8 @@
final int indexOfKey = mButtonDispatchers.indexOfKey(v.getId());
if (indexOfKey >= 0) {
mButtonDispatchers.valueAt(indexOfKey).addView(v);
- } else if (v instanceof ViewGroup) {
+ }
+ if (v instanceof ViewGroup) {
final ViewGroup viewGroup = (ViewGroup)v;
final int N = viewGroup.getChildCount();
for (int i = 0; i < N; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6dbe9f8..6cc96da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -260,6 +260,8 @@
new ButtonDispatcher(R.id.accessibility_button));
mButtonDispatchers.put(R.id.rotate_suggestion,
new ButtonDispatcher(R.id.rotate_suggestion));
+ mButtonDispatchers.put(R.id.menu_container,
+ new ButtonDispatcher(R.id.menu_container));
mDeadZone = new DeadZone(this);
}
@@ -368,6 +370,10 @@
return mButtonDispatchers.get(R.id.rotate_suggestion);
}
+ public ButtonDispatcher getMenuContainer() {
+ return mButtonDispatchers.get(R.id.menu_container);
+ }
+
public SparseArray<ButtonDispatcher> getButtonDispatchers() {
return mButtonDispatchers;
}
@@ -796,6 +802,10 @@
public boolean isRotateButtonVisible() { return mShowRotateButton; }
+ public void setMenuContainerVisibility(boolean visible) {
+ getMenuContainer().animateFade(visible);
+ }
+
@Override
public void onFinishInflate() {
mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 8bb73da..b650944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -199,7 +199,6 @@
private ValueAnimator mQsSizeChangeAnimator;
private boolean mShowEmptyShadeView;
- private boolean mShowDndView;
private boolean mQsScrimEnabled = true;
private boolean mLastAnnouncementWasQuickSettings;
@@ -1600,8 +1599,8 @@
// When only empty shade view is visible in QS collapsed state, simulate that we would have
// it in expanded QS state as well so we don't run into troubles when fading the view in/out
// and expanding/collapsing the whole panel from/to quick settings.
- if ((mNotificationStackScroller.getNotGoneChildCount() == 0
- && mShowEmptyShadeView) || mShowDndView) {
+ if (mNotificationStackScroller.getNotGoneChildCount() == 0
+ && mShowEmptyShadeView) {
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -2244,17 +2243,13 @@
return mDozing;
}
- public void showDndView(boolean dndViewVisible) {
- mShowDndView = dndViewVisible;
- mNotificationStackScroller.updateDndView(mShowDndView && !mQsExpanded);
- }
-
public void showEmptyShadeView(boolean emptyShadeViewVisible) {
mShowEmptyShadeView = emptyShadeViewVisible;
updateEmptyShadeView();
}
private void updateEmptyShadeView() {
+
// Hide "No notifications" in QS.
mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 6b0ac94..d9ba313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -327,7 +327,7 @@
- mNavigationBarView.getPaddingTop();
final int x1, x2, y1, y2;
if (mIsVertical) {
- x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingStart();
+ x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingLeft();
x2 = x1 + mTrackThickness;
y1 = mDragPositive ? height / 2 : mTrackPadding;
y2 = y1 + height / 2 - mTrackPadding;
@@ -401,6 +401,10 @@
mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
mTrackAnimator.setFloatValues(0, 1);
mTrackAnimator.start();
+
+ // Hide menu buttons on nav bar until quick scrub has ended
+ mNavigationBarView.setMenuContainerVisibility(false /* visible */);
+
try {
mOverviewEventSender.getProxy().onQuickScrubStart();
if (DEBUG_OVERVIEW_PROXY) {
@@ -416,6 +420,10 @@
private void endQuickScrub(boolean animate) {
if (mQuickScrubActive || mDragScrubActive) {
animateEnd();
+
+ // Restore the nav bar menu buttons visibility
+ mNavigationBarView.setMenuContainerVisibility(true /* visible */);
+
if (mQuickScrubActive) {
try {
mOverviewEventSender.getProxy().onQuickScrubEnd();
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 5f07599..061677c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -20,7 +20,6 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.provider.Settings.Global.ZEN_MODE_OFF;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
@@ -169,7 +168,6 @@
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
@@ -190,7 +188,6 @@
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -416,7 +413,7 @@
protected NotificationViewHierarchyManager mViewHierarchyManager;
protected AppOpsListener mAppOpsListener;
protected KeyguardViewMediator mKeyguardViewMediator;
- protected ZenModeController mZenController;
+ private ZenModeController mZenController;
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -881,7 +878,6 @@
mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
inflateEmptyShadeView();
- inflateDndView();
inflateFooterView();
mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
@@ -1149,7 +1145,6 @@
protected void reevaluateStyles() {
inflateFooterView();
updateFooter();
- inflateDndView();
inflateEmptyShadeView();
updateEmptyShadeView();
}
@@ -1171,19 +1166,6 @@
mStackScroller.setEmptyShadeView(mEmptyShadeView);
}
- private void inflateDndView() {
- if (mStackScroller == null) {
- return;
- }
- mDndView = (DndSuppressingNotificationsView) LayoutInflater.from(mContext).inflate(
- R.layout.status_bar_dnd_suppressing_notifications, mStackScroller, false);
- mDndView.setOnContentClickListener(v -> {
- Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
- startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
- });
- mStackScroller.setDndView(mDndView);
- }
-
private void inflateFooterView() {
if (mStackScroller == null) {
return;
@@ -1477,11 +1459,9 @@
@VisibleForTesting
protected void updateFooter() {
boolean showFooterView = mState != StatusBarState.KEYGUARD
- && !areNotificationsHidden()
&& mEntryManager.getNotificationData().getActiveNotifications().size() != 0
&& !mRemoteInputManager.getController().isRemoteInputActive();
boolean showDismissView = mClearAllEnabled && mState != StatusBarState.KEYGUARD
- && !areNotificationsHidden()
&& hasActiveClearableNotifications();
mStackScroller.updateFooterView(showFooterView, showDismissView);
@@ -1504,13 +1484,10 @@
return false;
}
- @VisibleForTesting
- protected void updateEmptyShadeView() {
- boolean showDndView = mState != StatusBarState.KEYGUARD && areNotificationsHidden();
- boolean showEmptyShadeView = !showDndView
- && mState != StatusBarState.KEYGUARD
- && mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
- mNotificationPanel.showDndView(showDndView);
+ private void updateEmptyShadeView() {
+ boolean showEmptyShadeView =
+ mState != StatusBarState.KEYGUARD &&
+ mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
mNotificationPanel.showEmptyShadeView(showEmptyShadeView);
}
@@ -5017,7 +4994,6 @@
protected NotificationShelf mNotificationShelf;
protected FooterView mFooterView;
protected EmptyShadeView mEmptyShadeView;
- protected DndSuppressingNotificationsView mDndView;
protected AssistManager mAssistManager;
@@ -5502,11 +5478,6 @@
mStackScroller.getChildCount() - offsetFromEnd++);
}
- if (mDndView != null) {
- mStackScroller.changeViewPosition(mDndView,
- mStackScroller.getChildCount() - offsetFromEnd++);
- }
-
mStackScroller.changeViewPosition(mEmptyShadeView,
mStackScroller.getChildCount() - offsetFromEnd++);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 6a8d3a5..48a9fb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -20,6 +20,7 @@
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
@@ -30,6 +31,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
+
/**
* Base class for dialogs that should appear over panels and keyguard.
*/
@@ -99,24 +101,40 @@
}
public static void registerDismissListener(Dialog dialog) {
- boolean[] registered = new boolean[1];
- Context context = dialog.getContext();
- final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (dialog != null) {
- dialog.dismiss();
- }
- }
- };
- context.registerReceiverAsUser(mReceiver, UserHandle.CURRENT,
- new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), null, null);
- registered[0] = true;
- dialog.setOnDismissListener(d -> {
- if (registered[0]) {
- context.unregisterReceiver(mReceiver);
- registered[0] = false;
- }
- });
+ DismissReceiver dismissReceiver = new DismissReceiver(dialog);
+ dismissReceiver.register();
}
-}
+
+ private static class DismissReceiver extends BroadcastReceiver implements OnDismissListener {
+ private static final IntentFilter INTENT_FILTER = new IntentFilter();
+ static {
+ INTENT_FILTER.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
+ }
+
+ private final Dialog mDialog;
+ private boolean mRegistered;
+
+ DismissReceiver(Dialog dialog) {
+ mDialog = dialog;
+ }
+
+ void register() {
+ mDialog.getContext()
+ .registerReceiverAsUser(this, UserHandle.CURRENT, INTENT_FILTER, null, null);
+ mRegistered = true;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mDialog.dismiss();
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mRegistered) {
+ mDialog.getContext().unregisterReceiver(this);
+ mRegistered = false;
+ }
+ }
+ }}
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 eeaa6cb..5275e27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -81,7 +81,6 @@
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
@@ -237,7 +236,6 @@
protected boolean mScrollingEnabled;
protected FooterView mFooterView;
protected EmptyShadeView mEmptyShadeView;
- protected DndSuppressingNotificationsView mDndView;
private boolean mDismissAllInProgress;
private boolean mFadeNotificationsOnDismiss;
@@ -1008,8 +1006,7 @@
private float getAppearEndPosition() {
int appearPosition;
int notGoneChildCount = getNotGoneChildCount();
- if ((mEmptyShadeView.getVisibility() == GONE && mDndView.getVisibility() == GONE)
- && notGoneChildCount != 0) {
+ if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
if (isHeadsUpTransition()
|| (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
appearPosition = getTopHeadsUpPinnedHeight();
@@ -1019,8 +1016,6 @@
appearPosition += mShelf.getIntrinsicHeight();
}
}
- } else if (mEmptyShadeView.getVisibility() == GONE) {
- appearPosition = mDndView.getHeight();
} else {
appearPosition = mEmptyShadeView.getHeight();
}
@@ -2613,6 +2608,19 @@
return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
}
+ public int getFirstChildIntrinsicHeight() {
+ final ExpandableView firstChild = getFirstChildNotGone();
+ int firstChildMinHeight = firstChild != null
+ ? firstChild.getIntrinsicHeight()
+ : mEmptyShadeView != null
+ ? mEmptyShadeView.getIntrinsicHeight()
+ : mCollapsedSize;
+ if (mOwnScrollY > 0) {
+ firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
+ }
+ return firstChildMinHeight;
+ }
+
public float getTopPaddingOverflow() {
return mTopPaddingOverflow;
}
@@ -3910,7 +3918,6 @@
final int textColor = Utils.getColorAttr(context, R.attr.wallpaperTextColor);
mFooterView.setTextColor(textColor);
mEmptyShadeView.setTextColor(textColor);
- mDndView.setColor(textColor);
}
public void goToFullShade(long delay) {
@@ -3918,7 +3925,6 @@
mFooterView.setInvisible();
}
mEmptyShadeView.setInvisible();
- mDndView.setInvisible();
mGoToFullShadeNeedsAnimation = true;
mGoToFullShadeDelay = delay;
mNeedsAnimation = true;
@@ -4070,39 +4076,25 @@
int newVisibility = visible ? VISIBLE : GONE;
boolean changedVisibility = oldVisibility != newVisibility;
- if (changedVisibility) {
+ if (changedVisibility || newVisibility != GONE) {
if (newVisibility != GONE) {
- showFooterView(mEmptyShadeView);
+ int oldText = mEmptyShadeView.getTextResource();
+ int newText;
+ if (mStatusBar.areNotificationsHidden()) {
+ newText = R.string.dnd_suppressing_shade_text;
+ } else {
+ newText = R.string.empty_shade_text;
+ }
+ if (changedVisibility || !Objects.equals(oldText, newText)) {
+ mEmptyShadeView.setText(newText);
+ showFooterView(mEmptyShadeView);
+ }
} else {
hideFooterView(mEmptyShadeView, true);
}
}
}
- public void setDndView(DndSuppressingNotificationsView dndView) {
- int index = -1;
- if (mDndView != null) {
- index = indexOfChild(mDndView);
- removeView(mDndView);
- }
- mDndView = dndView;
- addView(mDndView, index);
- }
-
- public void updateDndView(boolean visible) {
- int oldVisibility = mDndView.willBeGone() ? GONE : mDndView.getVisibility();
- int newVisibility = visible ? VISIBLE : GONE;
-
- boolean changedVisibility = oldVisibility != newVisibility;
- if (changedVisibility) {
- if (newVisibility != GONE) {
- showFooterView(mDndView);
- } else {
- hideFooterView(mDndView, true);
- }
- }
- }
-
public void updateFooterView(boolean visible, boolean showDismissView) {
if (mFooterView == null) {
return;
@@ -4127,16 +4119,10 @@
} else {
footerView.setInvisible();
}
- Runnable onShowFinishRunnable = new Runnable() {
- @Override
- public void run() {
- footerView.setVisibility(VISIBLE);
- footerView.setWillBeGone(false);
- updateContentHeight();
- notifyHeightChangeListener(footerView);
- }
- };
- footerView.performVisibilityAnimation(true, onShowFinishRunnable);
+ footerView.setVisibility(VISIBLE);
+ footerView.setWillBeGone(false);
+ updateContentHeight();
+ notifyHeightChangeListener(footerView);
}
private void hideFooterView(StackScrollerDecorView footerView, boolean isButtonVisible) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index 9a28657..210764a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -21,9 +21,6 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -35,6 +32,7 @@
import java.util.Collections;
import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicBoolean;
import androidx.slice.SliceProvider;
import androidx.slice.SliceSpecs;
@@ -58,12 +56,24 @@
@Test
public void showSlice_notifiesListener() {
ListBuilder builder = new ListBuilder(getContext(), mSliceUri);
- boolean[] notified = {false};
+ AtomicBoolean notified = new AtomicBoolean();
mKeyguardSliceView.setContentChangeListener((hasHeader)-> {
- notified[0] = true;
+ notified.set(true);
});
mKeyguardSliceView.onChanged(builder.build());
- Assert.assertTrue("Listener should be notified about slice changes.", notified[0]);
+ Assert.assertTrue("Listener should be notified about slice changes.",
+ notified.get());
+ }
+
+ @Test
+ public void showSlice_emptySliceNotifiesListener() {
+ AtomicBoolean notified = new AtomicBoolean();
+ mKeyguardSliceView.setContentChangeListener((hasHeader)-> {
+ notified.set(true);
+ });
+ mKeyguardSliceView.onChanged(null);
+ Assert.assertTrue("Listener should be notified about slice changes.",
+ notified.get());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index ab042d4..2a4a5ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -298,4 +298,13 @@
assertEquals(3, mGroupRow.getNumUniqueChannels());
}
+
+ @Test
+ public void testIconScrollXAfterTranslationAndReset() throws Exception {
+ mGroupRow.setTranslation(50);
+ assertEquals(50, -mGroupRow.getEntry().expandedIcon.getScrollX());
+
+ mGroupRow.resetTranslation();
+ assertEquals(0, mGroupRow.getEntry().expandedIcon.getScrollX());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
index d3c3746..8bdaff9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
@@ -18,6 +18,11 @@
import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER;
import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.Notification.CATEGORY_ALARM;
+import static android.app.Notification.CATEGORY_CALL;
+import static android.app.Notification.CATEGORY_EVENT;
+import static android.app.Notification.CATEGORY_MESSAGE;
+import static android.app.Notification.CATEGORY_REMINDER;
import static junit.framework.Assert.assertEquals;
@@ -312,6 +317,40 @@
assertFalse(mNotificationData.shouldSuppressAmbient(entry));
}
+ @Test
+ public void testIsNotExemptFromDndVisualSuppression_hiddenCategories() {
+ initStatusBarNotification(false);
+ when(mMockStatusBarNotification.getKey()).thenReturn(
+ TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY);
+ NotificationData.Entry entry = new NotificationData.Entry(mMockStatusBarNotification);
+ entry.mIsSystemNotification = true;
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_CALL).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+ assertTrue(mNotificationData.shouldSuppressAmbient(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_REMINDER).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_ALARM).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_EVENT).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+
+ when(mMockStatusBarNotification.getNotification()).thenReturn(
+ new Notification.Builder(mContext, "").setCategory(CATEGORY_MESSAGE).build());
+
+ assertFalse(mNotificationData.isExemptFromDndVisualSuppression(entry));
+ }
+
private void initStatusBarNotification(boolean allowDuringSetup) {
Bundle bundle = new Bundle();
bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardPresentationTest.java
new file mode 100644
index 0000000..5429153
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardPresentationTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class KeyguardPresentationTest extends SysuiTestCase {
+ @Test
+ public void testInflation_doesntCrash() {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ inflater.inflate(R.layout.keyguard_presentation, null);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 41cf869..37e0005 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -78,7 +78,6 @@
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.AppOpsListener;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.FooterView;
import com.android.systemui.statusbar.FooterViewButton;
@@ -104,7 +103,6 @@
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import org.junit.Before;
@@ -134,7 +132,6 @@
@Mock private ScrimController mScrimController;
@Mock private ArrayList<Entry> mNotificationList;
@Mock private FingerprintUnlockController mFingerprintUnlockController;
- @Mock private ZenModeController mZenController;
@Mock private NotificationData mNotificationData;
// Mock dependencies:
@@ -166,7 +163,6 @@
mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
- mDependency.injectTestDependency(ZenModeController.class, mZenController);
mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -217,7 +213,7 @@
mRemoteInputManager, mock(NotificationGroupManager.class),
mock(FalsingManager.class), mock(StatusBarWindowManager.class),
mock(NotificationIconAreaController.class), mock(DozeScrimController.class),
- mock(NotificationShelf.class), mLockscreenUserManager, mZenController,
+ mock(NotificationShelf.class), mLockscreenUserManager,
mock(CommandQueue.class));
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
@@ -680,60 +676,6 @@
}
@Test
- public void testDNDView_atEnd() {
- // add footer
- mStatusBar.reevaluateStyles();
-
- // add notification
- ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
- mStackScroller.addContainerView(row);
-
- mStatusBar.onUpdateRowStates();
-
- // move dnd view to end
- verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
- verify(mStackScroller).changeViewPosition(any(DndSuppressingNotificationsView.class),
- eq(-2 /* end */));
- }
-
- @Test
- public void updateEmptyShade_nonNotificationsDndOff() {
- mStatusBar.setBarStateForTest(StatusBarState.SHADE);
- when(mNotificationData.getActiveNotifications()).thenReturn(new ArrayList<>());
- assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
-
- mStatusBar.updateEmptyShadeView();
- verify(mNotificationPanelView).showDndView(false);
- verify(mNotificationPanelView).showEmptyShadeView(true);
- }
-
- @Test
- public void updateEmptyShade_noNotificationsDndOn() {
- mStatusBar.setBarStateForTest(StatusBarState.SHADE);
- when(mNotificationData.getActiveNotifications()).thenReturn(new ArrayList<>());
- assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
- when(mZenController.areNotificationsHiddenInShade()).thenReturn(true);
-
- mStatusBar.updateEmptyShadeView();
- verify(mNotificationPanelView).showDndView(true);
- verify(mNotificationPanelView).showEmptyShadeView(false);
- }
-
- @Test
- public void updateEmptyShade_yesNotificationsDndOff() {
- mStatusBar.setBarStateForTest(StatusBarState.SHADE);
- ArrayList<Entry> entries = new ArrayList<>();
- entries.add(mock(Entry.class));
- when(mNotificationData.getActiveNotifications()).thenReturn(entries);
- assertEquals(1, mEntryManager.getNotificationData().getActiveNotifications().size());
- when(mZenController.areNotificationsHiddenInShade()).thenReturn(false);
-
- mStatusBar.updateEmptyShadeView();
- verify(mNotificationPanelView).showDndView(false);
- verify(mNotificationPanelView).showEmptyShadeView(false);
- }
-
- @Test
public void testSetState_changesIsFullScreenUserSwitcherState() {
mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
assertFalse(mStatusBar.isFullScreenUserSwitcherState());
@@ -779,7 +721,6 @@
DozeScrimController dozeScrimController,
NotificationShelf notificationShelf,
NotificationLockscreenUserManager notificationLockscreenUserManager,
- ZenModeController zenController,
CommandQueue commandQueue) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
@@ -808,7 +749,6 @@
mDozeScrimController = dozeScrimController;
mNotificationShelf = notificationShelf;
mLockscreenUserManager = notificationLockscreenUserManager;
- mZenController = zenController;
mCommandQueue = commandQueue;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index 3d17ec4..eeb4209 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -18,7 +18,6 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -35,7 +34,6 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.TestableDependency;
-import com.android.systemui.statusbar.DndSuppressingNotificationsView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FooterView;
import com.android.systemui.statusbar.NotificationBlockingHelperManager;
@@ -71,7 +69,6 @@
@Mock private NotificationGroupManager mGroupManager;
@Mock private ExpandHelper mExpandHelper;
@Mock private EmptyShadeView mEmptyShadeView;
- @Mock private DndSuppressingNotificationsView mDndView;
@Before
@UiThreadTest
@@ -89,7 +86,6 @@
mStackScroller.setHeadsUpManager(mHeadsUpManager);
mStackScroller.setGroupManager(mGroupManager);
mStackScroller.setEmptyShadeView(mEmptyShadeView);
- mStackScroller.setDndView(mDndView);
// Stub out functionality that isn't necessary to test.
doNothing().when(mBar)
@@ -124,6 +120,40 @@
}
@Test
+ public void updateEmptyView_dndSuppressing() {
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
+ when(mBar.areNotificationsHidden()).thenReturn(true);
+
+ mStackScroller.updateEmptyShadeView(true);
+
+ verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
+ }
+
+ @Test
+ public void updateEmptyView_dndNotSuppressing() {
+ mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
+ when(mBar.areNotificationsHidden()).thenReturn(false);
+
+ mStackScroller.updateEmptyShadeView(true);
+
+ verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+ }
+
+ @Test
+ public void updateEmptyView_noNotificationsToDndSuppressing() {
+ mStackScroller.setEmptyShadeView(mEmptyShadeView);
+ when(mEmptyShadeView.willBeGone()).thenReturn(true);
+ when(mBar.areNotificationsHidden()).thenReturn(false);
+ mStackScroller.updateEmptyShadeView(true);
+ verify(mEmptyShadeView).setText(R.string.empty_shade_text);
+
+ when(mBar.areNotificationsHidden()).thenReturn(true);
+ mStackScroller.updateEmptyShadeView(true);
+ verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
+ }
+
+ @Test
@UiThreadTest
public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
mStackScroller.setExpandedHeight(0f);
@@ -143,7 +173,7 @@
mStackScroller.updateFooterView(true, false);
- verify(view).performVisibilityAnimation(eq(true), any());
+ verify(view).setVisibility(View.VISIBLE);
verify(view).performSecondaryVisibilityAnimation(false);
}
@@ -156,7 +186,7 @@
mStackScroller.updateFooterView(true, true);
- verify(view).performVisibilityAnimation(eq(true), any());
+ verify(view).setVisibility(View.VISIBLE);
verify(view).performSecondaryVisibilityAnimation(true);
}
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 7dd85ba..d61f228 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5740,6 +5740,41 @@
// OS: P
ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS = 1406;
+ // ACTION: Storage initialization wizard initialization choice of external/portable
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_INIT_EXTERNAL = 1407;
+
+ // ACTION: Storage initialization wizard initialization choice of internal/adoptable
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_INIT_INTERNAL = 1408;
+
+ // ACTION: Storage initialization wizard benchmark fast choice of continue
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_FAST_CONTINUE = 1409;
+
+ // ACTION: Storage initialization wizard benchmark slow choice of continue
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_SLOW_CONTINUE = 1410;
+
+ // ACTION: Storage initialization wizard benchmark slow choice of abort
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_BENCHMARK_SLOW_ABORT = 1411;
+
+ // ACTION: Storage initialization wizard migration choice of now
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_MIGRATE_NOW = 1412;
+
+ // ACTION: Storage initialization wizard migration choice of later
+ // CATEGORY: SETTINGS
+ // OS: P
+ ACTION_STORAGE_MIGRATE_LATER = 1413;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
index 90baea0..cc7304a 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformBackupTask.java
@@ -629,6 +629,8 @@
mFullBackupTask.unregisterTask();
switch (mStatus) {
case BackupTransport.TRANSPORT_OK:
+ case BackupTransport.TRANSPORT_QUOTA_EXCEEDED:
+ case BackupTransport.TRANSPORT_PACKAGE_REJECTED:
BackupObserverUtils.sendBackupFinished(mObserver,
BackupManager.SUCCESS);
break;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9994462..72f9d74 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -132,6 +132,7 @@
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
@@ -1992,13 +1993,6 @@
return ret;
}
- private boolean argsContain(String[] args, String target) {
- for (String arg : args) {
- if (target.equals(arg)) return true;
- }
- return false;
- }
-
private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
final long DIAG_TIME_MS = 5000;
@@ -2027,10 +2021,10 @@
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
if (asProto) return;
- if (argsContain(args, DIAG_ARG)) {
+ if (ArrayUtils.contains(args, DIAG_ARG)) {
dumpNetworkDiagnostics(pw);
return;
- } else if (argsContain(args, TETHERING_ARG)) {
+ } else if (ArrayUtils.contains(args, TETHERING_ARG)) {
mTethering.dump(fd, pw, args);
return;
}
@@ -2098,7 +2092,7 @@
pw.println();
mMultipathPolicyTracker.dump(pw);
- if (argsContain(args, SHORT_ARG) == false) {
+ if (ArrayUtils.contains(args, SHORT_ARG) == false) {
pw.println();
synchronized (mValidationLogs) {
pw.println("mValidationLogs (most recent first):");
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 6c35bda..00302b2 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2541,11 +2541,6 @@
synchronized (mLock) {
mLocalUnlockedUsers = ArrayUtils.appendInt(mLocalUnlockedUsers, userId);
}
- if (userId == UserHandle.USER_SYSTEM) {
- String propertyName = "sys.user." + userId + ".ce_available";
- Slog.d(TAG, "Setting property: " + propertyName + "=true");
- SystemProperties.set(propertyName, "true");
- }
}
@Override
@@ -2685,7 +2680,8 @@
}
// Ignore requests to create directories if CE storage is not available
- if (!SystemProperties.getBoolean(propertyName, false)) {
+ if ((userId == UserHandle.USER_SYSTEM)
+ && !SystemProperties.getBoolean(propertyName, false)) {
throw new IllegalStateException("Failed to prepare " + appPath);
}
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 26a8cf7..f24d8cd 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -71,6 +71,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.function.Predicate;
public class TextServicesManagerService extends ITextServicesManager.Stub {
private static final String TAG = TextServicesManagerService.class.getSimpleName();
@@ -396,10 +397,7 @@
final String packageName = sci.getPackageName();
final int change = isPackageDisappearing(packageName);
if (DBG) Slog.d(TAG, "Changing package name: " + packageName);
- if (// Package disappearing
- change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE
- // Package modified
- || isPackageModified(packageName)) {
+ if (change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE) {
SpellCheckerInfo availSci =
findAvailSystemSpellCheckerLocked(packageName, tsd);
// Set the spell checker settings if different than before
@@ -885,6 +883,11 @@
}
synchronized (mLock) {
mListeners.unregister(listener);
+ final IBinder scListenerBinder = listener.asBinder();
+ final Predicate<SessionRequest> removeCondition =
+ request -> request.mScListener.asBinder() == scListenerBinder;
+ mPendingSessionRequests.removeIf(removeCondition);
+ mOnGoingSessionRequests.removeIf(removeCondition);
cleanLocked();
}
}
@@ -934,6 +937,7 @@
if (mUnbindCalled) {
return;
}
+ mListeners.register(request.mScListener);
if (!mConnected) {
mPendingSessionRequests.add(request);
return;
@@ -959,7 +963,6 @@
if (mOnGoingSessionRequests.remove(request)) {
try {
request.mTsListener.onServiceConnected(newSession);
- mListeners.register(request.mScListener);
} catch (RemoteException e) {
// Technically this can happen if the spell checker client app is already
// dead. We can just forget about this request; the request is already
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f413639..b32ece7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -108,6 +108,8 @@
private static final boolean LOG_SERVICE_START_STOP = false;
+ private static final boolean SHOW_DUNGEON_NOTIFICATION = false;
+
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
@@ -942,6 +944,10 @@
smap.mActiveForegroundAppsChanged = false;
}
+ if (!SHOW_DUNGEON_NOTIFICATION) {
+ return;
+ }
+
final NotificationManager nm = (NotificationManager) mAm.mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
final Context context = mAm.mContext;
diff --git a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
index 1149e87..7599afa 100644
--- a/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
+++ b/services/core/java/com/android/server/am/CarUserSwitchingDialog.java
@@ -20,33 +20,41 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.R;
-import com.android.server.pm.UserManagerService;
-import java.io.FileDescriptor;
+
/**
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
* screen immediately after the dialog shows so that the user is informed that something is
* happening in the background rather than just freeze the screen and not know if the user-switch
* affordance was being handled.
- *
*/
final class CarUserSwitchingDialog extends UserSwitchingDialog {
+
private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
- UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
- String switchingToSystemUserMessage) {
+ UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
+ String switchingToSystemUserMessage) {
super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
- switchingToSystemUserMessage);
+ switchingToSystemUserMessage);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
@@ -58,18 +66,104 @@
Resources res = getContext().getResources();
// Custom view due to alignment and font size requirements
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
- null);
+ null);
UserManager userManager =
(UserManager) getContext().getSystemService(Context.USER_SERVICE);
Bitmap bitmap = userManager.getUserIcon(mNewUser.id);
if (bitmap != null) {
+ CircleFramedDrawable drawable = CircleFramedDrawable.getInstance(bitmap,
+ res.getDimension(R.dimen.car_fullscreen_user_pod_image_avatar_height));
((ImageView) view.findViewById(R.id.user_loading_avatar))
- .setImageBitmap(bitmap);
+ .setImageDrawable(drawable);
}
((TextView) view.findViewById(R.id.user_loading))
- .setText(res.getString(R.string.car_loading_profile));
+ .setText(res.getString(R.string.car_loading_profile));
setView(view);
}
+
+ /**
+ * Converts the user icon to a circularly clipped one. This is used in the User Picker and
+ * Settings.
+ */
+ static class CircleFramedDrawable extends Drawable {
+
+ private final Bitmap mBitmap;
+ private final int mSize;
+ private final Paint mPaint;
+
+ private float mScale;
+ private Rect mSrcRect;
+ private RectF mDstRect;
+
+ public static CircleFramedDrawable getInstance(Bitmap icon, float iconSize) {
+ CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
+ return instance;
+ }
+
+ public CircleFramedDrawable(Bitmap icon, int size) {
+ super();
+ mSize = size;
+
+ mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(mBitmap);
+
+ final int width = icon.getWidth();
+ final int height = icon.getHeight();
+ final int square = Math.min(width, height);
+
+ final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2,
+ square, square);
+ final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
+
+ final Path fillPath = new Path();
+ fillPath.addArc(circleRect, 0f, 360f);
+
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+ // opaque circle
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setColor(Color.BLACK);
+ mPaint.setStyle(Paint.Style.FILL);
+ canvas.drawPath(fillPath, mPaint);
+
+ // mask in the icon where the bitmap is opaque
+ mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
+
+ // prepare paint for frame drawing
+ mPaint.setXfermode(null);
+
+ mScale = 1f;
+
+ mSrcRect = new Rect(0, 0, mSize, mSize);
+ mDstRect = new RectF(0, 0, mSize, mSize);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ final float inside = mScale * mSize;
+ final float pad = (mSize - inside) / 2f;
+
+ mDstRect.set(pad, pad, mSize - pad, mSize - pad);
+ canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // Needed to implement abstract method. Do nothing.
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // Needed to implement abstract method. Do nothing.
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index b5047ae..a88f408 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -238,7 +238,9 @@
final ActivityStack targetStack = mDefaultDisplay.getStack(
WINDOWING_MODE_UNDEFINED, mTargetActivityType);
- final ActivityRecord targetActivity = targetStack.getTopActivity();
+ final ActivityRecord targetActivity = targetStack != null
+ ? targetStack.getTopActivity()
+ : null;
if (DEBUG) Slog.d(TAG, "onAnimationFinished(): targetStack=" + targetStack
+ " targetActivity=" + targetActivity
+ " mRestoreTargetBehindStack=" + mRestoreTargetBehindStack);
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index f427819..ac74598 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -20,6 +20,7 @@
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
+import android.net.ip.IpClient;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.IpConnectivityLog;
import android.os.Binder;
@@ -269,10 +270,12 @@
// Dump the rolling buffer of metrics event and pretty print events using a human readable
// format. Also print network dns/connect statistics and default network event time series.
static final String CMD_LIST = "list";
- // By default any other argument will fall into the default case which is remapped to the
- // "list" command. This includes most notably bug reports collected by dumpsys.cpp with
- // the "-a" argument.
- static final String CMD_DEFAULT = CMD_LIST;
+ // Dump all IpClient logs ("ipclient").
+ static final String CMD_IPCLIENT = IpClient.DUMP_ARG;
+ // By default any other argument will fall into the default case which is the equivalent
+ // of calling both the "list" and "ipclient" commands. This includes most notably bug
+ // reports collected by dumpsys.cpp with the "-a" argument.
+ static final String CMD_DEFAULT = "";
@Override
public int logEvent(ConnectivityMetricsEvent event) {
@@ -292,9 +295,20 @@
case CMD_PROTO:
cmdListAsProto(pw);
return;
- case CMD_LIST: // fallthrough
+ case CMD_IPCLIENT: {
+ final String[] ipclientArgs = ((args != null) && (args.length > 1))
+ ? Arrays.copyOfRange(args, 1, args.length)
+ : null;
+ IpClient.dumpAllLogs(pw, ipclientArgs);
+ return;
+ }
+ case CMD_LIST:
+ cmdList(pw);
+ return;
default:
cmdList(pw);
+ pw.println("");
+ IpClient.dumpAllLogs(pw, null);
return;
}
}
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index dbf0940..d0a3757 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import static android.content.Intent.FLAG_ACTIVITY_MATCH_EXTERNAL;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
@@ -366,6 +368,7 @@
final Intent failureIntent = new Intent(origIntent);
boolean requiresSecondPhase = false;
failureIntent.setFlags(failureIntent.getFlags() | Intent.FLAG_IGNORE_EPHEMERAL);
+ failureIntent.setFlags(failureIntent.getFlags() & ~Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
failureIntent.setLaunchToken(token);
ArrayList<AuxiliaryResolveInfo.AuxiliaryFilter> filters = null;
boolean isWebIntent = origIntent.isWebIntent();
@@ -408,6 +411,10 @@
if (filters != null && !filters.isEmpty()) {
return new AuxiliaryResolveInfo(token, requiresSecondPhase, failureIntent, filters);
}
+ // if the match external flag is set, return an empty resolve info
+ if ((origIntent.getFlags() & FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
+ return new AuxiliaryResolveInfo(token, false, failureIntent, null /* filters */);
+ }
// Hash or filter mis-match; no instant apps for this domain.
return null;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f7a0215..fa934fe 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,7 +17,6 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -74,6 +73,7 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.system.ErrnoException;
@@ -111,9 +111,9 @@
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -154,6 +154,8 @@
private static final String ATTR_NAME = "name";
private static final String ATTR_INSTALL_REASON = "installRason";
+ private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
+
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -255,6 +257,8 @@
@GuardedBy("mLock")
private final List<String> mResolvedInstructionSets = new ArrayList<>();
@GuardedBy("mLock")
+ private final List<String> mResolvedNativeLibPaths = new ArrayList<>();
+ @GuardedBy("mLock")
private File mInheritedFilesBase;
private static final FileFilter sAddedFilter = new FileFilter() {
@@ -971,6 +975,26 @@
final File oatDir = new File(toDir, "oat");
createOatDirs(mResolvedInstructionSets, oatDir);
}
+ // pre-create lib dirs for linking if necessary
+ if (!mResolvedNativeLibPaths.isEmpty()) {
+ for (String libPath : mResolvedNativeLibPaths) {
+ // "/lib/arm64" -> ["lib", "arm64"]
+ final int splitIndex = libPath.lastIndexOf('/');
+ if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+ Slog.e(TAG, "Skipping native library creation for linking due to "
+ + "invalid path: " + libPath);
+ continue;
+ }
+ final String libDirPath = libPath.substring(1, splitIndex);
+ final File libDir = new File(toDir, libDirPath);
+ if (!libDir.exists()) {
+ NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+ }
+ final String archDirPath = libPath.substring(splitIndex + 1);
+ NativeLibraryHelper.createNativeLibrarySubdir(
+ new File(libDir, archDirPath));
+ }
+ }
linkFiles(fromFiles, toDir, mInheritedFilesBase);
} else {
// TODO: this should delegate to DCS so the system process
@@ -988,7 +1012,7 @@
computeProgressLocked(true);
// Unpack native libraries
- extractNativeLibraries(mResolvedStageDir, params.abiOverride);
+ extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
// We've reached point of no return; call into PMS to install the stage.
// Regardless of success or failure we always destroy session.
@@ -1028,6 +1052,17 @@
}
/**
+ * Returns true if the session should attempt to inherit any existing native libraries already
+ * extracted at the current install location. This is necessary to prevent double loading of
+ * native libraries already loaded by the running app.
+ */
+ private boolean mayInheritNativeLibs() {
+ return SystemProperties.getBoolean(PROPERTY_NAME_INHERIT_NATIVE, true) &&
+ params.mode == SessionParams.MODE_INHERIT_EXISTING &&
+ (params.installFlags & PackageManager.DONT_KILL_APP) != 0;
+ }
+
+ /**
* Validate install by confirming that all application packages are have
* consistent package name, version code, and signing certificates.
* <p>
@@ -1249,6 +1284,38 @@
}
}
}
+
+ // Inherit native libraries for DONT_KILL sessions.
+ if (mayInheritNativeLibs() && removeSplitList.isEmpty()) {
+ File[] libDirs = new File[]{
+ new File(packageInstallDir, NativeLibraryHelper.LIB_DIR_NAME),
+ new File(packageInstallDir, NativeLibraryHelper.LIB64_DIR_NAME)};
+ for (File libDir : libDirs) {
+ if (!libDir.exists() || !libDir.isDirectory()) {
+ continue;
+ }
+ final List<File> libDirsToInherit = new LinkedList<>();
+ for (File archSubDir : libDir.listFiles()) {
+ if (!archSubDir.isDirectory()) {
+ continue;
+ }
+ String relLibPath;
+ try {
+ relLibPath = getRelativePath(archSubDir, packageInstallDir);
+ } catch (IOException e) {
+ Slog.e(TAG, "Skipping linking of native library directory!", e);
+ // shouldn't be possible, but let's avoid inheriting these to be safe
+ libDirsToInherit.clear();
+ break;
+ }
+ if (!mResolvedNativeLibPaths.contains(relLibPath)) {
+ mResolvedNativeLibPaths.add(relLibPath);
+ }
+ libDirsToInherit.addAll(Arrays.asList(archSubDir.listFiles()));
+ }
+ mResolvedInheritedFiles.addAll(libDirsToInherit);
+ }
+ }
}
}
@@ -1374,11 +1441,13 @@
Slog.d(TAG, "Copied " + fromFiles.size() + " files into " + toDir);
}
- private static void extractNativeLibraries(File packageDir, String abiOverride)
+ private static void extractNativeLibraries(File packageDir, String abiOverride, boolean inherit)
throws PackageManagerException {
- // Always start from a clean slate
final File libDir = new File(packageDir, NativeLibraryHelper.LIB_DIR_NAME);
- NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+ if (!inherit) {
+ // Start from a clean slate
+ NativeLibraryHelper.removeNativeBinariesFromDirLI(libDir, true);
+ }
NativeLibraryHelper.Handle handle = null;
try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 681b0c9..af5521d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16403,22 +16403,6 @@
}
}
- @Override
- public List<String> getPreviousCodePaths(String packageName) {
- final int callingUid = Binder.getCallingUid();
- final List<String> result = new ArrayList<>();
- if (getInstantAppPackageName(callingUid) != null) {
- return result;
- }
- final PackageSetting ps = mSettings.mPackages.get(packageName);
- if (ps != null
- && ps.oldCodePaths != null
- && !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
- result.addAll(ps.oldCodePaths);
- }
- return result;
- }
-
private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, final @ParseFlags int parseFlags,
final @ScanFlags int scanFlags, UserHandle user, int[] allUsers,
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 898ecf3..f8bf9c4 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -844,7 +844,12 @@
}
// If what we are scanning is a system (and possibly privileged) package,
// then make it so, regardless of whether it was previously installed only
- // in the data partition.
+ // in the data partition. Reset first.
+ pkgSetting.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
+ pkgSetting.pkgPrivateFlags &= ~(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
+ | ApplicationInfo.PRIVATE_FLAG_OEM
+ | ApplicationInfo.PRIVATE_FLAG_VENDOR
+ | ApplicationInfo.PRIVATE_FLAG_PRODUCT);
pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
pkgSetting.pkgPrivateFlags |=
pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 96c102b..045a295 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -24,6 +24,8 @@
import android.os.FileUtils;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.os.SystemProperties;
+import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -96,6 +98,14 @@
}
mInstaller.createUserData(volumeUuid, userId, userSerial, flags);
+
+ // CE storage is available after they are prepared.
+ if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 &&
+ (userId == UserHandle.USER_SYSTEM)) {
+ String propertyName = "sys.user." + userId + ".ce_available";
+ Slog.d(TAG, "Setting property: " + propertyName + "=true");
+ SystemProperties.set(propertyName, "true");
+ }
} catch (Exception e) {
logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid
+ " because we failed to prepare: " + e);
@@ -103,7 +113,8 @@
if (allowRecover) {
// Try one last time; if we fail again we're really in trouble
- prepareUserDataLI(volumeUuid, userId, userSerial, flags, false);
+ prepareUserDataLI(volumeUuid, userId, userSerial,
+ flags | StorageManager.FLAG_STORAGE_DE, false);
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 38fb30e..9621edd 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -393,6 +393,8 @@
/** Temporary float array to retrieve 3x3 matrix values. */
private final float[] mTmpFloats = new float[9];
+ private MagnificationSpec mMagnificationSpec;
+
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
final AppWindowToken atoken = w.mAppToken;
@@ -3837,10 +3839,22 @@
}
void applyMagnificationSpec(MagnificationSpec spec) {
+ if (spec.scale != 1.0) {
+ mMagnificationSpec = spec;
+ } else {
+ mMagnificationSpec = null;
+ }
+
applyMagnificationSpec(getPendingTransaction(), spec);
getPendingTransaction().apply();
}
+ void reapplyMagnificationSpec() {
+ if (mMagnificationSpec != null) {
+ applyMagnificationSpec(getPendingTransaction(), mMagnificationSpec);
+ }
+ }
+
@Override
void onParentSet() {
// Since we are the top of the SurfaceControl hierarchy here
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 86aed47..0de3c92 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -808,6 +808,8 @@
void onParentSet() {
super.onParentSet();
setDrawnStateEvaluated(false /*evaluated*/);
+
+ getDisplayContent().reapplyMagnificationSpec();
}
@Override
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index d6999dd..63ae09a 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -54,6 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IState;
import com.android.internal.util.Preconditions;
@@ -74,6 +75,7 @@
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -100,6 +102,36 @@
private static final Class[] sMessageClasses = { IpClient.class, DhcpClient.class };
private static final SparseArray<String> sWhatToString =
MessageUtils.findMessageNames(sMessageClasses);
+ // Two static concurrent hashmaps of interface name to logging classes.
+ // One holds StateMachine logs and the other connectivity packet logs.
+ private static final ConcurrentHashMap<String, SharedLog> sSmLogs = new ConcurrentHashMap<>();
+ private static final ConcurrentHashMap<String, LocalLog> sPktLogs = new ConcurrentHashMap<>();
+
+ // If |args| is non-empty, assume it's a list of interface names for which
+ // we should print IpClient logs (filter out all others).
+ public static void dumpAllLogs(PrintWriter writer, String[] args) {
+ for (String ifname : sSmLogs.keySet()) {
+ if (!ArrayUtils.isEmpty(args) && !ArrayUtils.contains(args, ifname)) continue;
+
+ writer.println(String.format("--- BEGIN %s ---", ifname));
+
+ final SharedLog smLog = sSmLogs.get(ifname);
+ if (smLog != null) {
+ writer.println("State machine log:");
+ smLog.dump(null, writer, null);
+ }
+
+ writer.println("");
+
+ final LocalLog pktLog = sPktLogs.get(ifname);
+ if (pktLog != null) {
+ writer.println("Connectivity packet log:");
+ pktLog.readOnlyLocalLog().dump(null, writer, null);
+ }
+
+ writer.println(String.format("--- END %s ---", ifname));
+ }
+ }
/**
* Callbacks for handling IpClient events.
@@ -680,8 +712,10 @@
mShutdownLatch = new CountDownLatch(1);
mNwService = deps.getNMS();
- mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
- mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
+ sSmLogs.putIfAbsent(mInterfaceName, new SharedLog(MAX_LOG_RECORDS, mTag));
+ mLog = sSmLogs.get(mInterfaceName);
+ sPktLogs.putIfAbsent(mInterfaceName, new LocalLog(MAX_PACKET_RECORDS));
+ mConnectivityPacketLog = sPktLogs.get(mInterfaceName);
mMsgStateLogger = new MessageHandlingLogger();
// TODO: Consider creating, constructing, and passing in some kind of
diff --git a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
index 949c504..b1dad5a 100644
--- a/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/PerformBackupTaskTest.java
@@ -419,7 +419,7 @@
runTask(task);
verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
- verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
}
@Test
@@ -467,8 +467,7 @@
verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS);
verify(mObserver).onResult(PACKAGE_2, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
- // TODO: Should we return the status of the last?
- verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
}
@Test
@@ -488,7 +487,7 @@
runTask(task);
verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
- verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
+ verify(mObserver).backupFinished(BackupManager.SUCCESS);
verify(agentMock.agent).onQuotaExceeded(anyLong(), anyLong());
}
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index fc46b9c..788924b 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -116,20 +116,6 @@
}
@Test
- public void testNetworkStatsSummary() throws Exception {
- stageFile(R.raw.net_dev_typical, file("net/dev"));
-
- final NetworkStats stats = mFactory.readNetworkStatsIfaceDev();
- assertEquals(6, stats.size());
- assertStatsEntry(stats, "lo", UID_ALL, SET_ALL, TAG_NONE, 8308L, 8308L);
- assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L, 489339L);
- assertStatsEntry(stats, "ifb0", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
- assertStatsEntry(stats, "ifb1", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
- assertStatsEntry(stats, "sit0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
- assertStatsEntry(stats, "ip6tnl0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
- }
-
- @Test
public void testNetworkStatsSingle() throws Exception {
stageFile(R.raw.xt_qtaguid_iface_typical, file("net/xt_qtaguid/iface_stat_all"));
diff --git a/tools/aapt2/format/binary/XmlFlattener.cpp b/tools/aapt2/format/binary/XmlFlattener.cpp
index d897941..2fe2424 100644
--- a/tools/aapt2/format/binary/XmlFlattener.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener.cpp
@@ -79,23 +79,31 @@
}
void Visit(const xml::Text* node) override {
- if (util::TrimWhitespace(node->text).empty()) {
- // Skip whitespace only text nodes.
+ std::string text = util::TrimWhitespace(node->text).to_string();
+
+ // Skip whitespace only text nodes.
+ if (text.empty()) {
return;
}
+ // Compact leading and trailing whitespace into a single space
+ if (isspace(node->text[0])) {
+ text = ' ' + text;
+ }
+ if (isspace(node->text[node->text.length() - 1])) {
+ text = text + ' ';
+ }
+
ChunkWriter writer(buffer_);
ResXMLTree_node* flat_node = writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE);
flat_node->lineNumber = util::HostToDevice32(node->line_number);
flat_node->comment.index = util::HostToDevice32(-1);
- ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();
-
// Process plain strings to make sure they get properly escaped.
- StringBuilder builder;
- builder.AppendText(node->text);
- AddString(builder.to_string(), kLowPriority, &flat_text->data);
+ text = StringBuilder(true /*preserve_spaces*/).AppendText(text).to_string();
+ ResXMLTree_cdataExt* flat_text = writer.NextBlock<ResXMLTree_cdataExt>();
+ AddString(text, kLowPriority, &flat_text->data);
writer.Finish();
}
diff --git a/tools/aapt2/format/binary/XmlFlattener_test.cpp b/tools/aapt2/format/binary/XmlFlattener_test.cpp
index 08243fe..25786b1 100644
--- a/tools/aapt2/format/binary/XmlFlattener_test.cpp
+++ b/tools/aapt2/format/binary/XmlFlattener_test.cpp
@@ -286,6 +286,165 @@
EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
}
+TEST_F(XmlFlattenerTest, ProcessQuotes) {
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
+ R"(<root>
+ <item>Regular text</item>
+ <item>"Text in double quotes"</item>
+ <item>'Text in single quotes'</item>
+ <item>Text containing "double quotes"</item>
+ <item>Text containing 'single quotes'</item>
+ </root>)");
+
+ size_t len;
+ android::ResXMLTree tree;
+
+ XmlFlattenerOptions options;
+ ASSERT_TRUE(Flatten(doc.get(), &tree, options));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Regular text"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"\"Text in double quotes\""));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"'Text in single quotes'"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing \"double quotes\""));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Text containing 'single quotes'"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
+}
+
+TEST_F(XmlFlattenerTest, ProcessWhitepspace) {
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
+ R"(<root>
+ <item> Compact Spaces </item>
+ <item>
+ A
+ </item>
+ <item>B </item>
+ <item>C </item>
+ <item> D </item>
+ <item> E</item>
+ <item> F</item>
+ <item> G </item>
+ <item> H </item>
+<item>
+I
+</item>
+<item>
+
+ J
+
+</item>
+ <item>
+ </item>
+ </root>)");
+
+ size_t len;
+ android::ResXMLTree tree;
+
+ XmlFlattenerOptions options;
+ ASSERT_TRUE(Flatten(doc.get(), &tree, options));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" Compact Spaces "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" A "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"B "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"C "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" D "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" E"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" F"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" G "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" H "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" I "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u" J "));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"item"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
+}
+
TEST_F(XmlFlattenerTest, FlattenRawValueOnlyMakesCompiledValueToo) {
std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element foo="bar" />)");
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index a274a8c..3f9588a 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -413,7 +413,8 @@
case SECTION_NONE:
continue;
case SECTION_FILE:
- printf(" new FileSection(%d, \"%s\"),\n", field->number(), s.args().c_str());
+ printf(" new FileSection(%d, \"%s\", %s),\n", field->number(), s.args().c_str(),
+ s.device_specific() ? "true" : "false");
break;
case SECTION_COMMAND:
printf(" new CommandSection(%d,", field->number());