[automerger skipped] Merge "Allow Cell Location for SYSTEM_UID and ROOT_UID" am: 9ca4d43922 -s ours
am: f0893a15ab -s ours
Change-Id: I039631fce137f11a1eb6d65d57f5150b50b73303
diff --git a/Android.bp b/Android.bp
index 294125f..fd4f71c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -769,6 +769,24 @@
dxflags: ["--core-library"],
}
+// ==== java proto host library ==============================
+java_library_host {
+ name: "platformprotos",
+ srcs: [
+ "cmds/am/proto/instrumentation_data.proto",
+ "core/proto/**/*.proto",
+ "libs/incident/proto/**/*.proto",
+ "cmds/statsd/src/**/*.proto",
+ ],
+ proto: {
+ include_dirs: ["external/protobuf/src"],
+ type: "full",
+ },
+ errorprone: {
+ javacflags: ["-Xep:MissingOverride:OFF"], // b/72714520
+ },
+}
+
// ==== c++ proto device library ==============================
cc_library {
name: "libplatformprotos",
@@ -1208,11 +1226,6 @@
doc_defaults {
name: "metalava-framework-docs-default",
srcs: [
- // test mock src files.
- "test-mock/src/android/test/mock/**/*.java",
- // test runner excluding mock src files.
- "test-runner/src/**/*.java",
- "test-base/src/**/*.java",
":opt-telephony-srcs",
":opt-net-voip-srcs",
":openjdk_javadoc_files",
diff --git a/Android.mk b/Android.mk
index c68eb46..031809c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -670,23 +670,6 @@
include $(BUILD_DROIDDOC)
-# ==== java proto host library ==============================
-include $(CLEAR_VARS)
-LOCAL_MODULE := platformprotos
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-LOCAL_PROTOC_FLAGS := \
- -Iexternal/protobuf/src
-LOCAL_SOURCE_FILES_ALL_GENERATED := true
-LOCAL_SRC_FILES := \
- cmds/am/proto/instrumentation_data.proto \
- cmds/statsd/src/perfetto/perfetto_config.proto \
- $(call all-proto-files-under, core/proto) \
- $(call all-proto-files-under, libs/incident/proto) \
- $(call all-proto-files-under, cmds/statsd/src)
-# b/72714520
-LOCAL_ERROR_PRONE_FLAGS := -Xep:MissingOverride:OFF
-include $(BUILD_HOST_JAVA_LIBRARY)
-
# ==== java proto device library (for test only) ==============================
include $(CLEAR_VARS)
LOCAL_MODULE := platformprotosnano
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index fda4f4b..cbbe915 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -137,6 +137,7 @@
Landroid/app/ActivityManager$StackInfo;->visible:Z
Landroid/app/ActivityManager$TaskDescription;->getBackgroundColor()I
Landroid/app/ActivityManager$TaskDescription;->getInMemoryIcon()Landroid/graphics/Bitmap;
+Landroid/app/ActivityManager$TaskDescription;->setIcon(Landroid/graphics/Bitmap;)V
Landroid/app/ActivityManager$TaskSnapshot;->getContentInsets()Landroid/graphics/Rect;
Landroid/app/ActivityManager$TaskSnapshot;->getOrientation()I
Landroid/app/ActivityManager$TaskSnapshot;->getScale()F
@@ -904,6 +905,7 @@
Landroid/app/SearchableInfo$ActionKeyInfo;->getQueryActionMsg()Ljava/lang/String;
Landroid/app/SearchableInfo$ActionKeyInfo;->getSuggestActionMsg()Ljava/lang/String;
Landroid/app/SearchableInfo$ActionKeyInfo;->getSuggestActionMsgColumn()Ljava/lang/String;
+Landroid/app/SearchableInfo;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;Landroid/content/ComponentName;)V
Landroid/app/SearchableInfo;->findActionKey(I)Landroid/app/SearchableInfo$ActionKeyInfo;
Landroid/app/SearchableInfo;->getActivityContext(Landroid/content/Context;)Landroid/content/Context;
Landroid/app/SearchableInfo;->getIconId()I
@@ -1243,6 +1245,7 @@
Landroid/bluetooth/IBluetooth$Stub;-><init>()V
Landroid/bluetooth/IBluetooth$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetooth;
Landroid/bluetooth/IBluetooth$Stub;->TRANSACTION_enable:I
+Landroid/bluetooth/IBluetooth;->fetchRemoteUuids(Landroid/bluetooth/BluetoothDevice;)Z
Landroid/bluetooth/IBluetooth;->getAddress()Ljava/lang/String;
Landroid/bluetooth/IBluetooth;->getRemoteAlias(Landroid/bluetooth/BluetoothDevice;)Ljava/lang/String;
Landroid/bluetooth/IBluetooth;->isEnabled()Z
@@ -1514,8 +1517,11 @@
Landroid/content/pm/IPackageInstallObserver2;->onPackageInstalled(Ljava/lang/String;ILjava/lang/String;Landroid/os/Bundle;)V
Landroid/content/pm/IPackageInstallObserver2;->onUserActionRequired(Landroid/content/Intent;)V
Landroid/content/pm/IPackageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Landroid/content/pm/IPackageManager$Stub$Proxy;->checkUidPermission(Ljava/lang/String;I)I
+Landroid/content/pm/IPackageManager$Stub$Proxy;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getInstallLocation()I
+Landroid/content/pm/IPackageManager$Stub$Proxy;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getPackagesForUid(I)[Ljava/lang/String;
Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
@@ -1534,6 +1540,7 @@
Landroid/content/pm/IPackageManager;->deleteApplicationCacheFiles(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)V
Landroid/content/pm/IPackageManager;->enterSafeMode()V
Landroid/content/pm/IPackageManager;->getApplicationEnabledSetting(Ljava/lang/String;I)I
+Landroid/content/pm/IPackageManager;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
Landroid/content/pm/IPackageManager;->getBlockUninstallForUser(Ljava/lang/String;I)Z
Landroid/content/pm/IPackageManager;->getComponentEnabledSetting(Landroid/content/ComponentName;I)I
Landroid/content/pm/IPackageManager;->getFlagsForUid(I)I
@@ -1745,6 +1752,7 @@
Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Ljava/io/File;Z)V
Landroid/content/pm/PackageParser;->collectCertificates(Landroid/content/pm/PackageParser$Package;Z)V
Landroid/content/pm/PackageParser;->generateActivityInfo(Landroid/content/pm/PackageParser$Activity;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ActivityInfo;
+Landroid/content/pm/PackageParser;->generateApplicationInfo(Landroid/content/pm/PackageParser$Package;ILandroid/content/pm/PackageUserState;)Landroid/content/pm/ApplicationInfo;
Landroid/content/pm/PackageParser;->generateApplicationInfo(Landroid/content/pm/PackageParser$Package;ILandroid/content/pm/PackageUserState;I)Landroid/content/pm/ApplicationInfo;
Landroid/content/pm/PackageParser;->generateInstrumentationInfo(Landroid/content/pm/PackageParser$Instrumentation;I)Landroid/content/pm/InstrumentationInfo;
Landroid/content/pm/PackageParser;->generatePackageInfo(Landroid/content/pm/PackageParser$Package;[IIJJLjava/util/Set;Landroid/content/pm/PackageUserState;)Landroid/content/pm/PackageInfo;
@@ -1756,6 +1764,7 @@
Landroid/content/pm/PackageParser;->mCallback:Landroid/content/pm/PackageParser$Callback;
Landroid/content/pm/PackageParser;->NEW_PERMISSIONS:[Landroid/content/pm/PackageParser$NewPermissionInfo;
Landroid/content/pm/PackageParser;->parseBaseApk(Ljava/lang/String;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Landroid/content/pm/PackageParser$Package;
+Landroid/content/pm/PackageParser;->parseBaseApplication(Landroid/content/pm/PackageParser$Package;Landroid/content/res/Resources;Landroid/content/res/XmlResourceParser;I[Ljava/lang/String;)Z
Landroid/content/pm/PackageParser;->parseMonolithicPackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;I)Landroid/content/pm/PackageParser$Package;
Landroid/content/pm/PackageParser;->parsePackage(Ljava/io/File;IZ)Landroid/content/pm/PackageParser$Package;
@@ -1803,6 +1812,7 @@
Landroid/content/pm/VerifierInfo;-><init>(Ljava/lang/String;Ljava/security/PublicKey;)V
Landroid/content/pm/XmlSerializerAndParser;->createFromXml(Lorg/xmlpull/v1/XmlPullParser;)Ljava/lang/Object;
Landroid/content/pm/XmlSerializerAndParser;->writeAsXml(Ljava/lang/Object;Lorg/xmlpull/v1/XmlSerializer;)V
+Landroid/content/res/ApkAssets;->getAssetPath()Ljava/lang/String;
Landroid/content/res/AssetFileDescriptor;->mFd:Landroid/os/ParcelFileDescriptor;
Landroid/content/res/AssetFileDescriptor;->mLength:J
Landroid/content/res/AssetFileDescriptor;->mStartOffset:J
@@ -1814,6 +1824,7 @@
Landroid/content/res/AssetManager;->addOverlayPath(Ljava/lang/String;)I
Landroid/content/res/AssetManager;->applyStyle(JIILandroid/content/res/XmlBlock$Parser;[IJJ)V
Landroid/content/res/AssetManager;->createTheme()J
+Landroid/content/res/AssetManager;->getApkAssets()[Landroid/content/res/ApkAssets;
Landroid/content/res/AssetManager;->getAssignedPackageIdentifiers()Landroid/util/SparseArray;
Landroid/content/res/AssetManager;->getGlobalAssetCount()I
Landroid/content/res/AssetManager;->getGlobalAssetManagerCount()I
@@ -1837,6 +1848,7 @@
Landroid/content/res/AssetManager;->setConfiguration(IILjava/lang/String;IIIIIIIIIIIIIII)V
Landroid/content/res/AssetManager;->sSystem:Landroid/content/res/AssetManager;
Landroid/content/res/ColorStateList$ColorStateListFactory;-><init>(Landroid/content/res/ColorStateList;)V
+Landroid/content/res/ColorStateList;-><init>()V
Landroid/content/res/ColorStateList;->canApplyTheme()Z
Landroid/content/res/ColorStateList;->getColors()[I
Landroid/content/res/ColorStateList;->getStates()[[I
@@ -1899,6 +1911,7 @@
Landroid/content/res/Resources;->updateSystemConfiguration(Landroid/content/res/Configuration;Landroid/util/DisplayMetrics;Landroid/content/res/CompatibilityInfo;)V
Landroid/content/res/ResourcesImpl;-><init>(Landroid/content/res/AssetManager;Landroid/util/DisplayMetrics;Landroid/content/res/Configuration;Landroid/view/DisplayAdjustments;)V
Landroid/content/res/ResourcesImpl;->getAssets()Landroid/content/res/AssetManager;
+Landroid/content/res/ResourcesImpl;->getDisplayMetrics()Landroid/util/DisplayMetrics;
Landroid/content/res/ResourcesImpl;->getValue(ILandroid/util/TypedValue;Z)V
Landroid/content/res/ResourcesImpl;->mAccessLock:Ljava/lang/Object;
Landroid/content/res/ResourcesImpl;->mAnimatorCache:Landroid/content/res/ConfigurationBoundResourceCache;
@@ -2158,6 +2171,7 @@
Landroid/graphics/CanvasProperty;->createPaint(Landroid/graphics/Paint;)Landroid/graphics/CanvasProperty;
Landroid/graphics/ColorMatrixColorFilter;->mMatrix:Landroid/graphics/ColorMatrix;
Landroid/graphics/ColorMatrixColorFilter;->setColorMatrix(Landroid/graphics/ColorMatrix;)V
+Landroid/graphics/ColorMatrixColorFilter;->setColorMatrixArray([F)V
Landroid/graphics/drawable/AnimatedImageDrawable;->onAnimationEnd()V
Landroid/graphics/drawable/AnimatedRotateDrawable;->setFramesCount(I)V
Landroid/graphics/drawable/AnimatedRotateDrawable;->setFramesDuration(I)V
@@ -4189,6 +4203,7 @@
Landroid/os/SELinux;->restoreconRecursive(Ljava/io/File;)Z
Landroid/os/ServiceManager;-><init>()V
Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;)V
+Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;Z)V
Landroid/os/ServiceManager;->addService(Ljava/lang/String;Landroid/os/IBinder;ZI)V
Landroid/os/ServiceManager;->checkService(Ljava/lang/String;)Landroid/os/IBinder;
Landroid/os/ServiceManager;->getIServiceManager()Landroid/os/IServiceManager;
@@ -4273,6 +4288,7 @@
Landroid/os/storage/VolumeInfo;->getDiskId()Ljava/lang/String;
Landroid/os/storage/VolumeInfo;->getEnvironmentForState(I)Ljava/lang/String;
Landroid/os/storage/VolumeInfo;->getFsUuid()Ljava/lang/String;
+Landroid/os/storage/VolumeInfo;->getInternalPath()Ljava/io/File;
Landroid/os/storage/VolumeInfo;->getInternalPathForUser(I)Ljava/io/File;
Landroid/os/storage/VolumeInfo;->getMountUserId()I
Landroid/os/storage/VolumeInfo;->getPath()Ljava/io/File;
@@ -4308,6 +4324,7 @@
Landroid/os/StrictMode;->sLastVmViolationTime:Ljava/util/HashMap;
Landroid/os/StrictMode;->sWindowManager:Landroid/util/Singleton;
Landroid/os/StrictMode;->violationsBeingTimed:Ljava/lang/ThreadLocal;
+Landroid/os/SystemClock;-><init>()V
Landroid/os/SystemClock;->currentThreadTimeMicro()J
Landroid/os/SystemClock;->currentTimeMicro()J
Landroid/os/SystemProperties;-><init>()V
@@ -4393,6 +4410,7 @@
Landroid/os/UserManager;->getUserStartRealtime()J
Landroid/os/UserManager;->getUserUnlockRealtime()J
Landroid/os/UserManager;->hasBaseUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
+Landroid/os/UserManager;->isDeviceInDemoMode(Landroid/content/Context;)Z
Landroid/os/UserManager;->isGuestUser(I)Z
Landroid/os/UserManager;->isLinkedUser()Z
Landroid/os/UserManager;->isUserAdmin(I)Z
@@ -4598,6 +4616,7 @@
Landroid/provider/Settings$Global;->ZEN_MODE_IMPORTANT_INTERRUPTIONS:I
Landroid/provider/Settings$Global;->ZEN_MODE_NO_INTERRUPTIONS:I
Landroid/provider/Settings$Global;->ZEN_MODE_OFF:I
+Landroid/provider/Settings$NameValueCache;->getStringForUser(Landroid/content/ContentResolver;Ljava/lang/String;I)Ljava/lang/String;
Landroid/provider/Settings$NameValueCache;->mProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
Landroid/provider/Settings$Secure;->ACCESSIBILITY_AUTOCLICK_ENABLED:Ljava/lang/String;
Landroid/provider/Settings$Secure;->ACCESSIBILITY_CAPTIONING_TYPEFACE:Ljava/lang/String;
@@ -4636,10 +4655,12 @@
Landroid/provider/Settings$Secure;->SETTINGS_TO_BACKUP:[Ljava/lang/String;
Landroid/provider/Settings$Secure;->SMS_DEFAULT_APPLICATION:Ljava/lang/String;
Landroid/provider/Settings$Secure;->sNameValueCache:Landroid/provider/Settings$NameValueCache;
+Landroid/provider/Settings$Secure;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
Landroid/provider/Settings$Secure;->VOICE_RECOGNITION_SERVICE:Ljava/lang/String;
Landroid/provider/Settings$System;->AIRPLANE_MODE_TOGGLEABLE_RADIOS:Ljava/lang/String;
Landroid/provider/Settings$System;->CAR_DOCK_SOUND:Ljava/lang/String;
Landroid/provider/Settings$System;->CAR_UNDOCK_SOUND:Ljava/lang/String;
+Landroid/provider/Settings$System;->CLONE_TO_MANAGED_PROFILE:Ljava/util/Set;
Landroid/provider/Settings$System;->DESK_DOCK_SOUND:Ljava/lang/String;
Landroid/provider/Settings$System;->DESK_UNDOCK_SOUND:Ljava/lang/String;
Landroid/provider/Settings$System;->DOCK_SOUNDS_ENABLED:Ljava/lang/String;
@@ -4651,6 +4672,9 @@
Landroid/provider/Settings$System;->LOCKSCREEN_SOUNDS_ENABLED:Ljava/lang/String;
Landroid/provider/Settings$System;->LOCK_SOUND:Ljava/lang/String;
Landroid/provider/Settings$System;->MASTER_MONO:Ljava/lang/String;
+Landroid/provider/Settings$System;->MOVED_TO_GLOBAL:Ljava/util/HashSet;
+Landroid/provider/Settings$System;->MOVED_TO_SECURE:Ljava/util/HashSet;
+Landroid/provider/Settings$System;->MOVED_TO_SECURE_THEN_GLOBAL:Ljava/util/HashSet;
Landroid/provider/Settings$System;->NOTIFICATION_LIGHT_PULSE:Ljava/lang/String;
Landroid/provider/Settings$System;->POINTER_LOCATION:Ljava/lang/String;
Landroid/provider/Settings$System;->POINTER_SPEED:Ljava/lang/String;
@@ -4665,6 +4689,7 @@
Landroid/provider/Settings$System;->sProviderHolder:Landroid/provider/Settings$ContentProviderHolder;
Landroid/provider/Settings$System;->TTY_MODE:Ljava/lang/String;
Landroid/provider/Settings$System;->UNLOCK_SOUND:Ljava/lang/String;
+Landroid/provider/Settings$System;->VALIDATORS:Ljava/util/Map;
Landroid/provider/Settings$System;->VIBRATE_IN_SILENT:Ljava/lang/String;
Landroid/provider/Settings;->ACTION_TRUSTED_CREDENTIALS_USER:Ljava/lang/String;
Landroid/provider/Settings;->ACTION_USER_DICTIONARY_INSERT:Ljava/lang/String;
@@ -5408,6 +5433,7 @@
Landroid/telephony/ServiceState;->mCdmaRoamingIndicator:I
Landroid/telephony/ServiceState;->mCssIndicator:Z
Landroid/telephony/ServiceState;->mIsManualNetworkSelection:Z
+Landroid/telephony/ServiceState;->mIsUsingCarrierAggregation:Z
Landroid/telephony/ServiceState;->mNetworkId:I
Landroid/telephony/ServiceState;->mSystemId:I
Landroid/telephony/ServiceState;->newFromBundle(Landroid/os/Bundle;)Landroid/telephony/ServiceState;
@@ -5773,6 +5799,7 @@
Landroid/transition/Scene;->setCurrentScene(Landroid/view/View;Landroid/transition/Scene;)V
Landroid/transition/Transition;->cancel()V
Landroid/transition/Transition;->end()V
+Landroid/transition/Transition;->getRunningAnimators()Landroid/util/ArrayMap;
Landroid/transition/TransitionManager;->getRunningTransitions()Landroid/util/ArrayMap;
Landroid/transition/TransitionManager;->sPendingTransitions:Ljava/util/ArrayList;
Landroid/transition/TransitionManager;->sRunningTransitions:Ljava/lang/ThreadLocal;
@@ -6220,6 +6247,7 @@
Landroid/view/SurfaceControl;->HIDDEN:I
Landroid/view/SurfaceControl;->hide()V
Landroid/view/SurfaceControl;->openTransaction()V
+Landroid/view/SurfaceControl;->screenshot(Landroid/graphics/Rect;III)Landroid/graphics/Bitmap;
Landroid/view/SurfaceControl;->screenshot(Landroid/graphics/Rect;IIIIZI)Landroid/graphics/Bitmap;
Landroid/view/SurfaceControl;->screenshot(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V
Landroid/view/SurfaceControl;->setDisplayLayerStack(Landroid/os/IBinder;I)V
@@ -7013,6 +7041,7 @@
Landroid/widget/ListView;->fillSpecific(II)Landroid/view/View;
Landroid/widget/ListView;->fillUp(II)Landroid/view/View;
Landroid/widget/ListView;->getHeightForPosition(I)I
+Landroid/widget/ListView;->isDirectChildHeaderOrFooter(Landroid/view/View;)Z
Landroid/widget/ListView;->makeAndAddView(IIZIZ)Landroid/view/View;
Landroid/widget/ListView;->mAreAllItemsSelectable:Z
Landroid/widget/ListView;->mDivider:Landroid/graphics/drawable/Drawable;
@@ -7561,6 +7590,7 @@
Lcom/android/internal/appwidget/IAppWidgetService;->bindAppWidgetId(Ljava/lang/String;IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
Lcom/android/internal/appwidget/IAppWidgetService;->bindRemoteViewsService(Ljava/lang/String;ILandroid/content/Intent;Landroid/app/IApplicationThread;Landroid/os/IBinder;Landroid/app/IServiceConnection;I)Z
Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetIds(Landroid/content/ComponentName;)[I
+Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetViews(Ljava/lang/String;I)Landroid/widget/RemoteViews;
Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V
Lcom/android/internal/backup/IBackupTransport$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/backup/IBackupTransport;
Lcom/android/internal/backup/IBackupTransport;->clearBackupData(Landroid/content/pm/PackageInfo;)I
@@ -7777,6 +7807,9 @@
Lcom/android/internal/R$attr;->text:I
Lcom/android/internal/R$attr;->title:I
Lcom/android/internal/R$attr;->webViewStyle:I
+Lcom/android/internal/R$bool;-><init>()V
+Lcom/android/internal/R$bool;->config_automatic_brightness_available:I
+Lcom/android/internal/R$bool;->config_intrusiveNotificationLed:I
Lcom/android/internal/R$bool;->config_mms_content_disposition_support:I
Lcom/android/internal/R$bool;->config_showNavigationBar:I
Lcom/android/internal/R$dimen;-><init>()V
@@ -8200,6 +8233,8 @@
Lcom/android/internal/R$styleable;->Window:[I
Lcom/android/internal/R$styleable;->WindowAnimation:[I
Lcom/android/internal/R$styleable;->Window_windowActionBarFullscreenDecorLayout:I
+Lcom/android/internal/R$styleable;->Window_windowBackground:I
+Lcom/android/internal/R$styleable;->Window_windowFullscreen:I
Lcom/android/internal/R$styleable;->Window_windowIsFloating:I
Lcom/android/internal/R$styleable;->Window_windowIsTranslucent:I
Lcom/android/internal/R$styleable;->Window_windowShowWallpaper:I
@@ -8269,6 +8304,7 @@
Lcom/android/internal/telephony/IPhoneStateListener;->onSignalStrengthChanged(I)V
Lcom/android/internal/telephony/IPhoneStateListener;->onSignalStrengthsChanged(Landroid/telephony/SignalStrength;)V
Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
Lcom/android/internal/telephony/IPhoneSubInfo$Stub;-><init>()V
Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneSubInfo;
Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->TRANSACTION_getDeviceId:I
@@ -8454,6 +8490,8 @@
Lcom/android/internal/view/menu/MenuBuilder;->addMenuPresenter(Lcom/android/internal/view/menu/MenuPresenter;Landroid/content/Context;)V
Lcom/android/internal/view/menu/MenuBuilder;->collapseItemActionView(Lcom/android/internal/view/menu/MenuItemImpl;)Z
Lcom/android/internal/view/menu/MenuBuilder;->getContext()Landroid/content/Context;
+Lcom/android/internal/view/menu/MenuBuilder;->getHeaderIcon()Landroid/graphics/drawable/Drawable;
+Lcom/android/internal/view/menu/MenuBuilder;->getHeaderTitle()Ljava/lang/CharSequence;
Lcom/android/internal/view/menu/MenuBuilder;->getNonActionItems()Ljava/util/ArrayList;
Lcom/android/internal/view/menu/MenuBuilder;->getRootMenu()Lcom/android/internal/view/menu/MenuBuilder;
Lcom/android/internal/view/menu/MenuBuilder;->getVisibleItems()Ljava/util/ArrayList;
@@ -8471,11 +8509,14 @@
Lcom/android/internal/view/menu/MenuItemImpl;->requestsActionButton()Z
Lcom/android/internal/view/menu/MenuItemImpl;->requiresActionButton()Z
Lcom/android/internal/view/menu/MenuItemImpl;->setActionViewExpanded(Z)V
+Lcom/android/internal/view/menu/MenuItemImpl;->setExclusiveCheckable(Z)V
Lcom/android/internal/view/menu/MenuItemImpl;->setMenuInfo(Landroid/view/ContextMenu$ContextMenuInfo;)V
Lcom/android/internal/view/menu/MenuPopupHelper;-><init>(Landroid/content/Context;Lcom/android/internal/view/menu/MenuBuilder;)V
Lcom/android/internal/view/menu/MenuPopupHelper;-><init>(Landroid/content/Context;Lcom/android/internal/view/menu/MenuBuilder;Landroid/view/View;)V
Lcom/android/internal/view/menu/MenuPopupHelper;->dismiss()V
+Lcom/android/internal/view/menu/MenuPopupHelper;->getPopup()Lcom/android/internal/view/menu/MenuPopup;
Lcom/android/internal/view/menu/MenuPopupHelper;->mForceShowIcon:Z
+Lcom/android/internal/view/menu/MenuPopupHelper;->setAnchorView(Landroid/view/View;)V
Lcom/android/internal/view/menu/MenuPopupHelper;->setForceShowIcon(Z)V
Lcom/android/internal/view/menu/MenuPopupHelper;->setGravity(I)V
Lcom/android/internal/view/menu/MenuPopupHelper;->show()V
@@ -8802,6 +8843,7 @@
Ljava/lang/reflect/Field;->getOffset()I
Ljava/lang/reflect/Parameter;-><init>(Ljava/lang/String;ILjava/lang/reflect/Executable;I)V
Ljava/lang/reflect/Proxy;->invoke(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;
+Ljava/lang/Runtime;-><init>()V
Ljava/lang/Runtime;->load(Ljava/lang/String;Ljava/lang/ClassLoader;)V
Ljava/lang/Runtime;->loadLibrary(Ljava/lang/String;Ljava/lang/ClassLoader;)V
Ljava/lang/Runtime;->loadLibrary0(Ljava/lang/ClassLoader;Ljava/lang/String;)V
@@ -9170,6 +9212,7 @@
Lorg/xml/sax/helpers/NamespaceSupport;->contexts:[Lorg/xml/sax/helpers/NamespaceSupport$Context;
Lorg/xml/sax/helpers/NamespaceSupport;->currentContext:Lorg/xml/sax/helpers/NamespaceSupport$Context;
Lorg/xml/sax/helpers/NamespaceSupport;->EMPTY_ENUMERATION:Ljava/util/Enumeration;
+Lorg/xml/sax/helpers/NamespaceSupport;->namespaceDeclUris:Z
Lorg/xml/sax/helpers/ParserAdapter;->attAdapter:Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;
Lorg/xml/sax/helpers/ParserAdapter;->atts:Lorg/xml/sax/helpers/AttributesImpl;
Lorg/xml/sax/helpers/ParserAdapter;->checkNotParsing(Ljava/lang/String;Ljava/lang/String;)V
@@ -9189,6 +9232,7 @@
Lorg/xml/sax/helpers/ParserAdapter;->reportError(Ljava/lang/String;)V
Lorg/xml/sax/helpers/ParserAdapter;->setup(Lorg/xml/sax/Parser;)V
Lorg/xml/sax/helpers/ParserAdapter;->setupParser()V
+Lorg/xml/sax/helpers/ParserAdapter;->uris:Z
Lorg/xml/sax/helpers/XMLFilterImpl;->contentHandler:Lorg/xml/sax/ContentHandler;
Lorg/xml/sax/helpers/XMLFilterImpl;->dtdHandler:Lorg/xml/sax/DTDHandler;
Lorg/xml/sax/helpers/XMLFilterImpl;->entityResolver:Lorg/xml/sax/EntityResolver;
diff --git a/core/java/android/animation/IntEvaluator.java b/core/java/android/animation/IntEvaluator.java
index 34fb0dc..1de2ae7 100644
--- a/core/java/android/animation/IntEvaluator.java
+++ b/core/java/android/animation/IntEvaluator.java
@@ -24,7 +24,7 @@
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
- * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
+ * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
@@ -39,4 +39,4 @@
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 1ea93a4..c22a43e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -2767,7 +2767,6 @@
*/
private void fixDuplicateExtras() {
if (extras != null) {
- fixDuplicateExtra(mSmallIcon, EXTRA_SMALL_ICON);
fixDuplicateExtra(mLargeIcon, EXTRA_LARGE_ICON);
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 22367b2..ff38c1f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9398,9 +9398,9 @@
* <ul>
* <li>{@link ApnSetting#getOperatorNumeric()}</li>
* <li>{@link ApnSetting#getApnName()}</li>
- * <li>{@link ApnSetting#getProxyAddress()}</li>
+ * <li>{@link ApnSetting#getProxyAddressAsString()}</li>
* <li>{@link ApnSetting#getProxyPort()}</li>
- * <li>{@link ApnSetting#getMmsProxyAddress()}</li>
+ * <li>{@link ApnSetting#getMmsProxyAddressAsString()}</li>
* <li>{@link ApnSetting#getMmsProxyPort()}</li>
* <li>{@link ApnSetting#getMmsc()}</li>
* <li>{@link ApnSetting#isEnabled()}</li>
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index d65e051..3120421 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1120,6 +1120,9 @@
/** @hide */
public String[] splitClassLoaderNames;
+ /** @hide */
+ public boolean hiddenUntilInstalled;
+
/**
* Represents the default policy. The actual policy used will depend on other properties of
* the application, e.g. the target SDK version.
@@ -1460,6 +1463,7 @@
compileSdkVersion = orig.compileSdkVersion;
compileSdkVersionCodename = orig.compileSdkVersionCodename;
mHiddenApiPolicy = orig.mHiddenApiPolicy;
+ hiddenUntilInstalled = orig.hiddenUntilInstalled;
}
public String toString() {
@@ -1534,6 +1538,7 @@
dest.writeString(compileSdkVersionCodename);
dest.writeString(appComponentFactory);
dest.writeInt(mHiddenApiPolicy);
+ dest.writeInt(hiddenUntilInstalled ? 1 : 0);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1605,6 +1610,7 @@
compileSdkVersionCodename = source.readString();
appComponentFactory = source.readString();
mHiddenApiPolicy = source.readInt();
+ hiddenUntilInstalled = source.readInt() != 0;
}
/**
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c988fa9..bc5b32c 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -598,6 +598,9 @@
boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId);
boolean getApplicationHiddenSettingAsUser(String packageName, int userId);
+ void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden);
+ boolean setSystemAppInstallState(String packageName, boolean installed, int userId);
+
IPackageInstaller getPackageInstaller();
boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7253e77..68d0da9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -147,6 +147,7 @@
GET_DISABLED_COMPONENTS,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
+ MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface PackageInfoFlags {}
@@ -164,6 +165,7 @@
MATCH_STATIC_SHARED_LIBRARIES,
GET_DISABLED_UNTIL_USED_COMPONENTS,
GET_UNINSTALLED_PACKAGES,
+ MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApplicationInfoFlags {}
@@ -522,6 +524,12 @@
public static final int MATCH_DEBUG_TRIAGED_MISSING = 0x10000000;
/**
+ * Internal flag used to indicate that a package is a hidden system app.
+ * @hide
+ */
+ public static final int MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS = 0x20000000;
+
+ /**
* Flag for {@link #addCrossProfileIntentFilter}: if this flag is set: when
* resolving an intent that matches the {@code CrossProfileIntentFilter},
* the current profile will be skipped. Only activities in the target user
@@ -4841,7 +4849,8 @@
* on the system for other users, also install it for the specified user.
* @hide
*/
- @RequiresPermission(anyOf = {
+ @RequiresPermission(anyOf = {
+ Manifest.permission.INSTALL_EXISTING_PACKAGES,
Manifest.permission.INSTALL_PACKAGES,
Manifest.permission.INTERACT_ACROSS_USERS_FULL})
public abstract int installExistingPackageAsUser(String packageName, @UserIdInt int userId)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 3f8a390..79f3e53 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -639,11 +639,19 @@
*/
private static boolean checkUseInstalledOrHidden(int flags, PackageUserState state,
ApplicationInfo appInfo) {
+ // Returns false if the package is hidden system app until installed.
+ if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
+ && !state.installed
+ && appInfo != null && appInfo.hiddenUntilInstalled) {
+ return false;
+ }
+
// If available for the target user, or trying to match uninstalled packages and it's
// a system app.
return state.isAvailable(flags)
|| (appInfo != null && appInfo.isSystemApp()
- && (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0);
+ && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
+ || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
}
public static boolean isAvailable(PackageUserState state) {
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 87c64cd..32c6898 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2365,13 +2365,25 @@
* {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, is defined relative to the active array rectangle given in
* this field, with <code>(0, 0)</code> being the top-left of this rectangle.</p>
* <p>The active array may be smaller than the full pixel array, since the full array may
- * include black calibration pixels or other inactive regions, and geometric correction
- * resulting in scaling or cropping may have been applied.</p>
+ * include black calibration pixels or other inactive regions.</p>
+ * <p>For devices that do not support {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the active
+ * array must be the same as {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.</p>
+ * <p>For devices that support {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the active array must
+ * be enclosed by {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. The difference between
+ * pre-correction active array and active array accounts for scaling or cropping caused
+ * by lens geometric distortion correction.</p>
+ * <p>In general, application should always refer to active array size for controls like
+ * metering regions or crop region. Two exceptions are when the application is dealing with
+ * RAW image buffers (RAW_SENSOR, RAW10, RAW12 etc), or when application explicitly set
+ * {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} to OFF. In these cases, application should refer
+ * to {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.</p>
* <p><b>Units</b>: Pixel coordinates on the image sensor</p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.graphics.Rect> SENSOR_INFO_ACTIVE_ARRAY_SIZE =
@@ -2616,9 +2628,9 @@
* <ol>
* <li>{@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion}.</li>
* </ol>
- * <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same
- * as the post-distortion-corrected rectangle given in
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
+ * <p>If the camera device doesn't support geometric distortion correction, or all of the
+ * geometric distortion fields are no-ops, this rectangle will be the same as the
+ * post-distortion-corrected rectangle given in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
* <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of
* the full pixel array, and the size of the full pixel array is given by
* {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p>
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 411a97e..aca77a5 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1269,11 +1269,26 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe}.</p>
- * <p>The coordinate system is based on the active pixel array,
- * with (0,0) being the top-left pixel in the active pixel array, and
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+ * the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
- * bottom-right pixel in the active pixel array.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+ * pixel in the pre-correction active pixel array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
* <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
* for every pixel in the area. This means that a large metering area
* with the same weight as a smaller area will have more effect in
@@ -1289,15 +1304,20 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
- * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+ * distortion correction capability and mode</p>
* <p><b>Range of valid values:</b><br>
* Coordinates must be between <code>[(0,0), (width, height))</code> of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+ * depending on distortion correction capability and mode</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AE_REGIONS =
@@ -1443,11 +1463,26 @@
* Otherwise will always be present.</p>
* <p>The maximum number of focus areas supported by the device is determined by the value
* of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf}.</p>
- * <p>The coordinate system is based on the active pixel array,
- * with (0,0) being the top-left pixel in the active pixel array, and
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+ * the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
- * bottom-right pixel in the active pixel array.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+ * pixel in the pre-correction active pixel array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
* <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
* for every pixel in the area. This means that a large metering area
* with the same weight as a smaller area will have more effect in
@@ -1464,15 +1499,20 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
- * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+ * distortion correction capability and mode</p>
* <p><b>Range of valid values:</b><br>
* Coordinates must be between <code>[(0,0), (width, height))</code> of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+ * depending on distortion correction capability and mode</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AF_REGIONS =
@@ -1612,11 +1652,26 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb}.</p>
- * <p>The coordinate system is based on the active pixel array,
- * with (0,0) being the top-left pixel in the active pixel array, and
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+ * the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
- * bottom-right pixel in the active pixel array.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+ * pixel in the pre-correction active pixel array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
* <p>The weight must range from 0 to 1000, and represents a weight
* for every pixel in the area. This means that a large metering area
* with the same weight as a smaller area will have more effect in
@@ -1632,15 +1687,20 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
- * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+ * distortion correction capability and mode</p>
* <p><b>Range of valid values:</b><br>
* Coordinates must be between <code>[(0,0), (width, height))</code> of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+ * depending on distortion correction capability and mode</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS =
@@ -2433,9 +2493,17 @@
/**
* <p>The desired region of the sensor to read out for this capture.</p>
* <p>This control can be used to implement digital zoom.</p>
- * <p>The crop region coordinate system is based off
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being the
- * top-left corner of the sensor active array.</p>
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+ * the top-left pixel of the active array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
* <p>Output streams use this rectangle to produce their output,
* cropping to a smaller region if necessary to maintain the
* stream's aspect ratio, then scaling the sensor input to
@@ -2454,20 +2522,30 @@
* outputs will crop horizontally (pillarbox), and 16:9
* streams will match exactly. These additional crops will
* be centered within the crop region.</p>
- * <p>The width and height of the crop region cannot
- * be set to be smaller than
+ * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height
+ * of the crop region cannot be set to be smaller than
* <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
* <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
+ * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, the width
+ * and height of the crop region cannot be set to be smaller than
+ * <code>floor( preCorrectionActiveArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>
+ * and
+ * <code>floor( preCorrectionActiveArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>,
+ * respectively.</p>
* <p>The camera device may adjust the crop region to account
* for rounding and other hardware requirements; the final
* crop region used will be included in the output capture
* result.</p>
* <p><b>Units</b>: Pixel coordinates relative to
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on distortion correction
+ * capability and mode</p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
@@ -3186,15 +3264,14 @@
* any correction at all would slow down capture rate. Every output stream will have a
* similar amount of enhancement applied.</p>
* <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
- * applied to any RAW output. Metadata coordinates such as face rectangles or metering
+ * applied to any RAW output. Metadata coordinates such as face rectangles or metering
* regions are also not affected by correction.</p>
- * <p>Applications enabling distortion correction need to pay extra attention when converting
- * image coordinates between corrected output buffers and the sensor array. For example, if
- * the app supports tap-to-focus and enables correction, it then has to apply the distortion
- * model described in {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} to the image buffer tap coordinates to properly
- * calculate the tap position on the sensor active array to be used with
- * {@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}. The same applies in reverse to detected face rectangles if
- * they need to be drawn on top of the corrected output buffers.</p>
+ * <p>This control will be on by default on devices that support this control. Applications
+ * disabling distortion correction need to pay extra attention with the coordinate system of
+ * metering regions, crop region, and face rectangles. When distortion correction is OFF,
+ * metadata coordinates follow the coordinate system of
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata
+ * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
@@ -3205,9 +3282,10 @@
* {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
- * @see CaptureRequest#CONTROL_AF_REGIONS
* @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
* @see CameraCharacteristics#LENS_DISTORTION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
* @see #DISTORTION_CORRECTION_MODE_OFF
* @see #DISTORTION_CORRECTION_MODE_FAST
* @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 6439338..75c27f5 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -730,11 +730,26 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe}.</p>
- * <p>The coordinate system is based on the active pixel array,
- * with (0,0) being the top-left pixel in the active pixel array, and
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+ * the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
- * bottom-right pixel in the active pixel array.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+ * pixel in the pre-correction active pixel array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
* <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
* for every pixel in the area. This means that a large metering area
* with the same weight as a smaller area will have more effect in
@@ -750,15 +765,20 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
- * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+ * distortion correction capability and mode</p>
* <p><b>Range of valid values:</b><br>
* Coordinates must be between <code>[(0,0), (width, height))</code> of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+ * depending on distortion correction capability and mode</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AE_REGIONS =
@@ -1152,11 +1172,26 @@
* Otherwise will always be present.</p>
* <p>The maximum number of focus areas supported by the device is determined by the value
* of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf}.</p>
- * <p>The coordinate system is based on the active pixel array,
- * with (0,0) being the top-left pixel in the active pixel array, and
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+ * the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
- * bottom-right pixel in the active pixel array.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+ * pixel in the pre-correction active pixel array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
* <p>The weight must be within <code>[0, 1000]</code>, and represents a weight
* for every pixel in the area. This means that a large metering area
* with the same weight as a smaller area will have more effect in
@@ -1173,15 +1208,20 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
- * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+ * distortion correction capability and mode</p>
* <p><b>Range of valid values:</b><br>
* Coordinates must be between <code>[(0,0), (width, height))</code> of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+ * depending on distortion correction capability and mode</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AF_REGIONS =
@@ -1730,11 +1770,26 @@
* Otherwise will always be present.</p>
* <p>The maximum number of regions supported by the device is determined by the value
* of {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb}.</p>
- * <p>The coordinate system is based on the active pixel array,
- * with (0,0) being the top-left pixel in the active pixel array, and
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with (0,0) being
+ * the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
- * bottom-right pixel in the active pixel array.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.height - 1) being the bottom-right
+ * pixel in the pre-correction active pixel array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array, and
+ * ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the bottom-right pixel in the
+ * active pixel array.</p>
* <p>The weight must range from 0 to 1000, and represents a weight
* for every pixel in the area. This means that a large metering area
* with the same weight as a smaller area will have more effect in
@@ -1750,15 +1805,20 @@
* region and output only the intersection rectangle as the metering region in the result
* metadata. If the region is entirely outside the crop region, it will be ignored and
* not reported in the result metadata.</p>
- * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * <p><b>Units</b>: Pixel coordinates within {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on
+ * distortion correction capability and mode</p>
* <p><b>Range of valid values:</b><br>
* Coordinates must be between <code>[(0,0), (width, height))</code> of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}
+ * depending on distortion correction capability and mode</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS =
@@ -3099,9 +3159,17 @@
/**
* <p>The desired region of the sensor to read out for this capture.</p>
* <p>This control can be used to implement digital zoom.</p>
- * <p>The crop region coordinate system is based off
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being the
- * top-left corner of the sensor active array.</p>
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+ * the top-left pixel of the active array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
* <p>Output streams use this rectangle to produce their output,
* cropping to a smaller region if necessary to maintain the
* stream's aspect ratio, then scaling the sensor input to
@@ -3120,20 +3188,30 @@
* outputs will crop horizontally (pillarbox), and 16:9
* streams will match exactly. These additional crops will
* be centered within the crop region.</p>
- * <p>The width and height of the crop region cannot
- * be set to be smaller than
+ * <p>If the coordinate system is android.sensor.info.activeArraysSize, the width and height
+ * of the crop region cannot be set to be smaller than
* <code>floor( activeArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code> and
* <code>floor( activeArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>, respectively.</p>
+ * <p>If the coordinate system is {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, the width
+ * and height of the crop region cannot be set to be smaller than
+ * <code>floor( preCorrectionActiveArraySize.width / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>
+ * and
+ * <code>floor( preCorrectionActiveArraySize.height / {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} )</code>,
+ * respectively.</p>
* <p>The camera device may adjust the crop region to account
* for rounding and other hardware requirements; the final
* crop region used will be included in the output capture
* result.</p>
* <p><b>Units</b>: Pixel coordinates relative to
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} or
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} depending on distortion correction
+ * capability and mode</p>
* <p>This key is available on all devices.</p>
*
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
@@ -3624,12 +3702,23 @@
/**
* <p>List of landmarks for detected
* faces.</p>
- * <p>The coordinate system is that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+ * the top-left pixel of the active array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
* <code>(0, 0)</code> being the top-left pixel of the active array.</p>
* <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} == FULL
* This key is available on all devices.</p>
*
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @hide
*/
@@ -3639,12 +3728,23 @@
/**
* <p>List of the bounding rectangles for detected
* faces.</p>
- * <p>The coordinate system is that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <p>For devices not supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system always follows that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with <code>(0, 0)</code> being
+ * the top-left pixel of the active array.</p>
+ * <p>For devices supporting {@link CaptureRequest#DISTORTION_CORRECTION_MODE android.distortionCorrection.mode} control, the coordinate
+ * system depends on the mode being set.
+ * When the distortion correction mode is OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the pre-correction active array.
+ * When the distortion correction mode is not OFF, the coordinate system follows
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
* <code>(0, 0)</code> being the top-left pixel of the active array.</p>
* <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} != OFF
* This key is available on all devices.</p>
*
+ * @see CaptureRequest#DISTORTION_CORRECTION_MODE
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @hide
*/
@@ -4478,15 +4578,14 @@
* any correction at all would slow down capture rate. Every output stream will have a
* similar amount of enhancement applied.</p>
* <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
- * applied to any RAW output. Metadata coordinates such as face rectangles or metering
+ * applied to any RAW output. Metadata coordinates such as face rectangles or metering
* regions are also not affected by correction.</p>
- * <p>Applications enabling distortion correction need to pay extra attention when converting
- * image coordinates between corrected output buffers and the sensor array. For example, if
- * the app supports tap-to-focus and enables correction, it then has to apply the distortion
- * model described in {@link CameraCharacteristics#LENS_DISTORTION android.lens.distortion} to the image buffer tap coordinates to properly
- * calculate the tap position on the sensor active array to be used with
- * {@link CaptureRequest#CONTROL_AF_REGIONS android.control.afRegions}. The same applies in reverse to detected face rectangles if
- * they need to be drawn on top of the corrected output buffers.</p>
+ * <p>This control will be on by default on devices that support this control. Applications
+ * disabling distortion correction need to pay extra attention with the coordinate system of
+ * metering regions, crop region, and face rectangles. When distortion correction is OFF,
+ * metadata coordinates follow the coordinate system of
+ * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}. When distortion is not OFF, metadata
+ * coordinates follow the coordinate system of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #DISTORTION_CORRECTION_MODE_OFF OFF}</li>
@@ -4497,9 +4596,10 @@
* {@link CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES android.distortionCorrection.availableModes}</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
- * @see CaptureRequest#CONTROL_AF_REGIONS
* @see CameraCharacteristics#DISTORTION_CORRECTION_AVAILABLE_MODES
* @see CameraCharacteristics#LENS_DISTORTION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE
* @see #DISTORTION_CORRECTION_MODE_OFF
* @see #DISTORTION_CORRECTION_MODE_FAST
* @see #DISTORTION_CORRECTION_MODE_HIGH_QUALITY
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index a040a09..1ee3c93 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -82,9 +82,9 @@
*
* </ul>
*
- * <p> As of {@link android.os.Build.VERSION_CODES#P Android P}, all formats can be used for
- * sharing, subject to device support. On prior API levels, only {@link ImageFormat#PRIVATE}
- * format may be used.</p>
+ * <p> As of {@link android.os.Build.VERSION_CODES#P Android P}, all formats except
+ * {@link ImageFormat#JPEG} and {@link ImageFormat#RAW_PRIVATE} can be used for sharing, subject to
+ * device support. On prior API levels, only {@link ImageFormat#PRIVATE} format may be used.</p>
*
* @see CameraDevice#createCaptureSessionByOutputConfigurations
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4347a30..2439d23 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7537,9 +7537,6 @@
*/
public static final String ASSIST_GESTURE_SENSITIVITY = "assist_gesture_sensitivity";
- private static final Validator ASSIST_GESTURE_SENSITIVITY_VALIDATOR =
- new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 1.0f);
-
/**
* Whether the assist gesture should silence alerts.
*
@@ -7569,8 +7566,6 @@
*/
public static final String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete";
- private static final Validator ASSIST_GESTURE_SETUP_COMPLETE_VALIDATOR = BOOLEAN_VALIDATOR;
-
/**
* Control whether Night display is currently activated.
* @hide
@@ -8026,8 +8021,6 @@
NFC_PAYMENT_DEFAULT_COMPONENT,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
ASSIST_GESTURE_ENABLED,
- ASSIST_GESTURE_SENSITIVITY,
- ASSIST_GESTURE_SETUP_COMPLETE,
ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
ASSIST_GESTURE_WAKE_ENABLED,
VR_DISPLAY_MODE,
@@ -8166,8 +8159,6 @@
VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
- VALIDATORS.put(ASSIST_GESTURE_SENSITIVITY, ASSIST_GESTURE_SENSITIVITY_VALIDATOR);
- VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, ASSIST_GESTURE_SETUP_COMPLETE_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
VALIDATORS.put(ASSIST_GESTURE_WAKE_ENABLED, ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR);
diff --git a/core/java/android/service/autofill/TextValueSanitizer.java b/core/java/android/service/autofill/TextValueSanitizer.java
index e5ad77a..a8c080a 100644
--- a/core/java/android/service/autofill/TextValueSanitizer.java
+++ b/core/java/android/service/autofill/TextValueSanitizer.java
@@ -37,7 +37,7 @@
* <p>For example, to remove spaces from groups of 4-digits in a credit card:
*
* <pre class="prettyprint">
- * new TextValueSanitizer(Pattern.compile("^(\\d{4})\\s?(\\d{4})\\s?(\\d{4})\\s?(\\d{4})$",
+ * new TextValueSanitizer(Pattern.compile("^(\\d{4})\\s?(\\d{4})\\s?(\\d{4})\\s?(\\d{4})$"),
* "$1$2$3$4")
* </pre>
*/
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 01562b3..6f1bd78 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -33,7 +33,6 @@
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -487,8 +486,9 @@
* intent. The possible values for this extra are
* {@link TextToSpeech#SUCCESS} and {@link TextToSpeech#ERROR}.
*
- * @deprecated No longer in use. If client ise interested in information about what
- * changed, is should send ACTION_CHECK_TTS_DATA intent to discover available voices.
+ * @deprecated No longer in use. If client is interested in information about what
+ * changed, it should use the ACTION_CHECK_TTS_DATA
+ * intent to discover available voices.
*/
@Deprecated
public static final String EXTRA_TTS_DATA_INSTALLED = "dataInstalled";
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index d7f1d6e..0c103e5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -143,7 +143,7 @@
* This class is called when something that might impact a
* browser UI happens, for instance, progress updates and
* JavaScript alerts are sent here (see <a
- * href="{@docRoot}guide/developing/debug-tasks.html#DebuggingWebPages">Debugging Tasks</a>).
+ * href="{@docRoot}guide/webapps/debugging.html">Debugging Web Apps</a>).
* </li>
* <li>Creating and setting a {@link android.webkit.WebViewClient} subclass.
* It will be called when things happen that impact the
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 6df76fa..e6f948f 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -21,6 +21,7 @@
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionGroupInfo;
@@ -590,7 +591,8 @@
private void addPermToList(List<MyPermissionInfo> permList,
MyPermissionInfo pInfo) {
if (pInfo.mLabel == null) {
- pInfo.mLabel = pInfo.loadLabel(mPm);
+ pInfo.mLabel = pInfo.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
+ | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
}
int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
@@ -611,7 +613,9 @@
}
MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
if (group != null) {
- pInfo.mLabel = pInfo.loadLabel(mPm);
+ pInfo.mLabel = pInfo.loadSafeLabel(mPm, 20000,
+ PackageItemInfo.SAFE_LABEL_FLAG_TRIM
+ | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
addPermToList(group.mAllPermissions, pInfo);
if (pInfo.mNew) {
addPermToList(group.mNewPermissions, pInfo);
@@ -622,14 +626,18 @@
for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
- pgrp.mLabel = pgrp.loadLabel(mPm);
+ pgrp.mLabel = pgrp.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
+ | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
} else {
ApplicationInfo app;
try {
app = mPm.getApplicationInfo(pgrp.packageName, 0);
- pgrp.mLabel = app.loadLabel(mPm);
+ pgrp.mLabel = app.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
+ | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
} catch (NameNotFoundException e) {
- pgrp.mLabel = pgrp.loadLabel(mPm);
+ pgrp.mLabel = pgrp.loadSafeLabel(mPm, 20000,
+ PackageItemInfo.SAFE_LABEL_FLAG_TRIM
+ | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
}
}
mPermGroupsList.add(pgrp);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 1372987..67b7100a 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -80,7 +80,7 @@
*
* <p>
* To learn more about Drawables, see: <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
- * To learn more about working with Bitmaps, see: <a href="{@docRoot}topic/performance/graphics/index.htm">Handling Bitmaps</a>.
+ * To learn more about working with Bitmaps, see: <a href="{@docRoot}topic/performance/graphics/index.html">Handling Bitmaps</a>.
* </p>
*
* @attr ref android.R.styleable#ImageView_adjustViewBounds
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index f6a69d9..5778544 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -18,6 +18,9 @@
import android.animation.TimeAnimator;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
+import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -25,12 +28,15 @@
import android.graphics.Path;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
import android.view.View;
import android.widget.FrameLayout;
+import org.json.JSONObject;
+
public class PlatLogoActivity extends Activity {
FrameLayout layout;
TimeAnimator anim;
@@ -87,7 +93,7 @@
darkest = 0;
for (int i=0; i<slots; i++) {
palette[i] = Color.HSVToColor(color);
- color[0] += 360f/slots;
+ color[0] = (color[0] + 360f/slots) % 360f;
if (lum(palette[i]) < lum(palette[darkest])) darkest = i;
}
@@ -178,27 +184,97 @@
bg = new PBackground();
layout.setBackground(bg);
+ final ContentResolver cr = getContentResolver();
+
layout.setOnTouchListener(new View.OnTouchListener() {
+ final String TOUCH_STATS = "touch.stats";
+
final PointerCoords pc0 = new PointerCoords();
final PointerCoords pc1 = new PointerCoords();
+ double pressure_min, pressure_max;
+ int maxPointers;
+ int tapCount;
+
@Override
public boolean onTouch(View v, MotionEvent event) {
+ final float pressure = event.getPressure();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
+ pressure_min = pressure_max = pressure;
+ // fall through
case MotionEvent.ACTION_MOVE:
- if (event.getPointerCount() > 1) {
+ if (pressure < pressure_min) pressure_min = pressure;
+ if (pressure > pressure_max) pressure_max = pressure;
+ final int pc = event.getPointerCount();
+ if (pc > maxPointers) maxPointers = pc;
+ if (pc > 1) {
event.getPointerCoords(0, pc0);
event.getPointerCoords(1, pc1);
bg.setRadius((float) Math.hypot(pc0.x - pc1.x, pc0.y - pc1.y) / 2f);
}
break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ try {
+ final String touchDataJson = Settings.System.getString(cr, TOUCH_STATS);
+ final JSONObject touchData = new JSONObject(
+ touchDataJson != null ? touchDataJson : "{}");
+ if (touchData.has("min")) {
+ pressure_min = Math.min(pressure_min, touchData.getDouble("min"));
+ }
+ if (touchData.has("max")) {
+ pressure_max = Math.max(pressure_max, touchData.getDouble("max"));
+ }
+ touchData.put("min", pressure_min);
+ touchData.put("max", pressure_max);
+ Settings.System.putString(cr, TOUCH_STATS, touchData.toString());
+ } catch (Exception e) {
+ Log.e("PlatLogoActivity", "Can't write touch settings", e);
+ }
+
+ if (maxPointers == 1) {
+ tapCount ++;
+ if (tapCount < 7) {
+ bg.randomizePalette();
+ } else {
+ launchNextStage();
+ }
+ } else {
+ tapCount = 0;
+ }
+ maxPointers = 0;
+ break;
}
return true;
}
});
}
+ private void launchNextStage() {
+ final ContentResolver cr = getContentResolver();
+
+ if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0) == 0) {
+ // For posterity: the moment this user unlocked the easter egg
+ try {
+ Settings.System.putLong(cr,
+ Settings.System.EGG_MODE,
+ System.currentTimeMillis());
+ } catch (RuntimeException e) {
+ Log.e("PlatLogoActivity", "Can't write settings", e);
+ }
+ }
+ try {
+ startActivity(new Intent(Intent.ACTION_MAIN)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ .addCategory("com.android.internal.category.PLATLOGO"));
+ } catch (ActivityNotFoundException ex) {
+ Log.e("PlatLogoActivity", "No more eggs.");
+ }
+ finish();
+ }
+
@Override
public void onStart() {
super.onStart();
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 26fb6b64..07bb453 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -27,9 +27,11 @@
public class AmbientDisplayConfiguration {
private final Context mContext;
+ private final boolean mAlwaysOnByDefault;
public AmbientDisplayConfiguration(Context context) {
mContext = context;
+ mAlwaysOnByDefault = mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnEnabled);
}
public boolean enabled(int user) {
@@ -101,8 +103,8 @@
}
public boolean alwaysOnEnabled(int user) {
- return boolSettingDefaultOn(Settings.Secure.DOZE_ALWAYS_ON, user) && alwaysOnAvailable()
- && !accessibilityInversionEnabled(user);
+ return boolSetting(Settings.Secure.DOZE_ALWAYS_ON, user, mAlwaysOnByDefault ? 1 : 0)
+ && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
}
public boolean alwaysOnAvailable() {
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 0fd6109..4ba93bc 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -60,6 +60,13 @@
public class MessagingLayout extends FrameLayout {
private static final float COLOR_SHIFT_AMOUNT = 60;
+ /**
+ * Pattren for filter some ingonable characters.
+ * p{Z} for any kind of whitespace or invisible separator.
+ * p{C} for any kind of punctuation character.
+ */
+ private static final Pattern IGNORABLE_CHAR_PATTERN
+ = Pattern.compile("[\\p{C}\\p{Z}]");
private static final Pattern SPECIAL_CHAR_PATTERN
= Pattern.compile ("[!@#$%&*()_+=|<>?{}\\[\\]~-]");
private static final Consumer<MessagingMessage> REMOVE_MESSAGE
@@ -233,7 +240,10 @@
continue;
}
if (!uniqueNames.containsKey(senderName)) {
- char c = senderName.charAt(0);
+ // Only use visible characters to get uniqueNames
+ String pureSenderName = IGNORABLE_CHAR_PATTERN
+ .matcher(senderName).replaceAll("" /* replacement */);
+ char c = pureSenderName.charAt(0);
if (uniqueCharacters.containsKey(c)) {
// this character was already used, lets make it more unique. We first need to
// resolve the existing character if it exists
@@ -245,7 +255,7 @@
uniqueNames.put(senderName, findNameSplit((String) senderName));
} else {
uniqueNames.put(senderName, Character.toString(c));
- uniqueCharacters.put(c, senderName);
+ uniqueCharacters.put(c, pureSenderName);
}
}
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 66c497e..cda1293 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2238,7 +2238,8 @@
android:description="@string/permdesc_install_shortcut"
android:protectionLevel="normal"/>
- <!--This permission is no longer supported.
+ <!-- <p class="caution"><strong>Don't use this permission in your app.</strong><br>This
+ permission is no longer supported.
-->
<permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"
android:label="@string/permlab_uninstall_shortcut"
@@ -3024,6 +3025,15 @@
<permission android:name="android.permission.INSTALL_PACKAGE_UPDATES"
android:protectionLevel="signature|privileged" />
+ <!-- Allows an application to install existing system packages. This is a limited
+ version of {@link android.Manifest.permission#INSTALL_PACKAGES}.
+ <p>Not for use by third-party applications.
+ TODO(b/80204953): remove this permission once we have a long-term solution.
+ @hide
+ -->
+ <permission android:name="com.android.permission.INSTALL_EXISTING_PACKAGES"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows an application to clear user data.
<p>Not for use by third-party applications
@hide
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9d36694..230af3f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -42,13 +42,13 @@
<item><xliff:g id="id">@string/status_bar_phone_evdo_signal</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_phone_signal</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_secure</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_managed_profile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_cast</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_vpn</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_bluetooth</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_location</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mute</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_volume</xliff:g></item>
- <item><xliff:g id="id">@string/status_bar_location</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_zen</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_ethernet</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_wifi</xliff:g></item>
@@ -667,9 +667,27 @@
<!-- Boolean indicating that wifi only link configuratios that have exact same credentials (i.e PSK) -->
<bool translatable="false" name="config_wifi_only_link_same_credential_configurations">true</bool>
- <!-- Boolean indicating whether framework needs to set the tx power limit for meeting SAR requirements
- during voice calls -->
- <bool translatable="false" name="config_wifi_framework_enable_voice_call_sar_tx_power_limit">false</bool>
+ <!-- Boolean indicating whether framework needs to set the tx power limit for meeting SAR requirements -->
+ <bool translatable="false" name="config_wifi_framework_enable_sar_tx_power_limit">false</bool>
+
+ <!-- Boolean indicating whether framework needs to use body proximity to set the tx power limit
+ for meeting SAR requirements -->
+ <bool translatable="false" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit">false</bool>
+
+ <!-- String for the sensor type for body/head proximity for SAR -->
+ <string translatable="false" name="config_wifi_sar_sensor_type"></string>
+
+ <!-- Integer indicating event id by sar sensor for free space -->
+ <integer translatable="false" name="config_wifi_framework_sar_free_space_event_id">1</integer>
+
+ <!-- Integer indicating event id by sar sensor for near hand -->
+ <integer translatable="false" name="config_wifi_framework_sar_near_hand_event_id">2</integer>
+
+ <!-- Integer indicating event id by sar sensor for near head -->
+ <integer translatable="false" name="config_wifi_framework_sar_near_head_event_id">3</integer>
+
+ <!-- Integer indicating event id by sar sensor for near body -->
+ <integer translatable="false" name="config_wifi_framework_sar_near_body_event_id">4</integer>
<!-- Wifi driver supports batched scan -->
<bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
@@ -2093,6 +2111,10 @@
states. -->
<bool name="config_dozeAlwaysOnDisplayAvailable">false</bool>
+ <!-- Control whether the always on display mode is enabled by default. This value will be used
+ during initialization when the setting is still null. -->
+ <bool name="config_dozeAlwaysOnEnabled">true</bool>
+
<!-- Whether the display blanks itself when transitioning from a doze to a non-doze state -->
<bool name="config_displayBlanksAfterDoze">false</bool>
@@ -3455,4 +3477,6 @@
<!-- Whether or not swipe up gesture's opt-in setting is available on this device -->
<bool name="config_swipe_up_gesture_setting_available">false</bool>
+ <!-- Whether or not we should show the option to show battery percentage -->
+ <bool name="config_battery_percentage_setting_available">true</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3c5159c..f660046 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3169,6 +3169,21 @@
<!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. -->
<string name="wifi_no_internet_detailed">Tap for options</string>
+ <!-- A notification is shown when the user's softap config has been changed due to underlying
+ hardware restrictions. This is the notifications's title.
+ [CHAR_LIMIT=NONE] -->
+ <string name="wifi_softap_config_change">Changes to your hotspot settings</string>
+
+ <!-- A notification is shown when the user's softap config has been changed due to underlying
+ hardware restrictions. This is the notification's summary message.
+ [CHAR_LIMIT=NONE] -->
+ <string name="wifi_softap_config_change_summary">Your hotspot band has changed.</string>
+
+ <!-- A notification is shown when the user's softap config has been changed due to underlying
+ hardware restrictions. This is the notification's full message.
+ [CHAR_LIMIT=NONE] -->
+ <string name="wifi_softap_config_change_detailed">This device doesn\u2019t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available.</string>
+
<!-- A notification might be shown if the device switches to another network type (e.g., mobile data) because it detects that the network it was using (e.g., Wi-Fi) has lost Internet connectivity. This is the notification's title. %1$s is the network type that the device switched to, e.g., cellular data. It is one of the strings in the network_switch_type_name array. -->
<string name="network_switch_metered">Switched to <xliff:g id="network_type">%1$s</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 65606e3..9a4f427 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -336,7 +336,13 @@
<java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
<java-symbol type="bool" name="config_wifi_framework_use_single_radio_chain_scan_results_network_selection" />
<java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
- <java-symbol type="bool" name="config_wifi_framework_enable_voice_call_sar_tx_power_limit" />
+ <java-symbol type="bool" name="config_wifi_framework_enable_sar_tx_power_limit" />
+ <java-symbol type="bool" name="config_wifi_framework_enable_body_proximity_sar_tx_power_limit" />
+ <java-symbol type="string" name="config_wifi_sar_sensor_type" />
+ <java-symbol type="integer" name="config_wifi_framework_sar_free_space_event_id" />
+ <java-symbol type="integer" name="config_wifi_framework_sar_near_hand_event_id" />
+ <java-symbol type="integer" name="config_wifi_framework_sar_near_head_event_id" />
+ <java-symbol type="integer" name="config_wifi_framework_sar_near_body_event_id" />
<java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
<java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
@@ -1055,6 +1061,9 @@
<java-symbol type="string" name="network_switch_type_name_unknown" />
<java-symbol type="string" name="wifi_no_internet" />
<java-symbol type="string" name="wifi_no_internet_detailed" />
+ <java-symbol type="string" name="wifi_softap_config_change" />
+ <java-symbol type="string" name="wifi_softap_config_change_summary" />
+ <java-symbol type="string" name="wifi_softap_config_change_detailed" />
<java-symbol type="string" name="wifi_connect_alert_title" />
<java-symbol type="string" name="wifi_connect_alert_message" />
<java-symbol type="string" name="wifi_connect_default_application" />
@@ -2194,6 +2203,7 @@
<java-symbol type="string" name="ext_media_move_failure_message" />
<java-symbol type="style" name="Animation.RecentApplications" />
<java-symbol type="integer" name="dock_enter_exit_duration" />
+ <java-symbol type="bool" name="config_battery_percentage_setting_available" />
<!-- ImfTest -->
<java-symbol type="layout" name="auto_complete_list" />
@@ -3232,6 +3242,7 @@
<java-symbol type="dimen" name="config_inCallNotificationVolume" />
<java-symbol type="string" name="config_inCallNotificationSound" />
<java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
+ <java-symbol type="bool" name="config_dozeAlwaysOnEnabled" />
<java-symbol type="bool" name="config_displayBlanksAfterDoze" />
<java-symbol type="bool" name="config_displayBrightnessBucketsInDoze" />
<java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index dea3235..e50efa9 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -508,6 +508,8 @@
Settings.Secure.ANR_SHOW_BACKGROUND,
Settings.Secure.ASSISTANT,
Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
+ Settings.Secure.ASSIST_GESTURE_SENSITIVITY,
+ Settings.Secure.ASSIST_GESTURE_SETUP_COMPLETE,
Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
Settings.Secure.ASSIST_STRUCTURE_ENABLED,
Settings.Secure.AUTOFILL_FEATURE_FIELD_CLASSIFICATION,
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 54358e3..e397ed9 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -57,6 +57,8 @@
import com.android.internal.R;
import com.android.internal.util.VirtualRefBasePtr;
+import dalvik.annotation.optimization.FastNative;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -64,7 +66,6 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import dalvik.annotation.optimization.FastNative;
/**
* This class animates properties of a {@link android.graphics.drawable.VectorDrawable} with
@@ -167,7 +168,7 @@
* </p>
* Below is an example of a VectorDrawable defined in vectordrawable.xml. This VectorDrawable is
* referred to by its file name (not including file suffix) in the
- * <a href="AVDExample">AnimatedVectorDrawable XML example</a>.
+ * <a href="#AVDExample">AnimatedVectorDrawable XML example</a>.
* <pre>
* <vector xmlns:android="http://schemas.android.com/apk/res/android"
* android:height="64dp"
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 2b5a37b..4c007cb 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -811,7 +811,7 @@
}
int errorCode = mKeyStore.importWrappedKey(
- Credentials.USER_SECRET_KEY + alias,
+ Credentials.USER_PRIVATE_KEY + alias,
entry.getWrappedKeyBytes(),
Credentials.USER_PRIVATE_KEY + entry.getWrappingKeyAlias(),
maskingKey,
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 107890e..0760f16 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -26,6 +26,7 @@
#include "DeviceInfo.h"
#include "Matrix.h"
#include "Properties.h"
+#include "utils/MathUtils.h"
using namespace android::uirenderer::renderthread;
@@ -116,9 +117,9 @@
paint.setBlendMode(SkBlendMode::kSrc);
// Apply a filter, which is matching OpenGL pipeline readback behaviour. Filter usage
// is codified by tests using golden images like DecodeAccuracyTest.
- if (skiaSrcRect.width() != bitmap->width() ||
- skiaSrcRect.height() != bitmap->height()) {
- // TODO: apply filter always, but check if tests will be fine
+ bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width())
+ && MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
+ if (!disableFilter) {
paint.setFilterQuality(kLow_SkFilterQuality);
}
scaledSurface->getCanvas()->concat(textureMatrix);
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index aae1f51..6bf52bd 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -323,8 +323,10 @@
StrictMode.setThreadPolicy(policy);
try {
- if (offset != mCurrentOffset) {
- seekTo(offset);
+ synchronized(this) {
+ if (offset != mCurrentOffset) {
+ seekTo(offset);
+ }
}
int n = mInputStream.read(data, 0, size);
@@ -366,7 +368,7 @@
}
@Override
- public long getSize() {
+ public synchronized long getSize() {
if (mConnection == null) {
try {
seekTo(0);
@@ -379,7 +381,7 @@
}
@Override
- public String getMIMEType() {
+ public synchronized String getMIMEType() {
if (mConnection == null) {
try {
seekTo(0);
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index c36858a..a45aa90 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -612,8 +612,12 @@
Image_setBufferItem(env, image, buffer);
env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
static_cast<jlong>(buffer->mTimestamp));
+ auto transform = buffer->mTransform;
+ if (buffer->mTransformToDisplayInverse) {
+ transform |= NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+ }
env->SetIntField(image, gSurfaceImageClassInfo.mTransform,
- static_cast<jint>(buffer->mTransform));
+ static_cast<jint>(transform));
env->SetIntField(image, gSurfaceImageClassInfo.mScalingMode,
static_cast<jint>(buffer->mScalingMode));
diff --git a/packages/EasterEgg/Android.bp b/packages/EasterEgg/Android.bp
new file mode 100644
index 0000000..43ed810
--- /dev/null
+++ b/packages/EasterEgg/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+
+android_app {
+ // the build system in pi-dev can't quite handle R.java in kt
+ // so we will have a mix of java and kotlin files
+ srcs: ["src/**/*.java", "src/**/*.kt"],
+
+ resource_dirs: ["res"],
+
+ name: "EasterEgg",
+
+ certificate: "platform",
+
+ sdk_version: "current",
+
+ optimize: {
+ enabled: false,
+ }
+}
diff --git a/packages/EasterEgg/Android.mk b/packages/EasterEgg/Android.mk
deleted file mode 100644
index 605a75d..0000000
--- a/packages/EasterEgg/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- jsr305
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- android-support-v4 \
- android-support-v13 \
- android-support-dynamic-animation \
- android-support-v7-recyclerview \
- android-support-v7-preference \
- android-support-v7-appcompat \
- android-support-v14-preference
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := EasterEgg
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
index 172490d..6651d9a 100644
--- a/packages/EasterEgg/AndroidManifest.xml
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -15,85 +15,28 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.egg"
- android:versionCode="1"
- android:versionName="1.0">
+ package="com.android.egg"
+ android:versionCode="1"
+ android:versionName="1.0">
- <uses-sdk android:minSdkVersion="26" />
+ <uses-sdk android:minSdkVersion="28" />
- <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <application
+ android:icon="@drawable/icon"
+ android:label="@string/app_name">
- <application android:label="@string/app_name" android:icon="@drawable/icon">
-
- <activity android:name=".octo.Ocquarium"
- android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen"
- android:label="@string/app_name">
+ <activity
+ android:name=".paint.PaintActivity"
+ android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme">
<intent-filter>
- <action android:name="android.intent.action.MAIN"/>
+ <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
+ <!--<category android:name="android.intent.category.LAUNCHER" />-->
<category android:name="com.android.internal.category.PLATLOGO" />
</intent-filter>
</activity>
-
- <!-- Android N lives on inside Android O... -->
-
- <!-- Long press the QS tile to get here -->
- <activity android:name=".neko.NekoLand"
- android:theme="@android:style/Theme.Material.NoActionBar"
- android:label="@string/app_name">
- <intent-filter>
- <action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <!-- This is where the magic happens -->
- <service
- android:name=".neko.NekoService"
- android:enabled="true"
- android:permission="android.permission.BIND_JOB_SERVICE"
- android:exported="true" >
- </service>
-
- <!-- Used to show over lock screen -->
- <activity android:name=".neko.NekoLockedActivity"
- android:excludeFromRecents="true"
- android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
- android:showOnLockScreen="true" />
-
- <!-- Used to enable easter egg -->
- <activity android:name=".neko.NekoActivationActivity"
- android:excludeFromRecents="true"
- android:theme="@android:style/Theme.NoDisplay"
- >
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
- <!-- The quick settings tile, disabled by default -->
- <service
- android:name=".neko.NekoTile"
- android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
- android:icon="@drawable/stat_icon"
- android:enabled="false"
- android:label="@string/default_tile_name">
- <intent-filter>
- <action android:name="android.service.quicksettings.action.QS_TILE" />
- </intent-filter>
- </service>
-
- <!-- FileProvider for sending pictures -->
- <provider
- android:name="android.support.v4.content.FileProvider"
- android:authorities="com.android.egg.fileprovider"
- android:grantUriPermissions="true"
- android:exported="false">
- <meta-data
- android:name="android.support.FILE_PROVIDER_PATHS"
- android:resource="@xml/filepaths" />
- </provider>
</application>
-</manifest>
+
+</manifest>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values/dimens.xml b/packages/EasterEgg/res/color-night/toolbar_icon_color.xml
similarity index 63%
copy from packages/EasterEgg/res/values/dimens.xml
copy to packages/EasterEgg/res/color-night/toolbar_icon_color.xml
index e9dcebd..c0a8152 100644
--- a/packages/EasterEgg/res/values/dimens.xml
+++ b/packages/EasterEgg/res/color-night/toolbar_icon_color.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <dimen name="neko_display_size">64dp</dimen>
-</resources>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#FFFF3333" android:state_selected="true" />
+ <item android:color="#FFFFFFFF" />
+</selector>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values/dimens.xml b/packages/EasterEgg/res/color/toolbar_icon_color.xml
similarity index 71%
rename from packages/EasterEgg/res/values/dimens.xml
rename to packages/EasterEgg/res/color/toolbar_icon_color.xml
index e9dcebd..d3247e4 100644
--- a/packages/EasterEgg/res/values/dimens.xml
+++ b/packages/EasterEgg/res/color/toolbar_icon_color.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+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.
@@ -14,6 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <dimen name="neko_display_size">64dp</dimen>
-</resources>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#FFCC0000" android:state_selected="true" />
+ <item android:color="#FF000000" />
+</selector>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/back.xml b/packages/EasterEgg/res/drawable/back.xml
deleted file mode 100644
index b55d65c..0000000
--- a/packages/EasterEgg/res/drawable/back.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="back" android:fillColor="#FF000000" android:pathData="M37.1,22c-1.1,0 -1.9,0.8 -1.9,1.9v5.6c0,1.1 0.8,1.9 1.9,1.9H39v-1.9v-5.6V22H37.1z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/belly.xml b/packages/EasterEgg/res/drawable/belly.xml
deleted file mode 100644
index 8b0e9af..0000000
--- a/packages/EasterEgg/res/drawable/belly.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="belly" android:fillColor="#FF000000" android:pathData="M20.5,25c-3.6,0 -6.5,2.9 -6.5,6.5V38h13v-6.5C27,27.9 24.1,25 20.5,25z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/body.xml b/packages/EasterEgg/res/drawable/body.xml
deleted file mode 100644
index 8608720..0000000
--- a/packages/EasterEgg/res/drawable/body.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="body" android:fillColor="#FF000000" android:pathData="M9,20h30v18h-30z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/bowtie.xml b/packages/EasterEgg/res/drawable/bowtie.xml
deleted file mode 100644
index 33fa921..0000000
--- a/packages/EasterEgg/res/drawable/bowtie.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="bowtie" android:fillColor="#FF000000" android:pathData="M29,16.8l-10,5l0,-5l10,5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/cap.xml b/packages/EasterEgg/res/drawable/cap.xml
deleted file mode 100644
index d8b4cc5..0000000
--- a/packages/EasterEgg/res/drawable/cap.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="cap" android:fillColor="#FF000000" android:pathData="M27.2,3.8c-1,-0.2 -2.1,-0.3 -3.2,-0.3s-2.1,0.1 -3.2,0.3c0.2,1.3 1.5,2.2 3.2,2.2C25.6,6.1 26.9,5.1 27.2,3.8z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/collar.xml b/packages/EasterEgg/res/drawable/collar.xml
deleted file mode 100644
index 5e4d0fd..0000000
--- a/packages/EasterEgg/res/drawable/collar.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="collar" android:fillColor="#FF000000" android:pathData="M9,18.4h30v1.7h-30z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/face_spot.xml b/packages/EasterEgg/res/drawable/face_spot.xml
deleted file mode 100644
index a89fb4f..0000000
--- a/packages/EasterEgg/res/drawable/face_spot.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="face_spot" android:fillColor="#FF000000" android:pathData="M19.5,15.2a4.5,3.2 0,1 0,9 0a4.5,3.2 0,1 0,-9 0z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/food_bits.xml b/packages/EasterEgg/res/drawable/food_bits.xml
deleted file mode 100644
index 1b2bb6f..0000000
--- a/packages/EasterEgg/res/drawable/food_bits.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M19.1,34l-3.5,1.3c-1,0.4,-2.2,-0.1,-2.6,-1.1l-1.2,-3c-0.4,-1,0.1,-2.2,1.1,-2.6l3.5,-1.3c1,-0.4,2.2,0.1,2.6,1.1l1.2,3 C20.6,32.4,20.1,33.6,19.1,34z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M25.2,28.1L22.9,28c-0.8,0,-1.5,-0.7,-1.4,-1.6l0.1,-2c0,-0.8,0.7,-1.5,1.6,-1.4l2.4,0.1c0.8,0,1.5,0.7,1.4,1.6l-0.1,2 C26.8,27.5,26.1,28.1,25.2,28.1z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M18.7,23.1L16.5,23c-0.5,0,-0.9,-0.4,-0.8,-0.9l0.1,-2.2c0,-0.5,0.4,-0.9,0.9,-0.8l2.2,0.1c0.5,0,0.9,0.4,0.8,0.9 l-0.1,2.2C19.6,22.8,19.2,23.1,18.7,23.1z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M32.2,35.3l-3.6,-1.8c-1,-0.5,-1.4,-1.7,-0.9,-2.7l1.6,-3.1c0.5,-1,1.7,-1.4,2.7,-0.9l3.6,1.8c1,0.5,1.4,1.7,0.9,2.7 l-1.6,3.1C34.4,35.4,33.2,35.7,32.2,35.3z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/food_chicken.xml b/packages/EasterEgg/res/drawable/food_chicken.xml
deleted file mode 100644
index 95b2fb5..0000000
--- a/packages/EasterEgg/res/drawable/food_chicken.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,12v14h10V11H9z M11.7,16.3c-0.7,0,-1.3,-0.6,-1.3,-1.3s0.6,-1.3,1.3,-1.3S13,14.3,13,15S12.4,16.3,11.7,16.3z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M5.7,20.1l1.6,-3.0l-1.6,-3.0l4.4,3.0z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M19.0,6.0l-2.3,2.3l-2.7,-2.6l-2.7,2.6l-2.3,-2.3l0.0,4.0l10.0,0.0z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M9,25c0,8.3,6.7,15,15,15s15,-6.7,15,-15H9z M29.9,31.5h-11v-1h12L29.9,31.5z M31.9,29.5h-13v-1h14L31.9,29.5z M33.9,27.5 h-15v-1h16L33.9,27.5z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M27.0,38.6h2.0v6.0h-2.0z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M17.4,44.6l-2.1999998,0.0l4.4000006,-6.0l2.1999989,0.0z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/food_cookie.xml b/packages/EasterEgg/res/drawable/food_cookie.xml
deleted file mode 100644
index 74dd134..0000000
--- a/packages/EasterEgg/res/drawable/food_cookie.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24">
- <group>
- <path
- android:fillColor="#55FFFFFF"
- android:fillType="evenOdd"
- android:pathData="M5.71 18.29A8.99 8.99 0 0 0 22 13c0-3-1.46-5.65-3.71-7.29A8.99 8.99 0 0 0 2 11c0 3 1.46 5.65 3.71 7.29z"/>
- <path
- android:fillColor="#FFFFFFFF"
- android:fillType="evenOdd"
- android:pathData="M7.25 19.18A8.5 8.5 0 0 0 19.19 7.24 9 9 0 0 1 7.24 19.19z"/>
- <path
- android:fillColor="#55FFFFFF"
- android:pathData="M10.5 3a0.5 0.5 0 1 1 1 0v2.05a0.5 0.5 0 1 1-1 0V3zm3.1 0.42a0.5 0.5 0 0 1 0.93 0.39l-0.8 1.88A0.5 0.5 0 1 1 12.8 5.3l0.8-1.88zm2.7 1.57a0.5 0.5 0 1 1 0.71 0.7l-1.45 1.46a0.5 0.5 0 0 1-0.7-0.71l1.44-1.45zm1.9 2.5a0.5 0.5 0 0 1 0.38 0.92l-1.9 0.77a0.5 0.5 0 0 1-0.37-0.93l1.9-0.77zM19 10.5a0.5 0.5 0 1 1 0 1h-2.05a0.5 0.5 0 0 1 0-1H19zm-0.42 3.1a0.5 0.5 0 0 1-0.39 0.93l-1.88-0.8a0.5 0.5 0 1 1 0.39-0.92l1.88 0.8zm-1.57 2.7a0.5 0.5 0 1 1-0.7 0.71l-1.46-1.45a0.5 0.5 0 0 1 0.71-0.7l1.45 1.44zm-2.5 1.9a0.5 0.5 0 1 1-0.92 0.38l-0.77-1.9a0.5 0.5 0 0 1 0.93-0.37l0.77 1.9zM11.5 19a0.5 0.5 0 1 1-1 0v-2.05a0.5 0.5 0 0 1 1 0V19zm-3.1-0.42a0.5 0.5 0 0 1-0.93-0.39l0.8-1.88A0.5 0.5 0 0 1 9.2 16.7l-0.8 1.88zm-2.7-1.57a0.5 0.5 0 1 1-0.71-0.7l1.45-1.46a0.5 0.5 0 0 1 0.7 0.71L5.7 17.01zm-1.9-2.48a0.5 0.5 0 0 1-0.38-0.92l1.88-0.8a0.5 0.5 0 0 1 0.4 0.92l-1.9 0.8zM3 11.5a0.5 0.5 0 1 1 0-1h2.05a0.5 0.5 0 1 1 0 1H3zm0.42-3.1A0.5 0.5 0 0 1 3.8 7.46l1.88 0.8A0.5 0.5 0 1 1 5.3 9.2L3.42 8.4zm1.57-2.7a0.5 0.5 0 1 1 0.7-0.71l1.46 1.45a0.5 0.5 0 0 1-0.71 0.7L4.99 5.7zm2.5-1.9A0.5 0.5 0 0 1 8.4 3.41l0.77 1.9a0.5 0.5 0 0 1-0.93 0.37L7.48 3.8z"/>
- </group>
-</vector>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/food_dish.xml b/packages/EasterEgg/res/drawable/food_dish.xml
deleted file mode 100644
index 3fff6a9..0000000
--- a/packages/EasterEgg/res/drawable/food_dish.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M24,13.8C11.3,13.8,1,18.3,1,24c0,5.7,10.3,10.2,23,10.2S47,29.7,47,24C47,18.3,36.7,13.8,24,13.8z M33.7,26.6 c1.1,-0.6,1.8,-1.3,1.8,-2c0,-2.1,-5.2,-3.8,-11.7,-3.8s-11.7,1.7,-11.7,3.8c0,0.6,0.4,1.2,1.2,1.7c-1.7,-0.8,-2.8,-1.7,-2.8,-2.8 c0,-2.5,6,-4.5,13.4,-4.5s13.4,2,13.4,4.5C37.4,24.7,36,25.8,33.7,26.6z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/food_donut.xml b/packages/EasterEgg/res/drawable/food_donut.xml
deleted file mode 100644
index eaf831e..0000000
--- a/packages/EasterEgg/res/drawable/food_donut.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M24,4.5c-10.5,0,-19,8.5,-19,19s8.5,19,19,19s19,-8.5,19,-19S34.5,4.5,24,4.5z M35.2,15.5l1.6,-1.1 c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1c0.2,0.3,0.1,0.6,-0.1,0.8l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1 C34.9,16.1,35,15.7,35.2,15.5z M32.7,10.7c0,-0.3,0.3,-0.5,0.6,-0.5l0.1,0c0.3,0,0.5,0.3,0.5,0.6l-0.2,2c0,0.3,-0.3,0.5,-0.6,0.5l-0.1,0 c-0.3,0,-0.5,-0.3,-0.5,-0.6L32.7,10.7z M31.7,15.1l1.5,-0.2c0.2,0,0.5,0.1,0.5,0.4l0,0.1c0,0.2,-0.1,0.5,-0.4,0.5l-1.5,0.2 c-0.2,0,-0.5,-0.1,-0.5,-0.4l0,-0.1C31.3,15.4,31.5,15.2,31.7,15.1z M28.8,10.6l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1 c0.2,0.3,0.1,0.6,-0.1,0.8l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1C28.4,11.1,28.5,10.8,28.8,10.6z M25.8,6 c0,-0.3,0.3,-0.5,0.6,-0.5l0.1,0c0.3,0,0.5,0.3,0.5,0.6l-0.2,2c0,0.3,-0.3,0.5,-0.6,0.5l-0.1,0c-0.3,0,-0.5,-0.3,-0.5,-0.6L25.8,6z M20.7,6.5l1.9,-0.7c0.3,-0.1,0.6,0,0.7,0.3l0,0.1c0.1,0.3,0,0.6,-0.3,0.7l-1.9,0.7c-0.3,0.1,-0.6,0,-0.7,-0.3l0,-0.1 C20.3,6.9,20.4,6.6,20.7,6.5z M19.9,10.9l1.5,-0.2c0.2,0,0.5,0.1,0.5,0.4l0,0.1c0,0.2,-0.1,0.5,-0.4,0.5l-1.5,0.2 c-0.2,0,-0.5,-0.1,-0.5,-0.4l0,-0.1C19.5,11.1,19.7,10.9,19.9,10.9z M16,10.9L16,10.9c0.2,-0.3,0.4,-0.4,0.6,-0.3l1.3,0.7 c0.2,0.1,0.3,0.4,0.2,0.6L18,12c-0.1,0.2,-0.4,0.3,-0.6,0.2l-1.3,-0.7C15.9,11.4,15.8,11.1,16,10.9z M15.8,18.5c0.2,0,0.4,0.1,0.5,0.4 l0,0.1c0,0.2,-0.1,0.4,-0.4,0.5l-1.5,0.2c-0.2,0,-0.4,-0.1,-0.5,-0.4l0,-0.1c0,-0.2,0.1,-0.4,0.4,-0.5L15.8,18.5z M14,21.8l-1.6,1.1 c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1 C14.3,21.3,14.3,21.6,14,21.8z M12.4,12L12.4,12c0.3,-0.2,0.5,-0.2,0.7,-0.1l1,1.1c0.2,0.2,0.2,0.4,0,0.6L14,13.7 c-0.2,0.2,-0.4,0.2,-0.6,0l-1,-1.1C12.2,12.4,12.2,12.1,12.4,12z M8.3,24.5c0,0.3,-0.3,0.5,-0.6,0.5l-0.1,0c-0.3,0,-0.5,-0.3,-0.5,-0.6 l0.2,-2c0,-0.3,0.3,-0.5,0.6,-0.5l0.1,0c0.3,0,0.5,0.3,0.5,0.6L8.3,24.5z M8.5,16.2v-0.1c0,-0.3,0.2,-0.6,0.6,-0.6h2 c0.3,0,0.6,0.2,0.6,0.6v0.1c0,0.3,-0.2,0.6,-0.6,0.6H9C8.7,16.7,8.5,16.5,8.5,16.2z M10.3,20.7c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1 c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1c0.2,0.3,0.1,0.6,-0.1,0.8L10.3,20.7z M11.3,28.3l0,-0.1 c-0.1,-0.3,0,-0.6,0.3,-0.7l1.9,-0.7c0.3,-0.1,0.6,0,0.7,0.3l0,0.1c0.1,0.3,0,0.6,-0.3,0.7L12,28.6C11.7,28.7,11.4,28.6,11.3,28.3z M14.4,33c0,0.2,-0.2,0.4,-0.4,0.4h-1.5c-0.2,0,-0.4,-0.2,-0.4,-0.4v-0.1c0,-0.2,0.2,-0.4,0.4,-0.4H14c0.2,0,0.4,0.2,0.4,0.4V33z M17.9,35.2 l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1l-0.1,-0.1c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1 C18.2,34.7,18.2,35.1,17.9,35.2z M20.7,33.8l-0.1,0.1c-0.1,0.3,-0.5,0.4,-0.8,0.2l-1.7,-1c-0.3,-0.1,-0.4,-0.5,-0.2,-0.8l0.1,-0.1 c0.1,-0.3,0.5,-0.4,0.8,-0.2l1.7,1C20.7,33.2,20.8,33.5,20.7,33.8z M17.5,23.5c0,-3.6,2.9,-6.5,6.5,-6.5s6.5,2.9,6.5,6.5 c0,3.6,-2.9,6.5,-6.5,6.5S17.5,27.1,17.5,23.5z M27.4,35.7l-1.9,0.7c-0.3,0.1,-0.6,0,-0.7,-0.3l0,-0.1c-0.1,-0.3,0,-0.6,0.3,-0.7l1.9,-0.7 c0.3,-0.1,0.6,0,0.7,0.3l0,0.1C27.9,35.3,27.7,35.6,27.4,35.7z M29.7,32.7l-1.4,0.5c-0.2,0.1,-0.5,0,-0.5,-0.3l0,-0.1 c-0.1,-0.2,0,-0.5,0.3,-0.5l1.4,-0.5c0.2,-0.1,0.5,0,0.5,0.3l0,0.1C30,32.3,29.9,32.6,29.7,32.7z M32.8,35.5l-0.1,0.1 c-0.1,0.3,-0.5,0.4,-0.8,0.2l-1.7,-1c-0.3,-0.1,-0.4,-0.5,-0.2,-0.8l0.1,-0.1c0.1,-0.3,0.5,-0.4,0.8,-0.2l1.7,1C32.8,34.9,32.9,35.2,32.8,35.5z M33.7,30.9c0,0.2,-0.2,0.4,-0.5,0.4l-0.1,0c-0.2,0,-0.4,-0.2,-0.4,-0.5l0.1,-1.5c0,-0.2,0.2,-0.4,0.5,-0.4l0.1,0c0.2,0,0.4,0.2,0.4,0.5 L33.7,30.9z M34.5,26.5l-1.3,0.9c-0.2,0.1,-0.5,0.1,-0.6,-0.1l-0.1,-0.1c-0.1,-0.2,-0.1,-0.5,0.1,-0.6l1.3,-0.9c0.2,-0.1,0.5,-0.1,0.6,0.1 l0.1,0.1C34.8,26.1,34.7,26.3,34.5,26.5z M35.6,20.6l-1.7,-1c-0.3,-0.1,-0.4,-0.5,-0.2,-0.8l0.1,-0.1c0.1,-0.3,0.5,-0.4,0.8,-0.2l1.7,1 c0.3,0.1,0.4,0.5,0.2,0.8l-0.1,0.1C36.2,20.6,35.8,20.7,35.6,20.6z M38.6,27.1l-1.6,1.1c-0.3,0.2,-0.6,0.1,-0.8,-0.1L36.1,28 c-0.2,-0.3,-0.1,-0.6,0.1,-0.8l1.6,-1.1c0.3,-0.2,0.6,-0.1,0.8,0.1l0.1,0.1C38.9,26.6,38.8,27,38.6,27.1z M39,19.4l-1.5,0.2 c-0.2,0,-0.5,-0.1,-0.5,-0.4l0,-0.1c0,-0.2,0.1,-0.5,0.4,-0.5l1.5,-0.2c0.2,0,0.5,0.1,0.5,0.4l0,0.1C39.4,19.1,39.2,19.3,39,19.4z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/food_sysuituna.xml b/packages/EasterEgg/res/drawable/food_sysuituna.xml
deleted file mode 100644
index 28cf4a2..0000000
--- a/packages/EasterEgg/res/drawable/food_sysuituna.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M46,18.4l-5.8,4.6c-3.9,-3.2,-8.9,-5.6,-14.6,-6.3l1.2,-6l-7.3,5.9C12.5,17.2,6.4,20,2,24.3l7.2,1.4L2,27 c4.3,4.2,10.4,7.1,17.3,7.6l3.1,2.5L22,34.8c7.1,0,13.5,-2.5,18.2,-6.5l5.8,4.6l-1.4,-7.2L46,18.4z M14.3,24.8l-0.6,0.6l-1.1,-1.1 l-1.1,1.1l-0.6,-0.6l1.1,-1.1l-1.1,-1.1l0.6,-0.6l1.1,1.1l1.1,-1.1l0.6,0.6l-1.1,1.1L14.3,24.8z M18.8,29.1c0.7,-0.8,1.1,-2.2,1.1,-3.8 c0,-1.6,-0.4,-3,-1.1,-3.8c1.1,0.5,1.9,2,1.9,3.8S19.9,28.5,18.8,29.1z M20.7,29.1c0.7,-0.8,1.1,-2.2,1.1,-3.8c0,-1.6,-0.4,-3,-1.1,-3.8 c1.1,0.5,1.9,2,1.9,3.8S21.8,28.5,20.7,29.1z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/foot1.xml b/packages/EasterEgg/res/drawable/foot1.xml
deleted file mode 100644
index 0d90859..0000000
--- a/packages/EasterEgg/res/drawable/foot1.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="foot1" android:fillColor="#FF000000" android:pathData="M11.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/foot2.xml b/packages/EasterEgg/res/drawable/foot2.xml
deleted file mode 100644
index 364ba0c..0000000
--- a/packages/EasterEgg/res/drawable/foot2.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="foot2" android:fillColor="#FF000000" android:pathData="M18.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/foot3.xml b/packages/EasterEgg/res/drawable/foot3.xml
deleted file mode 100644
index e3a512a..0000000
--- a/packages/EasterEgg/res/drawable/foot3.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="foot3" android:fillColor="#FF000000" android:pathData="M29.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/foot4.xml b/packages/EasterEgg/res/drawable/foot4.xml
deleted file mode 100644
index 66b78fa..0000000
--- a/packages/EasterEgg/res/drawable/foot4.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="foot4" android:fillColor="#FF000000" android:pathData="M36.5,43m-2.5,0a2.5,2.5 0,1 1,5 0a2.5,2.5 0,1 1,-5 0"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/head.xml b/packages/EasterEgg/res/drawable/head.xml
deleted file mode 100644
index df600a8..0000000
--- a/packages/EasterEgg/res/drawable/head.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="head" android:fillColor="#FF000000" android:pathData="M9,18.5c0,-8.3 6.8,-15 15,-15s15,6.7 15,15H9z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_clear.xml b/packages/EasterEgg/res/drawable/ic_clear.xml
new file mode 100644
index 0000000..489dcd2
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/ic_clear.xml
@@ -0,0 +1,27 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M19,6.41l-1.41,-1.41l-5.59,5.59l-5.59,-5.59l-1.41,1.41l5.59,5.59l-5.59,5.59l1.41,1.41l5.59,-5.59l5.59,5.59l1.41,-1.41l-5.59,-5.59z"
+ android:strokeWidth="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:strokeColor="#00000000"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_close.xml b/packages/EasterEgg/res/drawable/ic_close.xml
deleted file mode 100644
index 60ea36b..0000000
--- a/packages/EasterEgg/res/drawable/ic_close.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M19.0,6.41L17.59,5.0 12.0,10.59 6.41,5.0 5.0,6.41 10.59,12.0 5.0,17.59 6.41,19.0 12.0,13.41 17.59,19.0 19.0,17.59 13.41,12.0z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_dropper.xml b/packages/EasterEgg/res/drawable/ic_dropper.xml
new file mode 100644
index 0000000..2307309
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/ic_dropper.xml
@@ -0,0 +1,39 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M13.6789,5.6997L3,16.3784L3,20L4,21L7.6216,21L18.3004,10.3212L13.6789,5.6997ZM7,19L5,19L5,17L13.788,8.344L15.6561,10.212L7,19Z"
+ android:strokeWidth="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:strokeColor="#00000000"/>
+ <path
+ android:pathData="M20.9983,2.4982L21.5018,3.0017C22.0876,3.5875 22.0876,4.5373 21.5018,5.1231L18.1231,8.5018C17.5373,9.0876 16.5875,9.0876 16.0017,8.5018L15.4982,7.9983C14.9124,7.4125 14.9124,6.4627 15.4982,5.8769L18.8769,2.4982C19.4627,1.9124 20.4125,1.9124 20.9983,2.4982Z"
+ android:strokeWidth="1"
+ android:fillColor="#000000"
+ android:fillType="evenOdd"
+ android:strokeColor="#00000000"/>
+ <path
+ android:pathData="M13.8284,3l7.0711,7.0711l-2.8284,2.8284l-7.0711,-7.0711z"
+ android:strokeWidth="1"
+ android:fillColor="#000000"
+ android:fillType="evenOdd"
+ android:strokeColor="#00000000"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_hourglass.xml b/packages/EasterEgg/res/drawable/ic_hourglass.xml
new file mode 100644
index 0000000..fe4b9c4
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/ic_hourglass.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M12.5,11L16,7.5L16,4L8,4L8,7.5L11.5,11L11.5,13L8,16.5L8,20L16,20L16,16.5L12.5,13L12.5,11ZM6,2L18,2L18,8L17.99,8L18,8.01L14,12L18,16L17.99,16.01L18,16.01L18,22L6,22L6,16.01L6.01,16.01L6,16L10,12L6,8.01L6.01,8L6,8L6,2Z"
+ android:strokeWidth="1"
+ android:fillColor="#000000"
+ android:fillType="nonZero"
+ android:strokeColor="#00000000"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/ic_share.xml b/packages/EasterEgg/res/drawable/ic_share.xml
deleted file mode 100644
index 8cebc7e..0000000
--- a/packages/EasterEgg/res/drawable/ic_share.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M18.0,16.08c-0.76,0.0 -1.4,0.3 -1.9,0.77L8.91,12.7c0.05,-0.2 0.09,-0.4 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.5,0.5 1.2,0.81 2.0,0.81 1.66,0.0 3.0,-1.34 3.0,-3.0s-1.34,-3.0 -3.0,-3.0 -3.0,1.34 -3.0,3.0c0.0,0.2 0.0,0.4 0.0,0.7L8.04,9.81C7.5,9.31 6.79,9.0 6.0,9.0c-1.66,0.0 -3.0,1.34 -3.0,3.0s1.34,3.0 3.0,3.0c0.79,0.0 1.5,-0.31 2.04,-0.81l7.12,4.16c0.0,0.21 0.0,0.43 0.0,0.65 0.0,1.61 1.31,2.92 2.92,2.92 1.61,0.0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/icon.xml b/packages/EasterEgg/res/drawable/icon.xml
index 5ce9e51..2306b7b 100644
--- a/packages/EasterEgg/res/drawable/icon.xml
+++ b/packages/EasterEgg/res/drawable/icon.xml
@@ -1,7 +1,7 @@
<!--
-Copyright (C) 2017 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -13,28 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path
- android:pathData="M25.0,25.0m-20.5,0.0a20.5,20.5,0,1,1,41.0,0.0a20.5,20.5,0,1,1,-41.0,0.0"
- android:fillAlpha="0.066"
- android:fillColor="#000000"/>
- <path
- android:pathData="M24.0,24.0m-20.0,0.0a20.0,20.0,0,1,1,40.0,0.0a20.0,20.0,0,1,1,-40.0,0.0"
- android:fillColor="#283593"/>
- <path
- android:pathData="M44,24.2010101 L33.9004889,14.101499 L14.101499,33.9004889 L24.2010101,44 C29.2525804,43.9497929 34.2887564,41.9975027 38.1431296,38.1431296 C41.9975027,34.2887564 43.9497929,29.2525804 44,24.2010101 Z"
- android:fillColor="#1a237e"/>
- <path
- android:pathData="M24.0,24.0m-14.0,0.0a14.0,14.0,0,1,1,28.0,0.0a14.0,14.0,0,1,1,-28.0,0.0"
- android:fillColor="#5c6bc0"/>
- <path
- android:pathData="M37.7829445,26.469236 L29.6578482,18.3441397 L18.3441397,29.6578482 L26.469236,37.7829445 C29.1911841,37.2979273 31.7972024,36.0037754 33.9004889,33.9004889 C36.0037754,31.7972024 37.2979273,29.1911841 37.7829445,26.469236 Z"
- android:fillColor="#3f51b5"/>
- <path
- android:pathData="M24.0,24.0m-8.0,0.0a8.0,8.0,0,1,1,16.0,0.0a8.0,8.0,0,1,1,-16.0,0.0"
- android:fillColor="#FFFFFF"/>
-</vector>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/icon_bg"/>
+ <foreground android:drawable="@drawable/p"/>
+</adaptive-icon>
diff --git a/packages/EasterEgg/res/xml/filepaths.xml b/packages/EasterEgg/res/drawable/icon_bg.xml
similarity index 70%
rename from packages/EasterEgg/res/xml/filepaths.xml
rename to packages/EasterEgg/res/drawable/icon_bg.xml
index 2130025..c1553ce 100644
--- a/packages/EasterEgg/res/xml/filepaths.xml
+++ b/packages/EasterEgg/res/drawable/icon_bg.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2017 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,6 +14,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<paths>
- <external-path name="cats" path="Pictures/Cats" />
-</paths>
\ No newline at end of file
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#C5E1A5" />
\ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/left_ear.xml b/packages/EasterEgg/res/drawable/left_ear.xml
deleted file mode 100644
index 2b98736..0000000
--- a/packages/EasterEgg/res/drawable/left_ear.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="left_ear" android:fillColor="#FF000000" android:pathData="M15.4,1l5.1000004,5.3l-6.3,2.8000002z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/left_ear_inside.xml b/packages/EasterEgg/res/drawable/left_ear_inside.xml
deleted file mode 100644
index 1d947ed..0000000
--- a/packages/EasterEgg/res/drawable/left_ear_inside.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="left_ear_inside" android:fillColor="#FF000000" android:pathData="M15.4,1l3.5,6.2l-4.7,1.9z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/left_eye.xml b/packages/EasterEgg/res/drawable/left_eye.xml
deleted file mode 100644
index 4dde1b6..0000000
--- a/packages/EasterEgg/res/drawable/left_eye.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="left_eye" android:fillColor="#FF000000" android:pathData="M20.5,11c0,1.7 -3,1.7 -3,0C17.5,9.3 20.5,9.3 20.5,11z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/leg1.xml b/packages/EasterEgg/res/drawable/leg1.xml
deleted file mode 100644
index d72c746..0000000
--- a/packages/EasterEgg/res/drawable/leg1.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="leg1" android:fillColor="#FF000000" android:pathData="M9,37h5v6h-5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/leg2.xml b/packages/EasterEgg/res/drawable/leg2.xml
deleted file mode 100644
index a772a87..0000000
--- a/packages/EasterEgg/res/drawable/leg2.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="leg2" android:fillColor="#FF000000" android:pathData="M16,37h5v6h-5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/leg2_shadow.xml b/packages/EasterEgg/res/drawable/leg2_shadow.xml
deleted file mode 100644
index b01bd69..0000000
--- a/packages/EasterEgg/res/drawable/leg2_shadow.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="leg2_shadow" android:fillColor="#FF000000" android:pathData="M16,37h5v3h-5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/leg3.xml b/packages/EasterEgg/res/drawable/leg3.xml
deleted file mode 100644
index d471236..0000000
--- a/packages/EasterEgg/res/drawable/leg3.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="leg3" android:fillColor="#FF000000" android:pathData="M27,37h5v6h-5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/leg4.xml b/packages/EasterEgg/res/drawable/leg4.xml
deleted file mode 100644
index e5868eb..0000000
--- a/packages/EasterEgg/res/drawable/leg4.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="leg4" android:fillColor="#FF000000" android:pathData="M34,37h5v6h-5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/mouth.xml b/packages/EasterEgg/res/drawable/mouth.xml
deleted file mode 100644
index ddcf2e8..0000000
--- a/packages/EasterEgg/res/drawable/mouth.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="mouth"
- android:strokeColor="#FF000000"
- android:strokeWidth="1.2"
- android:strokeLineCap="round"
- android:pathData="M29,14.3c-0.4,0.8 -1.3,1.4 -2.3,1.4c-1.4,0 -2.7,-1.3 -2.7,-2.7
- M24,13c0,1.5 -1.2,2.7 -2.7,2.7c-1,0 -1.9,-0.5 -2.3,-1.4"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/nose.xml b/packages/EasterEgg/res/drawable/nose.xml
deleted file mode 100644
index d403cd1..0000000
--- a/packages/EasterEgg/res/drawable/nose.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="nose" android:fillColor="#FF000000" android:pathData="M25.2,13c0,1.3 -2.3,1.3 -2.3,0S25.2,11.7 25.2,13z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/octo_bg.xml b/packages/EasterEgg/res/drawable/octo_bg.xml
deleted file mode 100644
index 1e46cf4..0000000
--- a/packages/EasterEgg/res/drawable/octo_bg.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <gradient android:angle="-90"
- android:startColor="#FF205090"
- android:endColor="#FF001040"
- android:type="linear"
- />
-</shape>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/p.xml b/packages/EasterEgg/res/drawable/p.xml
new file mode 100644
index 0000000..596b782
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/p.xml
@@ -0,0 +1,33 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:pathData="M49,65L54,65C60.075,65 65,60.075 65,54C65,47.925 60.075,43 54,43C47.925,43 43,47.925 43,54L43,108"
+ android:strokeWidth="16"
+ android:fillColor="#00000000"
+ android:strokeColor="#7CB342"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="M51,65L54,65C60.075,65 65,60.075 65,54C65,47.925 60.075,43 54,43C47.925,43 43,47.925 43,54L43,108"
+ android:strokeWidth="8"
+ android:fillColor="#00000000"
+ android:strokeColor="#FFFFFF"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/right_ear.xml b/packages/EasterEgg/res/drawable/right_ear.xml
deleted file mode 100644
index b9fb4d1..0000000
--- a/packages/EasterEgg/res/drawable/right_ear.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="right_ear" android:fillColor="#FF000000" android:pathData="M32.6,1l-5.0999985,5.3l6.299999,2.8000002z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/right_ear_inside.xml b/packages/EasterEgg/res/drawable/right_ear_inside.xml
deleted file mode 100644
index 86b6e34..0000000
--- a/packages/EasterEgg/res/drawable/right_ear_inside.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
-
- <path android:name="right_ear_inside" android:fillColor="#FF000000" android:pathData="M33.8,9.1l-4.7,-1.9l3.5,-6.2z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/right_eye.xml b/packages/EasterEgg/res/drawable/right_eye.xml
deleted file mode 100644
index a1871a6..0000000
--- a/packages/EasterEgg/res/drawable/right_eye.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="right_eye" android:fillColor="#FF000000" android:pathData="M30.5,11c0,1.7 -3,1.7 -3,0C27.5,9.3 30.5,9.3 30.5,11z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/stat_icon.xml b/packages/EasterEgg/res/drawable/stat_icon.xml
deleted file mode 100644
index 608cb20..0000000
--- a/packages/EasterEgg/res/drawable/stat_icon.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,2C6.5,2 2,6.5 2,12c0,5.5 4.5,10 10,10s10,-4.5 10,-10C22,6.5 17.5,2 12,2zM5.5,11c0,-1.6 3,-1.6 3,0C8.5,12.7 5.5,12.7 5.5,11zM17.5,14.6c-0.6,1 -1.7,1.7 -2.9,1.7c-1.1,0 -2,-0.6 -2.6,-1.4c-0.6,0.9 -1.6,1.4 -2.7,1.4c-1.3,0 -2.3,-0.7 -2.9,-1.8c-0.2,-0.3 0,-0.7 0.3,-0.8c0.3,-0.2 0.7,0 0.8,0.3c0.3,0.7 1,1.1 1.8,1.1c0.9,0 1.6,-0.5 1.9,-1.3c-0.2,-0.2 -0.4,-0.4 -0.4,-0.7c0,-1.3 2.3,-1.3 2.3,0c0,0.3 -0.2,0.6 -0.4,0.7c0.3,0.8 1.1,1.3 1.9,1.3c0.8,0 1.5,-0.6 1.8,-1.1c0.2,-0.3 0.6,-0.4 0.9,-0.2C17.6,13.9 17.7,14.3 17.5,14.6zM15.5,11c0,-1.6 3,-1.6 3,0C18.5,12.7 15.5,12.7 15.5,11z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M5.2,1.0l4.1000004,4.2l-5.0,2.1000004z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M18.8,1.0l-4.0999994,4.2l5.000001,2.1000004z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/tail.xml b/packages/EasterEgg/res/drawable/tail.xml
deleted file mode 100644
index 0cca23c..0000000
--- a/packages/EasterEgg/res/drawable/tail.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="tail"
- android:strokeColor="#FF000000"
- android:strokeWidth="5"
- android:strokeLineCap="round"
- android:pathData="M35,35.5h5.9c2.1,0 3.8,-1.7 3.8,-3.8v-6.2"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/tail_cap.xml b/packages/EasterEgg/res/drawable/tail_cap.xml
deleted file mode 100644
index b82f6f9..0000000
--- a/packages/EasterEgg/res/drawable/tail_cap.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="tail_cap" android:fillColor="#FF000000" android:pathData="M42.2,25.5c0,-1.4 1.1,-2.5 2.5,-2.5s2.5,1.1 2.5,2.5H42.2z"/>
-</vector>
diff --git a/packages/EasterEgg/res/drawable/tail_shadow.xml b/packages/EasterEgg/res/drawable/tail_shadow.xml
deleted file mode 100644
index bb1ff12..0000000
--- a/packages/EasterEgg/res/drawable/tail_shadow.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
- <path android:name="tail_shadow" android:fillColor="#FF000000" android:pathData="M40,38l0,-5l-1,0l0,5z"/>
-</vector>
diff --git a/packages/EasterEgg/res/values/dimens.xml b/packages/EasterEgg/res/drawable/toolbar_bg.xml
similarity index 65%
copy from packages/EasterEgg/res/values/dimens.xml
copy to packages/EasterEgg/res/drawable/toolbar_bg.xml
index e9dcebd..0f0e702 100644
--- a/packages/EasterEgg/res/values/dimens.xml
+++ b/packages/EasterEgg/res/drawable/toolbar_bg.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,6 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <dimen name="neko_display_size">64dp</dimen>
-</resources>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="@color/toolbar_bg_color" />
+</shape>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/toolbar_button_bg.xml b/packages/EasterEgg/res/drawable/toolbar_button_bg.xml
new file mode 100644
index 0000000..1b6a53e
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/toolbar_button_bg.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?android:attr/colorControlHighlight">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/black" />
+ <corners android:radius="4dp" />
+ </shape>
+ </item>
+</ripple>
diff --git a/packages/EasterEgg/res/layout/activity_paint.xml b/packages/EasterEgg/res/layout/activity_paint.xml
new file mode 100644
index 0000000..a4c17af
--- /dev/null
+++ b/packages/EasterEgg/res/layout/activity_paint.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res/com.android.egg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#666"
+ tools:context=".paint.PaintActivity"
+ android:id="@+id/contentView" >
+
+ <include layout="@layout/toolbar"
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:layout_gravity="top"
+ />
+ <include layout="@layout/colors"
+ android:id="@+id/colors"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:layout_gravity="top"
+ android:visibility="gone"
+ />
+ <include layout="@layout/brushes"
+ android:id="@+id/brushes"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:layout_gravity="top"
+ android:visibility="gone"
+ />
+
+
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/layout/brushes.xml b/packages/EasterEgg/res/layout/brushes.xml
new file mode 100644
index 0000000..0c4b849
--- /dev/null
+++ b/packages/EasterEgg/res/layout/brushes.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="left"
+ android:background="@drawable/toolbar_bg"
+ android:elevation="10dp"
+ >
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/layout/cat_view.xml b/packages/EasterEgg/res/layout/cat_view.xml
deleted file mode 100644
index 85b494d..0000000
--- a/packages/EasterEgg/res/layout/cat_view.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software distributed under the
- License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the specific language governing
- permissions and limitations under the License.
- -->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingTop="8dp"
- android:paddingBottom="8dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:gravity="center_horizontal"
- android:clipToPadding="false">
-
- <FrameLayout
- android:layout_width="96dp"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="10dp"
- android:layout_gravity="center"
- android:scaleType="fitCenter" />
-
- <LinearLayout
- android:id="@+id/contextGroup"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="invisible"
- android:layout_gravity="bottom">
-
- <ImageView
- android:id="@android:id/shareText"
- android:layout_width="40dp"
- android:layout_height="40dp"
- android:padding="8dp"
- android:src="@drawable/ic_share"
- android:scaleType="fitCenter"
- android:background="#40000000"/>
-
- <Space
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <ImageView
- android:id="@android:id/closeButton"
- android:layout_width="40dp"
- android:layout_height="40dp"
- android:padding="4dp"
- android:src="@drawable/ic_close"
- android:scaleType="fitCenter"
- android:background="#40000000"/>
-
- </LinearLayout>
-
- </FrameLayout>
-
- <TextView
- android:id="@android:id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceListItem"
- android:gravity="center"/>
-</LinearLayout>
-
diff --git a/packages/EasterEgg/res/layout/colors.xml b/packages/EasterEgg/res/layout/colors.xml
new file mode 100644
index 0000000..b90f4d7
--- /dev/null
+++ b/packages/EasterEgg/res/layout/colors.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="left"
+ android:background="@drawable/toolbar_bg"
+ android:elevation="10dp"
+ >
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/layout/edit_text.xml b/packages/EasterEgg/res/layout/edit_text.xml
deleted file mode 100644
index 9f7ac802..0000000
--- a/packages/EasterEgg/res/layout/edit_text.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software distributed under the
- License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the specific language governing
- permissions and limitations under the License.
- -->
-
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="20dp"
- android:paddingEnd="20dp">
-
- <EditText
- android:id="@android:id/edit"
- android:maxLines="1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
-</FrameLayout>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/layout/food_layout.xml b/packages/EasterEgg/res/layout/food_layout.xml
deleted file mode 100644
index d0ca0c8..0000000
--- a/packages/EasterEgg/res/layout/food_layout.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software distributed under the
- License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the specific language governing
- permissions and limitations under the License.
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="?android:attr/selectableItemBackgroundBorderless"
- android:paddingLeft="4dp" android:paddingRight="4dp"
- android:paddingBottom="6dp" android:paddingTop="6dp">
- <ImageView
- android:layout_width="64dp"
- android:layout_height="64dp"
- android:id="@+id/icon"
- android:tint="?android:attr/colorControlNormal"/>
- <TextView android:layout_width="64dp" android:layout_height="wrap_content"
- android:gravity="top|center_horizontal"
- android:id="@+id/text" />
-</LinearLayout>
diff --git a/packages/EasterEgg/res/layout/neko_activity.xml b/packages/EasterEgg/res/layout/neko_activity.xml
deleted file mode 100644
index 21a4600..0000000
--- a/packages/EasterEgg/res/layout/neko_activity.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <android.support.v7.widget.RecyclerView
- android:id="@+id/holder"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"/>
-</FrameLayout>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/layout/toolbar.xml b/packages/EasterEgg/res/layout/toolbar.xml
new file mode 100644
index 0000000..9a5a9c5
--- /dev/null
+++ b/packages/EasterEgg/res/layout/toolbar.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<com.android.egg.paint.CutoutAvoidingToolbar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="50dp"
+ android:orientation="horizontal"
+ android:gravity="left"
+ android:background="@drawable/toolbar_bg"
+ android:elevation="20dp"
+ >
+
+ <Space
+ android:tag="cutoutLeft"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:tag="beforeCutout"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:layout_weight="1"
+ tools:ignore="UselessParent">
+
+ <ImageButton
+ android:id="@+id/btnBrush"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:tint="@color/toolbar_icon_color"
+ android:background="@drawable/toolbar_button_bg"
+ />
+
+ <ImageButton
+ android:id="@+id/btnColor"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:tint="@color/toolbar_icon_color"
+ android:background="@drawable/toolbar_button_bg"
+ />
+
+ <ImageButton
+ android:id="@+id/btnSample"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@drawable/toolbar_button_bg"
+ android:tint="@color/toolbar_icon_color"
+ android:src="@drawable/ic_dropper" />
+
+ </LinearLayout>
+
+ <Space
+ android:tag="cutoutCenter"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:tag="afterCutout"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:layout_weight="1"
+ tools:ignore="UselessParent">
+
+ <ImageButton
+ android:id="@+id/btnZen"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@drawable/toolbar_button_bg"
+ android:tint="@color/toolbar_icon_color"
+ android:src="@drawable/ic_hourglass" />
+
+ <ImageButton
+ android:id="@+id/btnClear"
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:background="@drawable/toolbar_button_bg"
+ android:tint="@color/toolbar_icon_color"
+ android:src="@drawable/ic_clear" />
+
+ </LinearLayout>
+
+ <Space
+ android:tag="cutoutRight"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ />
+
+</com.android.egg.paint.CutoutAvoidingToolbar>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values/dimens.xml b/packages/EasterEgg/res/values-night/colors.xml
similarity index 65%
copy from packages/EasterEgg/res/values/dimens.xml
copy to packages/EasterEgg/res/values-night/colors.xml
index e9dcebd..7c188f7 100644
--- a/packages/EasterEgg/res/values/dimens.xml
+++ b/packages/EasterEgg/res/values-night/colors.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,6 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <dimen name="neko_display_size">64dp</dimen>
-</resources>
+<resources>
+ <color name="toolbar_bg_color">#FF333333</color>
+ <color name="paper_color">#FF000000</color>
+ <color name="paint_color">#FFFFFFFF</color>
+</resources>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values-night/styles.xml b/packages/EasterEgg/res/values-night/styles.xml
new file mode 100644
index 0000000..4edf692
--- /dev/null
+++ b/packages/EasterEgg/res/values-night/styles.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<resources>
+ <style name="AppTheme" parent="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen">
+ <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
+ <item name="android:windowLightNavigationBar">false</item>
+ </style>
+</resources>
diff --git a/packages/EasterEgg/res/xml/filepaths.xml b/packages/EasterEgg/res/values/attrs_toolbar_view.xml
similarity index 68%
copy from packages/EasterEgg/res/xml/filepaths.xml
copy to packages/EasterEgg/res/values/attrs_toolbar_view.xml
index 2130025..ed1360f 100644
--- a/packages/EasterEgg/res/xml/filepaths.xml
+++ b/packages/EasterEgg/res/values/attrs_toolbar_view.xml
@@ -1,8 +1,7 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2017 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<paths>
- <external-path name="cats" path="Pictures/Cats" />
-</paths>
\ No newline at end of file
+<resources>
+ <declare-styleable name="ToolbarView">
+ </declare-styleable>
+</resources>
diff --git a/packages/EasterEgg/res/values/dimens.xml b/packages/EasterEgg/res/values/colors.xml
similarity index 66%
copy from packages/EasterEgg/res/values/dimens.xml
copy to packages/EasterEgg/res/values/colors.xml
index e9dcebd..1a5388b 100644
--- a/packages/EasterEgg/res/values/dimens.xml
+++ b/packages/EasterEgg/res/values/colors.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+ Copyright (C) 2018 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
+ 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
@@ -14,6 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <dimen name="neko_display_size">64dp</dimen>
-</resources>
+<resources>
+ <color name="toolbar_bg_color">#FFDDDDDD</color>
+ <color name="paper_color">#FFFFFFFF</color>
+ <color name="paint_color">#FF000000</color>
+</resources>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
index 61e3834..32dbc97 100644
--- a/packages/EasterEgg/res/values/strings.xml
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-Copyright (C) 2016 The Android Open Source Project
+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.
@@ -15,40 +15,5 @@
limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <string name="app_name" translatable="false">Android Easter Egg</string>
- <string name="notification_name" translatable="false">Android Neko</string>
- <string name="notification_channel_name" translatable="false">New cats</string>
- <string name="default_tile_name" translatable="false">\????</string>
- <string name="notification_title" translatable="false">A cat is here.</string>
- <string name="default_cat_name" translatable="false">Cat #%s</string>
- <string name="directory_name" translatable="false">Cats</string>
- <string name="confirm_delete" translatable="false">Forget %s?</string>
- <string-array name="food_names" translatable="false">
- <item>Empty dish</item>
- <item>Bits</item>
- <item>Fish</item>
- <item>Chicken</item>
- <item>Treat</item>
- </string-array>
- <array name="food_icons">
- <item>@drawable/food_dish</item>
- <item>@drawable/food_bits</item>
- <item>@drawable/food_sysuituna</item>
- <item>@drawable/food_chicken</item>
- <item>@drawable/food_cookie</item>
- </array>
- <integer-array name="food_intervals">
- <item>0</item>
- <item>15</item>
- <item>30</item>
- <item>60</item>
- <item>120</item>
- </integer-array>
- <integer-array name="food_new_cat_prob">
- <item>0</item>
- <item>5</item>
- <item>35</item>
- <item>65</item>
- <item>90</item>
- </integer-array>
+ <string name="app_name" translatable="false">PAINT.APK</string>
</resources>
diff --git a/packages/EasterEgg/res/values/styles.xml b/packages/EasterEgg/res/values/styles.xml
new file mode 100644
index 0000000..44e2ce5
--- /dev/null
+++ b/packages/EasterEgg/res/values/styles.xml
@@ -0,0 +1,23 @@
+<!--
+ 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.
+-->
+<resources>
+
+ <style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
+ <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
+ <item name="android:windowLightNavigationBar">true</item>
+ </style>
+
+</resources>
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
deleted file mode 100644
index dd1bd07..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/Cat.java
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.*;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-
-import java.io.ByteArrayOutputStream;
-import java.util.Random;
-import java.util.concurrent.ThreadLocalRandom;
-
-import com.android.egg.R;
-import com.android.internal.logging.MetricsLogger;
-
-import static com.android.egg.neko.NekoLand.CHAN_ID;
-
-public class Cat extends Drawable {
- public static final long[] PURR = {0, 40, 20, 40, 20, 40, 20, 40, 20, 40, 20, 40};
-
- private Random mNotSoRandom;
- private Bitmap mBitmap;
- private long mSeed;
- private String mName;
- private int mBodyColor;
- private int mFootType;
- private boolean mBowTie;
-
- private synchronized Random notSoRandom(long seed) {
- if (mNotSoRandom == null) {
- mNotSoRandom = new Random();
- mNotSoRandom.setSeed(seed);
- }
- return mNotSoRandom;
- }
-
- public static final float frandrange(Random r, float a, float b) {
- return (b-a)*r.nextFloat() + a;
- }
-
- public static final Object choose(Random r, Object...l) {
- return l[r.nextInt(l.length)];
- }
-
- public static final int chooseP(Random r, int[] a) {
- int pct = r.nextInt(1000);
- final int stop = a.length-2;
- int i=0;
- while (i<stop) {
- pct -= a[i];
- if (pct < 0) break;
- i+=2;
- }
- return a[i+1];
- }
-
- public static final int getColorIndex(int q, int[] a) {
- for(int i = 1; i < a.length; i+=2) {
- if (a[i] == q) {
- return i/2;
- }
- }
- return -1;
- }
-
- public static final int[] P_BODY_COLORS = {
- 180, 0xFF212121, // black
- 180, 0xFFFFFFFF, // white
- 140, 0xFF616161, // gray
- 140, 0xFF795548, // brown
- 100, 0xFF90A4AE, // steel
- 100, 0xFFFFF9C4, // buff
- 100, 0xFFFF8F00, // orange
- 5, 0xFF29B6F6, // blue..?
- 5, 0xFFFFCDD2, // pink!?
- 5, 0xFFCE93D8, // purple?!?!?
- 4, 0xFF43A047, // yeah, why not green
- 1, 0, // ?!?!?!
- };
-
- public static final int[] P_COLLAR_COLORS = {
- 250, 0xFFFFFFFF,
- 250, 0xFF000000,
- 250, 0xFFF44336,
- 50, 0xFF1976D2,
- 50, 0xFFFDD835,
- 50, 0xFFFB8C00,
- 50, 0xFFF48FB1,
- 50, 0xFF4CAF50,
- };
-
- public static final int[] P_BELLY_COLORS = {
- 750, 0,
- 250, 0xFFFFFFFF,
- };
-
- public static final int[] P_DARK_SPOT_COLORS = {
- 700, 0,
- 250, 0xFF212121,
- 50, 0xFF6D4C41,
- };
-
- public static final int[] P_LIGHT_SPOT_COLORS = {
- 700, 0,
- 300, 0xFFFFFFFF,
- };
-
- private CatParts D;
-
- public static void tint(int color, Drawable ... ds) {
- for (Drawable d : ds) {
- if (d != null) {
- d.mutate().setTint(color);
- }
- }
- }
-
- public static boolean isDark(int color) {
- final int r = (color & 0xFF0000) >> 16;
- final int g = (color & 0x00FF00) >> 8;
- final int b = color & 0x0000FF;
- return (r + g + b) < 0x80;
- }
-
- public Cat(Context context, long seed) {
- D = new CatParts(context);
- mSeed = seed;
-
- setName(context.getString(R.string.default_cat_name,
- String.valueOf(mSeed % 1000)));
-
- final Random nsr = notSoRandom(seed);
-
- // body color
- mBodyColor = chooseP(nsr, P_BODY_COLORS);
- if (mBodyColor == 0) mBodyColor = Color.HSVToColor(new float[] {
- nsr.nextFloat()*360f, frandrange(nsr,0.5f,1f), frandrange(nsr,0.5f, 1f)});
-
- tint(mBodyColor, D.body, D.head, D.leg1, D.leg2, D.leg3, D.leg4, D.tail,
- D.leftEar, D.rightEar, D.foot1, D.foot2, D.foot3, D.foot4, D.tailCap);
- tint(0x20000000, D.leg2Shadow, D.tailShadow);
- if (isDark(mBodyColor)) {
- tint(0xFFFFFFFF, D.leftEye, D.rightEye, D.mouth, D.nose);
- }
- tint(isDark(mBodyColor) ? 0xFFEF9A9A : 0x20D50000, D.leftEarInside, D.rightEarInside);
-
- tint(chooseP(nsr, P_BELLY_COLORS), D.belly);
- tint(chooseP(nsr, P_BELLY_COLORS), D.back);
- final int faceColor = chooseP(nsr, P_BELLY_COLORS);
- tint(faceColor, D.faceSpot);
- if (!isDark(faceColor)) {
- tint(0xFF000000, D.mouth, D.nose);
- }
-
- mFootType = 0;
- if (nsr.nextFloat() < 0.25f) {
- mFootType = 4;
- tint(0xFFFFFFFF, D.foot1, D.foot2, D.foot3, D.foot4);
- } else {
- if (nsr.nextFloat() < 0.25f) {
- mFootType = 2;
- tint(0xFFFFFFFF, D.foot1, D.foot3);
- } else if (nsr.nextFloat() < 0.25f) {
- mFootType = 3; // maybe -2 would be better? meh.
- tint(0xFFFFFFFF, D.foot2, D.foot4);
- } else if (nsr.nextFloat() < 0.1f) {
- mFootType = 1;
- tint(0xFFFFFFFF, (Drawable) choose(nsr, D.foot1, D.foot2, D.foot3, D.foot4));
- }
- }
-
- tint(nsr.nextFloat() < 0.333f ? 0xFFFFFFFF : mBodyColor, D.tailCap);
-
- final int capColor = chooseP(nsr, isDark(mBodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS);
- tint(capColor, D.cap);
- //tint(chooseP(nsr, isDark(bodyColor) ? P_LIGHT_SPOT_COLORS : P_DARK_SPOT_COLORS), D.nose);
-
- final int collarColor = chooseP(nsr, P_COLLAR_COLORS);
- tint(collarColor, D.collar);
- mBowTie = nsr.nextFloat() < 0.1f;
- tint(mBowTie ? collarColor : 0, D.bowtie);
- }
-
- public static Cat create(Context context) {
- return new Cat(context, Math.abs(ThreadLocalRandom.current().nextInt()));
- }
-
- public Notification.Builder buildNotification(Context context) {
- final Bundle extras = new Bundle();
- extras.putString("android.substName", context.getString(R.string.notification_name));
- final Intent intent = new Intent(Intent.ACTION_MAIN)
- .setClass(context, NekoLand.class)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- return new Notification.Builder(context)
- .setSmallIcon(Icon.createWithResource(context, R.drawable.stat_icon))
- .setLargeIcon(createNotificationLargeIcon(context))
- .setColor(getBodyColor())
- .setPriority(Notification.PRIORITY_LOW)
- .setContentTitle(context.getString(R.string.notification_title))
- .setShowWhen(true)
- .setCategory(Notification.CATEGORY_STATUS)
- .setContentText(getName())
- .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
- .setAutoCancel(true)
- .setChannel(CHAN_ID)
- .setVibrate(PURR)
- .addExtras(extras);
- }
-
- public long getSeed() {
- return mSeed;
- }
-
- @Override
- public void draw(Canvas canvas) {
- final int w = Math.min(canvas.getWidth(), canvas.getHeight());
- final int h = w;
-
- if (mBitmap == null || mBitmap.getWidth() != w || mBitmap.getHeight() != h) {
- mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- final Canvas bitCanvas = new Canvas(mBitmap);
- slowDraw(bitCanvas, 0, 0, w, h);
- }
- canvas.drawBitmap(mBitmap, 0, 0, null);
- }
-
- private void slowDraw(Canvas canvas, int x, int y, int w, int h) {
- for (int i = 0; i < D.drawingOrder.length; i++) {
- final Drawable d = D.drawingOrder[i];
- if (d != null) {
- d.setBounds(x, y, x+w, y+h);
- d.draw(canvas);
- }
- }
-
- }
-
- public Bitmap createBitmap(int w, int h) {
- if (mBitmap != null && mBitmap.getWidth() == w && mBitmap.getHeight() == h) {
- return mBitmap.copy(mBitmap.getConfig(), true);
- }
- Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- slowDraw(new Canvas(result), 0, 0, w, h);
- return result;
- }
-
- public static Icon recompressIcon(Icon bitmapIcon) {
- if (bitmapIcon.getType() != Icon.TYPE_BITMAP) return bitmapIcon;
- final Bitmap bits = bitmapIcon.getBitmap();
- final ByteArrayOutputStream ostream = new ByteArrayOutputStream(
- bits.getWidth() * bits.getHeight() * 2); // guess 50% compression
- final boolean ok = bits.compress(Bitmap.CompressFormat.PNG, 100, ostream);
- if (!ok) return null;
- return Icon.createWithData(ostream.toByteArray(), 0, ostream.size());
- }
-
- public Icon createNotificationLargeIcon(Context context) {
- final Resources res = context.getResources();
- final int w = 2*res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
- final int h = 2*res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
- return recompressIcon(createIcon(context, w, h));
- }
-
- public Icon createIcon(Context context, int w, int h) {
- Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(result);
- final Paint pt = new Paint();
- float[] hsv = new float[3];
- Color.colorToHSV(mBodyColor, hsv);
- hsv[2] = (hsv[2]>0.5f)
- ? (hsv[2] - 0.25f)
- : (hsv[2] + 0.25f);
- pt.setColor(Color.HSVToColor(hsv));
- float r = w/2;
- canvas.drawCircle(r, r, r, pt);
- int m = w/10;
-
- slowDraw(canvas, m, m, w-m-m, h-m-m);
-
- return Icon.createWithBitmap(result);
- }
-
- @Override
- public void setAlpha(int i) {
-
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
-
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- public String getName() {
- return mName;
- }
-
- public void setName(String name) {
- this.mName = name;
- }
-
- public int getBodyColor() {
- return mBodyColor;
- }
-
- public void logAdd(Context context) {
- logCatAction(context, "egg_neko_add");
- }
-
- public void logRename(Context context) {
- logCatAction(context, "egg_neko_rename");
- }
-
- public void logRemove(Context context) {
- logCatAction(context, "egg_neko_remove");
- }
-
- public void logShare(Context context) {
- logCatAction(context, "egg_neko_share");
- }
-
- private void logCatAction(Context context, String prefix) {
- MetricsLogger.count(context, prefix, 1);
- MetricsLogger.histogram(context, prefix +"_color",
- getColorIndex(mBodyColor, P_BODY_COLORS));
- MetricsLogger.histogram(context, prefix + "_bowtie", mBowTie ? 1 : 0);
- MetricsLogger.histogram(context, prefix + "_feet", mFootType);
- }
-
- public static class CatParts {
- public Drawable leftEar;
- public Drawable rightEar;
- public Drawable rightEarInside;
- public Drawable leftEarInside;
- public Drawable head;
- public Drawable faceSpot;
- public Drawable cap;
- public Drawable mouth;
- public Drawable body;
- public Drawable foot1;
- public Drawable leg1;
- public Drawable foot2;
- public Drawable leg2;
- public Drawable foot3;
- public Drawable leg3;
- public Drawable foot4;
- public Drawable leg4;
- public Drawable tail;
- public Drawable leg2Shadow;
- public Drawable tailShadow;
- public Drawable tailCap;
- public Drawable belly;
- public Drawable back;
- public Drawable rightEye;
- public Drawable leftEye;
- public Drawable nose;
- public Drawable bowtie;
- public Drawable collar;
- public Drawable[] drawingOrder;
-
- public CatParts(Context context) {
- body = context.getDrawable(R.drawable.body);
- head = context.getDrawable(R.drawable.head);
- leg1 = context.getDrawable(R.drawable.leg1);
- leg2 = context.getDrawable(R.drawable.leg2);
- leg3 = context.getDrawable(R.drawable.leg3);
- leg4 = context.getDrawable(R.drawable.leg4);
- tail = context.getDrawable(R.drawable.tail);
- leftEar = context.getDrawable(R.drawable.left_ear);
- rightEar = context.getDrawable(R.drawable.right_ear);
- rightEarInside = context.getDrawable(R.drawable.right_ear_inside);
- leftEarInside = context.getDrawable(R.drawable.left_ear_inside);
- faceSpot = context.getDrawable(R.drawable.face_spot);
- cap = context.getDrawable(R.drawable.cap);
- mouth = context.getDrawable(R.drawable.mouth);
- foot4 = context.getDrawable(R.drawable.foot4);
- foot3 = context.getDrawable(R.drawable.foot3);
- foot1 = context.getDrawable(R.drawable.foot1);
- foot2 = context.getDrawable(R.drawable.foot2);
- leg2Shadow = context.getDrawable(R.drawable.leg2_shadow);
- tailShadow = context.getDrawable(R.drawable.tail_shadow);
- tailCap = context.getDrawable(R.drawable.tail_cap);
- belly = context.getDrawable(R.drawable.belly);
- back = context.getDrawable(R.drawable.back);
- rightEye = context.getDrawable(R.drawable.right_eye);
- leftEye = context.getDrawable(R.drawable.left_eye);
- nose = context.getDrawable(R.drawable.nose);
- collar = context.getDrawable(R.drawable.collar);
- bowtie = context.getDrawable(R.drawable.bowtie);
- drawingOrder = getDrawingOrder();
- }
- private Drawable[] getDrawingOrder() {
- return new Drawable[] {
- collar,
- leftEar, leftEarInside, rightEar, rightEarInside,
- head,
- faceSpot,
- cap,
- leftEye, rightEye,
- nose, mouth,
- tail, tailCap, tailShadow,
- foot1, leg1,
- foot2, leg2,
- foot3, leg3,
- foot4, leg4,
- leg2Shadow,
- body, belly,
- bowtie
- };
- }
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Food.java b/packages/EasterEgg/src/com/android/egg/neko/Food.java
deleted file mode 100644
index 5c0f12e..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/Food.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-
-import com.android.egg.R;
-
-public class Food {
- private final int mType;
-
- private static int[] sIcons;
- private static String[] sNames;
-
- public Food(int type) {
- mType = type;
- }
-
- public Icon getIcon(Context context) {
- if (sIcons == null) {
- TypedArray icons = context.getResources().obtainTypedArray(R.array.food_icons);
- sIcons = new int[icons.length()];
- for (int i = 0; i < sIcons.length; i++) {
- sIcons[i] = icons.getResourceId(i, 0);
- }
- icons.recycle();
- }
- return Icon.createWithResource(context, sIcons[mType]);
- }
-
- public String getName(Context context) {
- if (sNames == null) {
- sNames = context.getResources().getStringArray(R.array.food_names);
- }
- return sNames[mType];
- }
-
- public long getInterval(Context context) {
- return context.getResources().getIntArray(R.array.food_intervals)[mType];
- }
-
- public int getType() {
- return mType;
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java b/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java
deleted file mode 100644
index c0b725c..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoActivationActivity.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-
-public class NekoActivationActivity extends Activity {
- private void toastUp(String s) {
- Toast toast = Toast.makeText(this, s, Toast.LENGTH_SHORT);
- toast.getView().setBackgroundDrawable(null);
- toast.show();
- }
-
- @Override
- public void onStart() {
- super.onStart();
-
- final PackageManager pm = getPackageManager();
- final ComponentName cn = new ComponentName(this, NekoTile.class);
- if (pm.getComponentEnabledSetting(cn) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- if (NekoLand.DEBUG) {
- Log.v("Neko", "Disabling tile.");
- }
- pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- MetricsLogger.histogram(this, "egg_neko_enable", 0);
- toastUp("\uD83D\uDEAB");
- } else {
- if (NekoLand.DEBUG) {
- Log.v("Neko", "Enabling tile.");
- }
- pm.setComponentEnabledSetting(cn, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
- MetricsLogger.histogram(this, "egg_neko_enable", 1);
- toastUp("\uD83D\uDC31");
- }
- finish();
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java b/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java
deleted file mode 100644
index 2d2fbe8..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.support.annotation.NonNull;
-import android.app.Dialog;
-import android.content.Context;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.egg.R;
-import com.android.internal.logging.MetricsLogger;
-
-import java.util.ArrayList;
-
-public class NekoDialog extends Dialog {
-
- private final Adapter mAdapter;
-
- public NekoDialog(@NonNull Context context) {
- super(context, android.R.style.Theme_Material_Dialog_NoActionBar);
- RecyclerView view = new RecyclerView(getContext());
- mAdapter = new Adapter(getContext());
- view.setLayoutManager(new GridLayoutManager(getContext(), 2));
- view.setAdapter(mAdapter);
- final float dp = context.getResources().getDisplayMetrics().density;
- final int pad = (int)(16*dp);
- view.setPadding(pad, pad, pad, pad);
- setContentView(view);
- }
-
- private void onFoodSelected(Food food) {
- PrefState prefs = new PrefState(getContext());
- int currentState = prefs.getFoodState();
- if (currentState == 0 && food.getType() != 0) {
- NekoService.registerJob(getContext(), food.getInterval(getContext()));
- }
- MetricsLogger.histogram(getContext(), "egg_neko_offered_food", food.getType());
- prefs.setFoodState(food.getType());
- dismiss();
- }
-
- private class Adapter extends RecyclerView.Adapter<Holder> {
-
- private final Context mContext;
- private final ArrayList<Food> mFoods = new ArrayList<>();
-
- public Adapter(Context context) {
- mContext = context;
- int[] foods = context.getResources().getIntArray(R.array.food_names);
- // skip food 0, you can't choose it
- for (int i=1; i<foods.length; i++) {
- mFoods.add(new Food(i));
- }
- }
-
- @Override
- public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
- return new Holder(LayoutInflater.from(parent.getContext())
- .inflate(R.layout.food_layout, parent, false));
- }
-
- @Override
- public void onBindViewHolder(final Holder holder, int position) {
- final Food food = mFoods.get(position);
- ((ImageView) holder.itemView.findViewById(R.id.icon))
- .setImageIcon(food.getIcon(mContext));
- ((TextView) holder.itemView.findViewById(R.id.text))
- .setText(food.getName(mContext));
- holder.itemView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onFoodSelected(mFoods.get(holder.getAdapterPosition()));
- }
- });
- }
-
- @Override
- public int getItemCount() {
- return mFoods.size();
- }
- }
-
- public static class Holder extends RecyclerView.ViewHolder {
-
- public Holder(View itemView) {
- super(itemView);
- }
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
deleted file mode 100644
index d2e37d8..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.Manifest;
-import android.app.ActionBar;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.media.MediaScannerConnection;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.provider.MediaStore.Images;
-import android.support.v4.content.FileProvider;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.util.Log;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnLongClickListener;
-import android.view.ViewGroup;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.egg.R;
-import com.android.egg.neko.PrefState.PrefsListener;
-import com.android.internal.logging.MetricsLogger;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-public class NekoLand extends Activity implements PrefsListener {
- public static String CHAN_ID = "EGG";
-
- public static boolean DEBUG = false;
- public static boolean DEBUG_NOTIFICATIONS = false;
-
- private static final int EXPORT_BITMAP_SIZE = 600;
-
- private static final int STORAGE_PERM_REQUEST = 123;
-
- private static boolean CAT_GEN = false;
- private PrefState mPrefs;
- private CatAdapter mAdapter;
- private Cat mPendingShareCat;
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.neko_activity);
- final ActionBar actionBar = getActionBar();
- if (actionBar != null) {
- actionBar.setLogo(Cat.create(this));
- actionBar.setDisplayUseLogoEnabled(false);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mPrefs = new PrefState(this);
- mPrefs.setListener(this);
- final RecyclerView recyclerView = findViewById(R.id.holder);
- mAdapter = new CatAdapter();
- recyclerView.setAdapter(mAdapter);
- recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
- int numCats = updateCats();
- MetricsLogger.histogram(this, "egg_neko_visit_gallery", numCats);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mPrefs.setListener(null);
- }
-
- private int updateCats() {
- Cat[] cats;
- if (CAT_GEN) {
- cats = new Cat[50];
- for (int i = 0; i < cats.length; i++) {
- cats[i] = Cat.create(this);
- }
- } else {
- final float[] hsv = new float[3];
- List<Cat> list = mPrefs.getCats();
- Collections.sort(list, new Comparator<Cat>() {
- @Override
- public int compare(Cat cat, Cat cat2) {
- Color.colorToHSV(cat.getBodyColor(), hsv);
- float bodyH1 = hsv[0];
- Color.colorToHSV(cat2.getBodyColor(), hsv);
- float bodyH2 = hsv[0];
- return Float.compare(bodyH1, bodyH2);
- }
- });
- cats = list.toArray(new Cat[0]);
- }
- mAdapter.setCats(cats);
- return cats.length;
- }
-
- private void onCatClick(Cat cat) {
- if (CAT_GEN) {
- mPrefs.addCat(cat);
- new AlertDialog.Builder(NekoLand.this)
- .setTitle("Cat added")
- .setPositiveButton(android.R.string.ok, null)
- .show();
- } else {
- showNameDialog(cat);
- }
-// noman.notify(1, cat.buildNotification(NekoLand.this).build());
- }
-
- private void onCatRemove(Cat cat) {
- cat.logRemove(this);
- mPrefs.removeCat(cat);
- }
-
- private void showNameDialog(final Cat cat) {
- final Context context = new ContextThemeWrapper(this,
- android.R.style.Theme_Material_Light_Dialog_NoActionBar);
- // TODO: Move to XML, add correct margins.
- View view = LayoutInflater.from(context).inflate(R.layout.edit_text, null);
- final EditText text = (EditText) view.findViewById(android.R.id.edit);
- text.setText(cat.getName());
- text.setSelection(cat.getName().length());
- final int size = context.getResources()
- .getDimensionPixelSize(android.R.dimen.app_icon_size);
- Drawable catIcon = cat.createIcon(this, size, size).loadDrawable(this);
- new AlertDialog.Builder(context)
- .setTitle(" ")
- .setIcon(catIcon)
- .setView(view)
- .setPositiveButton(android.R.string.ok, new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- cat.logRename(context);
- cat.setName(text.getText().toString().trim());
- mPrefs.addCat(cat);
- }
- }).show();
- }
-
- @Override
- public void onPrefsChanged() {
- updateCats();
- }
-
- private class CatAdapter extends RecyclerView.Adapter<CatHolder> {
-
- private Cat[] mCats;
-
- public void setCats(Cat[] cats) {
- mCats = cats;
- notifyDataSetChanged();
- }
-
- @Override
- public CatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- return new CatHolder(LayoutInflater.from(parent.getContext())
- .inflate(R.layout.cat_view, parent, false));
- }
-
- private void setContextGroupVisible(final CatHolder holder, boolean vis) {
- final View group = holder.contextGroup;
- if (vis && group.getVisibility() != View.VISIBLE) {
- group.setAlpha(0);
- group.setVisibility(View.VISIBLE);
- group.animate().alpha(1.0f).setDuration(333);
- Runnable hideAction = new Runnable() {
- @Override
- public void run() {
- setContextGroupVisible(holder, false);
- }
- };
- group.setTag(hideAction);
- group.postDelayed(hideAction, 5000);
- } else if (!vis && group.getVisibility() == View.VISIBLE) {
- group.removeCallbacks((Runnable) group.getTag());
- group.animate().alpha(0f).setDuration(250).withEndAction(new Runnable() {
- @Override
- public void run() {
- group.setVisibility(View.INVISIBLE);
- }
- });
- }
- }
-
- @Override
- public void onBindViewHolder(final CatHolder holder, int position) {
- Context context = holder.itemView.getContext();
- final int size = context.getResources().getDimensionPixelSize(R.dimen.neko_display_size);
- holder.imageView.setImageIcon(mCats[position].createIcon(context, size, size));
- holder.textView.setText(mCats[position].getName());
- holder.itemView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onCatClick(mCats[holder.getAdapterPosition()]);
- }
- });
- holder.itemView.setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- setContextGroupVisible(holder, true);
- return true;
- }
- });
- holder.delete.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setContextGroupVisible(holder, false);
- new AlertDialog.Builder(NekoLand.this)
- .setTitle(getString(R.string.confirm_delete, mCats[position].getName()))
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- onCatRemove(mCats[holder.getAdapterPosition()]);
- }
- })
- .show();
- }
- });
- holder.share.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setContextGroupVisible(holder, false);
- Cat cat = mCats[holder.getAdapterPosition()];
- if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
- != PackageManager.PERMISSION_GRANTED) {
- mPendingShareCat = cat;
- requestPermissions(
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- STORAGE_PERM_REQUEST);
- return;
- }
- shareCat(cat);
- }
- });
- }
-
- @Override
- public int getItemCount() {
- return mCats.length;
- }
- }
-
- private void shareCat(Cat cat) {
- final File dir = new File(
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
- getString(R.string.directory_name));
- if (!dir.exists() && !dir.mkdirs()) {
- Log.e("NekoLand", "save: error: can't create Pictures directory");
- return;
- }
- final File png = new File(dir, cat.getName().replaceAll("[/ #:]+", "_") + ".png");
- Bitmap bitmap = cat.createBitmap(EXPORT_BITMAP_SIZE, EXPORT_BITMAP_SIZE);
- if (bitmap != null) {
- try {
- OutputStream os = new FileOutputStream(png);
- bitmap.compress(Bitmap.CompressFormat.PNG, 0, os);
- os.close();
- MediaScannerConnection.scanFile(
- this,
- new String[] {png.toString()},
- new String[] {"image/png"},
- null);
- Log.v("Neko", "cat file: " + png);
- Uri uri = FileProvider.getUriForFile(this, "com.android.egg.fileprovider", png);
- Log.v("Neko", "cat uri: " + uri);
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
- intent.putExtra(Intent.EXTRA_SUBJECT, cat.getName());
- intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- intent.setType("image/png");
- startActivity(Intent.createChooser(intent, null));
- cat.logShare(this);
- } catch (IOException e) {
- Log.e("NekoLand", "save: error: " + e);
- }
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode,
- String permissions[], int[] grantResults) {
- if (requestCode == STORAGE_PERM_REQUEST) {
- if (mPendingShareCat != null) {
- shareCat(mPendingShareCat);
- mPendingShareCat = null;
- }
- }
- }
-
- private static class CatHolder extends RecyclerView.ViewHolder {
- private final ImageView imageView;
- private final TextView textView;
- private final View contextGroup;
- private final View delete;
- private final View share;
-
- public CatHolder(View itemView) {
- super(itemView);
- imageView = (ImageView) itemView.findViewById(android.R.id.icon);
- textView = (TextView) itemView.findViewById(android.R.id.title);
- contextGroup = itemView.findViewById(R.id.contextGroup);
- delete = itemView.findViewById(android.R.id.closeButton);
- share = itemView.findViewById(android.R.id.shareText);
- }
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java
deleted file mode 100644
index 5f01da8..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLockedActivity.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.support.annotation.Nullable;
-import android.app.Activity;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
-import android.os.Bundle;
-import android.view.WindowManager;
-
-public class NekoLockedActivity extends Activity implements OnDismissListener {
-
- private NekoDialog mDialog;
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
-
- mDialog = new NekoDialog(this);
- mDialog.setOnDismissListener(this);
- mDialog.show();
- }
-
- @Override
- public void onDismiss(DialogInterface dialog) {
- finish();
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
deleted file mode 100644
index 42506e6..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Bundle;
-
-import java.util.List;
-import android.util.Log;
-
-import com.android.egg.R;
-
-import java.util.Random;
-
-import static com.android.egg.neko.Cat.PURR;
-import static com.android.egg.neko.NekoLand.CHAN_ID;
-
-public class NekoService extends JobService {
-
- private static final String TAG = "NekoService";
-
- public static int JOB_ID = 42;
-
- public static int CAT_NOTIFICATION = 1;
- public static int DEBUG_NOTIFICATION = 1234;
-
- public static float CAT_CAPTURE_PROB = 1.0f; // generous
-
- public static long SECONDS = 1000;
- public static long MINUTES = 60 * SECONDS;
-
- public static long INTERVAL_FLEX = 5 * MINUTES;
-
- public static float INTERVAL_JITTER_FRAC = 0.25f;
-
- private static void setupNotificationChannels(Context context) {
- NotificationManager noman = context.getSystemService(NotificationManager.class);
- NotificationChannel eggChan = new NotificationChannel(CHAN_ID,
- context.getString(R.string.notification_channel_name),
- NotificationManager.IMPORTANCE_DEFAULT);
- eggChan.setSound(Uri.EMPTY, Notification.AUDIO_ATTRIBUTES_DEFAULT); // cats are quiet
- eggChan.setVibrationPattern(PURR); // not totally quiet though
- eggChan.setBlockableSystem(true); // unlike a real cat, you can push this one off your lap
- eggChan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); // cats sit in the window
- noman.createNotificationChannel(eggChan);
- }
-
- @Override
- public boolean onStartJob(JobParameters params) {
- Log.v(TAG, "Starting job: " + String.valueOf(params));
-
- NotificationManager noman = getSystemService(NotificationManager.class);
- if (NekoLand.DEBUG_NOTIFICATIONS) {
- final Bundle extras = new Bundle();
- extras.putString("android.substName", getString(R.string.notification_name));
- final int size = getResources()
- .getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
- final Cat cat = Cat.create(this);
- final Notification.Builder builder
- = cat.buildNotification(this)
- .setContentTitle("DEBUG")
- .setChannel(NekoLand.CHAN_ID)
- .setContentText("Ran job: " + params);
- noman.notify(DEBUG_NOTIFICATION, builder.build());
- }
-
- final PrefState prefs = new PrefState(this);
- int food = prefs.getFoodState();
- if (food != 0) {
- prefs.setFoodState(0); // nom
- final Random rng = new Random();
- if (rng.nextFloat() <= CAT_CAPTURE_PROB) {
- Cat cat;
- List<Cat> cats = prefs.getCats();
- final int[] probs = getResources().getIntArray(R.array.food_new_cat_prob);
- final float new_cat_prob = (float)((food < probs.length) ? probs[food] : 50) / 100f;
-
- if (cats.size() == 0 || rng.nextFloat() <= new_cat_prob) {
- cat = Cat.create(this);
- prefs.addCat(cat);
- cat.logAdd(this);
- Log.v(TAG, "A new cat is here: " + cat.getName());
- } else {
- cat = cats.get(rng.nextInt(cats.size()));
- Log.v(TAG, "A cat has returned: " + cat.getName());
- }
-
- final Notification.Builder builder = cat.buildNotification(this);
- noman.notify(CAT_NOTIFICATION, builder.build());
- }
- }
- cancelJob(this);
- return false;
- }
-
- @Override
- public boolean onStopJob(JobParameters jobParameters) {
- return false;
- }
-
- public static void registerJobIfNeeded(Context context, long intervalMinutes) {
- JobScheduler jss = context.getSystemService(JobScheduler.class);
- JobInfo info = jss.getPendingJob(JOB_ID);
- if (info == null) {
- registerJob(context, intervalMinutes);
- }
- }
-
- public static void registerJob(Context context, long intervalMinutes) {
- setupNotificationChannels(context);
-
- JobScheduler jss = context.getSystemService(JobScheduler.class);
- jss.cancel(JOB_ID);
- long interval = intervalMinutes * MINUTES;
- long jitter = (long)(INTERVAL_JITTER_FRAC * interval);
- interval += (long)(Math.random() * (2 * jitter)) - jitter;
- final JobInfo jobInfo = new JobInfo.Builder(JOB_ID,
- new ComponentName(context, NekoService.class))
- .setPeriodic(interval, INTERVAL_FLEX)
- .build();
-
- Log.v(TAG, "A cat will visit in " + interval + "ms: " + String.valueOf(jobInfo));
- jss.schedule(jobInfo);
-
- if (NekoLand.DEBUG_NOTIFICATIONS) {
- NotificationManager noman = context.getSystemService(NotificationManager.class);
- noman.notify(DEBUG_NOTIFICATION, new Notification.Builder(context)
- .setSmallIcon(R.drawable.stat_icon)
- .setContentTitle(String.format("Job scheduled in %d min", (interval / MINUTES)))
- .setContentText(String.valueOf(jobInfo))
- .setPriority(Notification.PRIORITY_MIN)
- .setCategory(Notification.CATEGORY_SERVICE)
- .setChannel(NekoLand.CHAN_ID)
- .setShowWhen(true)
- .build());
- }
- }
-
- public static void cancelJob(Context context) {
- JobScheduler jss = context.getSystemService(JobScheduler.class);
- Log.v(TAG, "Canceling job");
- jss.cancel(JOB_ID);
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java b/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
deleted file mode 100644
index 159b40a..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoTile.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.content.Intent;
-import android.service.quicksettings.Tile;
-import android.service.quicksettings.TileService;
-import android.util.Log;
-
-import com.android.egg.neko.PrefState.PrefsListener;
-import com.android.internal.logging.MetricsLogger;
-
-public class NekoTile extends TileService implements PrefsListener {
-
- private static final String TAG = "NekoTile";
-
- private PrefState mPrefs;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mPrefs = new PrefState(this);
- }
-
- @Override
- public void onStartListening() {
- super.onStartListening();
- mPrefs.setListener(this);
- updateState();
- }
-
- @Override
- public void onStopListening() {
- super.onStopListening();
- mPrefs.setListener(null);
- }
-
- @Override
- public void onTileAdded() {
- super.onTileAdded();
- MetricsLogger.count(this, "egg_neko_tile_added", 1);
- }
-
- @Override
- public void onTileRemoved() {
- super.onTileRemoved();
- MetricsLogger.count(this, "egg_neko_tile_removed", 1);
- }
-
- @Override
- public void onPrefsChanged() {
- updateState();
- }
-
- private void updateState() {
- Tile tile = getQsTile();
- int foodState = mPrefs.getFoodState();
- Food food = new Food(foodState);
- if (foodState != 0) {
- NekoService.registerJobIfNeeded(this, food.getInterval(this));
- }
- tile.setIcon(food.getIcon(this));
- tile.setLabel(food.getName(this));
- tile.setState(foodState != 0 ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
- tile.updateTile();
- }
-
- @Override
- public void onClick() {
- if (mPrefs.getFoodState() != 0) {
- // there's already food loaded, let's empty it
- MetricsLogger.count(this, "egg_neko_empty_food", 1);
- mPrefs.setFoodState(0);
- NekoService.cancelJob(this);
- } else {
- // time to feed the cats
- if (isLocked()) {
- if (isSecure()) {
- Log.d(TAG, "startActivityAndCollapse");
- Intent intent = new Intent(this, NekoLockedActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivityAndCollapse(intent);
- } else {
- unlockAndRun(new Runnable() {
- @Override
- public void run() {
- showNekoDialog();
- }
- });
- }
- } else {
- showNekoDialog();
- }
- }
- }
-
- private void showNekoDialog() {
- Log.d(TAG, "showNekoDialog");
- MetricsLogger.count(this, "egg_neko_select_food", 1);
- showDialog(new NekoDialog(this));
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java b/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
deleted file mode 100644
index bf71b19..0000000
--- a/packages/EasterEgg/src/com/android/egg/neko/PrefState.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.neko;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-public class PrefState implements OnSharedPreferenceChangeListener {
-
- private static final String FILE_NAME = "mPrefs";
-
- private static final String FOOD_STATE = "food";
-
- private static final String CAT_KEY_PREFIX = "cat:";
-
- private final Context mContext;
- private final SharedPreferences mPrefs;
- private PrefsListener mListener;
-
- public PrefState(Context context) {
- mContext = context;
- mPrefs = mContext.getSharedPreferences(FILE_NAME, 0);
- }
-
- // Can also be used for renaming.
- public void addCat(Cat cat) {
- mPrefs.edit()
- .putString(CAT_KEY_PREFIX + String.valueOf(cat.getSeed()), cat.getName())
- .apply();
- }
-
- public void removeCat(Cat cat) {
- mPrefs.edit().remove(CAT_KEY_PREFIX + String.valueOf(cat.getSeed())).apply();
- }
-
- public List<Cat> getCats() {
- ArrayList<Cat> cats = new ArrayList<>();
- Map<String, ?> map = mPrefs.getAll();
- for (String key : map.keySet()) {
- if (key.startsWith(CAT_KEY_PREFIX)) {
- long seed = Long.parseLong(key.substring(CAT_KEY_PREFIX.length()));
- Cat cat = new Cat(mContext, seed);
- cat.setName(String.valueOf(map.get(key)));
- cats.add(cat);
- }
- }
- return cats;
- }
-
- public int getFoodState() {
- return mPrefs.getInt(FOOD_STATE, 0);
- }
-
- public void setFoodState(int foodState) {
- mPrefs.edit().putInt(FOOD_STATE, foodState).apply();
- }
-
- public void setListener(PrefsListener listener) {
- mListener = listener;
- if (mListener != null) {
- mPrefs.registerOnSharedPreferenceChangeListener(this);
- } else {
- mPrefs.unregisterOnSharedPreferenceChangeListener(this);
- }
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- mListener.onPrefsChanged();
- }
-
- public interface PrefsListener {
- void onPrefsChanged();
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/octo/Ocquarium.java b/packages/EasterEgg/src/com/android/egg/octo/Ocquarium.java
deleted file mode 100644
index 8a06cc6..0000000
--- a/packages/EasterEgg/src/com/android/egg/octo/Ocquarium.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.octo;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import com.android.egg.R;
-
-public class Ocquarium extends Activity {
- ImageView mImageView;
- private OctopusDrawable mOcto;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- final float dp = getResources().getDisplayMetrics().density;
-
- getWindow().setBackgroundDrawableResource(R.drawable.octo_bg);
-
- FrameLayout bg = new FrameLayout(this);
- setContentView(bg);
- bg.setAlpha(0f);
- bg.animate().setStartDelay(500).setDuration(5000).alpha(1f).start();
-
- mImageView = new ImageView(this);
- bg.addView(mImageView, new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
-
- mOcto = new OctopusDrawable(getApplicationContext());
- mOcto.setSizePx((int) (OctopusDrawable.randfrange(40f,180f) * dp));
- mImageView.setImageDrawable(mOcto);
-
- mImageView.setOnTouchListener(new View.OnTouchListener() {
- boolean touching;
- @Override
- public boolean onTouch(View view, MotionEvent motionEvent) {
- switch (motionEvent.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- if (mOcto.hitTest(motionEvent.getX(), motionEvent.getY())) {
- touching = true;
- mOcto.stopDrift();
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (touching) {
- mOcto.moveTo(motionEvent.getX(), motionEvent.getY());
- }
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- touching = false;
- mOcto.startDrift();
- break;
- }
- return true;
- }
- });
- }
-
- @Override
- protected void onPause() {
- mOcto.stopDrift();
- super.onPause();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- mOcto.startDrift();
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/octo/OctopusDrawable.java b/packages/EasterEgg/src/com/android/egg/octo/OctopusDrawable.java
deleted file mode 100644
index 5dde6e1..0000000
--- a/packages/EasterEgg/src/com/android/egg/octo/OctopusDrawable.java
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.octo;
-
-import android.animation.TimeAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.DashPathEffect;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.animation.DynamicAnimation;
-import android.support.animation.SpringForce;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.animation.SpringAnimation;
-import android.support.animation.FloatValueHolder;
-
-public class OctopusDrawable extends Drawable {
- private static float BASE_SCALE = 100f;
- public static boolean PATH_DEBUG = false;
-
- private static int BODY_COLOR = 0xFF101010;
- private static int ARM_COLOR = 0xFF101010;
- private static int ARM_COLOR_BACK = 0xFF000000;
- private static int EYE_COLOR = 0xFF808080;
-
- private static int[] BACK_ARMS = {1, 3, 4, 6};
- private static int[] FRONT_ARMS = {0, 2, 5, 7};
-
- private Paint mPaint = new Paint();
- private Arm[] mArms = new Arm[8];
- final PointF point = new PointF();
- private int mSizePx = 100;
- final Matrix M = new Matrix();
- final Matrix M_inv = new Matrix();
- private TimeAnimator mDriftAnimation;
- private boolean mBlinking;
- private float[] ptmp = new float[2];
- private float[] scaledBounds = new float[2];
-
- public static float randfrange(float a, float b) {
- return (float) (Math.random()*(b-a) + a);
- }
- public static float clamp(float v, float a, float b) {
- return v<a?a:v>b?b:v;
- }
-
- public OctopusDrawable(Context context) {
- float dp = context.getResources().getDisplayMetrics().density;
- setSizePx((int) (100*dp));
- mPaint.setAntiAlias(true);
- for (int i=0; i<mArms.length; i++) {
- final float bias = (float)i/(mArms.length-1) - 0.5f;
- mArms[i] = new Arm(
- 0,0, // arm will be repositioned on moveTo
- 10f*bias + randfrange(0,20f), randfrange(20f,50f),
- 40f*bias+randfrange(-60f,60f), randfrange(30f, 80f),
- randfrange(-40f,40f), randfrange(-80f,40f),
- 14f, 2f);
- }
- }
-
- public void setSizePx(int size) {
- mSizePx = size;
- M.setScale(mSizePx/BASE_SCALE, mSizePx/BASE_SCALE);
- // TaperedPathStroke.setMinStep(20f*BASE_SCALE/mSizePx); // nice little floaty circles
- TaperedPathStroke.setMinStep(8f*BASE_SCALE/mSizePx); // classic tentacles
- M.invert(M_inv);
- }
-
- public void startDrift() {
- if (mDriftAnimation == null) {
- mDriftAnimation = new TimeAnimator();
- mDriftAnimation.setTimeListener(new TimeAnimator.TimeListener() {
- float MAX_VY = 35f;
- float JUMP_VY = -100f;
- float MAX_VX = 15f;
- private float ax = 0f, ay = 30f;
- private float vx, vy;
- long nextjump = 0;
- long unblink = 0;
- @Override
- public void onTimeUpdate(TimeAnimator timeAnimator, long t, long dt) {
- float t_sec = 0.001f * t;
- float dt_sec = 0.001f * dt;
- if (t > nextjump) {
- vy = JUMP_VY;
- nextjump = t + (long) randfrange(5000, 10000);
- }
- if (unblink > 0 && t > unblink) {
- setBlinking(false);
- unblink = 0;
- } else if (Math.random() < 0.001f) {
- setBlinking(true);
- unblink = t + 200;
- }
-
- ax = (float) (MAX_VX * Math.sin(t_sec*.25f));
-
- vx = clamp(vx + dt_sec * ax, -MAX_VX, MAX_VX);
- vy = clamp(vy + dt_sec * ay, -100*MAX_VY, MAX_VY);
-
- // oob check
- if (point.y - BASE_SCALE/2 > scaledBounds[1]) {
- vy = JUMP_VY;
- } else if (point.y + BASE_SCALE < 0) {
- vy = MAX_VY;
- }
-
- point.x = clamp(point.x + dt_sec * vx, 0, scaledBounds[0]);
- point.y = point.y + dt_sec * vy;
-
- repositionArms();
- }
- });
- }
- mDriftAnimation.start();
- }
-
- public void stopDrift() {
- mDriftAnimation.cancel();
- }
-
- @Override
- public void onBoundsChange(Rect bounds) {
- final float w = bounds.width();
- final float h = bounds.height();
-
- lockArms(true);
- moveTo(w/2, h/2);
- lockArms(false);
-
- scaledBounds[0] = w;
- scaledBounds[1] = h;
- M_inv.mapPoints(scaledBounds);
- }
-
- // real pixel coordinates
- public void moveTo(float x, float y) {
- point.x = x;
- point.y = y;
- mapPointF(M_inv, point);
- repositionArms();
- }
-
- public boolean hitTest(float x, float y) {
- ptmp[0] = x;
- ptmp[1] = y;
- M_inv.mapPoints(ptmp);
- return Math.hypot(ptmp[0] - point.x, ptmp[1] - point.y) < BASE_SCALE/2;
- }
-
- private void lockArms(boolean l) {
- for (Arm arm : mArms) {
- arm.setLocked(l);
- }
- }
- private void repositionArms() {
- for (int i=0; i<mArms.length; i++) {
- final float bias = (float)i/(mArms.length-1) - 0.5f;
- mArms[i].setAnchor(
- point.x+bias*30f,point.y+26f);
- }
- invalidateSelf();
- }
-
- private void drawPupil(Canvas canvas, float x, float y, float size, boolean open,
- Paint pt) {
- final float r = open ? size*.33f : size * .1f;
- canvas.drawRoundRect(x - size, y - r, x + size, y + r, r, r, pt);
- }
-
- @Override
- public void draw(@NonNull Canvas canvas) {
- canvas.save();
- {
- canvas.concat(M);
-
- // arms behind
- mPaint.setColor(ARM_COLOR_BACK);
- for (int i : BACK_ARMS) {
- mArms[i].draw(canvas, mPaint);
- }
-
- // head/body/thing
- mPaint.setColor(EYE_COLOR);
- canvas.drawCircle(point.x, point.y, 36f, mPaint);
- mPaint.setColor(BODY_COLOR);
- canvas.save();
- {
- canvas.clipOutRect(point.x - 61f, point.y + 8f,
- point.x + 61f, point.y + 12f);
- canvas.drawOval(point.x-40f,point.y-60f,point.x+40f,point.y+40f, mPaint);
- }
- canvas.restore();
-
- // eyes
- mPaint.setColor(EYE_COLOR);
- if (mBlinking) {
- drawPupil(canvas, point.x - 16f, point.y - 12f, 6f, false, mPaint);
- drawPupil(canvas, point.x + 16f, point.y - 12f, 6f, false, mPaint);
- } else {
- canvas.drawCircle(point.x - 16f, point.y - 12f, 6f, mPaint);
- canvas.drawCircle(point.x + 16f, point.y - 12f, 6f, mPaint);
- }
-
- // too much?
- if (false) {
- mPaint.setColor(0xFF000000);
- drawPupil(canvas, point.x - 16f, point.y - 12f, 5f, true, mPaint);
- drawPupil(canvas, point.x + 16f, point.y - 12f, 5f, true, mPaint);
- }
-
- // arms in front
- mPaint.setColor(ARM_COLOR);
- for (int i : FRONT_ARMS) {
- mArms[i].draw(canvas, mPaint);
- }
-
- if (PATH_DEBUG) for (Arm arm : mArms) {
- arm.drawDebug(canvas);
- }
- }
- canvas.restore();
- }
-
- public void setBlinking(boolean b) {
- mBlinking = b;
- invalidateSelf();
- }
-
- @Override
- public void setAlpha(int i) {
- }
-
- @Override
- public void setColorFilter(@Nullable ColorFilter colorFilter) {
-
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- static Path pathMoveTo(Path p, PointF pt) {
- p.moveTo(pt.x, pt.y);
- return p;
- }
- static Path pathQuadTo(Path p, PointF p1, PointF p2) {
- p.quadTo(p1.x, p1.y, p2.x, p2.y);
- return p;
- }
-
- static void mapPointF(Matrix m, PointF point) {
- float[] p = new float[2];
- p[0] = point.x;
- p[1] = point.y;
- m.mapPoints(p);
- point.x = p[0];
- point.y = p[1];
- }
-
- private class Link // he come to town
- implements DynamicAnimation.OnAnimationUpdateListener {
- final FloatValueHolder[] coords = new FloatValueHolder[2];
- final SpringAnimation[] anims = new SpringAnimation[coords.length];
- private float dx, dy;
- private boolean locked = false;
- Link next;
-
- Link(int index, float x1, float y1, float dx, float dy) {
- coords[0] = new FloatValueHolder(x1);
- coords[1] = new FloatValueHolder(y1);
- this.dx = dx;
- this.dy = dy;
- for (int i=0; i<coords.length; i++) {
- anims[i] = new SpringAnimation(coords[i]);
- anims[i].setSpring(new SpringForce()
- .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
- .setStiffness(
- index == 0 ? SpringForce.STIFFNESS_LOW
- : index == 1 ? SpringForce.STIFFNESS_VERY_LOW
- : SpringForce.STIFFNESS_VERY_LOW/2)
- .setFinalPosition(0f));
- anims[i].addUpdateListener(this);
- }
- }
- public void setLocked(boolean locked) {
- this.locked = locked;
- }
- public PointF start() {
- return new PointF(coords[0].getValue(), coords[1].getValue());
- }
- public PointF end() {
- return new PointF(coords[0].getValue()+dx,coords[1].getValue()+dy);
- }
- public PointF mid() {
- return new PointF(
- 0.5f*dx+(coords[0].getValue()),
- 0.5f*dy+(coords[1].getValue()));
- }
- public void animateTo(PointF target) {
- if (locked) {
- setStart(target.x, target.y);
- } else {
- anims[0].animateToFinalPosition(target.x);
- anims[1].animateToFinalPosition(target.y);
- }
- }
- @Override
- public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float v, float v1) {
- if (next != null) {
- next.animateTo(end());
- }
- OctopusDrawable.this.invalidateSelf();
- }
-
- public void setStart(float x, float y) {
- coords[0].setValue(x);
- coords[1].setValue(y);
- onAnimationUpdate(null, 0, 0);
- }
- }
-
- private class Arm {
- final Link link1, link2, link3;
- float max, min;
-
- public Arm(float x, float y, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3,
- float max, float min) {
- link1 = new Link(0, x, y, dx1, dy1);
- link2 = new Link(1, x+dx1, y+dy1, dx2, dy2);
- link3 = new Link(2, x+dx1+dx2, y+dy1+dy2, dx3, dy3);
- link1.next = link2;
- link2.next = link3;
-
- link1.setLocked(true);
- link2.setLocked(false);
- link3.setLocked(false);
-
- this.max = max;
- this.min = min;
- }
-
- // when the arm is locked, it moves rigidly, without physics
- public void setLocked(boolean locked) {
- link2.setLocked(locked);
- link3.setLocked(locked);
- }
-
- private void setAnchor(float x, float y) {
- link1.setStart(x,y);
- }
-
- public Path getPath() {
- Path p = new Path();
- pathMoveTo(p, link1.start());
- pathQuadTo(p, link2.start(), link2.mid());
- pathQuadTo(p, link2.end(), link3.end());
- return p;
- }
-
- public void draw(@NonNull Canvas canvas, Paint pt) {
- final Path p = getPath();
- TaperedPathStroke.drawPath(canvas, p, max, min, pt);
- }
-
- private final Paint dpt = new Paint();
- public void drawDebug(Canvas canvas) {
- dpt.setStyle(Paint.Style.STROKE);
- dpt.setStrokeWidth(0.75f);
- dpt.setStrokeCap(Paint.Cap.ROUND);
-
- dpt.setAntiAlias(true);
- dpt.setColor(0xFF336699);
-
- final Path path = getPath();
- canvas.drawPath(path, dpt);
-
- dpt.setColor(0xFFFFFF00);
-
- dpt.setPathEffect(new DashPathEffect(new float[] {2f, 2f}, 0f));
-
- canvas.drawLines(new float[] {
- link1.end().x, link1.end().y,
- link2.start().x, link2.start().y,
-
- link2.end().x, link2.end().y,
- link3.start().x, link3.start().y,
- }, dpt);
- dpt.setPathEffect(null);
-
- dpt.setColor(0xFF00CCFF);
-
- canvas.drawLines(new float[] {
- link1.start().x, link1.start().y,
- link1.end().x, link1.end().y,
-
- link2.start().x, link2.start().y,
- link2.end().x, link2.end().y,
-
- link3.start().x, link3.start().y,
- link3.end().x, link3.end().y,
- }, dpt);
-
- dpt.setColor(0xFFCCEEFF);
- canvas.drawCircle(link2.start().x, link2.start().y, 2f, dpt);
- canvas.drawCircle(link3.start().x, link3.start().y, 2f, dpt);
-
- dpt.setStyle(Paint.Style.FILL_AND_STROKE);
- canvas.drawCircle(link1.start().x, link1.start().y, 2f, dpt);
- canvas.drawCircle(link2.mid().x, link2.mid().y, 2f, dpt);
- canvas.drawCircle(link3.end().x, link3.end().y, 2f, dpt);
- }
-
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/octo/TaperedPathStroke.java b/packages/EasterEgg/src/com/android/egg/octo/TaperedPathStroke.java
deleted file mode 100644
index e014fbc..0000000
--- a/packages/EasterEgg/src/com/android/egg/octo/TaperedPathStroke.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.egg.octo;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PathMeasure;
-import android.os.Debug;
-
-import java.util.Arrays;
-
-public class TaperedPathStroke {
- static float sMinStepPx = 4f;
- static PathMeasure pm = new PathMeasure();
- static float[] pos = {0,0};
- static float[] tan = {0,0};
- static float lerp(float t, float a, float b) {
- return a + t*(b-a);
- }
- public static void setMinStep(float px) {
- sMinStepPx = px;
- }
-
- // it's the variable-width brush algorithm from the Markers app, basically
- public static void drawPath(Canvas c, Path p, float r1, float r2, Paint pt) {
- pm.setPath(p,false);
- final float len = pm.getLength();
- float t=0;
- boolean last=false;
- while (true) {
- if (t>=len) {
- t=len;
- last=true;
- }
- pm.getPosTan(t, pos, tan);
- float r = len > 0 ? lerp(t/len, r1, r2) : r1;
- c.drawCircle(pos[0], pos[1], r, pt);
- t += Math.max(r*0.25f, sMinStepPx); // walk forward 1/4 radius, not too small though
- if (last) break;
- }
- }
-}
diff --git a/packages/EasterEgg/src/com/android/egg/paint/BrushPropertyDrawable.kt b/packages/EasterEgg/src/com/android/egg/paint/BrushPropertyDrawable.kt
new file mode 100644
index 0000000..4a02ee6
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/BrushPropertyDrawable.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.egg.paint
+
+import android.content.Context
+import android.graphics.*
+import android.graphics.PixelFormat.TRANSLUCENT
+import android.graphics.drawable.Drawable
+import android.util.DisplayMetrics
+
+class BrushPropertyDrawable : Drawable {
+ val framePaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
+ it.color = Color.BLACK
+ it.style = Paint.Style.FILL
+ }
+ val wellPaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
+ it.color = Color.RED
+ it.style = Paint.Style.FILL
+ }
+
+ constructor(context: Context) {
+ _size = (24 * context.resources.displayMetrics.density).toInt()
+ }
+
+ private var _size = 24
+ private var _scale = 1f
+
+ fun setFrameColor(color: Int) {
+ framePaint.color = color
+ invalidateSelf()
+ }
+
+ fun setWellColor(color: Int) {
+ wellPaint.color = color
+ invalidateSelf()
+ }
+
+ fun setWellScale(scale: Float) {
+ _scale = scale
+ invalidateSelf()
+ }
+
+ override fun getIntrinsicWidth(): Int {
+ return _size
+ }
+
+ override fun getIntrinsicHeight(): Int {
+ return _size
+ }
+
+ override fun draw(c: Canvas?) {
+ c?.let {
+ val w = bounds.width().toFloat()
+ val h = bounds.height().toFloat()
+ val inset = _size / 12 // 2dp in a 24x24 icon
+ val r = Math.min(w, h) / 2
+
+ c.drawCircle(w/2, h/2, (r - inset) * _scale + 1 , wellPaint)
+
+ val p = Path()
+ p.addCircle(w/2, h/2, r, Path.Direction.CCW)
+ p.addCircle(w/2, h/2, r - inset, Path.Direction.CW)
+ c.drawPath(p, framePaint)
+ }
+ }
+
+ override fun setAlpha(p0: Int) {
+ //
+ }
+
+ override fun getOpacity(): Int {
+ return TRANSLUCENT
+ }
+
+ override fun setColorFilter(p0: ColorFilter?) {
+ //
+ }
+
+}
\ No newline at end of file
diff --git a/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt b/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
new file mode 100644
index 0000000..164fc5a
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/CutoutAvoidingToolbar.kt
@@ -0,0 +1,88 @@
+/*
+ * 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.egg.paint
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.*
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
+import android.widget.LinearLayout
+
+class CutoutAvoidingToolbar : LinearLayout {
+ private var _insets: WindowInsets? = null
+
+ constructor(context: Context) : super(context) {
+ init(null, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
+ init(attrs, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
+ init(attrs, defStyle)
+ }
+
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+ super.onSizeChanged(w, h, oldw, oldh)
+ adjustLayout()
+ }
+
+ override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets {
+ _insets = insets
+ adjustLayout()
+ return super.onApplyWindowInsets(insets)
+ }
+
+ fun adjustLayout() {
+ _insets?.displayCutout?.boundingRects?.let {
+ var cutoutCenter = 0
+ var cutoutLeft = 0
+ var cutoutRight = 0
+
+ // collect at most three cutouts
+ for (r in it) {
+ if (r.top > 0) continue
+
+ if (r.left == left) {
+ cutoutLeft = r.width()
+ } else if (r.right == right) {
+ cutoutRight = r.width()
+ } else {
+ cutoutCenter = r.width()
+ }
+ }
+
+ // apply to layout
+ (findViewWithTag("cutoutLeft") as View?)?.let {
+ it.layoutParams = LayoutParams(cutoutLeft, MATCH_PARENT)
+ }
+ (findViewWithTag("cutoutCenter") as View?)?.let {
+ it.layoutParams = LayoutParams(cutoutCenter, MATCH_PARENT)
+ }
+ (findViewWithTag("cutoutRight") as View?)?.let {
+ it.layoutParams = LayoutParams(cutoutRight, MATCH_PARENT)
+ }
+
+ requestLayout()
+ }
+ }
+
+ private fun init(attrs: AttributeSet?, defStyle: Int) {
+ }
+
+}
diff --git a/packages/EasterEgg/src/com/android/egg/paint/PaintActivity.java b/packages/EasterEgg/src/com/android/egg/paint/PaintActivity.java
new file mode 100644
index 0000000..ac47fbd
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/PaintActivity.java
@@ -0,0 +1,351 @@
+/*
+ * 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.egg.paint;
+
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.animation.OvershootInterpolator;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.Magnifier;
+
+import com.android.egg.R;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.stream.IntStream;
+
+public class PaintActivity extends Activity {
+ private static final float MAX_BRUSH_WIDTH_DP = 100f;
+ private static final float MIN_BRUSH_WIDTH_DP = 1f;
+
+ private static final int NUM_BRUSHES = 6;
+ private static final int NUM_COLORS = 6;
+
+ private Painting painting = null;
+ private CutoutAvoidingToolbar toolbar = null;
+ private LinearLayout brushes = null;
+ private LinearLayout colors = null;
+ private Magnifier magnifier = null;
+ private boolean sampling = false;
+
+ private View.OnClickListener buttonHandler = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.btnBrush:
+ view.setSelected(true);
+ hideToolbar(colors);
+ toggleToolbar(brushes);
+ break;
+ case R.id.btnColor:
+ view.setSelected(true);
+ hideToolbar(brushes);
+ toggleToolbar(colors);
+ break;
+ case R.id.btnClear:
+ painting.clear();
+ break;
+ case R.id.btnSample:
+ sampling = true;
+ view.setSelected(true);
+ break;
+ case R.id.btnZen:
+ painting.setZenMode(!painting.getZenMode());
+ view.animate()
+ .setStartDelay(200)
+ .setInterpolator(new OvershootInterpolator())
+ .rotation(painting.getZenMode() ? 0f : 90f);
+ break;
+ }
+ }
+ };
+
+ private void showToolbar(View bar) {
+ if (bar.getVisibility() != View.GONE) return;
+ bar.setVisibility(View.VISIBLE);
+ bar.setTranslationY(toolbar.getHeight()/2);
+ bar.animate()
+ .translationY(toolbar.getHeight())
+ .alpha(1f)
+ .setDuration(220)
+ .start();
+ }
+
+ private void hideToolbar(View bar) {
+ if (bar.getVisibility() != View.VISIBLE) return;
+ bar.animate()
+ .translationY(toolbar.getHeight()/2)
+ .alpha(0f)
+ .setDuration(150)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ bar.setVisibility(View.GONE);
+ }
+ })
+ .start();
+ }
+
+ private void toggleToolbar(View bar) {
+ if (bar.getVisibility() == View.VISIBLE) {
+ hideToolbar(bar);
+ } else {
+ showToolbar(bar);
+ }
+ }
+
+ private BrushPropertyDrawable widthButtonDrawable;
+ private BrushPropertyDrawable colorButtonDrawable;
+ private float maxBrushWidth, minBrushWidth;
+ private int nightMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
+
+ static final float lerp(float f, float a, float b) {
+ return a + (b-a) * f;
+ }
+
+ void setupViews(Painting oldPainting) {
+ setContentView(R.layout.activity_paint);
+
+ painting = oldPainting != null ? oldPainting : new Painting(this);
+ ((FrameLayout) findViewById(R.id.contentView)).addView(painting,
+ new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+
+ painting.setPaperColor(getColor(R.color.paper_color));
+ painting.setPaintColor(getColor(R.color.paint_color));
+
+ toolbar = findViewById(R.id.toolbar);
+ brushes = findViewById(R.id.brushes);
+ colors = findViewById(R.id.colors);
+
+ magnifier = new Magnifier(painting);
+
+ painting.setOnTouchListener(
+ new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ switch (event.getActionMasked()) {
+ case ACTION_DOWN:
+ case ACTION_MOVE:
+ if (sampling) {
+ magnifier.show(event.getX(), event.getY());
+ colorButtonDrawable.setWellColor(
+ painting.sampleAt(event.getX(), event.getY()));
+ return true;
+ }
+ break;
+ case ACTION_CANCEL:
+ if (sampling) {
+ findViewById(R.id.btnSample).setSelected(false);
+ sampling = false;
+ magnifier.dismiss();
+ }
+ break;
+ case ACTION_UP:
+ if (sampling) {
+ findViewById(R.id.btnSample).setSelected(false);
+ sampling = false;
+ magnifier.dismiss();
+ painting.setPaintColor(
+ painting.sampleAt(event.getX(), event.getY()));
+ refreshBrushAndColor();
+ }
+ break;
+ }
+ return false; // allow view to continue handling
+ }
+ });
+
+ findViewById(R.id.btnBrush).setOnClickListener(buttonHandler);
+ findViewById(R.id.btnColor).setOnClickListener(buttonHandler);
+ findViewById(R.id.btnClear).setOnClickListener(buttonHandler);
+ findViewById(R.id.btnSample).setOnClickListener(buttonHandler);
+ findViewById(R.id.btnZen).setOnClickListener(buttonHandler);
+
+ findViewById(R.id.btnColor).setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ colors.removeAllViews();
+ showToolbar(colors);
+ refreshBrushAndColor();
+ return true;
+ }
+ });
+
+ findViewById(R.id.btnClear).setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ painting.invertContents();
+ return true;
+ }
+ });
+
+ widthButtonDrawable = new BrushPropertyDrawable(this);
+ widthButtonDrawable.setFrameColor(getColor(R.color.toolbar_icon_color));
+ colorButtonDrawable = new BrushPropertyDrawable(this);
+ colorButtonDrawable.setFrameColor(getColor(R.color.toolbar_icon_color));
+
+ ((ImageButton) findViewById(R.id.btnBrush)).setImageDrawable(widthButtonDrawable);
+ ((ImageButton) findViewById(R.id.btnColor)).setImageDrawable(colorButtonDrawable);
+
+ refreshBrushAndColor();
+ }
+
+ private void refreshBrushAndColor() {
+ final LinearLayout.LayoutParams button_lp = new LinearLayout.LayoutParams(
+ 0, ViewGroup.LayoutParams.WRAP_CONTENT);
+ button_lp.weight = 1f;
+ if (brushes.getChildCount() == 0) {
+ for (int i = 0; i < NUM_BRUSHES; i++) {
+ final BrushPropertyDrawable icon = new BrushPropertyDrawable(this);
+ icon.setFrameColor(getColor(R.color.toolbar_icon_color));
+ // exponentially increasing brush size
+ final float width = lerp(
+ (float) Math.pow((float) i / NUM_BRUSHES, 2f), minBrushWidth,
+ maxBrushWidth);
+ icon.setWellScale(width / maxBrushWidth);
+ icon.setWellColor(getColor(R.color.toolbar_icon_color));
+ final ImageButton button = new ImageButton(this);
+ button.setImageDrawable(icon);
+ button.setBackground(getDrawable(R.drawable.toolbar_button_bg));
+ button.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ brushes.setSelected(false);
+ hideToolbar(brushes);
+ painting.setBrushWidth(width);
+ refreshBrushAndColor();
+ }
+ });
+ brushes.addView(button, button_lp);
+ }
+ }
+
+ if (colors.getChildCount() == 0) {
+ final Palette pal = new Palette(NUM_COLORS);
+ for (final int c : IntStream.concat(
+ IntStream.of(Color.BLACK, Color.WHITE),
+ Arrays.stream(pal.getColors())
+ ).toArray()) {
+ final BrushPropertyDrawable icon = new BrushPropertyDrawable(this);
+ icon.setFrameColor(getColor(R.color.toolbar_icon_color));
+ icon.setWellColor(c);
+ final ImageButton button = new ImageButton(this);
+ button.setImageDrawable(icon);
+ button.setBackground(getDrawable(R.drawable.toolbar_button_bg));
+ button.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ colors.setSelected(false);
+ hideToolbar(colors);
+ painting.setPaintColor(c);
+ refreshBrushAndColor();
+ }
+ });
+ colors.addView(button, button_lp);
+ }
+ }
+
+ widthButtonDrawable.setWellScale(painting.getBrushWidth() / maxBrushWidth);
+ widthButtonDrawable.setWellColor(painting.getPaintColor());
+ colorButtonDrawable.setWellColor(painting.getPaintColor());
+ }
+
+ private void refreshNightMode(Configuration config) {
+ int newNightMode =
+ (config.uiMode & Configuration.UI_MODE_NIGHT_MASK);
+ if (nightMode != newNightMode) {
+ if (nightMode != Configuration.UI_MODE_NIGHT_UNDEFINED) {
+ painting.invertContents();
+
+ ((ViewGroup) painting.getParent()).removeView(painting);
+ setupViews(painting);
+
+ final View decorView = getWindow().getDecorView();
+ int decorSUIV = decorView.getSystemUiVisibility();
+
+ if (newNightMode == Configuration.UI_MODE_NIGHT_YES) {
+ decorView.setSystemUiVisibility(
+ decorSUIV & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ } else {
+ decorView.setSystemUiVisibility(
+ decorSUIV | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+ }
+ }
+ nightMode = newNightMode;
+ }
+ }
+
+ public PaintActivity() {
+
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+
+ painting.onTrimMemory();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ refreshNightMode(newConfig);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ WindowManager.LayoutParams lp = getWindow().getAttributes();
+ lp.flags = lp.flags
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ getWindow().setAttributes(lp);
+
+ maxBrushWidth = MAX_BRUSH_WIDTH_DP * getResources().getDisplayMetrics().density;
+ minBrushWidth = MIN_BRUSH_WIDTH_DP * getResources().getDisplayMetrics().density;
+
+ setupViews(null);
+ refreshNightMode(getResources().getConfiguration());
+ }
+
+ @Override
+ public void onPostResume() {
+ super.onPostResume();
+ }
+
+}
diff --git a/packages/EasterEgg/src/com/android/egg/paint/Painting.kt b/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
new file mode 100644
index 0000000..a4a3d3d
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/Painting.kt
@@ -0,0 +1,358 @@
+/*
+ * 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.egg.paint
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.*
+import android.provider.Settings
+import android.util.AttributeSet
+import android.util.DisplayMetrics
+import android.view.MotionEvent
+import android.view.View
+import android.view.WindowInsets
+import java.util.concurrent.TimeUnit
+import android.util.Log
+import android.provider.Settings.System
+
+import org.json.JSONObject
+
+fun hypot(x: Float, y: Float): Float {
+ return Math.hypot(x.toDouble(), y.toDouble()).toFloat()
+}
+
+fun invlerp(x: Float, a: Float, b: Float): Float {
+ return if (b > a) {
+ (x - a) / (b - a)
+ } else 1.0f
+}
+
+public class Painting : View, SpotFilter.Plotter {
+ companion object {
+ val FADE_MINS = TimeUnit.MINUTES.toMillis(3) // about how long a drawing should last
+ val ZEN_RATE = TimeUnit.SECONDS.toMillis(2) // how often to apply the fade
+ val ZEN_FADE = Math.max(1f, ZEN_RATE / FADE_MINS * 255f)
+
+ val FADE_TO_WHITE_CF = ColorMatrixColorFilter(ColorMatrix(floatArrayOf(
+ 1f, 0f, 0f, 0f, ZEN_FADE,
+ 0f, 1f, 0f, 0f, ZEN_FADE,
+ 0f, 0f, 1f, 0f, ZEN_FADE,
+ 0f, 0f, 0f, 1f, 0f
+ )))
+
+ val FADE_TO_BLACK_CF = ColorMatrixColorFilter(ColorMatrix(floatArrayOf(
+ 1f, 0f, 0f, 0f, -ZEN_FADE,
+ 0f, 1f, 0f, 0f, -ZEN_FADE,
+ 0f, 0f, 1f, 0f, -ZEN_FADE,
+ 0f, 0f, 0f, 1f, 0f
+ )))
+
+ val INVERT_CF = ColorMatrixColorFilter(ColorMatrix(floatArrayOf(
+ -1f, 0f, 0f, 0f, 255f,
+ 0f, -1f, 0f, 0f, 255f,
+ 0f, 0f, -1f, 0f, 255f,
+ 0f, 0f, 0f, 1f, 0f
+ )))
+
+ val TOUCH_STATS = "touch.stats" // Settings.System key
+ }
+
+ var devicePressureMin = 0f; // ideal value
+ var devicePressureMax = 1f; // ideal value
+
+ var zenMode = true
+ set(value) {
+ if (field != value) {
+ field = value
+ removeCallbacks(fadeRunnable)
+ if (value && isAttachedToWindow) {
+ handler.postDelayed(fadeRunnable, ZEN_RATE)
+ }
+ }
+ }
+
+ var bitmap: Bitmap? = null
+ var paperColor : Int = 0xFFFFFFFF.toInt()
+
+ private var _paintCanvas: Canvas? = null
+ private val _bitmapLock = Object()
+
+ private var _drawPaint = Paint(Paint.ANTI_ALIAS_FLAG)
+ private var _lastX = 0f
+ private var _lastY = 0f
+ private var _lastR = 0f
+ private var _insets: WindowInsets? = null
+
+ private var _brushWidth = 100f
+
+ private var _filter = SpotFilter(10, 0.5f, 0.9f, this)
+
+ private val fadeRunnable = object : Runnable {
+ private val pt = Paint()
+ override fun run() {
+ val c = _paintCanvas
+ if (c != null) {
+ pt.colorFilter =
+ if (paperColor.and(0xFF) > 0x80)
+ FADE_TO_WHITE_CF
+ else
+ FADE_TO_BLACK_CF
+
+ synchronized(_bitmapLock) {
+ c.drawBitmap(bitmap, 0f, 0f, pt)
+ }
+ invalidate()
+ }
+ postDelayed(this, ZEN_RATE)
+ }
+ }
+
+ constructor(context: Context) : super(context) {
+ init(null, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
+ init(attrs, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
+ init(attrs, defStyle)
+ }
+
+ private fun init(attrs: AttributeSet?, defStyle: Int) {
+ loadDevicePressureData()
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+
+ setupBitmaps()
+
+ if (zenMode) {
+ handler.postDelayed(fadeRunnable, ZEN_RATE)
+ }
+ }
+
+ override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
+ super.onSizeChanged(w, h, oldw, oldh)
+ setupBitmaps()
+ }
+
+ override fun onDetachedFromWindow() {
+ if (zenMode) {
+ removeCallbacks(fadeRunnable)
+ }
+ super.onDetachedFromWindow()
+ }
+
+ fun onTrimMemory() {
+ }
+
+ override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets {
+ _insets = insets
+ if (insets != null && _paintCanvas == null) {
+ setupBitmaps()
+ }
+ return super.onApplyWindowInsets(insets)
+ }
+
+ private fun powf(a: Float, b: Float): Float {
+ return Math.pow(a.toDouble(), b.toDouble()).toFloat()
+ }
+
+ override fun plot(s: MotionEvent.PointerCoords) {
+ val c = _paintCanvas
+ if (c == null) return
+ synchronized(_bitmapLock) {
+ var x = _lastX
+ var y = _lastY
+ var r = _lastR
+ val newR = Math.max(1f, powf(adjustPressure(s.pressure), 2f).toFloat() * _brushWidth)
+
+ if (r >= 0) {
+ val d = hypot(s.x - x, s.y - y)
+ if (d > 1f && (r + newR) > 1f) {
+ val N = (2 * d / Math.min(4f, r + newR)).toInt()
+
+ val stepX = (s.x - x) / N
+ val stepY = (s.y - y) / N
+ val stepR = (newR - r) / N
+ for (i in 0 until N - 1) { // we will draw the last circle below
+ x += stepX
+ y += stepY
+ r += stepR
+ c.drawCircle(x, y, r, _drawPaint)
+ }
+ }
+ }
+
+ c.drawCircle(s.x, s.y, newR, _drawPaint)
+ _lastX = s.x
+ _lastY = s.y
+ _lastR = newR
+ }
+ }
+
+ private fun loadDevicePressureData() {
+ try {
+ val touchDataJson = Settings.System.getString(context.contentResolver, TOUCH_STATS)
+ val touchData = JSONObject(
+ if (touchDataJson != null) touchDataJson else "{}")
+ if (touchData.has("min")) devicePressureMin = touchData.getDouble("min").toFloat()
+ if (touchData.has("max")) devicePressureMax = touchData.getDouble("max").toFloat()
+ if (devicePressureMin < 0) devicePressureMin = 0f
+ if (devicePressureMax < devicePressureMin) devicePressureMax = devicePressureMin + 1f
+ } catch (e: Exception) {
+ }
+ }
+
+ private fun adjustPressure(pressure: Float): Float {
+ if (pressure > devicePressureMax) devicePressureMax = pressure
+ if (pressure < devicePressureMin) devicePressureMin = pressure
+ return invlerp(pressure, devicePressureMin, devicePressureMax)
+ }
+
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
+ val c = _paintCanvas
+ if (event == null || c == null) return super.onTouchEvent(event)
+
+ /*
+ val pt = Paint(Paint.ANTI_ALIAS_FLAG)
+ pt.style = Paint.Style.STROKE
+ pt.color = 0x800000FF.toInt()
+ _paintCanvas?.drawCircle(event.x, event.y, 20f, pt)
+ */
+
+ when (event.actionMasked) {
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+ _filter.add(event)
+ _filter.finish()
+ invalidate()
+ }
+
+ MotionEvent.ACTION_DOWN -> {
+ _lastR = -1f
+ _filter.add(event)
+ invalidate()
+ }
+
+ MotionEvent.ACTION_MOVE -> {
+ _filter.add(event)
+
+ invalidate()
+ }
+ }
+
+ return true
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+
+ bitmap?.let {
+ canvas.drawBitmap(bitmap, 0f, 0f, _drawPaint);
+ }
+ }
+
+ // public api
+ fun clear() {
+ bitmap = null
+ setupBitmaps()
+ invalidate()
+ }
+
+ fun sampleAt(x: Float, y: Float): Int {
+ val localX = (x - left).toInt()
+ val localY = (y - top).toInt()
+ return bitmap?.getPixel(localX, localY) ?: Color.BLACK
+ }
+
+ fun setPaintColor(color: Int) {
+ _drawPaint.color = color
+ }
+
+ fun getPaintColor(): Int {
+ return _drawPaint.color
+ }
+
+ fun setBrushWidth(w: Float) {
+ _brushWidth = w
+ }
+
+ fun getBrushWidth(): Float {
+ return _brushWidth
+ }
+
+ private fun setupBitmaps() {
+ val dm = DisplayMetrics()
+ display.getRealMetrics(dm)
+ val w = dm.widthPixels
+ val h = dm.heightPixels
+ val oldBits = bitmap
+ var bits = oldBits
+ if (bits == null || bits.width != w || bits.height != h) {
+ bits = Bitmap.createBitmap(
+ w,
+ h,
+ Bitmap.Config.ARGB_8888
+ )
+ }
+ if (bits == null) return
+
+ val c = Canvas(bits)
+
+ if (oldBits != null) {
+ if (oldBits.width < oldBits.height != bits.width < bits.height) {
+ // orientation change. let's rotate things so they fit better
+ val matrix = Matrix()
+ if (bits.width > bits.height) {
+ // now landscape
+ matrix.postRotate(-90f)
+ matrix.postTranslate(0f, bits.height.toFloat())
+ } else {
+ // now portrait
+ matrix.postRotate(90f)
+ matrix.postTranslate(bits.width.toFloat(), 0f)
+ }
+ if (bits.width != oldBits.height || bits.height != oldBits.width) {
+ matrix.postScale(
+ bits.width.toFloat()/oldBits.height,
+ bits.height.toFloat()/oldBits.width)
+ }
+ c.matrix = matrix
+ }
+ // paint the old artwork atop the new
+ c.drawBitmap(oldBits, 0f, 0f, _drawPaint)
+ c.matrix = Matrix()
+ } else {
+ c.drawColor(paperColor)
+ }
+
+ bitmap = bits
+ _paintCanvas = c
+ }
+
+ fun invertContents() {
+ val invertPaint = Paint()
+ invertPaint.colorFilter = INVERT_CF
+ synchronized(_bitmapLock) {
+ _paintCanvas?.drawBitmap(bitmap, 0f, 0f, invertPaint)
+ }
+ invalidate()
+ }
+}
+
diff --git a/packages/EasterEgg/src/com/android/egg/paint/Palette.kt b/packages/EasterEgg/src/com/android/egg/paint/Palette.kt
new file mode 100644
index 0000000..7043efe
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/Palette.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.egg.paint
+
+import android.graphics.Color
+
+class Palette {
+ var colors : IntArray
+ var lightest = 0
+ var darkest = 0
+
+ /**
+ * rough luminance calculation
+ * https://www.w3.org/TR/AERT/#color-contrast
+ */
+ private fun lum(rgb: Int): Float {
+ return (Color.red(rgb) * 299f + Color.green(rgb) * 587f + Color.blue(rgb) * 114f) / 1000f
+ }
+
+ /**
+ * create a random evenly-spaced color palette
+ * guaranteed to contrast!
+ */
+ fun randomize(S: Float, V: Float) {
+ val hsv = floatArrayOf((Math.random() * 360f).toFloat(), S, V)
+ val count = colors.size
+ colors[0] = Color.HSVToColor(hsv)
+ lightest = 0
+ darkest = 0
+
+ for (i in 0 until count) {
+ hsv[0] = (hsv[0] + 360f / count).rem(360f)
+ val color = Color.HSVToColor(hsv)
+ colors[i] = color
+
+ val lum = lum(colors[i])
+ if (lum < lum(colors[darkest])) darkest = i
+ if (lum > lum(colors[lightest])) lightest = i
+ }
+ }
+
+ override fun toString() : String {
+ val str = StringBuilder("Palette{ ")
+ for (c in colors) {
+ str.append(String.format("#%08x ", c))
+ }
+ str.append("}")
+ return str.toString()
+ }
+
+ constructor(count: Int) {
+ colors = IntArray(count)
+ randomize(1f, 1f)
+ }
+
+ constructor(count: Int, S: Float, V: Float) {
+ colors = IntArray(count)
+ randomize(S, V)
+ }
+
+ constructor(_colors: IntArray) {
+ colors = _colors
+ for (i in 0 until colors.size) {
+ val lum = lum(colors[i])
+ if (lum < lum(colors[darkest])) darkest = i
+ if (lum > lum(colors[lightest])) lightest = i
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/EasterEgg/src/com/android/egg/paint/SpotFilter.kt b/packages/EasterEgg/src/com/android/egg/paint/SpotFilter.kt
new file mode 100644
index 0000000..2c15c0d
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/SpotFilter.kt
@@ -0,0 +1,124 @@
+/*
+ * 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.egg.paint
+
+import java.util.LinkedList
+
+import android.view.MotionEvent
+
+class SpotFilter(internal var mBufSize: Int, posDecay: Float, pressureDecay: Float, internal var mPlotter: Plotter) {
+ val spots = LinkedList<MotionEvent.PointerCoords>() // newest at front
+ val tmpSpot = MotionEvent.PointerCoords()
+ var lastTool = MotionEvent.TOOL_TYPE_UNKNOWN
+
+ val posDecay: Float
+ val pressureDecay: Float
+
+ interface Plotter {
+ fun plot(s: MotionEvent.PointerCoords)
+ }
+
+ init {
+ this.posDecay = if (posDecay in 0f..1f) posDecay else 1f
+ this.pressureDecay = if (pressureDecay in 0f..1f) pressureDecay else 1f
+ }
+
+ fun filterInto(out: MotionEvent.PointerCoords, tool: Int): MotionEvent.PointerCoords {
+ lastTool = tool
+
+ var wi = 1f // weight for ith component (position)
+ var w = 0f // total weight
+ var wi_press = 1f // weight for ith component (pressure)
+ var w_press = 0f // total weight (pressure)
+
+ var x = 0f
+ var y = 0f
+ var pressure = 0f
+ var size = 0f
+ for (pi in spots) {
+ x += pi.x * wi
+ y += pi.y * wi
+
+ pressure += pi.pressure * wi_press
+ size += pi.size * wi_press
+
+ w += wi
+ wi *= posDecay // exponential backoff
+
+ w_press += wi_press
+ wi_press *= pressureDecay
+
+ if (PRECISE_STYLUS_INPUT && tool == MotionEvent.TOOL_TYPE_STYLUS) {
+ // just take the newest one, no need to average
+ break
+ }
+ }
+
+ out.x = x / w
+ out.y = y / w
+ out.pressure = pressure / w_press
+ out.size = size / w_press
+ return out
+ }
+
+ protected fun addInternal(c: MotionEvent.PointerCoords, tool: Int) {
+ val coord =
+ if (spots.size == mBufSize) {
+ spots.removeLast()
+ } else {
+ MotionEvent.PointerCoords()
+ }
+ coord.copyFrom(c)
+
+ spots.add(0, coord)
+
+ filterInto(tmpSpot, tool)
+ mPlotter.plot(tmpSpot)
+ }
+
+ fun add(cv: List<MotionEvent.PointerCoords>, tool: Int) {
+ for (c in cv) {
+ addInternal(c, tool)
+ }
+ }
+
+ fun add(evt: MotionEvent) {
+ val tool = evt.getToolType(0)
+ for (i in 0 until evt.historySize) {
+ evt.getHistoricalPointerCoords(0, i, tmpSpot)
+ addInternal(tmpSpot, tool)
+ }
+ evt.getPointerCoords(0, tmpSpot)
+ addInternal(tmpSpot, tool)
+ }
+
+ fun finish() {
+ while (spots.size > 0) {
+ filterInto(tmpSpot, lastTool)
+ spots.removeLast()
+ mPlotter.plot(tmpSpot)
+ }
+
+ spots.clear()
+ }
+
+ companion object {
+ var PRECISE_STYLUS_INPUT = true
+ }
+}
+
+
diff --git a/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt b/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
new file mode 100644
index 0000000..86b11e7
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/paint/ToolbarView.kt
@@ -0,0 +1,77 @@
+/*
+ * 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.egg.paint
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import android.text.TextPaint
+import android.transition.ChangeBounds
+import android.transition.Transition
+import android.transition.TransitionListenerAdapter
+import android.transition.TransitionManager
+import android.util.AttributeSet
+import android.view.*
+import android.view.animation.OvershootInterpolator
+import android.widget.FrameLayout
+
+class ToolbarView : FrameLayout {
+ var inTransition = false
+ var transitionListener: Transition.TransitionListener = object : TransitionListenerAdapter() {
+ override fun onTransitionStart(transition: Transition?) {
+ inTransition = true
+ }
+ override fun onTransitionEnd(transition: Transition?) {
+ inTransition = false
+ }
+ }
+
+ constructor(context: Context) : super(context) {
+ init(null, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
+ init(attrs, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
+ init(attrs, defStyle)
+ }
+
+ override fun onApplyWindowInsets(insets: WindowInsets?): WindowInsets {
+ var lp = layoutParams as FrameLayout.LayoutParams?
+ if (lp != null && insets != null) {
+ if (insets.hasStableInsets()) {
+ lp.topMargin = insets.stableInsetTop
+ lp.bottomMargin = insets.stableInsetBottom
+ } else {
+ lp.topMargin = insets.systemWindowInsetTop
+ lp.bottomMargin = insets.systemWindowInsetBottom
+ }
+ layoutParams = lp
+ }
+
+ return super.onApplyWindowInsets(insets)
+ }
+
+ private fun init(attrs: AttributeSet?, defStyle: Int) {
+ }
+
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index f728684..9d398b5 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -841,7 +841,19 @@
WifiConfiguration config = WifiConfiguration
.getWifiConfigFromBackup(new DataInputStream(new ByteArrayInputStream(data)));
if (DEBUG) Log.d(TAG, "Successfully unMarshaled WifiConfiguration ");
+ int originalApBand = config.apBand;
mWifiManager.setWifiApConfiguration(config);
+
+ // Depending on device hardware, we may need to notify the user of a setting change for
+ // the apBand preference
+ boolean dualMode = mWifiManager.isDualModeSupported();
+ int storedApBand = mWifiManager.getWifiApConfiguration().apBand;
+ if (dualMode) {
+ if (storedApBand != originalApBand) {
+ Log.d(TAG, "restored ap configuration requires a conversion, notify the user");
+ mWifiManager.notifyUserOfApBandConversion();
+ }
+ }
} catch (IOException | BackupUtils.BadVersionException e) {
Log.e(TAG, "Failed to unMarshal SoftAPConfiguration " + e.getMessage());
}
diff --git a/packages/SystemUI/res/drawable-hdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-hdpi/qs_scrubber_track.9.png
deleted file mode 100644
index 0899d35..0000000
--- a/packages/SystemUI/res/drawable-hdpi/qs_scrubber_track.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-mdpi/qs_scrubber_track.9.png
deleted file mode 100644
index 2266449..0000000
--- a/packages/SystemUI/res/drawable-mdpi/qs_scrubber_track.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-xhdpi/qs_scrubber_track.9.png
deleted file mode 100644
index 3328add..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/qs_scrubber_track.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-xxhdpi/qs_scrubber_track.9.png
deleted file mode 100644
index ed651da..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/qs_scrubber_track.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/qs_scrubber_track.9.png b/packages/SystemUI/res/drawable-xxxhdpi/qs_scrubber_track.9.png
deleted file mode 100644
index 06e1202..0000000
--- a/packages/SystemUI/res/drawable-xxxhdpi/qs_scrubber_track.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
index 9c24c2c..47e1059 100644
--- a/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
@@ -22,5 +22,5 @@
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M12.72,23H11C5.49,23 1,18.51 1,13h2c0,3.78 2.63,6.95 6.15,7.79L8.13,19L9.87,18L12.72,23zM13,1h-1.72l2.85,5L15.87,5l-1.02,-1.79C18.37,4.05 21,7.22 21,11h2C23,5.49 18.51,1 13,1zM10.23,6L18,13.76L13.77,18L6,10.24L10.23,6C10.23,6 10.23,6 10.23,6M10.23,4C9.72,4 9.21,4.2 8.82,4.59L4.59,8.82c-0.78,0.78 -0.78,2.04 0,2.82l7.77,7.77c0.39,0.39 0.9,0.59 1.41,0.59c0.51,0 1.02,-0.2 1.41,-0.59l4.24,-4.24c0.78,-0.78 0.78,-2.04 0,-2.82l-7.77,-7.77C11.26,4.2 10.75,4 10.23,4L10.23,4z"/>
+ android:pathData="M7.4,10.94H2.45V5.99l2,0.01v1.53l4.61,-4.61c0.64,-0.64 1.67,-0.66 2.29,-0.04l8.18,8.18h-2.83l-6.48,-6.48L5.86,8.95H7.4V10.94zM16.6,13.06l0.01,2h1.53l-4.36,4.36l-6.48,-6.48H4.46l8.19,8.19c0.62,0.62 1.65,0.6 2.29,-0.04l4.61,-4.61l0.01,0.01v1.53h1.99v-4.95H16.6z"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
index 2cd7883..3304c19 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_rotate_button.xml
@@ -17,16 +17,16 @@
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:name="root"
- android:width="21dp"
- android:height="21dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="28dp"
+ android:height="28dp"
+ android:viewportWidth="28.0"
+ android:viewportHeight="28.0">
<!-- Use scaleX to flip icon so arrows always point in the direction of motion -->
- <group android:name="icon" android:pivotX="12" android:pivotY="12"
+ <group android:name="icon" android:pivotX="14" android:pivotY="14"
android:scaleX="?attr/rotateButtonScaleX">
<!-- Tint color to be set directly -->
<path android:fillColor="#FFFFFFFF"
- android:pathData="M19,12c0,1.72 -0.63,3.3 -1.66,4.52l-1.44,-1.44C16.58,14.23 17,13.17 17,12c0,-2.76 -2.24,-5 -5,-5c-0.06,0 -0.11,0.01 -0.17,0.01l1.08,1.08L11.5,9.5L8,6l3.5,-3.5l1.41,1.42l-1.09,1.09C11.88,5.01 11.94,5 12,5C15.87,5 19,8.13 19,12zM12.5,14.51l-1.41,1.41l1.06,1.06C12.1,16.99 12.05,17 12,17c-2.76,0 -5,-2.24 -5,-5c0,-1.17 0.42,-2.23 1.09,-3.08L6.66,7.48C5.62,8.7 5,10.28 5,12c0,3.87 3.13,7 7,7c0.06,0 0.13,-0.01 0.19,-0.01v0l-1.1,1.1l1.41,1.41L16,18L12.5,14.51z"/>
+ android:pathData="M12.02,10.83L9.25,8.06l2.77,-2.77l1.12,1.12l-0.85,0.86h5.16c0.72,0 1.31,0.56 1.31,1.26v9.16l-1.58,-1.58V8.85h-4.89l0.86,0.86L12.02,10.83zM15.98,17.17l-1.12,1.12l0.85,0.86h-4.88v-7.26L9.25,10.3v9.17c0,0.7 0.59,1.26 1.31,1.26h5.16v0.01l-0.85,0.85l1.12,1.12l2.77,-2.77L15.98,17.17z"/>
</group>
</vector>
</aapt:attr>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 975055c..07f1ee0 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -137,8 +137,10 @@
<color name="remote_input_accent">#eeeeee</color>
- <color name="quick_step_track_background_dark">#61000000</color>
- <color name="quick_step_track_background_light">#33FFFFFF</color>
+ <color name="quick_step_track_background_background_dark">#1F000000</color>
+ <color name="quick_step_track_background_background_light">#33FFFFFF</color>
+ <color name="quick_step_track_background_foreground_dark">#38000000</color>
+ <color name="quick_step_track_background_foreground_light">#59FFFFFF</color>
<!-- Keyboard shortcuts colors -->
<color name="ksh_application_group_color">#fff44336</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f00957a..34d71da 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -764,9 +764,6 @@
<dimen name="volume_expander_margin_end">2dp</dimen>
<dimen name="volume_expander_margin_top">6dp</dimen>
- <!-- Padding between icon and text for managed profile toast -->
- <dimen name="managed_profile_toast_padding">4dp</dimen>
-
<!-- Thickness of the assist disclosure beams -->
<dimen name="assist_disclosure_thickness">2.5dp</dimen>
@@ -1012,4 +1009,7 @@
<!-- How much into a DisplayCutout's bounds we can go, on each side -->
<dimen name="display_cutout_margin_consumption">0px</dimen>
+ <!-- How much we expand the touchable region of the status bar below the notch to catch touches
+ that just start below the notch. -->
+ <dimen name="display_cutout_touchable_region_size">12dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index edf56af..18f378e 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1326,9 +1326,6 @@
<!-- Hide quick settings tile confirmation button -->
<string name="quick_settings_reset_confirmation_button">Hide</string>
- <!-- Toast shown when user unlocks screen and managed profile activity is in the foreground -->
- <string name="managed_profile_foreground_toast">You\'re using your work profile</string>
-
<!-- volume stream names. All nouns. -->
<string name="stream_voice_call">Call</string> <!-- STREAM_VOICE_CALL -->
<string name="stream_system">System</string> <!-- STREAM_SYSTEM -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
index cd831d1..d38cc0f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/NavigationBarCompat.java
@@ -54,6 +54,7 @@
public static final int HIT_TARGET_HOME = 2;
public static final int HIT_TARGET_OVERVIEW = 3;
public static final int HIT_TARGET_ROTATION = 4;
+ public static final int HIT_TARGET_DEAD_ZONE = 5;
@Retention(RetentionPolicy.SOURCE)
@IntDef({FLAG_DISABLE_SWIPE_UP,
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index 5b0f1c3..66475e2 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -334,8 +334,10 @@
break;
case SimPermDisabled:
- carrierText = getContext().getText(
- R.string.keyguard_permanent_disabled_sim_message_short);
+ carrierText = makeCarrierStringOnEmergencyCapable(
+ getContext().getText(
+ R.string.keyguard_permanent_disabled_sim_message_short),
+ text);
break;
case SimMissingLocked:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 41df196..225f7fc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -73,6 +73,7 @@
private ArraySet<View> mVisibleInDoze;
private boolean mPulsing;
+ private boolean mWasPulsing;
private float mDarkAmount = 0;
private int mTextColor;
private float mWidgetPadding;
@@ -224,7 +225,8 @@
boolean hasHeader = mKeyguardSlice.hasHeader();
boolean smallClock = hasHeader || mPulsing;
long duration = KeyguardSliceView.DEFAULT_ANIM_DURATION;
- long delay = smallClock ? 0 : duration / 4;
+ long delay = smallClock || mWasPulsing ? 0 : duration / 4;
+ mWasPulsing = false;
boolean shouldAnimate = mKeyguardSlice.getLayoutTransition() != null
&& mKeyguardSlice.getLayoutTransition().isRunning();
@@ -448,6 +450,12 @@
}
public void setPulsing(boolean pulsing, boolean animate) {
+ if (mPulsing == pulsing) {
+ return;
+ }
+ if (mPulsing) {
+ mWasPulsing = true;
+ }
mPulsing = pulsing;
mKeyguardSlice.setPulsing(pulsing, animate);
updateDozeVisibleViews();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 62cd13b..ef3aa42 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1589,6 +1589,10 @@
}
}
+ public boolean isKeyguardVisible() {
+ return mKeyguardIsVisible;
+ }
+
/**
* Notifies that the visibility state of Keyguard has changed.
*
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 59501f0..81dd5eb 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -55,6 +55,7 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.Utils.DisableStateTracker;
+import com.android.systemui.R;
import java.text.NumberFormat;
@@ -72,6 +73,7 @@
private int mTextColor;
private int mLevel;
private boolean mForceShowPercent;
+ private boolean mShowPercentAvailable;
private int mDarkModeBackgroundColor;
private int mDarkModeFillColor;
@@ -111,6 +113,9 @@
atts.recycle();
mSettingObserver = new SettingObserver(new Handler(context.getMainLooper()));
+ mShowPercentAvailable = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_battery_percentage_setting_available);
+
addOnAttachStateChangeListener(
new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS));
@@ -259,8 +264,11 @@
private void updateShowPercent() {
final boolean showing = mBatteryPercentView != null;
- if (0 != Settings.System.getIntForUser(getContext().getContentResolver(),
- SHOW_BATTERY_PERCENT, 0, mUser) || mForceShowPercent) {
+ final boolean systemSetting = 0 != Settings.System
+ .getIntForUser(getContext().getContentResolver(),
+ SHOW_BATTERY_PERCENT, 0, mUser);
+
+ if ((mShowPercentAvailable && systemSetting) || mForceShowPercent) {
if (!showing) {
mBatteryPercentView = loadPercentView();
if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index b8a57bf..50d862d 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -290,7 +290,7 @@
|| dh != mLastSurfaceHeight;
boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation
- || mSurfaceRedrawNeeded;
+ || mSurfaceRedrawNeeded || mNeedsDrawAfterLoadingWallpaper;
if (!redrawNeeded && !mOffsetsChanged) {
if (DEBUG) {
Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index efaf557..194679c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -52,6 +52,7 @@
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -89,6 +90,9 @@
private float mDensity;
private WindowManager mWindowManager;
private int mRotation;
+ private DisplayCutoutView mCutoutTop;
+ private DisplayCutoutView mCutoutBottom;
+ private boolean mPendingRotationChange;
@Override
public void start() {
@@ -122,6 +126,22 @@
@Override
public void onDisplayChanged(int displayId) {
+ if (mOverlay != null && mBottomOverlay != null
+ && mRotation != RotationUtils.getExactRotation(mContext)) {
+ // We cannot immediately update the orientation. Otherwise
+ // WindowManager is still deferring layout until it has finished dispatching
+ // the config changes, which may cause divergence between what we draw
+ // (new orientation), and where we are placed on the screen (old orientation).
+ // Instead we wait until either:
+ // - we are trying to redraw. This because WM resized our window and told us to.
+ // - the config change has been dispatched, so WM is no longer deferring layout.
+ mPendingRotationChange = true;
+ mOverlay.getViewTreeObserver().addOnPreDrawListener(
+ new RestartingPreDrawListener(mOverlay));
+ mBottomOverlay.getViewTreeObserver().addOnPreDrawListener(
+ new RestartingPreDrawListener(mBottomOverlay));
+
+ }
updateOrientation();
}
};
@@ -135,14 +155,14 @@
private void setupDecorations() {
mOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
- DisplayCutoutView cutoutTop = new DisplayCutoutView(mContext, true,
- this::updateWindowVisibilities);
- ((ViewGroup)mOverlay).addView(cutoutTop);
+ mCutoutTop = new DisplayCutoutView(mContext, true,
+ this::updateWindowVisibilities, this);
+ ((ViewGroup)mOverlay).addView(mCutoutTop);
mBottomOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
- DisplayCutoutView cutoutBottom = new DisplayCutoutView(mContext, false,
- this::updateWindowVisibilities);
- ((ViewGroup)mBottomOverlay).addView(cutoutBottom);
+ mCutoutBottom = new DisplayCutoutView(mContext, false,
+ this::updateWindowVisibilities, this);
+ ((ViewGroup)mBottomOverlay).addView(mCutoutBottom);
mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mOverlay.setAlpha(0);
@@ -172,8 +192,8 @@
((ImageView) mOverlay.findViewById(R.id.right)).setImageTintList(tintList);
((ImageView) mBottomOverlay.findViewById(R.id.left)).setImageTintList(tintList);
((ImageView) mBottomOverlay.findViewById(R.id.right)).setImageTintList(tintList);
- cutoutTop.setColor(tint);
- cutoutBottom.setColor(tint);
+ mCutoutTop.setColor(tint);
+ mCutoutBottom.setColor(tint);
}
};
setting.setListening(true);
@@ -199,6 +219,7 @@
@Override
protected void onConfigurationChanged(Configuration newConfig) {
+ mPendingRotationChange = false;
updateOrientation();
if (shouldDrawCutout() && mOverlay == null) {
setupDecorations();
@@ -206,6 +227,9 @@
}
protected void updateOrientation() {
+ if (mPendingRotationChange) {
+ return;
+ }
int newRotation = RotationUtils.getExactRotation(mContext);
if (newRotation != mRotation) {
mRotation = newRotation;
@@ -245,6 +269,9 @@
updateView(bottomRight, Gravity.TOP | Gravity.LEFT, 0);
}
+ mCutoutTop.setRotation(mRotation);
+ mCutoutBottom.setRotation(mRotation);
+
updateWindowVisibilities();
}
@@ -416,15 +443,19 @@
private final Rect mBoundingRect = new Rect();
private final Path mBoundingPath = new Path();
private final int[] mLocation = new int[2];
- private final boolean mStart;
+ private final boolean mInitialStart;
private final Runnable mVisibilityChangedListener;
+ private final ScreenDecorations mDecorations;
private int mColor = Color.BLACK;
+ private boolean mStart;
+ private int mRotation;
public DisplayCutoutView(Context context, boolean start,
- Runnable visibilityChangedListener) {
+ Runnable visibilityChangedListener, ScreenDecorations decorations) {
super(context);
- mStart = start;
+ mInitialStart = start;
mVisibilityChangedListener = visibilityChangedListener;
+ mDecorations = decorations;
setId(R.id.display_cutout);
}
@@ -475,7 +506,22 @@
}
}
+ public void setRotation(int rotation) {
+ mRotation = rotation;
+ update();
+ }
+
+ private boolean isStart() {
+ final boolean flipped = (mRotation == RotationUtils.ROTATION_SEASCAPE
+ || mRotation == RotationUtils.ROTATION_UPSIDE_DOWN);
+ return flipped ? !mInitialStart : mInitialStart;
+ }
+
private void update() {
+ if (!isAttachedToWindow() || mDecorations.mPendingRotationChange) {
+ return;
+ }
+ mStart = isStart();
requestLayout();
getDisplay().getDisplayInfo(mInfo);
mBounds.setEmpty();
@@ -560,31 +606,34 @@
resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0));
}
- public static void boundsFromDirection(DisplayCutout displayCutout, int gravity, Rect out) {
+ public static void boundsFromDirection(DisplayCutout displayCutout, int gravity,
+ Rect out) {
+ Region bounds = boundsFromDirection(displayCutout, gravity);
+ out.set(bounds.getBounds());
+ bounds.recycle();
+ }
+
+ public static Region boundsFromDirection(DisplayCutout displayCutout, int gravity) {
Region bounds = displayCutout.getBounds();
switch (gravity) {
case Gravity.TOP:
bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(),
Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
case Gravity.LEFT:
bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE,
Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
case Gravity.BOTTOM:
bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE,
Integer.MAX_VALUE, Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
case Gravity.RIGHT:
bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE,
Integer.MAX_VALUE, Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
}
- bounds.recycle();
+ return bounds;
}
private void localBounds(Rect out) {
@@ -635,4 +684,28 @@
return rotation == RotationUtils.ROTATION_LANDSCAPE || rotation ==
RotationUtils.ROTATION_SEASCAPE;
}
+
+ /**
+ * A pre-draw listener, that cancels the draw and restarts the traversal with the updated
+ * window attributes.
+ */
+ private class RestartingPreDrawListener implements ViewTreeObserver.OnPreDrawListener {
+
+ private final View mView;
+
+ private RestartingPreDrawListener(View view) {
+ mView = view;
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ mPendingRotationChange = false;
+ mView.getViewTreeObserver().removeOnPreDrawListener(this);
+ // This changes the window attributes - we need to restart the traversal for them to
+ // take effect.
+ updateOrientation();
+ mView.invalidate();
+ return false;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 9a43d9e..3c8a461 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
-import android.os.Trace;
import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
@@ -46,7 +45,7 @@
public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
private static final String TAG = "SysuiColorExtractor";
private boolean mWallpaperVisible;
- private boolean mMediaBackdropVisible;
+ private boolean mHasBackdrop;
// Colors to return when the wallpaper isn't visible
private final GradientColors mWpHiddenColors;
@@ -165,7 +164,7 @@
return mWpHiddenColors;
}
} else {
- if (mMediaBackdropVisible) {
+ if (mHasBackdrop) {
return mWpHiddenColors;
} else {
return super.getColors(which, type);
@@ -181,9 +180,9 @@
}
}
- public void setMediaBackdropVisible(boolean visible) {
- if (mMediaBackdropVisible != visible) {
- mMediaBackdropVisible = visible;
+ public void setHasBackdrop(boolean hasBackdrop) {
+ if (mHasBackdrop != hasBackdrop) {
+ mHasBackdrop = hasBackdrop;
triggerColorsChanged(WallpaperManager.FLAG_LOCK);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index cc60f87..42e5adc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -265,6 +265,8 @@
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
+ // Clear selected state so it is not announce by talkback.
+ info.setSelected(false);
if (!TextUtils.isEmpty(mAccessibilityClass)) {
info.setClassName(mAccessibilityClass);
if (Switch.class.getName().equals(mAccessibilityClass)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 8d8e206..ce9d7e1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -479,7 +479,7 @@
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
x, -mNavBarHeight / 2,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
flags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index 39485c3..29e0eda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -178,11 +178,7 @@
* @param translationX how to translate the horizontal position
*/
public void setPanelTranslation(float translationX) {
- if (isLayoutRtl()) {
- setTranslationX(translationX + mCutOutInset);
- } else {
- setTranslationX(translationX - mCutOutInset);
- }
+ setTranslationX(translationX);
updateDrawingRect();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 1287ced..25684ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -108,16 +108,6 @@
} else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
// Start the overview connection to the launcher service
Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser();
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- try {
- final int lastResumedActivityUserId =
- ActivityManager.getService().getLastResumedActivityUserId();
- if (mUserManager.isManagedProfile(lastResumedActivityUserId)) {
- showForegroundManagedProfileActivityToast();
- }
- } catch (RemoteException e) {
- // Abandon hope activity manager not running.
- }
} else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
@@ -224,7 +214,6 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_ADDED);
- filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiver(mBaseBroadcastReceiver, filter);
@@ -237,19 +226,6 @@
mSettingsObserver.onChange(false); // set up
}
- private void showForegroundManagedProfileActivityToast() {
- Toast toast = Toast.makeText(mContext,
- R.string.managed_profile_foreground_toast,
- Toast.LENGTH_SHORT);
- TextView text = toast.getView().findViewById(android.R.id.message);
- text.setCompoundDrawablesRelativeWithIntrinsicBounds(
- R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
- int paddingPx = mContext.getResources().getDimensionPixelSize(
- R.dimen.managed_profile_toast_padding);
- text.setCompoundDrawablePadding(paddingPx);
- toast.show();
- }
-
public boolean shouldShowLockscreenNotifications() {
return mShowLockscreenNotifications;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index fac7768..3063199 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -482,8 +482,8 @@
iconTransformDistance = Math.min(iconTransformDistance, fullHeight);
if (isLastChild) {
fullHeight = Math.min(fullHeight, row.getMinHeight() - getIntrinsicHeight());
- iconTransformDistance = Math.min(iconTransformDistance,
- row.getMinHeight() - getIntrinsicHeight() * icon.getIconScale());
+ iconTransformDistance = Math.min(iconTransformDistance, row.getMinHeight()
+ - getIntrinsicHeight());
}
float viewEnd = viewStart + fullHeight;
if (expandingAnimated && mAmbientState.getScrollY() == 0
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 27cb077..c0e7ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -197,6 +197,7 @@
mDarkAmount);
final int outerBounds = mStatusBarIconSize;
mIconScale = (float)imageBounds / (float)outerBounds;
+ updatePivot();
}
private void updateIconScaleForSystemIcons() {
@@ -859,6 +860,12 @@
mLayoutRunnable.run();
mLayoutRunnable = null;
}
+ updatePivot();
+ }
+
+ private void updatePivot() {
+ setPivotX((1 - mIconScale) / 2.0f * getWidth());
+ setPivotY((getHeight() - mIconScale * getWidth()) / 2.0f);
}
public void executeOnLayout(Runnable runnable) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 409a783..4e7f4f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -18,6 +18,7 @@
import android.graphics.Point;
import android.graphics.Rect;
+import android.view.DisplayCutout;
import android.view.View;
import android.view.WindowInsets;
@@ -159,8 +160,15 @@
}
WindowInsets windowInset = mStackScroller.getRootWindowInsets();
- return windowInset.getSystemWindowInsetLeft() + mStackScroller.getRight()
- + windowInset.getSystemWindowInsetRight() - realDisplaySize;
+ DisplayCutout cutout = (windowInset != null) ? windowInset.getDisplayCutout() : null;
+ int sysWinLeft = (windowInset != null) ? windowInset.getStableInsetLeft() : 0;
+ int sysWinRight = (windowInset != null) ? windowInset.getStableInsetRight() : 0;
+ int cutoutLeft = (cutout != null) ? cutout.getSafeInsetLeft() : 0;
+ int cutoutRight = (cutout != null) ? cutout.getSafeInsetRight() : 0;
+ int leftInset = Math.max(sysWinLeft, cutoutLeft);
+ int rightInset = Math.max(sysWinRight, cutoutRight);
+
+ return leftInset + mStackScroller.getRight() + rightInset - realDisplaySize;
}
public void updatePanelTranslation() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index fa0a774..0aad438 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -21,15 +21,22 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.Region.Op;
import android.support.v4.util.ArraySet;
import android.util.Log;
import android.util.Pools;
+import android.view.DisplayCutout;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.InternalInsetsInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.ScreenDecorations;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
@@ -41,6 +48,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashSet;
+import java.util.List;
import java.util.Stack;
/**
@@ -60,6 +68,7 @@
private int mStatusBarHeight;
private int mHeadsUpInset;
+ private int mDisplayCutoutTouchableRegionSize;
private boolean mTrackingHeadsUp;
private HashSet<String> mSwipedOutKeys = new HashSet<>();
private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
@@ -120,6 +129,8 @@
com.android.internal.R.dimen.status_bar_height);
mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
+ mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
+ R.dimen.display_cutout_touchable_region_size);
}
@Override
@@ -128,6 +139,11 @@
initResources();
}
+ @Override
+ public void onOverlayChanged() {
+ initResources();
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Public methods:
@@ -301,12 +317,32 @@
info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
- } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
- info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+ } else {
+ setCollapsedTouchableInsets(info);
}
}
+ private void setCollapsedTouchableInsets(ViewTreeObserver.InternalInsetsInfo info) {
+ info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+ updateRegionForNotch(info.touchableRegion);
+ }
+
+ private void updateRegionForNotch(Region region) {
+ DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
+ if (cutout == null) {
+ return;
+ }
+
+ // Expand touchable region such that we also catch touches that just start below the notch
+ // area.
+ Region bounds = ScreenDecorations.DisplayCutoutView.boundsFromDirection(
+ cutout, Gravity.TOP);
+ bounds.translate(0, mDisplayCutoutTouchableRegionSize);
+ region.op(bounds, Op.UNION);
+ bounds.recycle();
+ }
+
@Override
public void onConfigChanged(Configuration newConfig) {
Resources resources = mContext.getResources();
@@ -403,7 +439,8 @@
private void updateTouchableRegionListener() {
boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway
- || mWaitingOnCollapseWhenGoingAway;
+ || mWaitingOnCollapseWhenGoingAway
+ || mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null;
if (shouldObserve == mIsObserving) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 0bd3cc7..db84222 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -67,6 +67,7 @@
private static final int LAYOUT_CUTOUT = 1;
private static final int LAYOUT_NO_CUTOUT = 2;
+ private boolean mShowPercentAvailable;
private boolean mBatteryCharging;
private boolean mKeyguardUserSwitcherShowing;
private boolean mBatteryListening;
@@ -165,6 +166,8 @@
R.dimen.system_icons_super_container_avatarless_margin_end);
mCutoutSideNudge = getResources().getDimensionPixelSize(
R.dimen.display_cutout_margin_consumption);
+ mShowPercentAvailable = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_battery_percentage_setting_available);
}
private void updateVisibilities() {
@@ -186,7 +189,7 @@
mMultiUserSwitch.setVisibility(View.GONE);
}
}
- mBatteryView.setForceShowPercent(mBatteryCharging);
+ mBatteryView.setForceShowPercent(mBatteryCharging && mShowPercentAvailable);
}
private void updateSystemIconsLayoutParams() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 2a1f92f..f8b79c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -18,6 +18,7 @@
import static android.view.MotionEvent.ACTION_DOWN;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
@@ -328,15 +329,15 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- if (shouldDeadZoneConsumeTouchEvents(event)) {
- return true;
- }
+ final boolean deadZoneConsumed = shouldDeadZoneConsumeTouchEvents(event);
switch (event.getActionMasked()) {
case ACTION_DOWN:
int x = (int) event.getX();
int y = (int) event.getY();
mDownHitTarget = HIT_TARGET_NONE;
- if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) {
+ if (deadZoneConsumed) {
+ mDownHitTarget = HIT_TARGET_DEAD_ZONE;
+ } else if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_BACK;
} else if (getHomeButton().isVisible() && mHomeButtonBounds.contains(x, y)) {
mDownHitTarget = HIT_TARGET_HOME;
@@ -353,9 +354,7 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (shouldDeadZoneConsumeTouchEvents(event)) {
- return true;
- }
+ shouldDeadZoneConsumeTouchEvents(event);
if (mGestureHelper.onTouchEvent(event)) {
return true;
}
@@ -764,7 +763,7 @@
showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
}
- private void updateSlippery() {
+ public void updateSlippery() {
setSlippery(!isQuickStepSwipeUpEnabled() || mPanelView.isFullyExpanded());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 44d666e..2bfdfeb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -47,6 +47,8 @@
private final Rect mTintArea = new Rect();
private NotificationStackScrollLayout mNotificationScrollLayout;
private Context mContext;
+ private boolean mFullyDark;
+ private boolean mHasShelfIconsWhenFullyDark;
public NotificationIconAreaController(Context context, StatusBar statusBar) {
mStatusBar = statusBar;
@@ -173,13 +175,40 @@
public void updateNotificationIcons() {
updateStatusBarIcons();
- updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
- NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */,
- false /* hideRepliedMessages */);
+ updateShelfIcons();
+ updateHasShelfIconsWhenFullyDark();
applyNotificationIconsTint();
}
+ private void updateHasShelfIconsWhenFullyDark() {
+ boolean hasIconsWhenFullyDark = false;
+ for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) {
+ View view = mNotificationScrollLayout.getChildAt(i);
+ if (view instanceof ExpandableNotificationRow) {
+ NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
+ if (shouldShowNotificationIcon(ent,
+ NotificationShelf.SHOW_AMBIENT_ICONS /* showAmbient */,
+ false /* hideDismissed */,
+ true /* hideReplied */)) {
+ hasIconsWhenFullyDark = true;
+ break;
+ }
+ }
+ }
+ mHasShelfIconsWhenFullyDark = hasIconsWhenFullyDark;
+ }
+
+ public boolean hasShelfIconsWhenFullyDark() {
+ return mHasShelfIconsWhenFullyDark;
+ }
+
+ private void updateShelfIcons() {
+ updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
+ NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */,
+ mFullyDark /* hideRepliedMessages */);
+ }
+
public void updateStatusBarIcons() {
updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
false /* showAmbient */, true /* hideDismissed */, true /* hideRepliedMessages */);
@@ -320,6 +349,11 @@
v.setDecorColor(mIconTint);
}
+ public void setFullyDark(boolean fullyDark) {
+ mFullyDark = fullyDark;
+ updateShelfIcons();
+ }
+
public void setDark(boolean dark) {
mNotificationIcons.setDark(dark, false, 0);
mShelfIcons.setDark(dark, false, 0);
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 2f18aad9..7bd5fd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -221,6 +221,7 @@
private boolean mClosingWithAlphaFadeOut;
private boolean mHeadsUpAnimatingAway;
private boolean mLaunchingAffordance;
+ private boolean mAffordanceHasPreview;
private FalsingManager mFalsingManager;
private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
@@ -2489,7 +2490,7 @@
}
protected void setVerticalPanelTranslation(float translation) {
- mNotificationStackScroller.setTranslationX(translation);
+ mNotificationStackScroller.setVerticalPanelTranslation(translation);
mQsFrame.setTranslationX(translation);
int size = mVerticalTranslationListener.size();
for (int i = 0; i < size; i++) {
@@ -2569,6 +2570,7 @@
} else {
animate = false;
}
+ mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
mAffordanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}
@@ -2614,6 +2616,13 @@
}
/**
+ * Return true when a bottom affordance is launching an occluded activity with a splash screen.
+ */
+ public boolean isLaunchingAffordanceWithPreview() {
+ return mLaunchingAffordance && mAffordanceHasPreview;
+ }
+
+ /**
* Whether the camera application can be launched for the camera launch gesture.
*
* @param keyguardIsShowing whether keyguard is being shown
@@ -2736,13 +2745,14 @@
public void setPulsing(boolean pulsing) {
mPulsing = pulsing;
- final boolean canAnimatePulse =
- !DozeParameters.getInstance(mContext).getDisplayNeedsBlanking();
- if (canAnimatePulse) {
+ DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
+ final boolean animatePulse = !dozeParameters.getDisplayNeedsBlanking()
+ && dozeParameters.getAlwaysOn();
+ if (animatePulse) {
mAnimateNextPositionUpdate = true;
}
- mNotificationStackScroller.setPulsing(pulsing, canAnimatePulse);
- mKeyguardStatusView.setPulsing(pulsing, canAnimatePulse);
+ mNotificationStackScroller.setPulsing(pulsing, animatePulse);
+ mKeyguardStatusView.setPulsing(pulsing, animatePulse);
}
public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index c4d7e72..6f4a3cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -29,6 +29,7 @@
private static final boolean SPEW = false;
private boolean mBouncerShowing;
private boolean mExpanded;
+ protected float mPanelFraction;
public static final void LOG(String fmt, Object... args) {
if (!DEBUG) return;
@@ -77,6 +78,14 @@
if (mPanel != null) mPanel.setImportantForAccessibility(important);
}
+ public float getExpansionFraction() {
+ return mPanelFraction;
+ }
+
+ public boolean isExpanded() {
+ return mExpanded;
+ }
+
private void updateVisibility() {
mPanel.setVisibility(mExpanded || mBouncerShowing ? VISIBLE : INVISIBLE);
}
@@ -131,6 +140,7 @@
if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
PanelView pv = mPanel;
mExpanded = expanded;
+ mPanelFraction = frac;
updateVisibility();
// adjust any other panels that may be partially visible
if (expanded) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 5477f88..59863ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -59,7 +59,6 @@
private final PhoneStatusBarTransitions mBarTransitions;
private ScrimController mScrimController;
private float mMinFraction;
- private float mPanelFraction;
private Runnable mHideExpandedRunnable = new Runnable() {
@Override
public void run() {
@@ -269,7 +268,6 @@
@Override
public void panelExpansionChanged(float frac, boolean expanded) {
super.panelExpansionChanged(frac, expanded);
- mPanelFraction = frac;
updateScrimFraction();
if ((frac == 0 || frac == 1) && mBar.getNavigationBarView() != null) {
mBar.getNavigationBarView().onPanelExpandedChange(expanded);
@@ -331,30 +329,25 @@
// or letterboxing from the right or left sides.
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- if (mDisplayCutout == null) {
+ if (mDisplayCutout == null || mDisplayCutout.isEmpty()
+ || mLastOrientation != ORIENTATION_PORTRAIT || cornerCutoutMargins == null) {
lp.leftMargin = 0;
lp.rightMargin = 0;
return;
}
- lp.leftMargin = mDisplayCutout.getSafeInsetLeft();
- lp.rightMargin = mDisplayCutout.getSafeInsetRight();
+ lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first);
+ lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second);
- if (cornerCutoutMargins != null) {
- lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first);
- lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second);
-
- // If we're already inset enough (e.g. on the status bar side), we can have 0 margin
- WindowInsets insets = getRootWindowInsets();
- int leftInset = insets.getSystemWindowInsetLeft();
- int rightInset = insets.getSystemWindowInsetRight();
- if (lp.leftMargin <= leftInset) {
- lp.leftMargin = 0;
- }
- if (lp.rightMargin <= rightInset) {
- lp.rightMargin = 0;
- }
-
+ // If we're already inset enough (e.g. on the status bar side), we can have 0 margin
+ WindowInsets insets = getRootWindowInsets();
+ int leftInset = insets.getSystemWindowInsetLeft();
+ int rightInset = insets.getSystemWindowInsetRight();
+ if (lp.leftMargin <= leftInset) {
+ lp.leftMargin = 0;
+ }
+ if (lp.rightMargin <= rightInset) {
+ lp.rightMargin = 0;
}
}
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 860b77e..af1d220 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -22,20 +22,21 @@
import static com.android.systemui.Interpolators.ALPHA_OUT;
import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
import static com.android.systemui.OverviewProxyService.TAG_OPS;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
-import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.graphics.Shader;
import android.os.Handler;
import android.os.RemoteException;
import android.util.FloatProperty;
@@ -54,7 +55,6 @@
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.system.NavigationBarCompat;
-import com.android.internal.graphics.ColorUtils;
/**
* Class to detect gestures on the navigation bar and implement quick scrub.
@@ -65,6 +65,7 @@
private static final int ANIM_IN_DURATION_MS = 150;
private static final int ANIM_OUT_DURATION_MS = 134;
private static final float TRACK_SCALE = 0.95f;
+ private static final float GRADIENT_WIDTH = .75f;
private NavigationBarView mNavigationBarView;
@@ -78,23 +79,22 @@
private boolean mIsRTL;
private float mTrackAlpha;
private float mTrackScale = TRACK_SCALE;
- private int mLightTrackColor;
- private int mDarkTrackColor;
private float mDarkIntensity;
+ private RadialGradient mHighlight;
+ private float mHighlightCenter;
private AnimatorSet mTrackAnimator;
private ButtonDispatcher mHitTarget;
private View mCurrentNavigationBarView;
private final Handler mHandler = new Handler();
private final Rect mTrackRect = new Rect();
- private final Drawable mTrackDrawable;
private final OverviewProxyService mOverviewEventSender;
private final int mTrackThickness;
private final int mTrackEndPadding;
private final Context mContext;
private final Matrix mTransformGlobalMatrix = new Matrix();
private final Matrix mTransformLocalMatrix = new Matrix();
- private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator();
+ private final Paint mTrackPaint = new Paint();
private final FloatProperty<QuickStepController> mTrackAlphaProperty =
new FloatProperty<QuickStepController>("TrackAlpha") {
@@ -155,7 +155,8 @@
mOverviewEventSender = Dependency.get(OverviewProxyService.class);
mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
- mTrackDrawable = context.getDrawable(R.drawable.qs_scrubber_track).mutate();
+ mTrackPaint.setAntiAlias(true);
+ mTrackPaint.setDither(true);
}
public void setComponents(NavigationBarView navigationBarView) {
@@ -184,6 +185,8 @@
}
private boolean handleTouchEvent(MotionEvent event) {
+ final boolean deadZoneConsumed =
+ mNavigationBarView.getDownHitTarget() == HIT_TARGET_DEAD_ZONE;
if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
&& !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
return false;
@@ -287,6 +290,8 @@
} catch (RemoteException e) {
Log.e(TAG, "Failed to send progress of quick scrub.", e);
}
+ mHighlightCenter = x;
+ mNavigationBarView.invalidate();
}
break;
}
@@ -302,7 +307,7 @@
|| action == MotionEvent.ACTION_UP)) {
proxyMotionEvents(event);
}
- return mQuickScrubActive || mQuickStepStarted;
+ return mQuickScrubActive || mQuickStepStarted || deadZoneConsumed;
}
@Override
@@ -310,18 +315,18 @@
if (!mNavigationBarView.isQuickScrubEnabled()) {
return;
}
- int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor,
- mDarkTrackColor);
- int colorAlpha = ColorUtils.setAlphaComponent(color,
- (int) (Color.alpha(color) * mTrackAlpha));
- mTrackDrawable.setTint(colorAlpha);
+ mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
// Scale the track, but apply the inverse scale from the nav bar
+ final float radius = mTrackRect.height() / 2;
canvas.save();
+ float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
+ canvas.translate(translate, 0);
canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
1f / mNavigationBarView.getScaleY(),
mTrackRect.centerX(), mTrackRect.centerY());
- mTrackDrawable.draw(canvas);
+ canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
+ mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
canvas.restore();
}
@@ -346,12 +351,20 @@
x2 = x1 + width - 2 * mTrackEndPadding;
}
mTrackRect.set(x1, y1, x2, y2);
- mTrackDrawable.setBounds(mTrackRect);
+ updateHighlight();
}
@Override
public void onDarkIntensityChange(float intensity) {
+ final float oldIntensity = mDarkIntensity;
mDarkIntensity = intensity;
+
+ // When in quick scrub, invalidate gradient if changing intensity from black to white and
+ // vice-versa
+ if (mNavigationBarView.isQuickScrubEnabled()
+ && Math.round(intensity) != Math.round(oldIntensity)) {
+ updateHighlight();
+ }
mNavigationBarView.invalidate();
}
@@ -408,10 +421,8 @@
private void startQuickScrub() {
if (!mQuickScrubActive) {
+ updateHighlight();
mQuickScrubActive = true;
- mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
- mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
-
ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 1f),
PropertyValuesHolder.ofFloat(mTrackScaleProperty, 1f));
@@ -424,6 +435,9 @@
mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
mTrackAnimator.start();
+ // Disable slippery for quick scrub to not cancel outside the nav bar
+ mNavigationBarView.updateSlippery();
+
try {
mOverviewEventSender.getProxy().onQuickScrubStart();
if (DEBUG_OVERVIEW_PROXY) {
@@ -483,6 +497,25 @@
mQuickScrubActive = false;
mAllowGestureDetection = false;
mCurrentNavigationBarView = null;
+ updateHighlight();
+ }
+
+ private void updateHighlight() {
+ if (mTrackRect.isEmpty()) {
+ return;
+ }
+ int colorBase, colorGrad;
+ if (mDarkIntensity > 0.5f) {
+ colorBase = mContext.getColor(R.color.quick_step_track_background_background_dark);
+ colorGrad = mContext.getColor(R.color.quick_step_track_background_foreground_dark);
+ } else {
+ colorBase = mContext.getColor(R.color.quick_step_track_background_background_light);
+ colorGrad = mContext.getColor(R.color.quick_step_track_background_foreground_light);
+ }
+ mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
+ mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
+ Shader.TileMode.CLAMP);
+ mTrackPaint.setShader(mHighlight);
}
private boolean proxyMotionEvents(MotionEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 279ede9..61f0e1cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -29,9 +29,7 @@
import android.os.Trace;
import android.util.Log;
import android.util.MathUtils;
-import android.view.Choreographer;
import android.view.View;
-import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -43,12 +41,11 @@
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.function.TriConsumer;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.stack.ViewState;
import com.android.systemui.util.AlarmTimeout;
@@ -482,21 +479,13 @@
// Make sure we have the right gradients and their opacities will satisfy GAR.
if (mNeedsDrawableColorUpdate) {
mNeedsDrawableColorUpdate = false;
- final GradientColors currentScrimColors;
- if (mState == ScrimState.KEYGUARD || mState == ScrimState.BOUNCER_SCRIMMED
- || mState == ScrimState.BOUNCER) {
- // Always animate color changes if we're seeing the keyguard
- mScrimInFront.setColors(mLockColors, true /* animated */);
- mScrimBehind.setColors(mLockColors, true /* animated */);
- currentScrimColors = mLockColors;
- } else {
- // Only animate scrim color if the scrim view is actually visible
- boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0;
- boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0;
- mScrimInFront.setColors(mSystemColors, animateScrimInFront);
- mScrimBehind.setColors(mSystemColors, animateScrimBehind);
- currentScrimColors = mSystemColors;
- }
+ boolean isKeyguard = mKeyguardUpdateMonitor.isKeyguardVisible() && !mKeyguardOccluded;
+ GradientColors currentScrimColors = isKeyguard ? mLockColors : mSystemColors;
+ // Only animate scrim color if the scrim view is actually visible
+ boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0 && !mBlankScreen;
+ boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0 && !mBlankScreen;
+ mScrimInFront.setColors(currentScrimColors, animateScrimInFront);
+ mScrimBehind.setColors(currentScrimColors, animateScrimBehind);
// Calculate minimum scrim opacity for white or black text.
int textColor = currentScrimColors.supportsDarkText() ? Color.BLACK : Color.WHITE;
@@ -899,6 +888,18 @@
updateScrims();
}
+ public void setHasBackdrop(boolean hasBackdrop) {
+ for (ScrimState state : ScrimState.values()) {
+ state.setHasBackdrop(hasBackdrop);
+ }
+ }
+
+ public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
+ for (ScrimState state : ScrimState.values()) {
+ state.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
+ }
+ }
+
public interface Callback {
default void onStart() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 713356b..cdbad59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -20,7 +20,6 @@
import android.os.Trace;
import android.util.MathUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -106,8 +105,7 @@
public void prepare(ScrimState previousState) {
final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn();
mBlankScreen = mDisplayRequiresBlanking;
- mCurrentBehindAlpha = mWallpaperSupportsAmbientMode
- && !mKeyguardUpdateMonitor.hasLockscreenWallpaper() ? 0f : 1f;
+ mCurrentBehindAlpha = mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
mCurrentInFrontAlpha = alwaysOnEnabled ? mAodFrontScrimAlpha : 1f;
mCurrentInFrontTint = Color.BLACK;
mCurrentBehindTint = Color.BLACK;
@@ -131,8 +129,7 @@
public void prepare(ScrimState previousState) {
mCurrentInFrontAlpha = 0;
mCurrentInFrontTint = Color.BLACK;
- mCurrentBehindAlpha = mWallpaperSupportsAmbientMode
- && !mKeyguardUpdateMonitor.hasLockscreenWallpaper() ? 0f : 1f;
+ mCurrentBehindAlpha = mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f;
mCurrentBehindTint = Color.BLACK;
mBlankScreen = mDisplayRequiresBlanking;
}
@@ -147,6 +144,7 @@
mCurrentBehindAlpha = 0;
mCurrentInFrontAlpha = 0;
mAnimationDuration = StatusBar.FADE_KEYGUARD_DURATION;
+ mAnimateChange = !mLaunchingAffordanceWithPreview;
if (previousState == ScrimState.AOD || previousState == ScrimState.PULSING) {
// Fade from black to transparent when coming directly from AOD
@@ -178,8 +176,9 @@
DozeParameters mDozeParameters;
boolean mDisplayRequiresBlanking;
boolean mWallpaperSupportsAmbientMode;
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
int mIndex;
+ boolean mHasBackdrop;
+ boolean mLaunchingAffordanceWithPreview;
ScrimState(int index) {
mIndex = index;
@@ -190,7 +189,6 @@
mScrimBehind = scrimBehind;
mDozeParameters = dozeParameters;
mDisplayRequiresBlanking = dozeParameters.getDisplayNeedsBlanking();
- mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(scrimInFront.getContext());
}
public void prepare(ScrimState previousState) {
@@ -253,7 +251,15 @@
mWallpaperSupportsAmbientMode = wallpaperSupportsAmbientMode;
}
+ public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
+ mLaunchingAffordanceWithPreview = launchingAffordanceWithPreview;
+ }
+
public boolean isLowPowerState() {
return false;
}
+
+ public void setHasBackdrop(boolean hasBackdrop) {
+ mHasBackdrop = hasBackdrop;
+ }
}
\ No newline at end of file
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 7bbeed6..cd30104 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -52,6 +52,7 @@
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.TaskStackBuilder;
+import android.app.UiModeManager;
import android.app.WallpaperColors;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
@@ -326,6 +327,12 @@
/** If true, the lockscreen will show a distinct wallpaper */
private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
+ /** Whether to force dark theme if Configuration.UI_MODE_NIGHT_YES. */
+ private static final boolean DARK_THEME_IN_NIGHT_MODE = true;
+
+ /** Whether to switch the device into night mode in battery saver. */
+ private static final boolean NIGHT_MODE_IN_BATTERY_SAVER = true;
+
/**
* Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode
* won't draw anything and uninitialized memory will show through
@@ -607,6 +614,12 @@
maybeEscalateHeadsUp();
}
}
+
+ @Override
+ public void onStrongAuthStateChanged(int userId) {
+ super.onStrongAuthStateChanged(userId);
+ mEntryManager.updateNotifications();
+ }
};
private NavigationBarFragment mNavigationBar;
@@ -823,23 +836,31 @@
.createNotificationIconAreaController(context, this);
inflateShelf();
mNotificationIconAreaController.setupShelf(mNotificationShelf);
+ mStackScroller.setIconAreaController(mNotificationIconAreaController);
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
CollapsedStatusBarFragment statusBarFragment =
(CollapsedStatusBarFragment) fragment;
statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
+ PhoneStatusBarView oldStatusBarView = mStatusBarView;
mStatusBarView = (PhoneStatusBarView) fragment.getView();
mStatusBarView.setBar(this);
mStatusBarView.setPanel(mNotificationPanel);
mStatusBarView.setScrimController(mScrimController);
mStatusBarView.setBouncerShowing(mBouncerShowing);
+ if (oldStatusBarView != null) {
+ float fraction = oldStatusBarView.getExpansionFraction();
+ boolean expanded = oldStatusBarView.isExpanded();
+ mStatusBarView.panelExpansionChanged(fraction, expanded);
+ }
if (mHeadsUpAppearanceController != null) {
// This view is being recreated, let's destroy the old one
mHeadsUpAppearanceController.destroy();
}
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow);
+ mStatusBarWindow.setStatusBarView(mStatusBarView);
setAreThereNotifications();
checkBarModes();
}).getFragmentManager()
@@ -917,6 +938,10 @@
if (mDozeServiceHost != null) {
mDozeServiceHost.firePowerSaveChanged(isPowerSave);
}
+ if (NIGHT_MODE_IN_BATTERY_SAVER) {
+ mContext.getSystemService(UiModeManager.class).setNightMode(
+ isPowerSave ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO);
+ }
}
@Override
@@ -1645,8 +1670,12 @@
&& mStatusBarKeyguardViewManager.isOccluded();
final boolean hasArtwork = artworkDrawable != null;
+ mColorExtractor.setHasBackdrop(hasArtwork);
+ if (mScrimController != null) {
+ mScrimController.setHasBackdrop(hasArtwork);
+ }
- if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && !mDozing
+ if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
&& (mState != StatusBarState.SHADE || allowWhenShade)
&& mFingerprintUnlockController.getMode()
!= FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
@@ -1662,7 +1691,6 @@
mBackdrop.setAlpha(1f);
}
mStatusBarWindowManager.setBackdropShowing(true);
- mColorExtractor.setMediaBackdropVisible(true);
metaDataChanged = true;
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
@@ -1714,7 +1742,6 @@
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
}
- mColorExtractor.setMediaBackdropVisible(false);
boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange();
if (mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING
@@ -3112,6 +3139,7 @@
public void onConfigChanged(Configuration newConfig) {
updateResources();
updateDisplaySize(); // populates mDisplayMetrics
+ updateTheme();
if (DEBUG) {
Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
@@ -3846,13 +3874,18 @@
* Switches theme from light to dark and vice-versa.
*/
protected void updateTheme() {
- final boolean inflated = mStackScroller != null;
+ final boolean inflated = mStackScroller != null && mStatusBarWindowManager != null;
// The system wallpaper defines if QS should be light or dark.
WallpaperColors systemColors = mColorExtractor
.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
- final boolean useDarkTheme = systemColors != null
+ final boolean wallpaperWantsDarkTheme = systemColors != null
&& (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
+ final Configuration config = mContext.getResources().getConfiguration();
+ final boolean nightModeWantsDarkTheme = DARK_THEME_IN_NIGHT_MODE
+ && (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ final boolean useDarkTheme = wallpaperWantsDarkTheme || nightModeWantsDarkTheme;
if (isUsingDarkTheme() != useDarkTheme) {
mUiOffloadThread.submit(() -> {
try {
@@ -4720,6 +4753,10 @@
mScrimController.setExpansionAffectsAlpha(
!mFingerprintUnlockController.isFingerprintUnlock());
+ boolean launchingAffordanceWithPreview =
+ mNotificationPanel.isLaunchingAffordanceWithPreview();
+ mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
+
if (mBouncerShowing) {
// Bouncer needs the front scrim when it's on top of an activity,
// tapping on a notification, editing QS or being dismissed by
@@ -4729,7 +4766,8 @@
|| mStatusBarKeyguardViewManager.isFullscreenBouncer() ?
ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
mScrimController.transitionTo(state);
- } else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) {
+ } else if (isInLaunchTransition() || mLaunchCameraOnScreenTurningOn
+ || launchingAffordanceWithPreview) {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 5001d4f..b49ad46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -173,7 +173,7 @@
|| mStatusBar.isFullScreenUserSwitcherState()) {
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
} else if (mShowing && !mDozing) {
- if (!isWakeAndUnlocking()) {
+ if (!isWakeAndUnlocking() && !mStatusBar.isInLaunchTransition()) {
mBouncer.setExpansion(expansion);
}
if (expansion != KeyguardBouncer.EXPANSION_HIDDEN && tracking
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a79a41b..fa763c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -37,6 +37,7 @@
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.ActionMode;
+import android.view.DisplayCutout;
import android.view.InputDevice;
import android.view.InputQueue;
import android.view.KeyEvent;
@@ -75,6 +76,7 @@
private NotificationStackScrollLayout mStackScrollLayout;
private NotificationPanelView mNotificationPanel;
private View mBrightnessMirror;
+ private PhoneStatusBarView mStatusBarView;
private int mRightInset = 0;
private int mLeftInset = 0;
@@ -94,6 +96,12 @@
private boolean mExpandAnimationRunning;
private boolean mExpandAnimationPending;
+ /**
+ * If set to true, the current gesture started below the notch and we need to dispatch touch
+ * events manually as it's outside of the regular view bounds.
+ */
+ private boolean mExpandingBelowNotch;
+
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
@@ -112,10 +120,21 @@
boolean paddingChanged = insets.top != getPaddingTop()
|| insets.bottom != getPaddingBottom();
+ int rightCutout = 0;
+ int leftCutout = 0;
+ DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout();
+ if (displayCutout != null) {
+ leftCutout = displayCutout.getSafeInsetLeft();
+ rightCutout = displayCutout.getSafeInsetRight();
+ }
+
+ int targetLeft = Math.max(insets.left, leftCutout);
+ int targetRight = Math.max(insets.right, rightCutout);
+
// Super-special right inset handling, because scrims and backdrop need to ignore it.
- if (insets.right != mRightInset || insets.left != mLeftInset) {
- mRightInset = insets.right;
- mLeftInset = insets.left;
+ if (targetRight != mRightInset || targetLeft != mLeftInset) {
+ mRightInset = targetRight;
+ mLeftInset = targetLeft;
applyMargins();
}
// Drop top inset, and pass through bottom inset.
@@ -186,6 +205,10 @@
}
}
+ public void setStatusBarView(PhoneStatusBarView statusBarView) {
+ mStatusBarView = statusBarView;
+ }
+
public void setService(StatusBar service) {
mService = service;
setDragDownHelper(new DragDownHelper(getContext(), this, mStackScrollLayout, mService));
@@ -258,7 +281,16 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
+ boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
+
+ // Reset manual touch dispatch state here but make sure the UP/CANCEL event still gets
+ // delivered.
+ boolean expandingBelowNotch = mExpandingBelowNotch;
+ if (isUp || isCancel) {
+ mExpandingBelowNotch = false;
+ }
+
if (!isCancel && mService.shouldIgnoreTouch()) {
return false;
}
@@ -291,6 +323,17 @@
mService.mDozeScrimController.extendPulse();
}
+ // In case we start outside of the view bounds (below the status bar), we need to dispatch
+ // the touch manually as the view system can't accomodate for touches outside of the
+ // regular view bounds.
+ if (isDown && ev.getY() >= mBottom) {
+ mExpandingBelowNotch = true;
+ expandingBelowNotch = true;
+ }
+ if (expandingBelowNotch) {
+ return mStatusBarView.dispatchTouchEvent(ev);
+ }
+
return super.dispatchTouchEvent(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 2031b27..59b376f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -113,10 +113,6 @@
@Override
public void addCallback(Callback callback) {
- if (callback == null) {
- Slog.e(TAG, "Attempted to add a null callback.");
- return;
- }
mCallbacks.add(callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index c26568e..e80f483 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -137,6 +137,10 @@
// to look nice
customDelay = StackStateAnimator.ANIMATION_DELAY_HEADS_UP_CLICKED
+ StackStateAnimator.ANIMATION_DELAY_HEADS_UP;
+ } else if (ev.animationType == NotificationStackScrollLayout.AnimationEvent
+ .ANIMATION_TYPE_PULSE_APPEAR || ev.animationType ==
+ NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
+ customDelay = StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2;
}
}
}
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 9c26c69..9d0d295 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -101,6 +101,7 @@
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
@@ -140,7 +141,6 @@
private boolean mSwipingInProgress;
private int mCurrentStackHeight = Integer.MAX_VALUE;
private final Paint mBackgroundPaint = new Paint();
- private final Path mBackgroundPath = new Path();
private final boolean mShouldDrawNotificationBackground;
private float mExpandedHeight;
@@ -376,6 +376,11 @@
private View mForcedScroll;
private View mNeedingPulseAnimation;
private float mDarkAmount = 0f;
+
+ /**
+ * How fast the background scales in the X direction as a factor of the Y expansion.
+ */
+ private float mBackgroundXFactor = 1f;
private static final Property<NotificationStackScrollLayout, Float> DARK_AMOUNT =
new FloatProperty<NotificationStackScrollLayout>("darkAmount") {
@Override
@@ -416,6 +421,8 @@
private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
private int mHeadsUpInset;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
+ private NotificationIconAreaController mIconAreaController;
+ private float mVerticalPanelTranslation;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -532,10 +539,16 @@
final int lockScreenRight = getWidth() - mSidePaddings;
final int lockScreenTop = mCurrentBounds.top;
final int lockScreenBottom = mCurrentBounds.bottom;
- final int darkLeft = getWidth() / 2 - mSeparatorWidth / 2;
- final int darkRight = darkLeft + mSeparatorWidth;
- final int darkTop = (int) (mRegularTopPadding + mSeparatorThickness / 2f);
- final int darkBottom = darkTop + mSeparatorThickness;
+ int separatorWidth = 0;
+ int separatorThickness = 0;
+ if (mIconAreaController.hasShelfIconsWhenFullyDark()) {
+ separatorThickness = mSeparatorThickness;
+ separatorWidth = mSeparatorWidth;
+ }
+ final int darkLeft = getWidth() / 2 - separatorWidth / 2;
+ final int darkRight = darkLeft + separatorWidth;
+ final int darkTop = (int) (mRegularTopPadding + separatorThickness / 2f);
+ final int darkBottom = darkTop + separatorThickness;
if (mAmbientState.hasPulsingNotifications()) {
// No divider, we have a notification icon instead
@@ -548,7 +561,7 @@
float inverseDark = 1 - mDarkAmount;
float yProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(inverseDark);
float xProgress = Interpolators.FAST_OUT_SLOW_IN
- .getInterpolation(inverseDark * 2f);
+ .getInterpolation(inverseDark * mBackgroundXFactor);
mBackgroundAnimationRect.set(
(int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress),
@@ -2041,11 +2054,9 @@
}
private int getScrollRange() {
- int contentHeight = getContentHeight();
- int scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight);
+ int scrollRange = Math.max(0, mContentHeight - mMaxLayoutHeight);
int imeInset = getImeInset();
- scrollRange += Math.min(imeInset, Math.max(0,
- getContentHeight() - (getHeight() - imeInset)));
+ scrollRange += Math.min(imeInset, Math.max(0, mContentHeight - (getHeight() - imeInset)));
return scrollRange;
}
@@ -2146,10 +2157,6 @@
return count;
}
- public int getContentHeight() {
- return mContentHeight;
- }
-
private void updateContentHeight() {
int height = 0;
float previousPaddingRequest = mPaddingBetweenElements;
@@ -2213,7 +2220,11 @@
}
}
mIntrinsicContentHeight = height;
- mContentHeight = height + mTopPadding + mBottomMargin;
+
+ // We don't want to use the toppadding since that might be interpolated and we want
+ // to take the final value of the animation.
+ int topPadding = mAmbientState.isFullyDark() ? mDarkTopPadding : mRegularTopPadding;
+ mContentHeight = height + topPadding + mBottomMargin;
updateScrollability();
clampScrollPosition();
mAmbientState.setLayoutMaxHeight(mContentHeight);
@@ -3993,8 +4004,13 @@
notifyHeightChangeListener(mShelf);
}
- private void updateAntiBurnInTranslation() {
- setTranslationX(mAntiBurnInOffsetX * mDarkAmount);
+ private void updatePanelTranslation() {
+ setTranslationX(mVerticalPanelTranslation + mAntiBurnInOffsetX * mDarkAmount);
+ }
+
+ public void setVerticalPanelTranslation(float verticalPanelTranslation) {
+ mVerticalPanelTranslation = verticalPanelTranslation;
+ updatePanelTranslation();
}
/**
@@ -4011,16 +4027,20 @@
mDarkAmount = darkAmount;
boolean wasFullyDark = mAmbientState.isFullyDark();
mAmbientState.setDarkAmount(darkAmount);
- if (mAmbientState.isFullyDark() != wasFullyDark) {
+ boolean nowFullyDark = mAmbientState.isFullyDark();
+ if (nowFullyDark != wasFullyDark) {
updateContentHeight();
DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
- if (mAmbientState.isFullyDark() && dozeParameters.shouldControlScreenOff()) {
+ if (nowFullyDark && dozeParameters.shouldControlScreenOff()) {
mShelf.fadeInTranslating();
}
+ if (mIconAreaController != null) {
+ mIconAreaController.setFullyDark(nowFullyDark);
+ }
}
updateAlgorithmHeightAndPadding();
updateBackgroundDimming();
- updateAntiBurnInTranslation();
+ updatePanelTranslation();
requestChildrenUpdate();
}
@@ -4028,21 +4048,37 @@
return mDarkAmount;
}
+ /**
+ * Cancel any previous dark animations - to avoid race conditions - and creates a new one.
+ * This function also sets {@code mBackgroundXFactor} based on the current {@code mDarkAmount}.
+ */
private void startDarkAmountAnimation() {
- ObjectAnimator darkAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount,
- mAmbientState.isDark() ? 1f : 0);
- darkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
- darkAnimator.setInterpolator(Interpolators.ALPHA_IN);
- darkAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean dark = mAmbientState.isDark();
+ if (mDarkAmountAnimator != null) {
+ mDarkAmountAnimator.cancel();
+ }
+
+ long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+ // Longer animation when sleeping with more than 1 notification
+ if (dark && getNotGoneChildCount() > 2) {
+ duration *= 1.2f;
+ }
+
+ mDarkAmountAnimator = ObjectAnimator.ofFloat(this, DARK_AMOUNT, mDarkAmount,
+ dark ? 1f : 0);
+ // We only swap the scaling factor if we're fully dark or fully awake to avoid
+ // interpolation issues when playing with the power button.
+ if (mDarkAmount == 0 || mDarkAmount == 1) {
+ mBackgroundXFactor = dark ? 2.5f : 1.5f;
+ }
+ mDarkAmountAnimator.setDuration(duration);
+ mDarkAmountAnimator.setInterpolator(Interpolators.LINEAR);
+ mDarkAmountAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mDarkAmountAnimator = null;
}
});
- if (mDarkAmountAnimator != null) {
- mDarkAmountAnimator.cancel();
- }
- mDarkAmountAnimator = darkAnimator;
mDarkAmountAnimator.start();
}
@@ -4572,7 +4608,7 @@
public void setAntiBurnInOffsetX(int antiBurnInOffsetX) {
mAntiBurnInOffsetX = antiBurnInOffsetX;
- updateAntiBurnInTranslation();
+ updatePanelTranslation();
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -4618,6 +4654,10 @@
mHeadsUpAppearanceController = headsUpAppearanceController;
}
+ public void setIconAreaController(NotificationIconAreaController controller) {
+ mIconAreaController = controller;
+ }
+
/**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@@ -5031,11 +5071,13 @@
// ANIMATION_TYPE_PULSE_APPEAR
new AnimationFilter()
.animateAlpha()
+ .hasDelays()
.animateY(),
// ANIMATION_TYPE_PULSE_DISAPPEAR
new AnimationFilter()
.animateAlpha()
+ .hasDelays()
.animateY(),
};
@@ -5099,10 +5141,10 @@
StackStateAnimator.ANIMATION_DURATION_STANDARD,
// ANIMATION_TYPE_PULSE_APPEAR
- KeyguardSliceView.DEFAULT_ANIM_DURATION,
+ StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR,
// ANIMATION_TYPE_PULSE_DISAPPEAR
- KeyguardSliceView.DEFAULT_ANIM_DURATION / 2,
+ StackStateAnimator.ANIMATION_DURATION_PULSE_APPEAR / 2,
};
static final int ANIMATION_TYPE_ADD = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index a75d40f..b83a09d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -24,6 +24,7 @@
import android.view.ViewGroup;
import android.view.animation.Interpolator;
+import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -51,6 +52,8 @@
= (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
* HeadsUpAppearInterpolator.getFractionUntilOvershoot());
public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+ public static final int ANIMATION_DURATION_PULSE_APPEAR =
+ KeyguardSliceView.DEFAULT_ANIM_DURATION;
public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
@@ -430,15 +433,26 @@
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_PULSE_APPEAR) {
ExpandableViewState viewState = finalState.getViewStateForView(changingView);
- mTmpState.copyFrom(viewState);
- mTmpState.yTranslation += mPulsingAppearingTranslation;
- mTmpState.alpha = 0;
- mTmpState.applyToView(changingView);
+ if (viewState != null) {
+ mTmpState.copyFrom(viewState);
+ mTmpState.yTranslation += mPulsingAppearingTranslation;
+ mTmpState.alpha = 0;
+ mTmpState.applyToView(changingView);
+ }
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) {
ExpandableViewState viewState = finalState.getViewStateForView(changingView);
- viewState.yTranslation += mPulsingAppearingTranslation;
- viewState.alpha = 0;
+ if (viewState != null) {
+ viewState.alpha = 0;
+ // We want to animate the alpha away before the view starts translating,
+ // otherwise everything will overlap and look xtra ugly.
+ float originalYTranslation = viewState.yTranslation;
+ viewState.yTranslation = changingView.getTranslationY();
+ mAnimationFilter.animateAlpha = true;
+ mAnimationProperties.duration = ANIMATION_DURATION_PULSE_APPEAR / 2;
+ viewState.animateTo(changingView, mAnimationProperties);
+ viewState.yTranslation = originalYTranslation;
+ }
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_HEADS_UP_APPEAR) {
// This item is added, initialize it's properties.
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index eca6127..6812410 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -26,11 +26,14 @@
/**
* Allows lambda iteration over a list. It is done in reverse order so it is safe
- * to add or remove items during the iteration.
+ * to add or remove items during the iteration. Skips over null items.
*/
public static <T> void safeForeach(List<T> list, Consumer<T> c) {
for (int i = list.size() - 1; i >= 0; i--) {
- c.accept(list.get(i));
+ T item = list.get(i);
+ if (item != null) {
+ c.accept(item);
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
index 8153953..13dc36d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
@@ -93,7 +93,7 @@
SysuiColorExtractor extractor = getTestableExtractor(colors);
simulateEvent(extractor);
extractor.setWallpaperVisible(true);
- extractor.setMediaBackdropVisible(true);
+ extractor.setHasBackdrop(true);
ColorExtractor.GradientColors fallbackColors = extractor.getFallbackColors();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
index 64507be..bb67d6e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java
@@ -16,7 +16,7 @@
package com.android.systemui.doze;
-import static org.junit.Assert.assertTrue;
+import static junit.framework.TestCase.assertEquals;
import android.os.UserHandle;
import android.provider.Settings;
@@ -42,14 +42,15 @@
}
@Test
- public void alwaysOn_onByDefault() throws Exception {
+ public void alwaysOn_followsConfigByDefault() throws Exception {
if (!mDozeConfig.alwaysOnAvailable()) {
return;
}
Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.DOZE_ALWAYS_ON,
null);
-
- assertTrue(mDozeConfig.alwaysOnEnabled(UserHandle.USER_CURRENT));
+ boolean defaultValue = mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_dozeAlwaysOnEnabled);
+ assertEquals(mDozeConfig.alwaysOnEnabled(UserHandle.USER_CURRENT), defaultValue);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index e95702c..89d562a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -44,7 +44,6 @@
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.internal.util.function.TriConsumer;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.util.wakelock.WakeLock;
@@ -94,6 +93,7 @@
mScrimInFrontColor = scrimInFrontColor;
},
visible -> mScrimVisibility = visible, mDozeParamenters, mAlarmManager);
+ mScrimController.setHasBackdrop(false);
}
@Test
@@ -140,12 +140,7 @@
@Test
public void transitionToAod_withAodWallpaperAndLockScreenWallpaper() {
- ScrimState.AOD.mKeyguardUpdateMonitor = new KeyguardUpdateMonitor(getContext()) {
- @Override
- public boolean hasLockscreenWallpaper() {
- return true;
- }
- };
+ mScrimController.setHasBackdrop(true);
mScrimController.setWallpaperSupportsAmbientMode(true);
mScrimController.transitionTo(ScrimState.AOD);
mScrimController.finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 85135ac..94ab9d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -177,6 +177,14 @@
verify(mBouncer, never()).setExpansion(anyFloat());
}
+ @Test
+ public void onPanelExpansionChanged_neverTranslatesBouncerWhenLaunchingApp() {
+ when(mStatusBar.isInLaunchTransition()).thenReturn(true);
+ mStatusBarKeyguardViewManager.onPanelExpansionChanged(KeyguardBouncer.EXPANSION_VISIBLE,
+ false /* tracking */);
+ verify(mBouncer, never()).setExpansion(anyFloat());
+ }
+
private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
public TestableStatusBarKeyguardViewManager(Context context,
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 4328d94..143fa86 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -6116,7 +6116,21 @@
// OS: P
FIELD_AUTOFILL_SESSION_ID = 1456;
+ // NOTIFICATION_SINCE_INTERRUPTION_MILLIS added to P
+ // NOTIFICATION_INTERRUPTION added to P
+
// ---- End P Constants, all P constants go above this line ----
+
+ // Time since this notification last interrupted (visibly or audible) the user
+ NOTIFICATION_SINCE_INTERRUPTION_MILLIS = 1500;
+
+ // OPEN: Notification interrupted the user, either audibly or visually.
+ // Tagged data: NOTIFICATION_SINCE_INTERRUPTION_MILLIS
+ // CATEGORY: NOTIFICATION
+ NOTIFICATION_INTERRUPTION = 1501;
+
+ // ---- End Q Constants, all Q constants go above this line ----
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index a9a14ca..fba639c 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -212,6 +212,10 @@
// Package: android
NOTE_AUTO_SAVER_SUGGESTION = 49;
+ // Notify the user that their softap config preference has changed.
+ // Package: android
+ NOTE_SOFTAP_CONFIG_CHANGED = 50;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 607db4e..ad9fa40 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1588,10 +1588,10 @@
// Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast.
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ // Create a version of the intent with the number always populated.
Intent intentWithPhoneNumber = new Intent(intent);
- if (!TextUtils.isEmpty(incomingNumber)) {
- intentWithPhoneNumber.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
- }
+ intentWithPhoneNumber.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
+
// Send broadcast twice, once for apps that have PRIVILEGED permission and once for those
// that have the runtime one
mContext.sendBroadcastAsUser(intentWithPhoneNumber, UserHandle.ALL,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 928f6ef..385d038 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2207,6 +2207,9 @@
}
}
callbacks.finishBroadcast();
+ // We have to clean up the RemoteCallbackList here, because otherwise it will
+ // needlessly hold the enclosed callbacks until the remote process dies.
+ callbacks.kill();
} break;
case UPDATE_TIME_ZONE: {
synchronized (ActivityManagerService.this) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index cc7a230..f58f717 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1658,7 +1658,10 @@
// Some activity is waiting for another activity to become visible before it's being
// stopped, which means that we also want to wait with stopping this one to avoid
// flickers.
- if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.isEmpty()) {
+ if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.isEmpty()
+ && !mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
+ if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "adding to waiting visible activity=" + r
+ + " existing=" + mStackSupervisor.mActivitiesWaitingForVisibleActivity);
mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index e034b82..c520101 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1634,6 +1634,8 @@
* @param markFrozenIfConfigChanged Whether to set {@link ActivityRecord#frozenBeforeDestroy} to
* {@code true} if config changed.
* @param deferResume Whether to defer resume while updating config.
+ * @return 'true' if starting activity was kept or wasn't provided, 'false' if it was relaunched
+ * because of configuration update.
*/
boolean ensureVisibilityAndConfig(ActivityRecord starting, int displayId,
boolean markFrozenIfConfigChanged, boolean deferResume) {
@@ -1644,6 +1646,11 @@
ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */, false /* notifyClients */);
+ if (displayId == INVALID_DISPLAY) {
+ // The caller didn't provide a valid display id, skip updating config.
+ return true;
+ }
+
// Force-update the orientation from the WindowManager, since we need the true configuration
// to send to the client now.
final Configuration config = mWindowManager.updateOrientationFromAppTokens(
@@ -3930,6 +3937,10 @@
stops = new ArrayList<>();
}
stops.add(s);
+
+ // Make sure to remove it in all cases in case we entered this block with
+ // shouldSleepOrShutDown
+ mActivitiesWaitingForVisibleActivity.remove(s);
mStoppingActivities.remove(activityNdx);
}
}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 49fa902..9eb22d7 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -543,14 +543,25 @@
final long idleTimeMs = latest.mControllerIdleTimeMs - lastIdleMs;
final long scanTimeMs = latest.mControllerScanTimeMs - lastScanMs;
- if (txTimeMs < 0 || rxTimeMs < 0 || scanTimeMs < 0) {
+ if (txTimeMs < 0 || rxTimeMs < 0 || scanTimeMs < 0 || idleTimeMs < 0) {
// The stats were reset by the WiFi system (which is why our delta is negative).
- // Returns the unaltered stats.
- delta.mControllerEnergyUsed = latest.mControllerEnergyUsed;
- delta.mControllerRxTimeMs = latest.mControllerRxTimeMs;
- delta.mControllerTxTimeMs = latest.mControllerTxTimeMs;
- delta.mControllerIdleTimeMs = latest.mControllerIdleTimeMs;
- delta.mControllerScanTimeMs = latest.mControllerScanTimeMs;
+ // Returns the unaltered stats. The total on time should not exceed the time
+ // duartion between reports.
+ final long totalOnTimeMs = latest.mControllerTxTimeMs + latest.mControllerRxTimeMs
+ + latest.mControllerIdleTimeMs;
+ if (totalOnTimeMs <= timePeriodMs + MAX_WIFI_STATS_SAMPLE_ERROR_MILLIS) {
+ delta.mControllerEnergyUsed = latest.mControllerEnergyUsed;
+ delta.mControllerRxTimeMs = latest.mControllerRxTimeMs;
+ delta.mControllerTxTimeMs = latest.mControllerTxTimeMs;
+ delta.mControllerIdleTimeMs = latest.mControllerIdleTimeMs;
+ delta.mControllerScanTimeMs = latest.mControllerScanTimeMs;
+ } else {
+ delta.mControllerEnergyUsed = 0;
+ delta.mControllerRxTimeMs = 0;
+ delta.mControllerTxTimeMs = 0;
+ delta.mControllerIdleTimeMs = 0;
+ delta.mControllerScanTimeMs = 0;
+ }
Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
} else {
final long totalActiveTimeMs = txTimeMs + rxTimeMs;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0b9832d..87dd756 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -236,7 +236,6 @@
private static final int MSG_PERSIST_RINGER_MODE = 3;
private static final int MSG_AUDIO_SERVER_DIED = 4;
private static final int MSG_PLAY_SOUND_EFFECT = 5;
- private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
private static final int MSG_LOAD_SOUND_EFFECTS = 7;
private static final int MSG_SET_FORCE_USE = 8;
private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
@@ -268,6 +267,7 @@
private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
private static final int MSG_DISABLE_AUDIO_FOR_UID = 104;
private static final int MSG_SET_HEARING_AID_CONNECTION_STATE = 105;
+ private static final int MSG_BTA2DP_DOCK_TIMEOUT = 106;
// end of messages handled under wakelock
private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
@@ -2632,6 +2632,7 @@
broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
}
+ @GuardedBy("mSettingsLock")
private void muteRingerModeStreams() {
// Mute stream if not previously muted by ringer mode and (ringer mode
// is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
@@ -2719,10 +2720,9 @@
synchronized(mSettingsLock) {
change = mRingerMode != ringerMode;
mRingerMode = ringerMode;
+ muteRingerModeStreams();
}
- muteRingerModeStreams();
-
// Post a persist ringer mode msg
if (persist) {
sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
@@ -4521,13 +4521,21 @@
}
synchronized (mLastDeviceConnectMsgTime) {
long time = SystemClock.uptimeMillis() + delay;
- handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
- if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
- msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
- msg == MSG_SET_A2DP_SINK_CONNECTION_STATE ||
- msg == MSG_SET_HEARING_AID_CONNECTION_STATE) {
+
+ if (msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
+ msg == MSG_SET_A2DP_SINK_CONNECTION_STATE ||
+ msg == MSG_SET_HEARING_AID_CONNECTION_STATE ||
+ msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
+ msg == MSG_A2DP_DEVICE_CONFIG_CHANGE ||
+ msg == MSG_BTA2DP_DOCK_TIMEOUT) {
+ if (mLastDeviceConnectMsgTime >= time) {
+ // add a little delay to make sure messages are ordered as expected
+ time = mLastDeviceConnectMsgTime + 30;
+ }
mLastDeviceConnectMsgTime = time;
}
+
+ handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
}
}
@@ -4689,6 +4697,13 @@
} else {
delay = 0;
}
+
+ if (DEBUG_DEVICES) {
+ Log.d(TAG, "setBluetoothA2dpDeviceConnectionStateInt device: " + device
+ + " state: " + state + " delay(ms): " + delay
+ + " suppressNoisyIntent: " + suppressNoisyIntent);
+ }
+
queueMsgUnderWakeLock(mAudioHandler,
(profile == BluetoothProfile.A2DP ?
MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
@@ -5597,6 +5612,7 @@
synchronized (mConnectedDevices) {
makeA2dpDeviceUnavailableNow( (String) msg.obj );
}
+ mAudioEventWakeLock.release();
break;
case MSG_SET_FORCE_USE:
@@ -5827,6 +5843,9 @@
// must be called synchronized on mConnectedDevices
private void makeA2dpDeviceUnavailableNow(String address) {
+ if (address == null) {
+ return;
+ }
synchronized (mA2dpAvrcpLock) {
mAvrcpAbsVolSupported = false;
}
@@ -5836,6 +5855,9 @@
makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
// Remove A2DP routes as well
setCurrentAudioRouteName(null);
+ if (mDockAddress == address) {
+ mDockAddress = null;
+ }
}
// must be called synchronized on mConnectedDevices
@@ -5847,9 +5869,12 @@
mConnectedDevices.remove(
makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
// send the delayed message to make the device unavailable later
- Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address);
- mAudioHandler.sendMessageDelayed(msg, delayMs);
-
+ queueMsgUnderWakeLock(mAudioHandler,
+ MSG_BTA2DP_DOCK_TIMEOUT,
+ 0,
+ 0,
+ address,
+ delayMs);
}
// must be called synchronized on mConnectedDevices
@@ -5921,7 +5946,8 @@
private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state, int a2dpVolume)
{
if (DEBUG_DEVICES) {
- Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
+ Log.d(TAG, "onSetA2dpSinkConnectionState btDevice= " + btDevice+" state= " + state
+ + " is dock: "+btDevice.isBluetoothDock());
}
if (btDevice == null) {
return;
@@ -5958,7 +5984,7 @@
} else {
// this could be a connection of another A2DP device before the timeout of
// a dock: cancel the dock timeout, and make the dock unavailable now
- if(hasScheduledA2dpDockTimeout()) {
+ if (hasScheduledA2dpDockTimeout() && mDockAddress != null) {
cancelA2dpDeviceTimeout();
makeA2dpDeviceUnavailableNow(mDockAddress);
}
@@ -6177,17 +6203,6 @@
}
}
- if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
- mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
- mAudioHandler.hasMessages(MSG_SET_HEARING_AID_CONNECTION_STATE) ||
- mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
- synchronized (mLastDeviceConnectMsgTime) {
- long time = SystemClock.uptimeMillis();
- if (mLastDeviceConnectMsgTime > time) {
- delay = (int)(mLastDeviceConnectMsgTime - time) + 30;
- }
- }
- }
return delay;
}
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 4f53ed4..33525fd 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -46,6 +46,7 @@
import libcore.io.Streams;
import com.android.server.LocalServices;
+import com.android.server.policy.WindowManagerPolicy;
/**
* <p>
@@ -63,7 +64,7 @@
// The layer for the electron beam surface.
// This is currently hardcoded to be one layer above the boot animation.
- private static final int COLOR_FADE_LAYER = 0x40000001;
+ private static final int COLOR_FADE_LAYER = WindowManagerPolicy.COLOR_FADE_LAYER;
// The number of frames to draw when preparing the animation so that it will
// be ready to run smoothly. We use 3 frames because we are triple-buffered.
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8d730b4..0ec1f9c 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -254,7 +254,7 @@
// 1 second, or 1 Hz frequency.
private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000;
// Default update duration in milliseconds for REQUEST_LOCATION.
- private static final long LOCATION_UPDATE_DURATION_MILLIS = 0;
+ private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000;
/** simpler wrapper for ProviderRequest + Worksource */
private static class GpsRequest {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 36b04fc..c6a8712 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -955,12 +955,18 @@
@GuardedBy("mSeparateChallengeLock")
private void setSeparateProfileChallengeEnabledLocked(@UserIdInt int userId, boolean enabled,
String managedUserPassword) {
+ final boolean old = getBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, false, userId);
setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, enabled, userId);
- if (enabled) {
- mStorage.removeChildProfileLock(userId);
- removeKeystoreProfileKey(userId);
- } else {
- tieManagedProfileLockIfNecessary(userId, managedUserPassword);
+ try {
+ if (enabled) {
+ mStorage.removeChildProfileLock(userId);
+ removeKeystoreProfileKey(userId);
+ } else {
+ tieManagedProfileLockIfNecessary(userId, managedUserPassword);
+ }
+ } catch (IllegalStateException e) {
+ setBoolean(SEPARATE_PROFILE_CHALLENGE_KEY, old, userId);
+ throw e;
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0897b8a..cafc6fc 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4525,6 +4525,15 @@
@GuardedBy("mNotificationLock")
@VisibleForTesting
protected boolean isVisuallyInterruptive(NotificationRecord old, NotificationRecord r) {
+ // Ignore summary updates because we don't display most of the information.
+ if (r.sbn.isGroup() && r.sbn.getNotification().isGroupSummary()) {
+ if (DEBUG_INTERRUPTIVENESS) {
+ Log.v(TAG, "INTERRUPTIVENESS: "
+ + r.getKey() + " is not interruptive: summary");
+ }
+ return false;
+ }
+
if (old == null) {
if (DEBUG_INTERRUPTIVENESS) {
Log.v(TAG, "INTERRUPTIVENESS: "
@@ -4562,15 +4571,6 @@
return false;
}
- // Ignore summary updates because we don't display most of the information.
- if (r.sbn.isGroup() && r.sbn.getNotification().isGroupSummary()) {
- if (DEBUG_INTERRUPTIVENESS) {
- Log.v(TAG, "INTERRUPTIVENESS: "
- + r.getKey() + " is not interruptive: summary");
- }
- return false;
- }
-
final String oldTitle = String.valueOf(oldN.extras.get(Notification.EXTRA_TITLE));
final String newTitle = String.valueOf(newN.extras.get(Notification.EXTRA_TITLE));
if (!Objects.equals(oldTitle, newTitle)) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 0f3f44e..75b9f13 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -95,6 +95,7 @@
static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final int MAX_LOGTAG_LENGTH = 35;
final StatusBarNotification sbn;
+ IActivityManager mAm;
final int mTargetSdkVersion;
final int mOriginalFlags;
private final Context mContext;
@@ -127,6 +128,11 @@
// The most recent update time, or the creation time if no updates.
private long mUpdateTimeMs;
+ // The most recent interruption time, or the creation time if no updates. Differs from the
+ // above value because updates are filtered based on whether they actually interrupted the
+ // user
+ private long mInterruptionTimeMs;
+
// Is this record an update of an old record?
public boolean isUpdate;
private int mPackagePriority;
@@ -174,10 +180,12 @@
this.sbn = sbn;
mTargetSdkVersion = LocalServices.getService(PackageManagerInternal.class)
.getPackageTargetSdkVersion(sbn.getPackageName());
+ mAm = ActivityManager.getService();
mOriginalFlags = sbn.getNotification().flags;
mRankingTimeMs = calculateRankingTimeMs(0L);
mCreationTimeMs = sbn.getPostTime();
mUpdateTimeMs = mCreationTimeMs;
+ mInterruptionTimeMs = mCreationTimeMs;
mContext = context;
stats = new NotificationUsageStats.SingleNotificationStats();
mChannel = channel;
@@ -523,6 +531,7 @@
pw.println(prefix + "mCreationTimeMs=" + mCreationTimeMs);
pw.println(prefix + "mVisibleSinceMs=" + mVisibleSinceMs);
pw.println(prefix + "mUpdateTimeMs=" + mUpdateTimeMs);
+ pw.println(prefix + "mInterruptionTimeMs=" + mInterruptionTimeMs);
pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
if (mPreChannelsNotification) {
pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
@@ -784,6 +793,10 @@
return mVisibleSinceMs == 0 ? 0 : (int) (now - mVisibleSinceMs);
}
+ public int getInterruptionMs(long now) {
+ return (int) (now - mInterruptionTimeMs);
+ }
+
/**
* Set the visibility of the notification.
*/
@@ -842,7 +855,7 @@
public void setSeen() {
mStats.setSeen();
if (mTextChanged) {
- mIsInterruptive = true;
+ setInterruptive(true);
}
}
@@ -938,6 +951,17 @@
public void setInterruptive(boolean interruptive) {
mIsInterruptive = interruptive;
+ final long now = System.currentTimeMillis();
+ mInterruptionTimeMs = interruptive ? now : mInterruptionTimeMs;
+
+ if (interruptive) {
+ MetricsLogger.action(getLogMaker()
+ .setCategory(MetricsEvent.NOTIFICATION_INTERRUPTION)
+ .setType(MetricsEvent.TYPE_OPEN)
+ .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_INTERRUPTION_MILLIS,
+ getInterruptionMs(now)));
+ MetricsLogger.histogram(mContext, "note_interruptive", getInterruptionMs(now));
+ }
}
public void setTextChanged(boolean textChanged) {
@@ -1036,16 +1060,17 @@
* Collect all {@link Uri} that should have permission granted to whoever
* will be rendering it.
*/
- private void calculateGrantableUris() {
+ protected void calculateGrantableUris() {
final Notification notification = getNotification();
notification.visitUris((uri) -> {
- visitGrantableUri(uri);
+ visitGrantableUri(uri, false);
});
if (notification.getChannelId() != null) {
NotificationChannel channel = getChannel();
if (channel != null) {
- visitGrantableUri(channel.getSound());
+ visitGrantableUri(channel.getSound(), (channel.getUserLockedFields()
+ & NotificationChannel.USER_LOCKED_SOUND) != 0);
}
}
}
@@ -1058,18 +1083,17 @@
* {@link #mGrantableUris}. Otherwise, this will either log or throw
* {@link SecurityException} depending on target SDK of enqueuing app.
*/
- private void visitGrantableUri(Uri uri) {
+ private void visitGrantableUri(Uri uri, boolean userOverriddenUri) {
if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
// We can't grant Uri permissions from system
final int sourceUid = sbn.getUid();
if (sourceUid == android.os.Process.SYSTEM_UID) return;
- final IActivityManager am = ActivityManager.getService();
final long ident = Binder.clearCallingIdentity();
try {
// This will throw SecurityException if caller can't grant
- am.checkGrantUriPermission(sourceUid, null,
+ mAm.checkGrantUriPermission(sourceUid, null,
ContentProvider.getUriWithoutUserId(uri),
Intent.FLAG_GRANT_READ_URI_PERMISSION,
ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
@@ -1081,10 +1105,12 @@
} catch (RemoteException ignored) {
// Ignored because we're in same process
} catch (SecurityException e) {
- if (mTargetSdkVersion >= Build.VERSION_CODES.P) {
- throw e;
- } else {
- Log.w(TAG, "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage());
+ if (!userOverriddenUri) {
+ if (mTargetSdkVersion >= Build.VERSION_CODES.P) {
+ throw e;
+ } else {
+ Log.w(TAG, "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage());
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -1112,7 +1138,9 @@
sbn.getNotification().isGroupSummary() ? 1 : 0)
.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
.addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
- .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now));
+ .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now))
+ .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_INTERRUPTION_MILLIS,
+ getInterruptionMs(now));
}
public LogMaker getLogMaker() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1b8c2cc..c2d6798 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13967,6 +13967,68 @@
return false;
}
+ @Override
+ public void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden) {
+ enforceSystemOrPhoneCaller("setSystemAppHiddenUntilInstalled");
+ synchronized (mPackages) {
+ final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ if (pkgSetting == null || !pkgSetting.isSystem()) {
+ return;
+ }
+ PackageParser.Package pkg = pkgSetting.pkg;
+ if (pkg != null && pkg.applicationInfo != null) {
+ pkg.applicationInfo.hiddenUntilInstalled = hidden;
+ }
+ final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(packageName);
+ if (disabledPs == null) {
+ return;
+ }
+ pkg = disabledPs.pkg;
+ if (pkg != null && pkg.applicationInfo != null) {
+ pkg.applicationInfo.hiddenUntilInstalled = hidden;
+ }
+ }
+ }
+
+ @Override
+ public boolean setSystemAppInstallState(String packageName, boolean installed, int userId) {
+ enforceSystemOrPhoneCaller("setSystemAppInstallState");
+ synchronized (mPackages) {
+ final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ // The target app should always be in system
+ if (pkgSetting == null || !pkgSetting.isSystem()) {
+ return false;
+ }
+ // Check if the install state is the same
+ if (pkgSetting.getInstalled(userId) == installed) {
+ return false;
+ }
+ }
+
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ if (installed) {
+ // install the app from uninstalled state
+ installExistingPackageAsUser(
+ packageName,
+ userId,
+ 0 /*installFlags*/,
+ PackageManager.INSTALL_REASON_DEVICE_SETUP);
+ return true;
+ }
+
+ // uninstall the app from installed state
+ deletePackageVersioned(
+ new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
+ new LegacyPackageDeleteObserver(null).getBinder(),
+ userId,
+ PackageManager.DELETE_SYSTEM_APP);
+ return true;
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
private void sendApplicationHiddenForUser(String packageName, PackageSetting pkgSetting,
int userId) {
final PackageRemovedInfo info = new PackageRemovedInfo(this);
@@ -14031,10 +14093,16 @@
@Override
public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
int installReason) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
- null);
- PackageSetting pkgSetting;
final int callingUid = Binder.getCallingUid();
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.INSTALL_EXISTING_PACKAGES)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Neither user " + callingUid + " nor current process has "
+ + android.Manifest.permission.INSTALL_PACKAGES + ".");
+ }
+ PackageSetting pkgSetting;
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */,
"installExistingPackage for user " + userId);
@@ -14178,7 +14246,7 @@
unactionedPackages.add(packageName);
continue;
}
- if (!canSuspendPackageForUserLocked(packageName, userId)) {
+ if (suspended && !canSuspendPackageForUserLocked(packageName, userId)) {
unactionedPackages.add(packageName);
continue;
}
@@ -14333,44 +14401,44 @@
@GuardedBy("mPackages")
private boolean canSuspendPackageForUserLocked(String packageName, int userId) {
if (isPackageDeviceAdmin(packageName, userId)) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": has an active device admin");
return false;
}
String activeLauncherPackageName = getActiveLauncherPackageName(userId);
if (packageName.equals(activeLauncherPackageName)) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": contains the active launcher");
return false;
}
if (packageName.equals(mRequiredInstallerPackage)) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": required for package installation");
return false;
}
if (packageName.equals(mRequiredUninstallerPackage)) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": required for package uninstallation");
return false;
}
if (packageName.equals(mRequiredVerifierPackage)) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": required for package verification");
return false;
}
if (packageName.equals(getDefaultDialerPackageName(userId))) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": is the default dialer");
return false;
}
if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
- Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName
+ Slog.w(TAG, "Cannot suspend package \"" + packageName
+ "\": protected package");
return false;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5177995..a7e3830 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4120,7 +4120,8 @@
continue;
}
final boolean shouldInstall = ps.isSystem() &&
- !ArrayUtils.contains(disallowedPackages, ps.name);
+ !ArrayUtils.contains(disallowedPackages, ps.name) &&
+ !ps.pkg.applicationInfo.hiddenUntilInstalled;
// Only system apps are initially installed.
ps.setInstalled(shouldInstall, userHandle);
if (!shouldInstall) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 599e5a5..b9c3048 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -132,6 +132,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -1573,6 +1574,24 @@
"Ephemeral apps can't use ShortcutManager");
}
+ private void verifyShortcutInfoPackage(String callerPackage, ShortcutInfo si) {
+ if (si == null) {
+ return;
+ }
+ if (!Objects.equals(callerPackage, si.getPackage())) {
+ android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, "");
+ throw new SecurityException("Shortcut package name mismatch");
+ }
+ }
+
+ private void verifyShortcutInfoPackages(
+ String callerPackage, List<ShortcutInfo> list) {
+ final int size = list.size();
+ for (int i = 0; i < size; i++) {
+ verifyShortcutInfoPackage(callerPackage, list.get(i));
+ }
+ }
+
// Overridden in unit tests to execute r synchronously.
void injectPostToHandler(Runnable r) {
mHandler.post(r);
@@ -1720,6 +1739,7 @@
verifyCaller(packageName, userId);
final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+ verifyShortcutInfoPackages(packageName, newShortcuts);
final int size = newShortcuts.size();
final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
@@ -1774,6 +1794,7 @@
verifyCaller(packageName, userId);
final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+ verifyShortcutInfoPackages(packageName, newShortcuts);
final int size = newShortcuts.size();
final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
@@ -1859,6 +1880,7 @@
verifyCaller(packageName, userId);
final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
+ verifyShortcutInfoPackages(packageName, newShortcuts);
final int size = newShortcuts.size();
final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
@@ -1921,6 +1943,7 @@
Preconditions.checkNotNull(shortcut);
Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
verifyCaller(packageName, userId);
+ verifyShortcutInfoPackage(packageName, shortcut);
final Intent ret;
synchronized (mLock) {
@@ -1942,6 +1965,7 @@
private boolean requestPinItem(String packageName, int userId, ShortcutInfo shortcut,
AppWidgetProviderInfo appWidget, Bundle extras, IntentSender resultIntent) {
verifyCaller(packageName, userId);
+ verifyShortcutInfoPackage(packageName, shortcut);
final boolean ret;
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index c9aa1ef..1ae59cb 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -833,11 +833,11 @@
getSystemPackage(textClassifierPackageName);
if (textClassifierPackage != null
&& doesPackageSupportRuntimePermissions(textClassifierPackage)) {
- grantRuntimePermissions(textClassifierPackage, PHONE_PERMISSIONS, true, userId);
- grantRuntimePermissions(textClassifierPackage, SMS_PERMISSIONS, true, userId);
- grantRuntimePermissions(textClassifierPackage, CALENDAR_PERMISSIONS, true, userId);
- grantRuntimePermissions(textClassifierPackage, LOCATION_PERMISSIONS, true, userId);
- grantRuntimePermissions(textClassifierPackage, CONTACTS_PERMISSIONS, true, userId);
+ grantRuntimePermissions(textClassifierPackage, PHONE_PERMISSIONS, false, userId);
+ grantRuntimePermissions(textClassifierPackage, SMS_PERMISSIONS, false, userId);
+ grantRuntimePermissions(textClassifierPackage, CALENDAR_PERMISSIONS, false, userId);
+ grantRuntimePermissions(textClassifierPackage, LOCATION_PERMISSIONS, false, userId);
+ grantRuntimePermissions(textClassifierPackage, CONTACTS_PERMISSIONS, false, userId);
}
}
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index a02ee22..e11b642 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -157,6 +157,8 @@
int FINISH_LAYOUT_REDO_WALLPAPER = 0x0004;
/** Need to recompute animations */
int FINISH_LAYOUT_REDO_ANIM = 0x0008;
+ /** Layer for the screen off animation */
+ int COLOR_FADE_LAYER = 0x40000001;
/**
* Register shortcuts for window manager to dispatch.
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 08d0ae9..fa6079c 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
@@ -1377,7 +1378,7 @@
setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
// We can now show all of the drawn windows!
- if (!mService.mOpeningApps.contains(this)) {
+ if (!mService.mOpeningApps.contains(this) && canShowWindows()) {
showAllWindowsLocked();
}
}
@@ -2270,4 +2271,21 @@
boolean isClosingOrEnteringPip() {
return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
}
+
+ /**
+ * @return Whether we are allowed to show non-starting windows at the moment. We disallow
+ * showing windows during transitions in case we have windows that have wide-color-gamut
+ * color mode set to avoid jank in the middle of the transition.
+ */
+ boolean canShowWindows() {
+ return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
+ }
+
+ /**
+ * @return true if we have a window that has a non-default color mode set; false otherwise.
+ */
+ private boolean hasNonDefaultColorWindow() {
+ return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
+ true /* topToBottom */);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index b0e6208..47dbccb 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -404,7 +404,7 @@
WindowStateAnimator winAnimator = w.mWinAnimator;
final AppWindowToken atoken = w.mAppToken;
if (winAnimator.mDrawState == READY_TO_SHOW) {
- if (atoken == null || atoken.allDrawn) {
+ if (atoken == null || atoken.canShowWindows()) {
if (w.performShowLocked()) {
pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
if (DEBUG_LAYOUT_REPEATS) {
@@ -1106,11 +1106,12 @@
}
}
+ forAllWindows(w -> {
+ w.forceSeamlesslyRotateIfAllowed(oldRotation, rotation);
+ }, true /* traverseTopToBottom */);
+
if (rotateSeamlessly) {
- forAllWindows(w -> {
- w.mWinAnimator.seamlesslyRotateWindow(getPendingTransaction(),
- oldRotation, rotation);
- }, true /* traverseTopToBottom */);
+ seamlesslyRotate(getPendingTransaction(), oldRotation, rotation);
}
mService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
@@ -3538,7 +3539,14 @@
// docked or freeform stack is visible...except for the home stack/task if the
// docked stack is minimized and it actually set something.
if (mHomeStack != null && mHomeStack.isVisible()
- && mDividerControllerLocked.isMinimizedDock()) {
+ && mDividerControllerLocked.isMinimizedDock()
+ // TODO(b/110159357): Work around to unblock the release for failing test
+ // ActivityManagerAppConfigurationTests#testSplitscreenPortraitAppOrientationRequests
+ // which shouldn't be failing since home stack shouldn't be visible. We need
+ // to dig deeper to see why it is failing. NOTE: Not failing on current
+ // master...
+ && !(mDividerControllerLocked.isHomeStackResizable()
+ && mHomeStack.matchParentBounds())) {
final int orientation = mHomeStack.getOrientation();
if (orientation != SCREEN_ORIENTATION_UNSET) {
return orientation;
@@ -3694,6 +3702,19 @@
}
@Override
+ SurfaceControl.Builder makeChildSurface(WindowContainer child) {
+ final SurfaceControl.Builder builder = super.makeChildSurface(child);
+ if (child instanceof WindowToken && ((WindowToken) child).mRoundedCornerOverlay) {
+ // To draw above the ColorFade layer during the screen off transition, the
+ // rounded corner overlays need to be at the root of the surface hierarchy.
+ // TODO: move the ColorLayer into the display overlay layer such that this is not
+ // necessary anymore.
+ builder.setParent(null);
+ }
+ return builder;
+ }
+
+ @Override
void assignChildLayers(SurfaceControl.Transaction t) {
assignChildLayers(t, null /* imeContainer */);
}
@@ -3709,6 +3730,10 @@
wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
continue;
}
+ if (wt.mRoundedCornerOverlay) {
+ wt.assignLayer(t, WindowManagerPolicy.COLOR_FADE_LAYER + 1);
+ continue;
+ }
wt.assignLayer(t, j);
wt.assignChildLayers(t);
diff --git a/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
new file mode 100644
index 0000000..3218e83
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ForcedSeamlessRotator.java
@@ -0,0 +1,77 @@
+/*
+ * 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.server.wm;
+
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.graphics.Matrix;
+import android.view.DisplayInfo;
+
+import com.android.server.wm.utils.CoordinateTransforms;
+
+/**
+ * Helper class for forced seamless rotation.
+ *
+ * Works by transforming the window token back into the old display rotation.
+ *
+ * Uses deferTransactionUntil instead of latching on the buffer size to allow for seamless 180
+ * degree rotations.
+ */
+public class ForcedSeamlessRotator {
+
+ private final Matrix mTransform = new Matrix();
+ private final float[] mFloat9 = new float[9];
+
+ public ForcedSeamlessRotator(int oldRotation, int newRotation, DisplayInfo info) {
+ final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
+ final int h = flipped ? info.logicalWidth : info.logicalHeight;
+ final int w = flipped ? info.logicalHeight : info.logicalWidth;
+
+ final Matrix tmp = new Matrix();
+ CoordinateTransforms.transformLogicalToPhysicalCoordinates(oldRotation, w, h, mTransform);
+ CoordinateTransforms.transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
+ mTransform.postConcat(tmp);
+ }
+
+ /**
+ * Applies a transform to the window token's surface that undoes the effect of the global
+ * display rotation.
+ */
+ public void unrotate(WindowToken token) {
+ token.getPendingTransaction().setMatrix(token.getSurfaceControl(), mTransform, mFloat9);
+ }
+
+ /**
+ * Removes the transform to the window token's surface that undoes the effect of the global
+ * display rotation.
+ *
+ * Removing the transform and the result of the WindowState's layout are both tied to the
+ * WindowState's next frame, such that they apply at the same time the client draws the
+ * window in the new orientation.
+ */
+ public void finish(WindowToken token, WindowState win) {
+ mTransform.reset();
+ token.getPendingTransaction().setMatrix(token.mSurfaceControl, mTransform, mFloat9);
+ token.getPendingTransaction().deferTransactionUntil(token.mSurfaceControl,
+ win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+ win.getFrameNumber());
+ win.getPendingTransaction().deferTransactionUntil(win.mSurfaceControl,
+ win.mWinAnimator.mSurfaceController.mSurfaceControl.getHandle(),
+ win.getFrameNumber());
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 19c5a3d..8fe7063 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -736,6 +736,20 @@
}
/**
+ * Seamlessly rotates the container, by recomputing the location in the new
+ * rotation, and rotating buffers until they are updated for the new rotation.
+ *
+ * @param t the transaction to perform the seamless rotation in
+ * @param oldRotation the rotation we are rotating from
+ * @param newRotation the rotation we are rotating to
+ */
+ void seamlesslyRotate(Transaction t, int oldRotation, int newRotation) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ mChildren.get(i).seamlesslyRotate(t, oldRotation, newRotation);
+ }
+ }
+
+ /**
* Returns true if this container is opaque and fills all the space made available by its parent
* container.
*
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7a2c28b..ef74586 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1883,6 +1883,12 @@
}
win.setFrameNumber(frameNumber);
+
+ if (win.mPendingForcedSeamlessRotate != null && !mWaitingForConfig) {
+ win.mPendingForcedSeamlessRotate.finish(win.mToken, win);
+ win.mPendingForcedSeamlessRotate = null;
+ }
+
int attrChanges = 0;
int flagChanges = 0;
if (attrs != null) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index bee70a0..a7f432d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -150,6 +150,8 @@
import static com.android.server.wm.WindowStateProto.VISIBLE_FRAME;
import static com.android.server.wm.WindowStateProto.VISIBLE_INSETS;
import static com.android.server.wm.WindowStateProto.WINDOW_CONTAINER;
+import static com.android.server.wm.utils.CoordinateTransforms.transformRect;
+import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
import android.annotation.CallSuper;
import android.app.AppOpsManager;
@@ -278,6 +280,13 @@
private boolean mDragResizing;
private boolean mDragResizingChangeReported = true;
private int mResizeMode;
+ /**
+ * Special mode that is intended only for the rounded corner overlay: during rotation
+ * transition, we un-rotate the window token such that the window appears as it did before the
+ * rotation.
+ */
+ final boolean mForceSeamlesslyRotate;
+ ForcedSeamlessRotator mPendingForcedSeamlessRotate;
private RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
@@ -667,6 +676,14 @@
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
+ void forceSeamlesslyRotateIfAllowed(int oldRotation, int rotation) {
+ if (mForceSeamlesslyRotate) {
+ mPendingForcedSeamlessRotate = new ForcedSeamlessRotator(
+ oldRotation, rotation, getDisplayInfo());
+ mPendingForcedSeamlessRotate.unrotate(this.mToken);
+ }
+ }
+
interface PowerManagerWrapper {
void wakeUp(long time, String reason);
@@ -713,6 +730,7 @@
mSeq = seq;
mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
mPowerManagerWrapper = powerManagerWrapper;
+ mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
if (localLOGV) Slog.v(
TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -1811,7 +1829,8 @@
&& (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
&& !isDragResizing() && !adjustedForMinimizedDockOrIme
&& getWindowConfiguration().hasMovementAnimations()
- && !mWinAnimator.mLastHidden) {
+ && !mWinAnimator.mLastHidden
+ && !mSeamlesslyRotated) {
startMoveAnimation(left, top);
}
@@ -4697,7 +4716,10 @@
transformFrameToSurfacePosition(mFrame.left, mFrame.top, mSurfacePosition);
- if (!mSurfaceAnimator.hasLeash() && !mLastSurfacePosition.equals(mSurfacePosition)) {
+ // Freeze position while we're unrotated, so the surface remains at the position it was
+ // prior to the rotation.
+ if (!mSurfaceAnimator.hasLeash() && mPendingForcedSeamlessRotate == null &&
+ !mLastSurfacePosition.equals(mSurfacePosition)) {
t.setPosition(mSurfaceControl, mSurfacePosition.x, mSurfacePosition.y);
mLastSurfacePosition.set(mSurfacePosition.x, mSurfacePosition.y);
if (surfaceInsetsChanging() && mWinAnimator.hasSurface()) {
@@ -4850,6 +4872,31 @@
mFrameNumber = frameNumber;
}
+ @Override
+ void seamlesslyRotate(Transaction t, int oldRotation, int newRotation) {
+ // Invisible windows, the wallpaper, and force seamlessly rotated windows do not participate
+ // in the regular seamless rotation animation.
+ if (!isVisibleNow() || mIsWallpaper || mForceSeamlesslyRotate) {
+ return;
+ }
+ final Matrix transform = mTmpMatrix;
+
+ mService.markForSeamlessRotation(this, true);
+
+ // We rotated the screen, but have not performed a new layout pass yet. In the mean time,
+ // we recompute the coordinates of mFrame in the new orientation, so the surface can be
+ // properly placed.
+ transformToRotation(oldRotation, newRotation, getDisplayInfo(), transform);
+ transformRect(transform, mFrame, null /* tmpRectF */);
+
+ updateSurfacePosition(t);
+ mWinAnimator.seamlesslyRotate(t, oldRotation, newRotation);
+
+ // Dispatch to children only after mFrame has been updated, as it's needed in the
+ // child's updateSurfacePosition.
+ super.seamlesslyRotate(t, oldRotation, newRotation);
+ }
+
private final class MoveAnimationSpec implements AnimationSpec {
private final long mDuration;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3eef125..a05e04d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -41,18 +41,18 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
import static com.android.server.wm.WindowStateAnimatorProto.LAST_CLIP_RECT;
import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
import android.os.Debug;
import android.os.Trace;
@@ -366,7 +366,8 @@
mDrawState = READY_TO_SHOW;
boolean result = false;
final AppWindowToken atoken = mWin.mAppToken;
- if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
+ if (atoken == null || atoken.canShowWindows()
+ || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = mWin.performShowLocked();
}
return result;
@@ -685,8 +686,11 @@
final int displayId = mWin.getDisplayId();
final ScreenRotationAnimation screenRotationAnimation =
mAnimator.getScreenRotationAnimationLocked(displayId);
- final boolean screenAnimation =
- screenRotationAnimation != null && screenRotationAnimation.isAnimating();
+ final boolean windowParticipatesInScreenRotationAnimation =
+ !mWin.mForceSeamlesslyRotate;
+ final boolean screenAnimation = screenRotationAnimation != null
+ && screenRotationAnimation.isAnimating()
+ && windowParticipatesInScreenRotationAnimation;
if (screenAnimation) {
// cache often used attributes locally
@@ -798,6 +802,13 @@
return false;
}
+ // During forced seamless rotation, the surface bounds get updated with the crop in the
+ // new rotation, which is not compatible with showing the surface in the old rotation.
+ // To work around that we disable cropping for such windows, as it is not necessary anyways.
+ if (w.mForceSeamlesslyRotate) {
+ return false;
+ }
+
// If we're animating, the wallpaper should only
// be updated at the end of the animation.
if (w.mAttrs.type == TYPE_WALLPAPER) {
@@ -1492,40 +1503,14 @@
}
}
- void seamlesslyRotateWindow(SurfaceControl.Transaction t,
- int oldRotation, int newRotation) {
+ void seamlesslyRotate(SurfaceControl.Transaction t, int oldRotation, int newRotation) {
final WindowState w = mWin;
- if (!w.isVisibleNow() || w.mIsWallpaper) {
- return;
- }
- final Rect cropRect = mService.mTmpRect;
- final Rect displayRect = mService.mTmpRect2;
- final RectF frameRect = mService.mTmpRectF;
+ // We rotated the screen, but have not received a new buffer with the correct size yet. In
+ // the mean time, we rotate the buffer we have to the new orientation.
final Matrix transform = mService.mTmpTransform;
-
- final float x = w.mFrame.left;
- final float y = w.mFrame.top;
- final float width = w.mFrame.width();
- final float height = w.mFrame.height();
-
- mService.getDefaultDisplayContentLocked().getBounds(displayRect);
- final float displayWidth = displayRect.width();
- final float displayHeight = displayRect.height();
-
- // Compute a transform matrix to undo the coordinate space transformation,
- // and present the window at the same physical position it previously occupied.
- final int deltaRotation = DisplayContent.deltaRotation(newRotation, oldRotation);
- DisplayContent.createRotationMatrix(deltaRotation, x, y, displayWidth, displayHeight,
+ transformToRotation(oldRotation, newRotation, w.mFrame.width(), w.mFrame.height(),
transform);
-
- // We just need to apply a rotation matrix to the window. For example
- // if we have a portrait window and rotate to landscape, the window is still portrait
- // and now extends off the bottom of the screen (and only halfway across). Essentially we
- // apply a transform to display the current buffer at it's old position
- // (in the new coordinate space). We then freeze layer updates until the resize
- // occurs, at which point we undo, them.
- mService.markForSeamlessRotation(w, true);
transform.getValues(mService.mTmpFloats);
float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index b97460a..e411c0a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -270,12 +270,6 @@
dc.reParentWindowToken(this);
mDisplayContent = dc;
- // The rounded corner overlay should not be rotated. We ensure that by moving it outside
- // the windowing layer.
- if (mRoundedCornerOverlay) {
- mDisplayContent.reparentToOverlay(mPendingTransaction, mSurfaceControl);
- }
-
// TODO(b/36740756): One day this should perhaps be hooked
// up with goodToGo, so we don't move a window
// to another display before the window behind
diff --git a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java
index 09d7b5d..a2f37a5 100644
--- a/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java
+++ b/services/core/java/com/android/server/wm/utils/CoordinateTransforms.java
@@ -22,7 +22,11 @@
import static android.view.Surface.ROTATION_90;
import android.annotation.Dimension;
+import android.annotation.Nullable;
import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.view.DisplayInfo;
import android.view.Surface.Rotation;
public class CoordinateTransforms {
@@ -59,4 +63,93 @@
throw new IllegalArgumentException("Unknown rotation: " + rotation);
}
}
+
+ /**
+ * Sets a matrix such that given a rotation, it transforms that rotation's logical coordinates
+ * to physical coordinates.
+ *
+ * @param rotation the rotation to which the matrix should transform
+ * @param out the matrix to be set
+ */
+ public static void transformLogicalToPhysicalCoordinates(@Rotation int rotation,
+ @Dimension int physicalWidth, @Dimension int physicalHeight, Matrix out) {
+ switch (rotation) {
+ case ROTATION_0:
+ out.reset();
+ break;
+ case ROTATION_90:
+ out.setRotate(90);
+ out.preTranslate(0, -physicalWidth);
+ break;
+ case ROTATION_180:
+ out.setRotate(180);
+ out.preTranslate(-physicalWidth, -physicalHeight);
+ break;
+ case ROTATION_270:
+ out.setRotate(270);
+ out.preTranslate(-physicalHeight, 0);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown rotation: " + rotation);
+ }
+ }
+
+ /**
+ * Sets a matrix such that given a two rotations, that it transforms coordinates given in the
+ * old rotation to coordinates that refer to the same physical location in the new rotation.
+ *
+ * @param oldRotation the rotation to transform from
+ * @param newRotation the rotation to transform to
+ * @param info the display info
+ * @param out a matrix that will be set to the transform
+ */
+ public static void transformToRotation(@Rotation int oldRotation,
+ @Rotation int newRotation, DisplayInfo info, Matrix out) {
+ final boolean flipped = info.rotation == ROTATION_90 || info.rotation == ROTATION_270;
+ final int h = flipped ? info.logicalWidth : info.logicalHeight;
+ final int w = flipped ? info.logicalHeight : info.logicalWidth;
+
+ final Matrix tmp = new Matrix();
+ transformLogicalToPhysicalCoordinates(oldRotation, w, h, out);
+ transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
+ out.postConcat(tmp);
+ }
+
+ /**
+ * Sets a matrix such that given a two rotations, that it transforms coordinates given in the
+ * old rotation to coordinates that refer to the same physical location in the new rotation.
+ *
+ * @param oldRotation the rotation to transform from
+ * @param newRotation the rotation to transform to
+ * @param newWidth the width of the area to transform, in the new rotation
+ * @param newHeight the height of the area to transform, in the new rotation
+ * @param out a matrix that will be set to the transform
+ */
+ public static void transformToRotation(@Rotation int oldRotation,
+ @Rotation int newRotation, int newWidth, int newHeight, Matrix out) {
+ final boolean flipped = newRotation == ROTATION_90 || newRotation == ROTATION_270;
+ final int h = flipped ? newWidth : newHeight;
+ final int w = flipped ? newHeight : newWidth;
+
+ final Matrix tmp = new Matrix();
+ transformLogicalToPhysicalCoordinates(oldRotation, w, h, out);
+ transformPhysicalToLogicalCoordinates(newRotation, w, h, tmp);
+ out.postConcat(tmp);
+ }
+
+ /**
+ * Transforms a rect using a transformation matrix
+ *
+ * @param transform the transformation to apply to the rect
+ * @param inOutRect the rect to transform
+ * @param tmp a temporary value, if null the function will allocate its own.
+ */
+ public static void transformRect(Matrix transform, Rect inOutRect, @Nullable RectF tmp) {
+ if (tmp == null) {
+ tmp = new RectF();
+ }
+ tmp.set(inOutRect);
+ transform.mapRect(tmp);
+ inOutRect.set((int) tmp.left, (int) tmp.top, (int) tmp.right, (int) tmp.bottom);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 85e846d..9f113ad 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import android.graphics.Rect;
+import android.view.SurfaceControl;
import android.view.WindowManager;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,6 +31,8 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
+import static android.view.Surface.ROTATION_0;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -48,8 +52,10 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -349,6 +355,32 @@
assertThat(app.getDisplayId(), is(mDisplayContent.getDisplayId()));
}
+ @Test
+ public void testSeamlesslyRotateWindow() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+
+ app.mHasSurface = true;
+ app.mSurfaceControl = mock(SurfaceControl.class);
+ app.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class);
+ try {
+ app.mFrame.set(10, 20, 60, 80);
+
+ app.seamlesslyRotate(t, ROTATION_0, ROTATION_90);
+
+ assertTrue(app.mSeamlesslyRotated);
+ assertEquals(new Rect(20, mDisplayInfo.logicalWidth - 60,
+ 80, mDisplayInfo.logicalWidth - 10), app.mFrame);
+
+ verify(t).setPosition(app.mSurfaceControl, app.mFrame.left, app.mFrame.top);
+ verify(app.mWinAnimator.mSurfaceController).setPosition(t, 0, 50, false);
+ verify(app.mWinAnimator.mSurfaceController).setMatrix(t, 0, -1, 1, 0, false);
+ } finally {
+ app.mSurfaceControl = null;
+ app.mHasSurface = false;
+ }
+ }
+
private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
reset(mPowerManagerWrapper);
final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
index 40a10e0..f82b012 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/CoordinateTransformsTest.java
@@ -21,14 +21,19 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static com.android.server.wm.utils.CoordinateTransforms.transformLogicalToPhysicalCoordinates;
import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
+
+import static com.android.server.wm.utils.CoordinateTransforms.transformToRotation;
+
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
+import android.view.DisplayInfo;
import org.junit.Before;
import org.junit.Rule;
@@ -41,6 +46,7 @@
private static final int H = 400;
private final Matrix mMatrix = new Matrix();
+ private final Matrix mMatrix2 = new Matrix();
@Rule
public final ErrorCollector mErrorCollector = new ErrorCollector();
@@ -48,39 +54,140 @@
@Before
public void setUp() throws Exception {
mMatrix.setTranslate(0xdeadbeef, 0xdeadbeef);
+ mMatrix2.setTranslate(0xbeefdead, 0xbeefdead);
}
@Test
- public void transformPhysicalToLogicalCoordinates_rot0() throws Exception {
+ public void transformPhysicalToLogicalCoordinates_rot0() {
transformPhysicalToLogicalCoordinates(ROTATION_0, W, H, mMatrix);
assertThat(mMatrix, is(Matrix.IDENTITY_MATRIX));
}
@Test
- public void transformPhysicalToLogicalCoordinates_rot90() throws Exception {
+ public void transformPhysicalToLogicalCoordinates_rot90() {
transformPhysicalToLogicalCoordinates(ROTATION_90, W, H, mMatrix);
- checkDevicePoint(0, 0).mapsToLogicalPoint(0, W);
- checkDevicePoint(W, H).mapsToLogicalPoint(H, 0);
+ checkPoint(0, 0).transformsTo(0, W);
+ checkPoint(W, H).transformsTo(H, 0);
}
@Test
- public void transformPhysicalToLogicalCoordinates_rot180() throws Exception {
+ public void transformPhysicalToLogicalCoordinates_rot180() {
transformPhysicalToLogicalCoordinates(ROTATION_180, W, H, mMatrix);
- checkDevicePoint(0, 0).mapsToLogicalPoint(W, H);
- checkDevicePoint(W, H).mapsToLogicalPoint(0, 0);
+ checkPoint(0, 0).transformsTo(W, H);
+ checkPoint(W, H).transformsTo(0, 0);
}
@Test
- public void transformPhysicalToLogicalCoordinates_rot270() throws Exception {
+ public void transformPhysicalToLogicalCoordinates_rot270() {
transformPhysicalToLogicalCoordinates(ROTATION_270, W, H, mMatrix);
- checkDevicePoint(0, 0).mapsToLogicalPoint(H, 0);
- checkDevicePoint(W, H).mapsToLogicalPoint(0, W);
+ checkPoint(0, 0).transformsTo(H, 0);
+ checkPoint(W, H).transformsTo(0, W);
}
- private DevicePointAssertable checkDevicePoint(int x, int y) {
+ @Test
+ public void transformLogicalToPhysicalCoordinates_rot0() {
+ transformLogicalToPhysicalCoordinates(ROTATION_0, W, H, mMatrix);
+ assertThat(mMatrix, is(Matrix.IDENTITY_MATRIX));
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinates_rot90() {
+ transformLogicalToPhysicalCoordinates(ROTATION_90, W, H, mMatrix);
+
+ checkPoint(0, W).transformsTo(0, 0);
+ checkPoint(H, 0).transformsTo(W, H);
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinates_rot180() {
+ transformLogicalToPhysicalCoordinates(ROTATION_180, W, H, mMatrix);
+
+ checkPoint(W, H).transformsTo(0, 0);
+ checkPoint(0, 0).transformsTo(W, H);
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinates_rot270() {
+ transformLogicalToPhysicalCoordinates(ROTATION_270, W, H, mMatrix);
+
+ checkPoint(H, 0).transformsTo(0, 0);
+ checkPoint(0, W).transformsTo(W, H);
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinatesIsInverse_rot0() {
+ transformLogicalToPhysicalCoordinates(ROTATION_0, W, H, mMatrix);
+ transformPhysicalToLogicalCoordinates(ROTATION_0, W, H, mMatrix2);
+
+ assertMatricesAreInverses(mMatrix, mMatrix2);
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinatesIsInverse_rot90() {
+ transformLogicalToPhysicalCoordinates(ROTATION_90, W, H, mMatrix);
+ transformPhysicalToLogicalCoordinates(ROTATION_90, W, H, mMatrix2);
+
+ assertMatricesAreInverses(mMatrix, mMatrix2);
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinatesIsInverse_rot180() {
+ transformLogicalToPhysicalCoordinates(ROTATION_180, W, H, mMatrix);
+ transformPhysicalToLogicalCoordinates(ROTATION_180, W, H, mMatrix2);
+
+ assertMatricesAreInverses(mMatrix, mMatrix2);
+ }
+
+ @Test
+ public void transformLogicalToPhysicalCoordinatesIsInverse_rot270() {
+ transformLogicalToPhysicalCoordinates(ROTATION_270, W, H, mMatrix);
+ transformPhysicalToLogicalCoordinates(ROTATION_270, W, H, mMatrix2);
+
+ assertMatricesAreInverses(mMatrix, mMatrix2);
+ }
+
+ @Test
+ public void transformBetweenRotations_rot180_rot270() {
+ // W,H are flipped, because they need to be given in the new orientation, i.e. ROT_270.
+ transformToRotation(ROTATION_180, ROTATION_270, H, W, mMatrix);
+
+ checkPoint(0, 0).transformsTo(0, W);
+ checkPoint(W, H).transformsTo(H, 0);
+ }
+
+ @Test
+ public void transformBetweenRotations_rot90_rot0() {
+ transformToRotation(ROTATION_180, ROTATION_270, W, H, mMatrix);
+
+ checkPoint(0, 0).transformsTo(0, H);
+ // H,W is bottom right in ROT_90
+ checkPoint(H, W).transformsTo(W, 0);
+ }
+
+ @Test
+ public void transformBetweenRotations_displayInfo() {
+ final DisplayInfo di = new DisplayInfo();
+ di.rotation = ROTATION_90;
+ di.logicalWidth = H; // dimensions are flipped in ROT_90
+ di.logicalHeight = W;
+ transformToRotation(ROTATION_180, ROTATION_270, di, mMatrix);
+
+ // W,H are flipped, because they need to be given in the new orientation, i.e. ROT_270.
+ transformToRotation(ROTATION_180, ROTATION_270, H, W, mMatrix2);
+
+ assertEquals(mMatrix2, mMatrix);
+ }
+
+ private void assertMatricesAreInverses(Matrix matrix, Matrix matrix2) {
+ final Matrix concat = new Matrix();
+ concat.setConcat(matrix, matrix2);
+ assertTrue("expected identity, but was: " + concat, concat.isIdentity());
+ }
+
+ private TransformPointAssertable checkPoint(int x, int y) {
final Point devicePoint = new Point(x, y);
final float[] fs = new float[] {x, y};
mMatrix.mapPoints(fs);
@@ -92,7 +199,7 @@
};
}
- public interface DevicePointAssertable {
- void mapsToLogicalPoint(int x, int y);
+ public interface TransformPointAssertable {
+ void transformsTo(int x, int y);
}
}
\ No newline at end of file
diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
index 345c1d7..eec852b 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
@@ -31,6 +31,7 @@
protected static final String PKG_N_MR1 = "com.example.n_mr1";
protected static final String PKG_O = "com.example.o";
+ protected static final String PKG_P = "com.example.p";
@Rule
public final TestableContext mContext =
@@ -57,6 +58,8 @@
return Build.VERSION_CODES.N_MR1;
case PKG_O:
return Build.VERSION_CODES.O;
+ case PKG_P:
+ return Build.VERSION_CODES.P;
default:
return Build.VERSION_CODES.CUR_DEVELOPMENT;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index a408438..cdbf3c6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2942,6 +2942,20 @@
}
@Test
+ public void testVisualDifference_summaryNewNotification() {
+ Notification.Builder nb2 = new Notification.Builder(mContext, "")
+ .setGroup("bananas")
+ .setFlag(Notification.FLAG_GROUP_SUMMARY, true)
+ .setContentText("bar");
+ StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
+ nb2.build(), new UserHandle(mUid), null, 0);
+ NotificationRecord r2 =
+ new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
+
+ assertFalse(mService.isVisuallyInterruptive(null, r2));
+ }
+
+ @Test
public void testHideAndUnhideNotificationsOnSuspendedPackageBroadcast() {
// post 2 notification from this package
final NotificationRecord notif1 = generateNotificationRecord(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index c1868e7..e286991 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -29,9 +29,17 @@
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
+import android.app.IActivityManager;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationChannel;
@@ -44,12 +52,14 @@
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.Bundle;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.notification.Adjustment;
import android.service.notification.StatusBarNotification;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Slog;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.UiServiceTestCase;
@@ -58,7 +68,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.Objects;
@@ -67,7 +76,7 @@
@RunWith(AndroidJUnit4.class)
public class NotificationRecordTest extends UiServiceTestCase {
- private final Context mMockContext = Mockito.mock(Context.class);
+ private final Context mMockContext = mock(Context.class);
@Mock PackageManager mPm;
private final String pkg = PKG_N_MR1;
@@ -93,8 +102,6 @@
new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
NotificationManager.IMPORTANCE_UNSPECIFIED);
private android.os.UserHandle mUser = UserHandle.of(ActivityManager.getCurrentUser());
- final ApplicationInfo legacy = new ApplicationInfo();
- final ApplicationInfo upgrade = new ApplicationInfo();
private static final long[] CUSTOM_VIBRATION = new long[] {
300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
@@ -115,12 +122,12 @@
when(mMockContext.getResources()).thenReturn(getContext().getResources());
when(mMockContext.getPackageManager()).thenReturn(mPm);
+ when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
}
- private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
+ private StatusBarNotification getNotification(String pkg, boolean noisy, boolean defaultSound,
boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights,
String group) {
- when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
final Builder builder = new Builder(mMockContext)
.setContentTitle("foo")
.setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -159,22 +166,14 @@
}
builder.setDefaults(defaults);
- if (!preO) {
- builder.setChannelId(channelId);
- }
+ builder.setChannelId(channelId);
if(group != null) {
builder.setGroup(group);
}
Notification n = builder.build();
- if (preO) {
- return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n,
- mUser, null, uid);
- } else {
- return new StatusBarNotification(pkg2, pkg2, id2, tag2, uid2, uid2, n,
- mUser, null, uid2);
- }
+ return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n, mUser, null, uid);
}
//
@@ -185,7 +184,7 @@
public void testSound_default_preUpgradeUsesNotification() throws Exception {
defaultChannel.setSound(null, null);
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -198,7 +197,7 @@
public void testSound_custom_preUpgradeUsesNotification() throws Exception {
defaultChannel.setSound(null, null);
// pre upgrade, custom sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -212,7 +211,7 @@
defaultChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -224,7 +223,7 @@
@Test
public void testSound_noSound_preUpgrade() throws Exception {
// pre upgrade, default sound.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -237,7 +236,7 @@
public void testSound_default_upgradeUsesChannel() throws Exception {
channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
// post upgrade, default sound.
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -250,7 +249,7 @@
public void testVibration_default_preUpgradeUsesNotification() throws Exception {
defaultChannel.enableVibration(false);
// pre upgrade, default vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, false /* noisy */,
false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -262,7 +261,7 @@
public void testVibration_custom_preUpgradeUsesNotification() throws Exception {
defaultChannel.enableVibration(false);
// pre upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -275,7 +274,7 @@
defaultChannel.enableVibration(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
// pre upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -287,7 +286,7 @@
public void testVibration_custom_upgradeUsesChannel() throws Exception {
channel.enableVibration(true);
// post upgrade, custom vibration.
- StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, false /* noisy */,
false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -297,7 +296,7 @@
@Test
public void testImportance_preUpgrade() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
@@ -308,7 +307,7 @@
public void testImportance_locked_preUpgrade() throws Exception {
defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -320,7 +319,7 @@
public void testImportance_locked_unspecified_preUpgrade() throws Exception {
defaultChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
defaultChannel.lockFields(USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
@@ -330,7 +329,7 @@
@Test
public void testImportance_upgrade() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -339,7 +338,7 @@
@Test
public void testLights_preUpgrade_noLight() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
@@ -349,7 +348,7 @@
@Test
public void testLights_preUpgrade() throws Exception {
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
@@ -360,7 +359,7 @@
public void testLights_locked_preUpgrade() throws Exception {
defaultChannel.enableLights(true);
defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
- StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /* defaultLights */, null /* group */);
@@ -379,7 +378,7 @@
NotificationRecord.Light expected = new NotificationRecord.Light(
defaultLightColor, defaultLightOn, defaultLightOff);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, true /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -395,7 +394,7 @@
NotificationRecord.Light expected = new NotificationRecord.Light(
Color.BLUE, defaultLightOn, defaultLightOff);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
true /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -404,7 +403,7 @@
@Test
public void testLights_upgrade_noLight() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
@@ -413,7 +412,7 @@
@Test
public void testLogmakerShortChannel() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -426,7 +425,7 @@
@Test
public void testLogmakerLongChannel() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channelLongId);
@@ -437,7 +436,7 @@
@Test
public void testLogmakerNoGroup() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /*defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -446,7 +445,7 @@
@Test
public void testLogmakerShortGroup() throws Exception {
- StatusBarNotification sbn = getNotification(false /*reO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -456,7 +455,7 @@
@Test
public void testLogmakerLongGroup() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupIdLong /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -467,7 +466,7 @@
@Test
public void testLogmakerOverrideGroup() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -483,7 +482,7 @@
@Test
public void testNotificationStats() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -526,7 +525,7 @@
@Test
public void testUserSentiment() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -544,7 +543,7 @@
@Test
public void testUserSentiment_appImportanceUpdatesSentiment() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -556,7 +555,7 @@
@Test
public void testUserSentiment_appImportanceBlocksNegativeSentimentUpdate() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -573,7 +572,7 @@
@Test
public void testUserSentiment_userLocked() throws Exception {
channel.lockFields(USER_LOCKED_IMPORTANCE);
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -591,7 +590,7 @@
@Test
public void testAppImportance_returnsCorrectly() throws Exception {
- StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -605,7 +604,7 @@
@Test
public void testIsInterruptive_textChanged_notSeen() {
- StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -618,7 +617,7 @@
@Test
public void testIsInterruptive_textChanged_seen() {
- StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -632,7 +631,7 @@
@Test
public void testIsInterruptive_textNotChanged_seen() {
- StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ StatusBarNotification sbn = getNotification(PKG_O, false /* noisy */,
false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, null /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
@@ -643,4 +642,59 @@
record.setSeen();
assertEquals(false, record.isInterruptive());
}
+
+ @Test
+ public void testCalculateGrantableUris_PappProvided() throws RemoteException {
+ IActivityManager am = mock(IActivityManager.class);
+ when(am.checkGrantUriPermission(anyInt(), eq(null), any(),
+ anyInt(), anyInt())).thenThrow(new SecurityException());
+
+ Notification n = mock(Notification.class);
+ when(n.getChannelId()).thenReturn(channel.getId());
+ StatusBarNotification sbn =
+ new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ record.mAm = am;
+
+ try {
+ record.calculateGrantableUris();
+ fail("App provided uri for p targeting app should throw exception");
+ } catch (SecurityException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testCalculateGrantableUris_PuserOverridden() throws RemoteException {
+ IActivityManager am = mock(IActivityManager.class);
+ when(am.checkGrantUriPermission(anyInt(), eq(null), any(),
+ anyInt(), anyInt())).thenThrow(SecurityException.class);
+
+ channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
+ Notification n = mock(Notification.class);
+ when(n.getChannelId()).thenReturn(channel.getId());
+ StatusBarNotification sbn =
+ new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ record.mAm = am;
+
+ record.calculateGrantableUris();
+ }
+
+ @Test
+ public void testCalculateGrantableUris_prePappProvided() throws RemoteException {
+ IActivityManager am = mock(IActivityManager.class);
+ when(am.checkGrantUriPermission(anyInt(), eq(null), any(),
+ anyInt(), anyInt())).thenThrow(SecurityException.class);
+
+ Notification n = mock(Notification.class);
+ when(n.getChannelId()).thenReturn(channel.getId());
+ StatusBarNotification sbn =
+ new StatusBarNotification(PKG_O, PKG_O, id1, tag1, uid, uid, n, mUser, null, uid);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+ record.mAm = am;
+
+ record.calculateGrantableUris();
+ // should not throw
+ }
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 3bf951d..3e97c8f 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -45,6 +45,7 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.nio.channels.Channels;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -861,8 +862,11 @@
public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) {
mFdFromInCall = fromInCall;
mFdToInCall = toInCall;
+
+ // Wrap the FileInputStream in a Channel so that it's interruptible.
mPipeFromInCall = new InputStreamReader(
- new FileInputStream(fromInCall.getFileDescriptor()));
+ Channels.newInputStream(Channels.newChannel(
+ new FileInputStream(fromInCall.getFileDescriptor()))));
mPipeToInCall = new OutputStreamWriter(
new FileOutputStream(toInCall.getFileDescriptor()));
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c39b743..3ba699d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -335,11 +335,18 @@
* <p>
* The {@link #EXTRA_STATE} extra indicates the new call state.
* If a receiving app has {@link android.Manifest.permission#READ_CALL_LOG} permission, a second
- * extra {@link #EXTRA_INCOMING_NUMBER} provides the phone number for incoming and outoing calls
- * as a String. Note: If the receiving app has
+ * extra {@link #EXTRA_INCOMING_NUMBER} provides the phone number for incoming and outgoing
+ * calls as a String.
+ * <p>
+ * If the receiving app has
* {@link android.Manifest.permission#READ_CALL_LOG} and
* {@link android.Manifest.permission#READ_PHONE_STATE} permission, it will receive the
- * broadcast twice; one with the phone number and another without it.
+ * broadcast twice; one with the {@link #EXTRA_INCOMING_NUMBER} populated with the phone number,
+ * and another with it blank. Due to the nature of broadcasts, you cannot assume the order
+ * in which these broadcasts will arrive, however you are guaranteed to receive two in this
+ * case. Apps which are interested in the {@link #EXTRA_INCOMING_NUMBER} can ignore the
+ * broadcasts where {@link #EXTRA_INCOMING_NUMBER} is not present in the extras (e.g. where
+ * {@link Intent#hasExtra(String)} returns {@code false}).
* <p class="note">
* This was a {@link android.content.Context#sendStickyBroadcast sticky}
* broadcast in version 1.0, but it is no longer sticky.
@@ -488,10 +495,19 @@
public static final String EXTRA_STATE_OFFHOOK = PhoneConstants.State.OFFHOOK.toString();
/**
- * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
- * for a String containing the incoming phone number.
- * Only valid when the new call state is RINGING.
- *
+ * Extra key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
+ * for a String containing the incoming or outgoing phone number.
+ * <p>
+ * This extra is only populated for receivers of the {@link #ACTION_PHONE_STATE_CHANGED}
+ * broadcast which have been granted the {@link android.Manifest.permission#READ_CALL_LOG} and
+ * {@link android.Manifest.permission#READ_PHONE_STATE} permissions.
+ * <p>
+ * For incoming calls, the phone number is only guaranteed to be populated when the
+ * {@link #EXTRA_STATE} changes from {@link #EXTRA_STATE_IDLE} to {@link #EXTRA_STATE_RINGING}.
+ * If the incoming caller is from an unknown number, the extra will be populated with an empty
+ * string.
+ * For outgoing calls, the phone number is only guaranteed to be populated when the
+ * {@link #EXTRA_STATE} changes from {@link #EXTRA_STATE_IDLE} to {@link #EXTRA_STATE_OFFHOOK}.
* <p class="note">
* Retrieve with
* {@link android.content.Intent#getStringExtra(String)}.
@@ -5464,23 +5480,6 @@
}
/**
- * @return true if the IMS resolver is busy resolving a binding and should not be considered
- * available, false if the IMS resolver is idle.
- * @hide
- */
- public boolean isResolvingImsBinding() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.isResolvingImsBinding();
- }
- } catch (RemoteException e) {
- Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
- }
- return false;
- }
-
- /**
* Set IMS registration state
*
* @param Registration state
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a2b8580..f875a98 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -31,6 +31,7 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
@@ -628,33 +629,33 @@
int maxConns, int waitTime, int maxConnsTime, int mtu, int mvnoType,
String mvnoMatchData, int apnSetId) {
return new Builder()
- .setId(id)
- .setOperatorNumeric(operatorNumeric)
- .setEntryName(entryName)
- .setApnName(apnName)
- .setProxyAddress(proxyAddress)
- .setProxyPort(proxyPort)
- .setMmsc(mmsc)
- .setMmsProxyAddress(mmsProxyAddress)
- .setMmsProxyPort(mmsProxyPort)
- .setUser(user)
- .setPassword(password)
- .setAuthType(authType)
- .setApnTypeBitmask(mApnTypeBitmask)
- .setProtocol(protocol)
- .setRoamingProtocol(roamingProtocol)
- .setCarrierEnabled(carrierEnabled)
- .setNetworkTypeBitmask(networkTypeBitmask)
- .setProfileId(profileId)
- .setModemCognitive(modemCognitive)
- .setMaxConns(maxConns)
- .setWaitTime(waitTime)
- .setMaxConnsTime(maxConnsTime)
- .setMtu(mtu)
- .setMvnoType(mvnoType)
- .setMvnoMatchData(mvnoMatchData)
- .setApnSetId(apnSetId)
- .buildWithoutCheck();
+ .setId(id)
+ .setOperatorNumeric(operatorNumeric)
+ .setEntryName(entryName)
+ .setApnName(apnName)
+ .setProxyAddress(proxyAddress)
+ .setProxyPort(proxyPort)
+ .setMmsc(mmsc)
+ .setMmsProxyAddress(mmsProxyAddress)
+ .setMmsProxyPort(mmsProxyPort)
+ .setUser(user)
+ .setPassword(password)
+ .setAuthType(authType)
+ .setApnTypeBitmask(mApnTypeBitmask)
+ .setProtocol(protocol)
+ .setRoamingProtocol(roamingProtocol)
+ .setCarrierEnabled(carrierEnabled)
+ .setNetworkTypeBitmask(networkTypeBitmask)
+ .setProfileId(profileId)
+ .setModemCognitive(modemCognitive)
+ .setMaxConns(maxConns)
+ .setWaitTime(waitTime)
+ .setMaxConnsTime(maxConnsTime)
+ .setMtu(mtu)
+ .setMvnoType(mvnoType)
+ .setMvnoMatchData(mvnoMatchData)
+ .setApnSetId(apnSetId)
+ .buildWithoutCheck();
}
/** @hide */
@@ -686,56 +687,56 @@
}
return makeApnSetting(
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
- cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
- portFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
- UriFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
- cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
- portFromString(cursor.getString(
- cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
- apnTypesBitmask,
- getProtocolIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
- getProtocolIntFromString(
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
+ cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
+ UriFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+ cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
+ portFromString(cursor.getString(
+ cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
+ apnTypesBitmask,
+ getProtocolIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
+ getProtocolIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.ROAMING_PROTOCOL))),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.CARRIER_ENABLED)) == 1,
+ networkTypeBitmask,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MAX_CONNS_TIME)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
+ getMvnoTypeIntFromString(
+ cursor.getString(cursor.getColumnIndexOrThrow(
+ Telephony.Carriers.MVNO_TYPE))),
cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.ROAMING_PROTOCOL))),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.CARRIER_ENABLED)) == 1,
- networkTypeBitmask,
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MODEM_COGNITIVE)) == 1,
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
- cursor.getInt(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MAX_CONNS_TIME)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
- getMvnoTypeIntFromString(
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_TYPE))),
- cursor.getString(cursor.getColumnIndexOrThrow(
- Telephony.Carriers.MVNO_MATCH_DATA)),
- cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)));
+ Telephony.Carriers.MVNO_MATCH_DATA)),
+ cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)));
}
/** @hide */
public static ApnSetting makeApnSetting(ApnSetting apn) {
return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
- apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
- apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
- apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
- apn.mProfileId, apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime,
- apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId);
+ apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
+ apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
+ apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
+ apn.mProfileId, apn.mModemCognitive, apn.mMaxConns, apn.mWaitTime,
+ apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId);
}
/**
@@ -925,16 +926,16 @@
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ApnSettingV5] ")
- .append(mEntryName)
- .append(", ").append(mId)
- .append(", ").append(mOperatorNumeric)
- .append(", ").append(mApnName)
- .append(", ").append(mProxyAddress)
- .append(", ").append(UriToString(mMmsc))
- .append(", ").append(mMmsProxyAddress)
- .append(", ").append(portToString(mMmsProxyPort))
- .append(", ").append(portToString(mProxyPort))
- .append(", ").append(mAuthType).append(", ");
+ .append(mEntryName)
+ .append(", ").append(mId)
+ .append(", ").append(mOperatorNumeric)
+ .append(", ").append(mApnName)
+ .append(", ").append(mProxyAddress)
+ .append(", ").append(UriToString(mMmsc))
+ .append(", ").append(mMmsProxyAddress)
+ .append(", ").append(portToString(mMmsProxyPort))
+ .append(", ").append(portToString(mProxyPort))
+ .append(", ").append(mAuthType).append(", ");
final String[] types = getApnTypesStringFromBitmask(mApnTypeBitmask).split(",");
sb.append(TextUtils.join(" | ", types));
sb.append(", ").append(PROTOCOL_INT_MAP.get(mProtocol));
@@ -1016,31 +1017,31 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mId, other.mId)
- && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
- && Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxyAddress, other.mProxyAddress)
- && Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
- && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
- && Objects.equals(mProxyPort, other.mProxyPort)
- && Objects.equals(mUser, other.mUser)
- && Objects.equals(mPassword, other.mPassword)
- && Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
- && Objects.equals(mProtocol, other.mProtocol)
- && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(mProfileId, other.mProfileId)
- && Objects.equals(mModemCognitive, other.mModemCognitive)
- && Objects.equals(mMaxConns, other.mMaxConns)
- && Objects.equals(mWaitTime, other.mWaitTime)
- && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
- && Objects.equals(mMtu, other.mMtu)
- && Objects.equals(mMvnoType, other.mMvnoType)
- && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
- && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId);
+ && Objects.equals(mId, other.mId)
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort,other.mProxyPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+ && Objects.equals(mProtocol, other.mProtocol)
+ && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(mApnSetId, other.mApnSetId);
}
/**
@@ -1063,29 +1064,29 @@
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
- && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
- && Objects.equals(mApnName, other.mApnName)
- && Objects.equals(mProxyAddress, other.mProxyAddress)
- && Objects.equals(mMmsc, other.mMmsc)
- && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
- && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
- && Objects.equals(mProxyPort, other.mProxyPort)
- && Objects.equals(mUser, other.mUser)
- && Objects.equals(mPassword, other.mPassword)
- && Objects.equals(mAuthType, other.mAuthType)
- && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
- && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
- && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
- && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(mProfileId, other.mProfileId)
- && Objects.equals(mModemCognitive, other.mModemCognitive)
- && Objects.equals(mMaxConns, other.mMaxConns)
- && Objects.equals(mWaitTime, other.mWaitTime)
- && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
- && Objects.equals(mMtu, other.mMtu)
- && Objects.equals(mMvnoType, other.mMvnoType)
- && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
- && Objects.equals(mApnSetId, other.mApnSetId);
+ && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+ && Objects.equals(mApnName, other.mApnName)
+ && Objects.equals(mProxyAddress, other.mProxyAddress)
+ && Objects.equals(mMmsc, other.mMmsc)
+ && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+ && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+ && Objects.equals(mProxyPort, other.mProxyPort)
+ && Objects.equals(mUser, other.mUser)
+ && Objects.equals(mPassword, other.mPassword)
+ && Objects.equals(mAuthType, other.mAuthType)
+ && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+ && (isDataRoaming || Objects.equals(mProtocol,other.mProtocol))
+ && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+ && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(mProfileId, other.mProfileId)
+ && Objects.equals(mModemCognitive, other.mModemCognitive)
+ && Objects.equals(mMaxConns, other.mMaxConns)
+ && Objects.equals(mWaitTime, other.mWaitTime)
+ && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+ && Objects.equals(mMtu, other.mMtu)
+ && Objects.equals(mMvnoType, other.mMvnoType)
+ && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+ && Objects.equals(mApnSetId, other.mApnSetId);
}
/**
@@ -1097,22 +1098,22 @@
*/
public boolean similar(ApnSetting other) {
return (!this.canHandleType(TYPE_DUN)
- && !other.canHandleType(TYPE_DUN)
- && Objects.equals(this.mApnName, other.mApnName)
- && !typeSameAny(this, other)
- && xorEquals(this.mProxyAddress, other.mProxyAddress)
- && xorEqualsInt(this.mProxyPort, other.mProxyPort)
- && xorEquals(this.mProtocol, other.mProtocol)
- && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
- && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
- && Objects.equals(this.mProfileId, other.mProfileId)
- && Objects.equals(this.mMvnoType, other.mMvnoType)
- && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
- && xorEquals(this.mMmsc, other.mMmsc)
- && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
- && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
- && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
- && Objects.equals(mApnSetId, other.mApnSetId);
+ && !other.canHandleType(TYPE_DUN)
+ && Objects.equals(this.mApnName, other.mApnName)
+ && !typeSameAny(this, other)
+ && xorEquals(this.mProxyAddress, other.mProxyAddress)
+ && xorEqualsInt(this.mProxyPort, other.mProxyPort)
+ && xorEquals(this.mProtocol, other.mProtocol)
+ && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
+ && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+ && Objects.equals(this.mProfileId, other.mProfileId)
+ && Objects.equals(this.mMvnoType, other.mMvnoType)
+ && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+ && xorEquals(this.mMmsc, other.mMmsc)
+ && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
+ && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
+ && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+ && Objects.equals(mApnSetId, other.mApnSetId);
}
// Equal or one is null.
@@ -1336,13 +1337,13 @@
new Parcelable.Creator<ApnSetting>() {
@Override
public ApnSetting createFromParcel(Parcel in) {
- return readFromParcel(in);
- }
+ return readFromParcel(in);
+ }
@Override
public ApnSetting[] newArray(int size) {
- return new ApnSetting[size];
- }
+ return new ApnSetting[size];
+ }
};
/**
diff --git a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
index bcad554..a1bea4d 100644
--- a/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/java/com/android/internal/telephony/CarrierAppUtils.java
@@ -21,7 +21,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -145,6 +144,18 @@
telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) ==
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+ // add hiddenUntilInstalled flag for carrier apps and associated apps
+ packageManager.setSystemAppHiddenUntilInstalled(packageName, true);
+ List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
+ if (associatedAppList != null) {
+ for (ApplicationInfo associatedApp : associatedAppList) {
+ packageManager.setSystemAppHiddenUntilInstalled(
+ associatedApp.packageName,
+ true
+ );
+ }
+ }
+
if (hasPrivileges) {
// Only update enabled state for the app on /system. Once it has been
// updated we shouldn't touch it.
@@ -152,9 +163,14 @@
&& (ai.enabledSetting ==
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ || (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0)) {
Slog.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ userId);
+ packageManager.setSystemAppInstallState(
+ packageName,
+ true /*installed*/,
+ userId);
packageManager.setApplicationEnabledSetting(
packageName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
@@ -164,15 +180,20 @@
}
// Also enable any associated apps for this carrier app.
- List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
if (associatedApp.enabledSetting ==
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| associatedApp.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED
+ || (associatedApp.flags
+ & ApplicationInfo.FLAG_INSTALLED) == 0) {
Slog.i(TAG, "Update associated state(" + associatedApp.packageName
+ "): ENABLED for user " + userId);
+ packageManager.setSystemAppInstallState(
+ associatedApp.packageName,
+ true /*installed*/,
+ userId);
packageManager.setApplicationEnabledSetting(
associatedApp.packageName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
@@ -190,36 +211,33 @@
// updated we shouldn't touch it.
if (!ai.isUpdatedSystemApp()
&& ai.enabledSetting ==
- PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
Slog.i(TAG, "Update state(" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
- packageManager.setApplicationEnabledSetting(
+ packageManager.setSystemAppInstallState(
packageName,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
- 0,
- userId,
- callingPackage);
+ false /*installed*/,
+ userId);
}
// Also disable any associated apps for this carrier app if this is the first
// run. We avoid doing this a second time because it is brittle to rely on the
// distinction between "default" and "enabled".
if (!hasRunOnce) {
- List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
if (associatedApp.enabledSetting
- == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
+ == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ && (associatedApp.flags
+ & ApplicationInfo.FLAG_INSTALLED) != 0) {
Slog.i(TAG,
"Update associated state(" + associatedApp.packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
- packageManager.setApplicationEnabledSetting(
+ packageManager.setSystemAppInstallState(
associatedApp.packageName,
- PackageManager
- .COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED,
- 0,
- userId,
- callingPackage);
+ false /*installed*/,
+ userId);
}
}
}
@@ -357,7 +375,8 @@
String packageName) {
try {
ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
- PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, userId);
+ PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS, userId);
if (ai != null && ai.isSystemApp()) {
return ai;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f02f27d..89a4caa 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -817,12 +817,6 @@
IImsConfig getImsConfig(int slotId, int feature);
/**
- * @return true if the IMS resolver is busy resolving a binding and should not be considered
- * available, false if the IMS resolver is idle.
- */
- boolean isResolvingImsBinding();
-
- /**
* @return true if the ImsService to bind to for the slot id specified was set, false otherwise.
*/
boolean setImsService(int slotId, boolean isCarrierImsService, String packageName);
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 66ccc6c..af44b7e 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -147,6 +147,8 @@
boolean setWifiApConfiguration(in WifiConfiguration wifiConfig, String packageName);
+ void notifyUserOfApBandConversion(String packageName);
+
Messenger getWifiServiceMessenger(String packageName);
void enableTdls(String remoteIPAddress, boolean enable);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 25f35d0..6963ed0 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2170,6 +2170,21 @@
}
/**
+ * Method that triggers a notification to the user about a conversion to their saved AP config.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public void notifyUserOfApBandConversion() {
+ Log.d(TAG, "apBand was converted, notify the user");
+ try {
+ mService.notifyUserOfApBandConversion(mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Enable/Disable TDLS on a specific local route.
*
* <p>