Merge "Remove unused string for Bluetooth Active device summary" into pi-dev
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/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/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/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/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/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/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/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/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/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/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 1a1839d..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;
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/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/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 99944625..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/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index 58d5340..f24d8cd 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -397,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
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/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());
}