mirror of
https://github.com/alesimula/Murine-launcher.git
synced 2026-10-28 09:43:42 +00:00
update to android 15 s1 release version
This commit is contained in:
1 parent
7d1211c099
commit
3b9c71a66e
1624 files changed
+105506
-41777
No files matched your search
+112
-148
@@ -17,48 +17,44 @@ package {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
min_launcher3_sdk_version = "26"
|
||||
min_launcher3_sdk_version = "30"
|
||||
|
||||
// Common source files used to build launcher (java and kotlin)
|
||||
// All sources are split so they can be reused in many other libraries/apps in other folders
|
||||
|
||||
// Main Launcher source, excluding the build config
|
||||
filegroup {
|
||||
name: "launcher-src",
|
||||
srcs: [ "src/**/*.java", "src/**/*.kt" ],
|
||||
srcs: [
|
||||
"src/**/*.java",
|
||||
"src/**/*.kt",
|
||||
],
|
||||
}
|
||||
|
||||
// Source code for quickstep build, on top of launcher-src
|
||||
filegroup {
|
||||
name: "launcher-quickstep-src",
|
||||
srcs: [ "quickstep/src/**/*.java", "quickstep/src/**/*.kt" ],
|
||||
srcs: [
|
||||
"quickstep/src/**/*.java",
|
||||
"quickstep/src/**/*.kt",
|
||||
],
|
||||
}
|
||||
|
||||
// Alternate source when quickstep is not included
|
||||
filegroup {
|
||||
name: "launcher-go-src",
|
||||
srcs: [ "go/src/**/*.java", "go/src/**/*.kt" ],
|
||||
name: "launcher-src_no_quickstep",
|
||||
srcs: [
|
||||
"src_no_quickstep/**/*.java",
|
||||
"src_no_quickstep/**/*.kt",
|
||||
],
|
||||
}
|
||||
|
||||
// Default build config for Launcher3
|
||||
filegroup {
|
||||
name: "launcher-go-quickstep-src",
|
||||
srcs: [ "go/quickstep/src/**/*.java", "go/quickstep/src/**/*.kt" ],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "launcher-src_shortcuts_overrides",
|
||||
srcs: [ "src_shortcuts_overrides/**/*.java", "src_shortcuts_overrides/**/*.kt" ],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "launcher-src_ui_overrides",
|
||||
srcs: [ "src_ui_overrides/**/*.java", "src_ui_overrides/**/*.kt" ],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "launcher-ext_tests",
|
||||
srcs: [ "ext_tests/**/*.java", "ext_tests/**/*.kt" ],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "launcher-quickstep-ext_tests",
|
||||
srcs: [ "quickstep/ext_tests/**/*.java", "quickstep/ext_tests/**/*.kt" ],
|
||||
name: "launcher-build-config",
|
||||
srcs: [
|
||||
"src_build_config/**/*.java",
|
||||
],
|
||||
}
|
||||
|
||||
// Proguard files for Launcher3
|
||||
@@ -79,13 +75,14 @@ android_library {
|
||||
"androidx.test.uiautomator_uiautomator",
|
||||
"androidx.preference_preference",
|
||||
"SystemUISharedLib",
|
||||
"animationlib",
|
||||
"//frameworks/libs/systemui:animationlib",
|
||||
"launcher-testing-shared",
|
||||
],
|
||||
srcs: [
|
||||
"tests/tapl/**/*.java",
|
||||
"tests/tapl/**/*.kt",
|
||||
],
|
||||
resource_dirs: [ ],
|
||||
resource_dirs: [],
|
||||
manifest: "tests/tapl/AndroidManifest.xml",
|
||||
platform_apis: true,
|
||||
}
|
||||
@@ -99,7 +96,7 @@ java_library_static {
|
||||
sdk_version: "current",
|
||||
proto: {
|
||||
type: "lite",
|
||||
local_include_dirs:[
|
||||
local_include_dirs: [
|
||||
"protos",
|
||||
"protos_overrides",
|
||||
],
|
||||
@@ -115,14 +112,14 @@ java_library_static {
|
||||
sdk_version: "current",
|
||||
proto: {
|
||||
type: "lite",
|
||||
local_include_dirs:[
|
||||
local_include_dirs: [
|
||||
"quickstep/protos_overrides",
|
||||
],
|
||||
},
|
||||
static_libs: [
|
||||
"libprotobuf-java-lite",
|
||||
"launcher_log_protos_lite"
|
||||
],
|
||||
"libprotobuf-java-lite",
|
||||
"launcher_log_protos_lite",
|
||||
],
|
||||
}
|
||||
|
||||
java_library {
|
||||
@@ -139,11 +136,12 @@ java_library {
|
||||
// Library with all the dependencies for building Launcher3
|
||||
android_library {
|
||||
name: "Launcher3ResLib",
|
||||
srcs: [ ],
|
||||
srcs: [],
|
||||
resource_dirs: ["res"],
|
||||
static_libs: [
|
||||
"LauncherPluginLib",
|
||||
"launcher_quickstep_log_protos_lite",
|
||||
"android.os.flags-aconfig-java",
|
||||
"androidx-constraintlayout_constraintlayout",
|
||||
"androidx.recyclerview_recyclerview",
|
||||
"androidx.dynamicanimation_dynamicanimation",
|
||||
@@ -151,33 +149,28 @@ android_library {
|
||||
"androidx.preference_preference",
|
||||
"androidx.slice_slice-view",
|
||||
"androidx.cardview_cardview",
|
||||
"androidx.window_window",
|
||||
"com.google.android.material_material",
|
||||
"iconloader_base",
|
||||
"view_capture"
|
||||
],
|
||||
manifest: "AndroidManifest-common.xml",
|
||||
sdk_version: "current",
|
||||
min_sdk_version: min_launcher3_sdk_version,
|
||||
lint: {
|
||||
baseline_filename: "lint-baseline-res-lib.xml",
|
||||
},
|
||||
}
|
||||
|
||||
//
|
||||
// Build rule for Launcher3 dependencies lib.
|
||||
//
|
||||
android_library {
|
||||
name: "Launcher3CommonDepsLib",
|
||||
srcs: ["src_build_config/**/*.java"],
|
||||
static_libs: [
|
||||
"Launcher3ResLib",
|
||||
"//frameworks/libs/systemui:iconloader_base",
|
||||
"//frameworks/libs/systemui:view_capture",
|
||||
"//frameworks/libs/systemui:animationlib",
|
||||
"SystemUI-statsd",
|
||||
"launcher-testing-shared",
|
||||
"androidx.lifecycle_lifecycle-common-java8",
|
||||
"androidx.lifecycle_lifecycle-extensions",
|
||||
"androidx.lifecycle_lifecycle-runtime-ktx",
|
||||
"kotlinx_coroutines_android",
|
||||
"kotlinx_coroutines",
|
||||
"com_android_launcher3_flags_lib",
|
||||
"com_android_wm_shell_flags_lib",
|
||||
"android.appwidget.flags-aconfig-java",
|
||||
"com.android.window.flags.window-aconfig-java",
|
||||
],
|
||||
manifest: "AndroidManifest-common.xml",
|
||||
sdk_version: "current",
|
||||
min_sdk_version: min_launcher3_sdk_version,
|
||||
manifest: "AndroidManifest-common.xml",
|
||||
lint: {
|
||||
baseline_filename: "lint-baseline-common-deps-lib.xml",
|
||||
baseline_filename: "lint-baseline.xml",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -188,17 +181,14 @@ android_app {
|
||||
name: "Launcher3",
|
||||
|
||||
static_libs: [
|
||||
"Launcher3CommonDepsLib",
|
||||
"Launcher3ResLib",
|
||||
],
|
||||
srcs: [
|
||||
":launcher-src",
|
||||
":launcher-src_shortcuts_overrides",
|
||||
":launcher-src_ui_overrides",
|
||||
":launcher-ext_tests",
|
||||
],
|
||||
resource_dirs: [
|
||||
"ext_tests/res",
|
||||
":launcher-src_no_quickstep",
|
||||
":launcher-build-config",
|
||||
],
|
||||
|
||||
optimize: {
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
// Proguard is disable for testing. Derivarive prjects to keep proguard enabled
|
||||
@@ -224,14 +214,14 @@ android_app {
|
||||
"AndroidManifest-common.xml",
|
||||
],
|
||||
lint: {
|
||||
baseline_filename: "lint-baseline-launcher3.xml",
|
||||
baseline_filename: "lint-baseline.xml",
|
||||
},
|
||||
}
|
||||
|
||||
// Library with all the dependencies for building quickstep
|
||||
android_library {
|
||||
name: "QuickstepResLib",
|
||||
srcs: [ ],
|
||||
srcs: [],
|
||||
resource_dirs: [
|
||||
"quickstep/res",
|
||||
],
|
||||
@@ -242,25 +232,22 @@ android_library {
|
||||
"Launcher3ResLib",
|
||||
"lottie",
|
||||
"SystemUISharedLib",
|
||||
"SystemUI-statsd",
|
||||
"animationlib",
|
||||
"SettingsLibSettingsTheme",
|
||||
],
|
||||
manifest: "quickstep/AndroidManifest.xml",
|
||||
min_sdk_version: "current",
|
||||
}
|
||||
|
||||
|
||||
// Library with all the dependencies for building Launcher Go
|
||||
// Library with all the source code and dependencies for building Launcher Go
|
||||
android_library {
|
||||
name: "LauncherGoResLib",
|
||||
name: "Launcher3GoLib",
|
||||
srcs: [
|
||||
":launcher-src",
|
||||
":launcher-quickstep-src",
|
||||
":launcher-go-src",
|
||||
":launcher-go-quickstep-src",
|
||||
"go/quickstep/src/**/*.java",
|
||||
"go/quickstep/src/**/*.kt",
|
||||
],
|
||||
resource_dirs: [
|
||||
"go/res",
|
||||
"go/quickstep/res",
|
||||
],
|
||||
// Note the ordering here is important when it comes to resource
|
||||
@@ -268,29 +255,27 @@ android_library {
|
||||
// in QuickstepResLib to take precendece, so it should be the final
|
||||
// dependency. See b/205278434 for how this can go wrong.
|
||||
static_libs: [
|
||||
"Launcher3CommonDepsLib",
|
||||
"QuickstepResLib",
|
||||
"androidx.room_room-runtime",
|
||||
],
|
||||
plugins: ["androidx.room_room-compiler-plugin"],
|
||||
manifest: "quickstep/AndroidManifest-launcher.xml",
|
||||
manifest: "quickstep/AndroidManifest.xml",
|
||||
additional_manifests: [
|
||||
"go/AndroidManifest.xml",
|
||||
"AndroidManifest-common.xml",
|
||||
],
|
||||
min_sdk_version: "current",
|
||||
lint: {
|
||||
baseline_filename: "lint-baseline-go-res-lib.xml",
|
||||
},
|
||||
// TODO(b/319712088): re-enable use_resource_processor
|
||||
use_resource_processor: false,
|
||||
}
|
||||
|
||||
// Build rule for Quickstep library
|
||||
// Library with all the source code and dependencies for building Quickstep
|
||||
android_library {
|
||||
name: "Launcher3QuickStepLib",
|
||||
srcs: [
|
||||
":launcher-src",
|
||||
":launcher-quickstep-src",
|
||||
":launcher-src_shortcuts_overrides",
|
||||
":launcher-build-config",
|
||||
],
|
||||
resource_dirs: [],
|
||||
libs: [
|
||||
@@ -302,60 +287,13 @@ android_library {
|
||||
// dependency. See b/208647810 for how this can go wrong.
|
||||
static_libs: [
|
||||
"SystemUI-statsd",
|
||||
"SystemUISharedLib",
|
||||
"Launcher3CommonDepsLib",
|
||||
"QuickstepResLib",
|
||||
"animationlib",
|
||||
],
|
||||
manifest: "quickstep/AndroidManifest.xml",
|
||||
platform_apis: true,
|
||||
min_sdk_version: "current",
|
||||
lint: {
|
||||
baseline_filename: "lint-baseline-launcher3.xml",
|
||||
},
|
||||
}
|
||||
|
||||
// Build rule for Launcher3 Go app for Android Go devices.
|
||||
android_app {
|
||||
name: "Launcher3Go",
|
||||
|
||||
static_libs: ["Launcher3CommonDepsLib"],
|
||||
|
||||
srcs: [
|
||||
":launcher-src",
|
||||
":launcher-go-src",
|
||||
":launcher-src_ui_overrides",
|
||||
],
|
||||
|
||||
resource_dirs: ["go/res"],
|
||||
|
||||
optimize: {
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
},
|
||||
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "current",
|
||||
target_sdk_version: "current",
|
||||
privileged: true,
|
||||
system_ext_specific: true,
|
||||
overrides: [
|
||||
"Home",
|
||||
"Launcher2",
|
||||
"Launcher3",
|
||||
"Launcher3QuickStep",
|
||||
],
|
||||
required: ["privapp_whitelist_com.android.launcher3"],
|
||||
|
||||
additional_manifests: [
|
||||
"AndroidManifest.xml",
|
||||
"AndroidManifest-common.xml",
|
||||
],
|
||||
|
||||
manifest: "go/AndroidManifest.xml",
|
||||
jacoco: {
|
||||
include_filter: ["com.android.launcher3.*"],
|
||||
}
|
||||
|
||||
// TODO(b/319712088): re-enable use_resource_processor
|
||||
use_resource_processor: false,
|
||||
}
|
||||
|
||||
// Build rule for Quickstep app.
|
||||
@@ -390,32 +328,24 @@ android_app {
|
||||
manifest: "quickstep/AndroidManifest.xml",
|
||||
jacoco: {
|
||||
include_filter: ["com.android.launcher3.*"],
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
// Build rule for Launcher3 Go app with quickstep for Android Go devices.
|
||||
android_app {
|
||||
name: "Launcher3QuickStepGo",
|
||||
|
||||
static_libs: [
|
||||
"SystemUI-statsd",
|
||||
"SystemUISharedLib",
|
||||
"LauncherGoResLib",
|
||||
],
|
||||
// Build rule for Launcher3 Go app with quickstep for Android Go devices.
|
||||
// Note that the following two rules are exactly same, and should
|
||||
// eventually be merged into a single target
|
||||
android_app {
|
||||
name: "Launcher3Go",
|
||||
|
||||
static_libs: ["Launcher3GoLib"],
|
||||
resource_dirs: [],
|
||||
|
||||
platform_apis: true,
|
||||
min_sdk_version: "current",
|
||||
target_sdk_version: "current",
|
||||
|
||||
srcs: [ ],
|
||||
|
||||
resource_dirs: [
|
||||
"go/quickstep/res",
|
||||
"go/res",
|
||||
"quickstep/res",
|
||||
],
|
||||
|
||||
optimize: {
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
enabled: true,
|
||||
@@ -440,7 +370,41 @@ android_app {
|
||||
manifest: "quickstep/AndroidManifest.xml",
|
||||
jacoco: {
|
||||
include_filter: ["com.android.launcher3.*"],
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
android_app {
|
||||
name: "Launcher3QuickStepGo",
|
||||
|
||||
static_libs: ["Launcher3GoLib"],
|
||||
resource_dirs: [],
|
||||
|
||||
platform_apis: true,
|
||||
min_sdk_version: "current",
|
||||
target_sdk_version: "current",
|
||||
|
||||
optimize: {
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
privileged: true,
|
||||
system_ext_specific: true,
|
||||
overrides: [
|
||||
"Home",
|
||||
"Launcher2",
|
||||
"Launcher3",
|
||||
"Launcher3QuickStep",
|
||||
],
|
||||
required: ["privapp_whitelist_com.android.launcher3"],
|
||||
|
||||
additional_manifests: [
|
||||
"go/AndroidManifest.xml",
|
||||
"go/AndroidManifest-launcher.xml",
|
||||
"AndroidManifest-common.xml",
|
||||
],
|
||||
|
||||
manifest: "quickstep/AndroidManifest.xml",
|
||||
jacoco: {
|
||||
include_filter: ["com.android.launcher3.*"],
|
||||
},
|
||||
}
|
||||
+15
-10
@@ -52,21 +52,22 @@
|
||||
name in the permissions. eq com.mypackage.permission.READ_SETTINGS
|
||||
-->
|
||||
<permission
|
||||
android:name="${packageName}.permission.READ_SETTINGS"
|
||||
android:name="${applicationId}.permission.READ_SETTINGS"
|
||||
android:protectionLevel="signatureOrSystem"
|
||||
android:label="@string/permlab_read_settings"
|
||||
android:description="@string/permdesc_read_settings"/>
|
||||
<permission
|
||||
android:name="${packageName}.permission.WRITE_SETTINGS"
|
||||
android:name="${applicationId}.permission.WRITE_SETTINGS"
|
||||
android:protectionLevel="signatureOrSystem"
|
||||
android:label="@string/permlab_write_settings"
|
||||
android:description="@string/permdesc_write_settings"/>
|
||||
|
||||
<uses-permission android:name="${packageName}.permission.READ_SETTINGS" />
|
||||
<uses-permission android:name="${packageName}.permission.WRITE_SETTINGS" />
|
||||
<uses-permission android:name="${applicationId}.permission.READ_SETTINGS" />
|
||||
<uses-permission android:name="${applicationId}.permission.WRITE_SETTINGS" />
|
||||
|
||||
<application
|
||||
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
|
||||
android:name="com.android.launcher3.LauncherApplication"
|
||||
android:fullBackupOnly="true"
|
||||
android:backupInForeground="true"
|
||||
android:fullBackupContent="@xml/backupscheme"
|
||||
@@ -125,10 +126,10 @@
|
||||
-->
|
||||
<provider
|
||||
android:name="com.android.launcher3.LauncherProvider"
|
||||
android:authorities="${packageName}.settings"
|
||||
android:authorities="${applicationId}.settings"
|
||||
android:exported="true"
|
||||
android:writePermission="${packageName}.permission.WRITE_SETTINGS"
|
||||
android:readPermission="${packageName}.permission.READ_SETTINGS" />
|
||||
android:writePermission="${applicationId}.permission.WRITE_SETTINGS"
|
||||
android:readPermission="${applicationId}.permission.READ_SETTINGS" />
|
||||
|
||||
<!--
|
||||
The content provider for exposing various launcher grid options.
|
||||
@@ -136,7 +137,7 @@
|
||||
-->
|
||||
<provider
|
||||
android:name="com.android.launcher3.graphics.GridCustomizationsProvider"
|
||||
android:authorities="${packageName}.grid_control"
|
||||
android:authorities="${applicationId}.grid_control"
|
||||
android:exported="true" />
|
||||
|
||||
<!--
|
||||
@@ -156,7 +157,7 @@
|
||||
|
||||
<provider
|
||||
android:name="com.android.launcher3.testing.TestInformationProvider"
|
||||
android:authorities="${packageName}.TestInfo"
|
||||
android:authorities="${applicationId}.TestInfo"
|
||||
android:readPermission="android.permission.WRITE_SECURE_SETTINGS"
|
||||
android:writePermission="android.permission.WRITE_SECURE_SETTINGS"
|
||||
android:exported="true"
|
||||
@@ -178,10 +179,14 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
|
||||
<!-- Disable eager initialization of Jetpack libraries. See bug 197780098. -->
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
tools:node="remove" />
|
||||
|
||||
<property
|
||||
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
|
||||
android:value="true" />
|
||||
</application>
|
||||
</manifest>
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.launcher3">
|
||||
<uses-sdk android:targetSdkVersion="33" android:minSdkVersion="26"/>
|
||||
<uses-sdk android:targetSdkVersion="33" android:minSdkVersion="30"/>
|
||||
<!--
|
||||
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
|
||||
Refer comments around specific entries on how to extend individual components.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src_build_config" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src_no_quickstep" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src_plugins" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="quickstep" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="go" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="quickstep" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="go" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="quickstep" />
|
||||
<orderEntry type="module" module-name="go" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -5,14 +5,51 @@
|
||||
#
|
||||
|
||||
adamcohen@google.com
|
||||
captaincole@google.com
|
||||
hyunyoungs@google.com
|
||||
sunnygoyal@google.com
|
||||
twickham@google.com
|
||||
vadimt@google.com
|
||||
winsonc@google.com
|
||||
jonmiranda@google.com
|
||||
awickham@google.com
|
||||
agvard@google.com
|
||||
|
||||
# Launcher workspace eng team
|
||||
captaincole@google.com
|
||||
sunnygoyal@google.com
|
||||
charlander@google.com
|
||||
fbaron@google.com
|
||||
fengjial@google.com
|
||||
fransebas@google.com
|
||||
pinyaoting@google.com
|
||||
andonian@google.com
|
||||
sihua@google.com
|
||||
|
||||
# Multitasking eng team
|
||||
tracyzhou@google.com
|
||||
peanutbutter@google.com
|
||||
jeremysim@google.com
|
||||
atsjenk@google.com
|
||||
brianji@google.com
|
||||
|
||||
# Overview eng team
|
||||
alexchau@google.com
|
||||
samcackett@google.com
|
||||
silvajordan@google.com
|
||||
uwaisashraf@google.com
|
||||
|
||||
# Physical Keyboard & Trackpad eng team
|
||||
patmanning@google.com
|
||||
helencheuk@google.com
|
||||
|
||||
# Widget Picker team
|
||||
shamalip@google.com
|
||||
zakcohen@google.com
|
||||
|
||||
per-file FeatureFlags.java, globs = set noparent
|
||||
per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com, captaincole@google.com
|
||||
|
||||
per-file DeviceConfigWrapper.java, globs = set noparent
|
||||
per-file DeviceConfigWrapper.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com
|
||||
|
||||
# Predictive Back
|
||||
per-file LauncherBackAnimationController.java = shanh@google.com, gallmann@google.com
|
||||
+10
-1
@@ -1,4 +1,13 @@
|
||||
[Builtin Hooks]
|
||||
ktfmt = true
|
||||
|
||||
[Builtin Hooks Options]
|
||||
ktfmt = --kotlinlang-style
|
||||
|
||||
[Tool Paths]
|
||||
ktfmt = ${REPO_ROOT}/external/ktfmt/ktfmt.sh
|
||||
|
||||
[Hook Scripts]
|
||||
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --config_xml tools/checkstyle.xml --sha ${PREUPLOAD_COMMIT}
|
||||
|
||||
ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check ${PREUPLOAD_FILES}
|
||||
flag_hook = ${REPO_ROOT}/frameworks/base/packages/SystemUI/flag_check.py --msg=${PREUPLOAD_COMMIT_MESSAGE} --files=${PREUPLOAD_FILES} --project=${REPO_PATH}
|
||||
@@ -18,7 +18,8 @@
|
||||
* Launcher3-12(可以编译Quickstep版本)
|
||||
* Launcher3-13-Qc(高通版本,可以编译Quickstep版本)
|
||||
* Launcher3-13 (Launcher3-13.0.0_r83(7e9e70085176ea46bf773019a5054942d2fc3811))--Android-13
|
||||
* master (Launcher3-android14-s2-release)--Android-14
|
||||
* Launcher3-14-s2-release (android14-s2-release)
|
||||
* main (android15-s1-release)--Android-15
|
||||
|
||||
## 源码参考
|
||||
https://cs.android.com/android/platform/superproject/+/master:packages/apps/Launcher3/
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2023 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 {
|
||||
// See: http://go/android-license-faq
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
aconfig_declarations {
|
||||
name: "com_android_launcher3_flags",
|
||||
package: "com.android.launcher3",
|
||||
container: "system_ext",
|
||||
srcs: ["**/*.aconfig"],
|
||||
}
|
||||
|
||||
java_aconfig_library {
|
||||
name: "com_android_launcher3_flags_lib",
|
||||
aconfig_declarations: "com_android_launcher3_flags",
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
package: "com.android.launcher3"
|
||||
container: "system_ext"
|
||||
|
||||
flag {
|
||||
name: "enable_expanding_pause_work_button"
|
||||
namespace: "launcher"
|
||||
description: "Expand and collapse pause work button while scrolling."
|
||||
bug: "270390779"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_twoline_allapps"
|
||||
namespace: "launcher"
|
||||
description: "Enables two line label inside all apps."
|
||||
bug: "270390937"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_twoline_toggle"
|
||||
namespace: "launcher"
|
||||
description: "Enables visibility in home settings to see the toggle to turn on/off two lines in all apps."
|
||||
bug: "316027081"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_grid_only_overview"
|
||||
namespace: "launcher"
|
||||
description: "Enable a grid-only overview without a focused task."
|
||||
bug: "257950105"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_cursor_hover_states"
|
||||
namespace: "launcher"
|
||||
description: "Enables cursor hover states for certain elements."
|
||||
bug: "243191650"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_responsive_workspace"
|
||||
namespace: "launcher"
|
||||
description: "Enables new workspace grid calculations method."
|
||||
bug: "302189128"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_overview_icon_menu"
|
||||
namespace: "launcher"
|
||||
description: "Enable updated overview icon and menu within task."
|
||||
bug: "257950105"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_focus_outline"
|
||||
namespace: "launcher"
|
||||
description: "Enables focus states outline for launcher."
|
||||
bug: "310953377"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_taskbar_no_recreate"
|
||||
namespace: "launcher"
|
||||
description: "Enables taskbar with no recreation from lifecycle changes of TaskbarActivityContext."
|
||||
bug: "299193589"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_home_transition_listener"
|
||||
namespace: "launcher"
|
||||
description: "Enables launcher to listen to all transitions that include home activity"
|
||||
bug: "306053414"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_taskbar_pinning"
|
||||
namespace: "launcher"
|
||||
description: "Enables taskbar pinning to allow user to switch between transient and persistent taskbar flavors."
|
||||
bug: "296231746"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_taskbar_customization"
|
||||
namespace: "launcher"
|
||||
description: "Enables taskbar customization framework."
|
||||
bug: "347281365"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_unfolded_two_pane_picker"
|
||||
namespace: "launcher"
|
||||
description: "Enables two pane widget picker for unfolded foldables"
|
||||
bug: "313922374"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_tablet_two_pane_picker_v2"
|
||||
namespace: "launcher"
|
||||
description: "Enables full width two pane widget picker for tablets in landscape and portrait"
|
||||
bug: "315055849"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_two_pane_launcher_settings"
|
||||
namespace: "launcher"
|
||||
description: "Enables two panel settings when on large enough displays"
|
||||
bug: "204463748"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_predictive_back_gesture"
|
||||
namespace: "launcher"
|
||||
description: "Enable predictive back gesture on Launcher (including all apps and widget picker)."
|
||||
bug: "238475505"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_shortcut_dont_suggest_app"
|
||||
namespace: "launcher"
|
||||
description: "Enables don't suggest app shortcut for suggested apps"
|
||||
bug: "319250810"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_support_for_archiving"
|
||||
namespace: "launcher"
|
||||
description: "Enables support for archived apps in Launcher3, such as empty progress bar etc."
|
||||
bug: "210590852"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_private_space_install_shortcut"
|
||||
namespace: "launcher"
|
||||
description: "Enables long-press shortcut to install a copy of an app to Private space"
|
||||
bug: "316118005"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_launcher_br_metrics_fixed"
|
||||
namespace: "launcher"
|
||||
description: "Enables logging of Launcher restore metrics to the Backup & Restore team"
|
||||
bug: "307527314"
|
||||
is_fixed_read_only: true
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_reboot_unlock_animation"
|
||||
namespace: "launcher"
|
||||
description: "Enables unlock animation after device reboot"
|
||||
bug: "298231234"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_workspace_inflation"
|
||||
namespace: "launcher"
|
||||
description: "Enables asnc inflation of workspace icons"
|
||||
bug: "318539160"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_unfold_state_animation"
|
||||
namespace: "launcher"
|
||||
description: "Tie unfold animation with state animation"
|
||||
bug: "297057373"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_generated_previews"
|
||||
namespace: "launcher"
|
||||
description: "Enables support for RemoteViews previews in the widget picker."
|
||||
bug: "306546610"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_categorized_widget_suggestions"
|
||||
namespace: "launcher"
|
||||
description: "Enables widget suggestions in widget picker to be displayed in categories"
|
||||
bug: "318410881"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "force_monochrome_app_icons"
|
||||
namespace: "launcher"
|
||||
description: "Enable the ability to generate monochromatic icons, if it is not provided by the app"
|
||||
bug: "270396209"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_add_app_widget_via_config_activity_v2"
|
||||
namespace: "launcher"
|
||||
description: "When adding app widget through config activity, directly add it to workspace to reduce flicker"
|
||||
bug: "284236964"
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "use_activity_overlay"
|
||||
namespace: "launcher"
|
||||
description: "Use an activity for home screen overlay"
|
||||
bug: "273828110"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_grid_migration_fix"
|
||||
namespace: "launcher"
|
||||
description: "Keep items in place when migrating to a bigger grid"
|
||||
bug: "325286145"
|
||||
is_fixed_read_only: true
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_narrow_grid_restore"
|
||||
namespace: "launcher"
|
||||
description: "Using only the most recent workspace when restoring to avoid confusion."
|
||||
is_fixed_read_only: true
|
||||
bug: "325285743"
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_scaling_reveal_home_animation"
|
||||
namespace: "launcher"
|
||||
description: "Enables the Home gesture animation"
|
||||
bug: "308801666"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_widget_tap_to_add"
|
||||
namespace: "launcher"
|
||||
description: "Enables an add button in the widget picker"
|
||||
bug: "323886237"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_refactor_task_thumbnail"
|
||||
namespace: "launcher"
|
||||
description: "Enables rewritten version of TaskThumbnailViews in Overview"
|
||||
bug: "331753115"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_handle_delayed_gesture_callbacks"
|
||||
namespace: "launcher"
|
||||
description: "Enables additional handling for delayed mid-gesture callbacks"
|
||||
bug: "285636175"
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_fallback_overview_in_window"
|
||||
namespace: "launcher"
|
||||
description: "Enables fallback recents opening inside of a window instead of an activity."
|
||||
bug: "292269949"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_smartspace_as_a_widget"
|
||||
namespace: "launcher"
|
||||
description: "Enables smartspace as a widget"
|
||||
bug: "300140279"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_smartspace_removal_toggle"
|
||||
namespace: "launcher"
|
||||
description: "Enables smartspace removal toggle"
|
||||
bug: "303471576"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_additional_home_animations"
|
||||
namespace: "launcher"
|
||||
description: "Enables custom home animations for non-running tasks"
|
||||
bug: "237638627"
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enabled_folders_in_all_apps"
|
||||
namespace: "launcher"
|
||||
description: "Enables folders in all apps"
|
||||
bug: "341582436"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_recents_in_taskbar"
|
||||
namespace: "launcher"
|
||||
description: "Replace hybrid hotseat app predictions with strictly Recent Apps"
|
||||
bug: "315354060"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_first_screen_broadcast_archiving_extras"
|
||||
namespace: "launcher"
|
||||
description: "adds Extras to first screen broadcast for archived apps"
|
||||
bug: "322314760"
|
||||
is_fixed_read_only: true
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "floating_search_bar"
|
||||
namespace: "launcher"
|
||||
description: "Search bar persists at the bottom of the screen across Launcher states"
|
||||
bug: "346408388"
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package: "com.android.launcher3"
|
||||
container: "system_ext"
|
||||
|
||||
flag {
|
||||
name: "enable_private_space"
|
||||
namespace: "launcher_search"
|
||||
description: "Enables all Launcher features associated with private space."
|
||||
bug: "306187906"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "private_space_animation"
|
||||
namespace: "launcher_search"
|
||||
description: "This flag enables the animation of the Private Space container"
|
||||
bug: "299294792"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "private_space_sys_apps_separation"
|
||||
namespace: "launcher_search"
|
||||
description: "This flag enables showing system apps separate in Private Space container."
|
||||
bug: "308054233"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "private_space_app_installer_button"
|
||||
namespace: "launcher_search"
|
||||
description: "This flag enables addition of App Installer button in Private Space container."
|
||||
bug: "308064949"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "private_space_restrict_accessibility_drag"
|
||||
namespace: "launcher_search"
|
||||
description: "This flag disables accessibility drag for Private Space Apps."
|
||||
bug: "289223923"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "private_space_restrict_item_drag"
|
||||
namespace: "launcher_search"
|
||||
description: "This flag disables drag and drop for Private Space Items."
|
||||
bug: "289223923"
|
||||
}
|
||||
|
||||
|
||||
flag {
|
||||
name: "private_space_add_floating_mask_view"
|
||||
namespace: "launcher_search"
|
||||
description: "This flag enables the floating mask view as part of the Private Space animation. "
|
||||
bug: "339850589"
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
@@ -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 {
|
||||
default_team: "trendy_team_motion",
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
android_library {
|
||||
name: "animationlib",
|
||||
manifest: "AndroidManifest.xml",
|
||||
sdk_version: "system_current",
|
||||
min_sdk_version: "26",
|
||||
static_libs: [
|
||||
"androidx.core_core-animation",
|
||||
"androidx.core_core-ktx",
|
||||
"androidx.annotation_annotation",
|
||||
],
|
||||
srcs: [
|
||||
"src/**/*.java",
|
||||
"src/**/*.kt",
|
||||
],
|
||||
resource_dirs: [
|
||||
"res",
|
||||
],
|
||||
kotlincflags: ["-Xjvm-default=all"],
|
||||
}
|
||||
|
||||
android_library {
|
||||
name: "animationlib-tests-base",
|
||||
libs: [
|
||||
"android.test.base",
|
||||
"androidx.test.core",
|
||||
],
|
||||
static_libs: [
|
||||
"animationlib",
|
||||
"androidx.test.ext.junit",
|
||||
"androidx.test.rules",
|
||||
"testables",
|
||||
],
|
||||
}
|
||||
|
||||
android_app {
|
||||
name: "TestAnimationLibApp",
|
||||
platform_apis: true,
|
||||
static_libs: [
|
||||
"animationlib-tests-base",
|
||||
],
|
||||
}
|
||||
|
||||
android_robolectric_test {
|
||||
enabled: true,
|
||||
name: "animationlib_robo_tests",
|
||||
srcs: [
|
||||
"tests/src/**/*.kt",
|
||||
"tests/robolectric/src/**/*.kt",
|
||||
],
|
||||
java_resource_dirs: ["tests/robolectric/config"],
|
||||
instrumentation_for: "TestAnimationLibApp",
|
||||
upstream: true,
|
||||
strict_mode: false,
|
||||
}
|
||||
|
||||
android_test {
|
||||
name: "animationlib_tests",
|
||||
manifest: "tests/AndroidManifest.xml",
|
||||
|
||||
static_libs: [
|
||||
"animationlib-tests-base",
|
||||
],
|
||||
srcs: [
|
||||
"tests/src/**/*.java",
|
||||
"tests/src/**/*.kt",
|
||||
],
|
||||
kotlincflags: ["-Xjvm-default=all"],
|
||||
test_suites: ["general-tests"],
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 The Android Open Source Project
|
||||
<!--
|
||||
Copyright (C) 2023 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.
|
||||
@@ -13,8 +14,7 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle" >
|
||||
<solid android:color="@color/taskbar_divider_background"/>
|
||||
<corners android:radius="1dp" />
|
||||
</shape>
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.app.animation">
|
||||
</manifest>
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "animationlib_tests"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
|
||||
compileSdkVersion COMPILE_SDK
|
||||
|
||||
namespace = "com.android.app.animation"
|
||||
testNamespace = "com.android.app.animation.tests"
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 34
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
}
|
||||
androidTest {
|
||||
java.srcDirs = ["tests/src", "tests/robolectric/src"]
|
||||
manifest.srcFile 'tests/AndroidManifest.xml'
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
tasks.lint.enabled = false
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
freeCompilerArgs = ["-Xjvm-default=all"]
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0"
|
||||
implementation "androidx.core:core-animation:1.0.0"
|
||||
implementation "androidx.core:core-ktx:1.13.1"
|
||||
// androidTestImplementation libs.robolectric
|
||||
androidTestImplementation "androidx.test.ext:junit:1.2.1"
|
||||
androidTestImplementation "androidx.test:rules:1.5.0"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2023 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
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:controlX1="0.3"
|
||||
android:controlY1="0"
|
||||
android:controlX2="0.8"
|
||||
android:controlY2="0.15"/>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2023 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
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:controlX1="0.05"
|
||||
android:controlY1="0.7"
|
||||
android:controlX2="0.1"
|
||||
android:controlY2="1"/>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~ Copyright (C) 2023 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.
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~ Copyright (C) 2023 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.
|
||||
@@ -12,7 +12,7 @@
|
||||
~ 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.
|
||||
~ limitations under the License
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2022 The Android Open Source Project
|
||||
~ Copyright (C) 2023 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.
|
||||
@@ -12,7 +12,7 @@
|
||||
~ 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.
|
||||
~ limitations under the License
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2023 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
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:controlX1="0.2"
|
||||
android:controlY1="0"
|
||||
android:controlX2="0"
|
||||
android:controlY2="1"/>
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.app.animation;
|
||||
|
||||
import android.graphics.Path;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
/**
|
||||
* Utility class to receive interpolators from.
|
||||
*
|
||||
* Make sure that changes made to this class are also reflected in {@link InterpolatorsAndroidX}.
|
||||
* Please consider using the androidx dependencies featuring better testability altogether.
|
||||
*/
|
||||
public class Interpolators {
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Emphasized interpolators.
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* The default emphasized interpolator. Used for hero / emphasized movement of content.
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
|
||||
|
||||
/**
|
||||
* Complement to {@link #EMPHASIZED}. Used when animating hero movement in two dimensions to
|
||||
* create a smooth, emphasized, curved movement.
|
||||
* <br>
|
||||
* Example usage: Animate y-movement with {@link #EMPHASIZED} and x-movement with this.
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_COMPLEMENT = createEmphasizedComplement();
|
||||
|
||||
/**
|
||||
* The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
|
||||
* is disappearing e.g. when moving off screen.
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
|
||||
0.3f, 0f, 0.8f, 0.15f);
|
||||
|
||||
/**
|
||||
* The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
|
||||
* is appearing e.g. when coming from off screen
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
|
||||
0.05f, 0.7f, 0.1f, 1f);
|
||||
|
||||
|
||||
public static final Interpolator EXAGGERATED_EASE;
|
||||
static {
|
||||
Path exaggeratedEase = new Path();
|
||||
exaggeratedEase.moveTo(0, 0);
|
||||
exaggeratedEase.cubicTo(0.05f, 0f, 0.133333f, 0.08f, 0.166666f, 0.4f);
|
||||
exaggeratedEase.cubicTo(0.225f, 0.94f, 0.5f, 1f, 1f, 1f);
|
||||
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
|
||||
}
|
||||
|
||||
public static final Interpolator INSTANT = t -> 1;
|
||||
/**
|
||||
* All values of t map to 0 until t == 1. This is primarily useful for setting view visibility,
|
||||
* which should only happen at the very end of the animation (when it's already hidden).
|
||||
*/
|
||||
public static final Interpolator FINAL_FRAME = t -> t < 1 ? 0 : 1;
|
||||
|
||||
public static final Interpolator OVERSHOOT_0_75 = new OvershootInterpolator(0.75f);
|
||||
public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
|
||||
public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Standard interpolators.
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* The standard interpolator that should be used on every normal animation
|
||||
*/
|
||||
public static final Interpolator STANDARD = new PathInterpolator(
|
||||
0.2f, 0f, 0f, 1f);
|
||||
|
||||
/**
|
||||
* The standard accelerating interpolator that should be used on every regular movement of
|
||||
* content that is disappearing e.g. when moving off screen.
|
||||
*/
|
||||
public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(
|
||||
0.3f, 0f, 1f, 1f);
|
||||
|
||||
/**
|
||||
* The standard decelerating interpolator that should be used on every regular movement of
|
||||
* content that is appearing e.g. when coming from off screen.
|
||||
*/
|
||||
public static final Interpolator STANDARD_DECELERATE = new PathInterpolator(
|
||||
0f, 0f, 0f, 1f);
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Legacy
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* The default legacy interpolator as defined in Material 1. Also known as FAST_OUT_SLOW_IN.
|
||||
*/
|
||||
public static final Interpolator LEGACY = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
|
||||
|
||||
/**
|
||||
* The default legacy accelerating interpolator as defined in Material 1.
|
||||
* Also known as FAST_OUT_LINEAR_IN.
|
||||
*/
|
||||
public static final Interpolator LEGACY_ACCELERATE = new PathInterpolator(0.4f, 0f, 1f, 1f);
|
||||
|
||||
/**
|
||||
* The default legacy decelerating interpolator as defined in Material 1.
|
||||
* Also known as LINEAR_OUT_SLOW_IN.
|
||||
*/
|
||||
public static final Interpolator LEGACY_DECELERATE = new PathInterpolator(0f, 0f, 0.2f, 1f);
|
||||
|
||||
/**
|
||||
* Linear interpolator. Often used if the interpolator is for different properties who need
|
||||
* different interpolations.
|
||||
*/
|
||||
public static final Interpolator LINEAR = new LinearInterpolator();
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Custom interpolators
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
public static final Interpolator FAST_OUT_SLOW_IN = LEGACY;
|
||||
public static final Interpolator FAST_OUT_LINEAR_IN = LEGACY_ACCELERATE;
|
||||
public static final Interpolator LINEAR_OUT_SLOW_IN = LEGACY_DECELERATE;
|
||||
|
||||
/**
|
||||
* Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
|
||||
* goes from 1 to 0 instead of 0 to 1).
|
||||
*/
|
||||
public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
|
||||
new PathInterpolator(0.8f, 0f, 0.6f, 1f);
|
||||
public static final Interpolator SLOW_OUT_LINEAR_IN = new PathInterpolator(0.8f, 0f, 1f, 1f);
|
||||
public static final Interpolator AGGRESSIVE_EASE = new PathInterpolator(0.2f, 0f, 0f, 1f);
|
||||
public static final Interpolator AGGRESSIVE_EASE_IN_OUT = new PathInterpolator(0.6f,0, 0.4f, 1);
|
||||
|
||||
public static final Interpolator DECELERATED_EASE = new PathInterpolator(0, 0, .2f, 1f);
|
||||
public static final Interpolator ACCELERATED_EASE = new PathInterpolator(0.4f, 0, 1f, 1f);
|
||||
public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
|
||||
public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
|
||||
public static final Interpolator ACCELERATE = new AccelerateInterpolator();
|
||||
public static final Interpolator ACCELERATE_0_5 = new AccelerateInterpolator(0.5f);
|
||||
public static final Interpolator ACCELERATE_0_75 = new AccelerateInterpolator(0.75f);
|
||||
public static final Interpolator ACCELERATE_1_5 = new AccelerateInterpolator(1.5f);
|
||||
public static final Interpolator ACCELERATE_2 = new AccelerateInterpolator(2);
|
||||
public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
|
||||
public static final Interpolator DECELERATE = new DecelerateInterpolator();
|
||||
public static final Interpolator DECELERATE_1_5 = new DecelerateInterpolator(1.5f);
|
||||
public static final Interpolator DECELERATE_1_7 = new DecelerateInterpolator(1.7f);
|
||||
public static final Interpolator DECELERATE_2 = new DecelerateInterpolator(2);
|
||||
public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
|
||||
public static final Interpolator DECELERATE_3 = new DecelerateInterpolator(3f);
|
||||
public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
|
||||
public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
|
||||
public static final Interpolator ICON_OVERSHOT_LESS = new PathInterpolator(0.4f, 0f, 0.2f,
|
||||
1.1f);
|
||||
public static final Interpolator PANEL_CLOSE_ACCELERATED = new PathInterpolator(0.3f, 0, 0.5f,
|
||||
1);
|
||||
public static final Interpolator BOUNCE = new BounceInterpolator();
|
||||
/**
|
||||
* For state transitions on the control panel that lives in GlobalActions.
|
||||
*/
|
||||
public static final Interpolator CONTROL_STATE = new PathInterpolator(0.4f, 0f, 0.2f,
|
||||
1.0f);
|
||||
|
||||
/**
|
||||
* Interpolator to be used when animating a move based on a click. Pair with enough duration.
|
||||
*/
|
||||
public static final Interpolator TOUCH_RESPONSE =
|
||||
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
|
||||
|
||||
/**
|
||||
* Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
|
||||
* goes from 1 to 0 instead of 0 to 1).
|
||||
*/
|
||||
public static final Interpolator TOUCH_RESPONSE_REVERSE =
|
||||
new PathInterpolator(0.9f, 0f, 0.7f, 1f);
|
||||
|
||||
public static final Interpolator TOUCH_RESPONSE_ACCEL_DEACCEL =
|
||||
v -> ACCELERATE_DECELERATE.getInterpolation(TOUCH_RESPONSE.getInterpolation(v));
|
||||
|
||||
|
||||
/**
|
||||
* Inversion of ZOOM_OUT, compounded with an ease-out.
|
||||
*/
|
||||
public static final Interpolator ZOOM_IN = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float v) {
|
||||
return DECELERATE_3.getInterpolation(1 - ZOOM_OUT.getInterpolation(1 - v));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Interpolator ZOOM_OUT = new Interpolator() {
|
||||
|
||||
private static final float FOCAL_LENGTH = 0.35f;
|
||||
|
||||
@Override
|
||||
public float getInterpolation(float v) {
|
||||
return zInterpolate(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* This interpolator emulates the rate at which the perceived scale of an object changes
|
||||
* as its distance from a camera increases. When this interpolator is applied to a scale
|
||||
* animation on a view, it evokes the sense that the object is shrinking due to moving away
|
||||
* from the camera.
|
||||
*/
|
||||
private float zInterpolate(float input) {
|
||||
return (1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + input)) /
|
||||
(1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + 1.0f));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Interpolator SCROLL = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float t) {
|
||||
t -= 1.0f;
|
||||
return t*t*t*t*t + 1;
|
||||
}
|
||||
};
|
||||
|
||||
public static final Interpolator SCROLL_CUBIC = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float t) {
|
||||
t -= 1.0f;
|
||||
return t*t*t + 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this interpolator for animating progress values coming from the back callback to get
|
||||
* the predictive-back-typical decelerate motion.
|
||||
*
|
||||
* This interpolator is similar to {@link Interpolators#STANDARD_DECELERATE} but has a slight
|
||||
* acceleration phase at the start.
|
||||
*/
|
||||
public static final Interpolator BACK_GESTURE = new PathInterpolator(0.1f, 0.1f, 0f, 1f);
|
||||
|
||||
private static final float FAST_FLING_PX_MS = 10;
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Functions / Utilities
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
public static Interpolator scrollInterpolatorForVelocity(float velocity) {
|
||||
return Math.abs(velocity) > FAST_FLING_PX_MS ? SCROLL : SCROLL_CUBIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an OvershootInterpolator with tension directly related to the velocity (in px/ms).
|
||||
* @param velocity The start velocity of the animation we want to overshoot.
|
||||
*/
|
||||
public static Interpolator overshootInterpolatorForVelocity(float velocity) {
|
||||
return new OvershootInterpolator(Math.min(Math.abs(velocity), 3f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the amount of overshoot using an exponential falloff function with desired
|
||||
* properties, where the overshoot smoothly transitions at the 1.0f boundary into the
|
||||
* overshoot, retaining its acceleration.
|
||||
*
|
||||
* @param progress a progress value going from 0 to 1
|
||||
* @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
|
||||
* value of the overall progress will be at 1.1.
|
||||
* @param overshootStart the point in (0,1] where the result should reach 1
|
||||
* @return the interpolated overshoot
|
||||
*/
|
||||
public static float getOvershootInterpolation(float progress, float overshootAmount,
|
||||
float overshootStart) {
|
||||
if (overshootAmount == 0.0f || overshootStart == 0.0f) {
|
||||
throw new IllegalArgumentException("Invalid values for overshoot");
|
||||
}
|
||||
float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
|
||||
return MathUtils.max(0.0f,
|
||||
(float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
|
||||
* starts immediately here, instead of first having a section of non-overshooting
|
||||
*
|
||||
* @param progress a progress value going from 0 to 1
|
||||
*/
|
||||
public static float getOvershootInterpolation(float progress) {
|
||||
return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
|
||||
}
|
||||
|
||||
// Create the default emphasized interpolator
|
||||
private static PathInterpolator createEmphasizedInterpolator() {
|
||||
Path path = new Path();
|
||||
// Doing the same as fast_out_extra_slow_in
|
||||
path.moveTo(0f, 0f);
|
||||
path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
|
||||
path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
|
||||
return new PathInterpolator(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complement to {@link #createEmphasizedInterpolator()} for use when animating in
|
||||
* two dimensions.
|
||||
*/
|
||||
private static PathInterpolator createEmphasizedComplement() {
|
||||
Path path = new Path();
|
||||
path.moveTo(0f, 0f);
|
||||
path.cubicTo(0.1217f, 0.0462f, 0.15f, 0.4686f, 0.1667f, 0.66f);
|
||||
path.cubicTo(0.1834f, 0.8878f, 0.1667f, 1f, 1f, 1f);
|
||||
return new PathInterpolator(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that runs the given interpolator such that the entire progress is set
|
||||
* between the given bounds. That is, we set the interpolation to 0 until lowerBound and reach
|
||||
* 1 by upperBound.
|
||||
*/
|
||||
public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
|
||||
float upperBound) {
|
||||
if (upperBound < lowerBound) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("upperBound (%f) must be greater than lowerBound (%f)",
|
||||
upperBound, lowerBound));
|
||||
}
|
||||
return t -> clampToProgress(interpolator, t, lowerBound, upperBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the progress value's progress between the lower and upper bounds. That is, the
|
||||
* progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
|
||||
*
|
||||
* Between lowerBound and upperBound, the progress value will be interpolated using the provided
|
||||
* interpolator.
|
||||
*/
|
||||
public static float clampToProgress(
|
||||
Interpolator interpolator, float progress, float lowerBound, float upperBound) {
|
||||
if (upperBound < lowerBound) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("upperBound (%f) must be greater than lowerBound (%f)",
|
||||
upperBound, lowerBound));
|
||||
}
|
||||
|
||||
if (progress == lowerBound && progress == upperBound) {
|
||||
return progress == 0f ? 0 : 1;
|
||||
}
|
||||
if (progress < lowerBound) {
|
||||
return 0;
|
||||
}
|
||||
if (progress > upperBound) {
|
||||
return 1;
|
||||
}
|
||||
return interpolator.getInterpolation((progress - lowerBound) / (upperBound - lowerBound));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the progress value's progress between the lower and upper bounds. That is, the
|
||||
* progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
|
||||
*/
|
||||
public static float clampToProgress(float progress, float lowerBound, float upperBound) {
|
||||
return clampToProgress(Interpolators.LINEAR, progress, lowerBound, upperBound);
|
||||
}
|
||||
|
||||
private static float mapRange(float value, float min, float max) {
|
||||
return min + (value * (max - min));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given interpolator such that the interpolated value is mapped to the given range.
|
||||
* This is useful, for example, if we only use this interpolator for part of the animation,
|
||||
* such as to take over a user-controlled animation when they let go.
|
||||
*/
|
||||
public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
|
||||
float upperBound) {
|
||||
return t -> mapRange(interpolator.getInterpolation(t), lowerBound, upperBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reverse of the provided interpolator, following the formula: g(x) = 1 - f(1 - x).
|
||||
* In practice, this means that if f is an interpolator used to model a value animating between
|
||||
* m and n, g is the interpolator to use to obtain the specular behavior when animating from n
|
||||
* to m.
|
||||
*/
|
||||
public static Interpolator reverse(Interpolator interpolator) {
|
||||
return t -> 1 - interpolator.getInterpolation(1 - t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.app.animation;
|
||||
|
||||
import android.graphics.Path;
|
||||
|
||||
import androidx.core.animation.AccelerateDecelerateInterpolator;
|
||||
import androidx.core.animation.AccelerateInterpolator;
|
||||
import androidx.core.animation.BounceInterpolator;
|
||||
import androidx.core.animation.DecelerateInterpolator;
|
||||
import androidx.core.animation.Interpolator;
|
||||
import androidx.core.animation.LinearInterpolator;
|
||||
import androidx.core.animation.OvershootInterpolator;
|
||||
import androidx.core.animation.PathInterpolator;
|
||||
|
||||
/**
|
||||
* Utility class to receive interpolators from. (androidx compatible version)
|
||||
*
|
||||
* This is the androidx compatible version of {@link Interpolators}. Make sure that changes made to
|
||||
* this class are also reflected in {@link Interpolators}.
|
||||
*
|
||||
* Using the androidx versions of {@link androidx.core.animation.ValueAnimator} or
|
||||
* {@link androidx.core.animation.ObjectAnimator} improves animation testability. This file provides
|
||||
* the androidx compatible versions of the interpolators defined in {@link Interpolators}.
|
||||
* AnimatorTestRule can be used in Tests to manipulate the animation under test (e.g. artificially
|
||||
* advancing the time).
|
||||
*/
|
||||
public class InterpolatorsAndroidX {
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Emphasized interpolators.
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* The default emphasized interpolator. Used for hero / emphasized movement of content.
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
|
||||
|
||||
/**
|
||||
* Complement to {@link #EMPHASIZED}. Used when animating hero movement in two dimensions to
|
||||
* create a smooth, emphasized, curved movement.
|
||||
* <br>
|
||||
* Example usage: Animate y-movement with {@link #EMPHASIZED} and x-movement with this.
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_COMPLEMENT = createEmphasizedComplement();
|
||||
|
||||
/**
|
||||
* The accelerated emphasized interpolator. Used for hero / emphasized movement of content that
|
||||
* is disappearing e.g. when moving off screen.
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
|
||||
0.3f, 0f, 0.8f, 0.15f);
|
||||
|
||||
/**
|
||||
* The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
|
||||
* is appearing e.g. when coming from off screen
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
|
||||
0.05f, 0.7f, 0.1f, 1f);
|
||||
|
||||
public static final Interpolator EXAGGERATED_EASE;
|
||||
static {
|
||||
Path exaggeratedEase = new Path();
|
||||
exaggeratedEase.moveTo(0, 0);
|
||||
exaggeratedEase.cubicTo(0.05f, 0f, 0.133333f, 0.08f, 0.166666f, 0.4f);
|
||||
exaggeratedEase.cubicTo(0.225f, 0.94f, 0.5f, 1f, 1f, 1f);
|
||||
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
|
||||
}
|
||||
|
||||
public static final Interpolator INSTANT = t -> 1;
|
||||
/**
|
||||
* All values of t map to 0 until t == 1. This is primarily useful for setting view visibility,
|
||||
* which should only happen at the very end of the animation (when it's already hidden).
|
||||
*/
|
||||
public static final Interpolator FINAL_FRAME = t -> t < 1 ? 0 : 1;
|
||||
|
||||
public static final Interpolator OVERSHOOT_0_75 = new OvershootInterpolator(0.75f);
|
||||
public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
|
||||
public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Standard interpolators.
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* The standard interpolator that should be used on every normal animation
|
||||
*/
|
||||
public static final Interpolator STANDARD = new PathInterpolator(
|
||||
0.2f, 0f, 0f, 1f);
|
||||
|
||||
/**
|
||||
* The standard accelerating interpolator that should be used on every regular movement of
|
||||
* content that is disappearing e.g. when moving off screen.
|
||||
*/
|
||||
public static final Interpolator STANDARD_ACCELERATE = new PathInterpolator(
|
||||
0.3f, 0f, 1f, 1f);
|
||||
|
||||
/**
|
||||
* The standard decelerating interpolator that should be used on every regular movement of
|
||||
* content that is appearing e.g. when coming from off screen.
|
||||
*/
|
||||
public static final Interpolator STANDARD_DECELERATE = new PathInterpolator(
|
||||
0f, 0f, 0f, 1f);
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Legacy
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* The default legacy interpolator as defined in Material 1. Also known as FAST_OUT_SLOW_IN.
|
||||
*/
|
||||
public static final Interpolator LEGACY = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
|
||||
|
||||
/**
|
||||
* The default legacy accelerating interpolator as defined in Material 1.
|
||||
* Also known as FAST_OUT_LINEAR_IN.
|
||||
*/
|
||||
public static final Interpolator LEGACY_ACCELERATE = new PathInterpolator(0.4f, 0f, 1f, 1f);
|
||||
|
||||
/**
|
||||
* The default legacy decelerating interpolator as defined in Material 1.
|
||||
* Also known as LINEAR_OUT_SLOW_IN.
|
||||
*/
|
||||
public static final Interpolator LEGACY_DECELERATE = new PathInterpolator(0f, 0f, 0.2f, 1f);
|
||||
|
||||
/**
|
||||
* Linear interpolator. Often used if the interpolator is for different properties who need
|
||||
* different interpolations.
|
||||
*/
|
||||
public static final Interpolator LINEAR = new LinearInterpolator();
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Custom interpolators
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
public static final Interpolator FAST_OUT_SLOW_IN = LEGACY;
|
||||
public static final Interpolator FAST_OUT_LINEAR_IN = LEGACY_ACCELERATE;
|
||||
public static final Interpolator LINEAR_OUT_SLOW_IN = LEGACY_DECELERATE;
|
||||
|
||||
/**
|
||||
* Like {@link #FAST_OUT_SLOW_IN}, but used in case the animation is played in reverse (i.e. t
|
||||
* goes from 1 to 0 instead of 0 to 1).
|
||||
*/
|
||||
public static final Interpolator FAST_OUT_SLOW_IN_REVERSE =
|
||||
new PathInterpolator(0.8f, 0f, 0.6f, 1f);
|
||||
public static final Interpolator SLOW_OUT_LINEAR_IN = new PathInterpolator(0.8f, 0f, 1f, 1f);
|
||||
public static final Interpolator AGGRESSIVE_EASE = new PathInterpolator(0.2f, 0f, 0f, 1f);
|
||||
public static final Interpolator AGGRESSIVE_EASE_IN_OUT = new PathInterpolator(0.6f,0, 0.4f, 1);
|
||||
|
||||
public static final Interpolator DECELERATED_EASE = new PathInterpolator(0, 0, .2f, 1f);
|
||||
public static final Interpolator ACCELERATED_EASE = new PathInterpolator(0.4f, 0, 1f, 1f);
|
||||
public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
|
||||
public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
|
||||
public static final Interpolator ACCELERATE = new AccelerateInterpolator();
|
||||
public static final Interpolator ACCELERATE_0_5 = new AccelerateInterpolator(0.5f);
|
||||
public static final Interpolator ACCELERATE_0_75 = new AccelerateInterpolator(0.75f);
|
||||
public static final Interpolator ACCELERATE_1_5 = new AccelerateInterpolator(1.5f);
|
||||
public static final Interpolator ACCELERATE_2 = new AccelerateInterpolator(2);
|
||||
public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
|
||||
public static final Interpolator DECELERATE = new DecelerateInterpolator();
|
||||
public static final Interpolator DECELERATE_1_5 = new DecelerateInterpolator(1.5f);
|
||||
public static final Interpolator DECELERATE_1_7 = new DecelerateInterpolator(1.7f);
|
||||
public static final Interpolator DECELERATE_2 = new DecelerateInterpolator(2);
|
||||
public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
|
||||
public static final Interpolator DECELERATE_3 = new DecelerateInterpolator(3f);
|
||||
public static final Interpolator CUSTOM_40_40 = new PathInterpolator(0.4f, 0f, 0.6f, 1f);
|
||||
public static final Interpolator ICON_OVERSHOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
|
||||
public static final Interpolator ICON_OVERSHOT_LESS = new PathInterpolator(0.4f, 0f, 0.2f,
|
||||
1.1f);
|
||||
public static final Interpolator PANEL_CLOSE_ACCELERATED = new PathInterpolator(0.3f, 0, 0.5f,
|
||||
1);
|
||||
public static final Interpolator BOUNCE = new BounceInterpolator();
|
||||
/**
|
||||
* For state transitions on the control panel that lives in GlobalActions.
|
||||
*/
|
||||
public static final Interpolator CONTROL_STATE = new PathInterpolator(0.4f, 0f, 0.2f,
|
||||
1.0f);
|
||||
|
||||
/**
|
||||
* Interpolator to be used when animating a move based on a click. Pair with enough duration.
|
||||
*/
|
||||
public static final Interpolator TOUCH_RESPONSE =
|
||||
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
|
||||
|
||||
/**
|
||||
* Like {@link #TOUCH_RESPONSE}, but used in case the animation is played in reverse (i.e. t
|
||||
* goes from 1 to 0 instead of 0 to 1).
|
||||
*/
|
||||
public static final Interpolator TOUCH_RESPONSE_REVERSE =
|
||||
new PathInterpolator(0.9f, 0f, 0.7f, 1f);
|
||||
|
||||
public static final Interpolator TOUCH_RESPONSE_ACCEL_DEACCEL =
|
||||
v -> ACCELERATE_DECELERATE.getInterpolation(TOUCH_RESPONSE.getInterpolation(v));
|
||||
|
||||
|
||||
/**
|
||||
* Inversion of ZOOM_OUT, compounded with an ease-out.
|
||||
*/
|
||||
public static final Interpolator ZOOM_IN = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float v) {
|
||||
return DECELERATE_3.getInterpolation(1 - ZOOM_OUT.getInterpolation(1 - v));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Interpolator ZOOM_OUT = new Interpolator() {
|
||||
|
||||
private static final float FOCAL_LENGTH = 0.35f;
|
||||
|
||||
@Override
|
||||
public float getInterpolation(float v) {
|
||||
return zInterpolate(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* This interpolator emulates the rate at which the perceived scale of an object changes
|
||||
* as its distance from a camera increases. When this interpolator is applied to a scale
|
||||
* animation on a view, it evokes the sense that the object is shrinking due to moving away
|
||||
* from the camera.
|
||||
*/
|
||||
private float zInterpolate(float input) {
|
||||
return (1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + input)) /
|
||||
(1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + 1.0f));
|
||||
}
|
||||
};
|
||||
|
||||
public static final Interpolator SCROLL = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float t) {
|
||||
t -= 1.0f;
|
||||
return t*t*t*t*t + 1;
|
||||
}
|
||||
};
|
||||
|
||||
public static final Interpolator SCROLL_CUBIC = new Interpolator() {
|
||||
@Override
|
||||
public float getInterpolation(float t) {
|
||||
t -= 1.0f;
|
||||
return t*t*t + 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Use this interpolator for animating progress values coming from the back callback to get
|
||||
* the predictive-back-typical decelerate motion.
|
||||
*
|
||||
* This interpolator is similar to {@link Interpolators#STANDARD_DECELERATE} but has a slight
|
||||
* acceleration phase at the start.
|
||||
*/
|
||||
public static final Interpolator BACK_GESTURE = new PathInterpolator(0.1f, 0.1f, 0f, 1f);
|
||||
|
||||
private static final float FAST_FLING_PX_MS = 10;
|
||||
|
||||
/*
|
||||
* ============================================================================================
|
||||
* Functions / Utilities
|
||||
* ============================================================================================
|
||||
*/
|
||||
|
||||
public static Interpolator scrollInterpolatorForVelocity(float velocity) {
|
||||
return Math.abs(velocity) > FAST_FLING_PX_MS ? SCROLL : SCROLL_CUBIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an OvershootInterpolator with tension directly related to the velocity (in px/ms).
|
||||
* @param velocity The start velocity of the animation we want to overshoot.
|
||||
*/
|
||||
public static Interpolator overshootInterpolatorForVelocity(float velocity) {
|
||||
return new OvershootInterpolator(Math.min(Math.abs(velocity), 3f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the amount of overshoot using an exponential falloff function with desired
|
||||
* properties, where the overshoot smoothly transitions at the 1.0f boundary into the
|
||||
* overshoot, retaining its acceleration.
|
||||
*
|
||||
* @param progress a progress value going from 0 to 1
|
||||
* @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
|
||||
* value of the overall progress will be at 1.1.
|
||||
* @param overshootStart the point in (0,1] where the result should reach 1
|
||||
* @return the interpolated overshoot
|
||||
*/
|
||||
public static float getOvershootInterpolation(float progress, float overshootAmount,
|
||||
float overshootStart) {
|
||||
if (overshootAmount == 0.0f || overshootStart == 0.0f) {
|
||||
throw new IllegalArgumentException("Invalid values for overshoot");
|
||||
}
|
||||
float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
|
||||
return MathUtils.max(0.0f,
|
||||
(float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #getOvershootInterpolation(float, float, float)} but the overshoot
|
||||
* starts immediately here, instead of first having a section of non-overshooting
|
||||
*
|
||||
* @param progress a progress value going from 0 to 1
|
||||
*/
|
||||
public static float getOvershootInterpolation(float progress) {
|
||||
return MathUtils.max(0.0f, (float) (1.0f - Math.exp(-4 * progress)));
|
||||
}
|
||||
|
||||
// Create the default emphasized interpolator
|
||||
private static PathInterpolator createEmphasizedInterpolator() {
|
||||
Path path = new Path();
|
||||
// Doing the same as fast_out_extra_slow_in
|
||||
path.moveTo(0f, 0f);
|
||||
path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
|
||||
path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
|
||||
return new PathInterpolator(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a complement to {@link #createEmphasizedInterpolator()} for use when animating in
|
||||
* two dimensions.
|
||||
*/
|
||||
private static PathInterpolator createEmphasizedComplement() {
|
||||
Path path = new Path();
|
||||
path.moveTo(0f, 0f);
|
||||
path.cubicTo(0.1217f, 0.0462f, 0.15f, 0.4686f, 0.1667f, 0.66f);
|
||||
path.cubicTo(0.1834f, 0.8878f, 0.1667f, 1f, 1f, 1f);
|
||||
return new PathInterpolator(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that runs the given interpolator such that the entire progress is set
|
||||
* between the given bounds. That is, we set the interpolation to 0 until lowerBound and reach
|
||||
* 1 by upperBound.
|
||||
*/
|
||||
public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
|
||||
float upperBound) {
|
||||
if (upperBound < lowerBound) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("upperBound (%f) must be greater than lowerBound (%f)",
|
||||
upperBound, lowerBound));
|
||||
}
|
||||
return t -> clampToProgress(interpolator, t, lowerBound, upperBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the progress value's progress between the lower and upper bounds. That is, the
|
||||
* progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
|
||||
*
|
||||
* Between lowerBound and upperBound, the progress value will be interpolated using the provided
|
||||
* interpolator.
|
||||
*/
|
||||
public static float clampToProgress(
|
||||
Interpolator interpolator, float progress, float lowerBound, float upperBound) {
|
||||
if (upperBound < lowerBound) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("upperBound (%f) must be greater than lowerBound (%f)",
|
||||
upperBound, lowerBound));
|
||||
}
|
||||
|
||||
if (progress == lowerBound && progress == upperBound) {
|
||||
return progress == 0f ? 0 : 1;
|
||||
}
|
||||
if (progress < lowerBound) {
|
||||
return 0;
|
||||
}
|
||||
if (progress > upperBound) {
|
||||
return 1;
|
||||
}
|
||||
return interpolator.getInterpolation((progress - lowerBound) / (upperBound - lowerBound));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the progress value's progress between the lower and upper bounds. That is, the
|
||||
* progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
|
||||
*/
|
||||
public static float clampToProgress(float progress, float lowerBound, float upperBound) {
|
||||
return clampToProgress(LINEAR, progress, lowerBound, upperBound);
|
||||
}
|
||||
|
||||
private static float mapRange(float value, float min, float max) {
|
||||
return min + (value * (max - min));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given interpolator such that the interpolated value is mapped to the given range.
|
||||
* This is useful, for example, if we only use this interpolator for part of the animation,
|
||||
* such as to take over a user-controlled animation when they let go.
|
||||
*/
|
||||
public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
|
||||
float upperBound) {
|
||||
return t -> mapRange(interpolator.getInterpolation(t), lowerBound, upperBound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reverse of the provided interpolator, following the formula: g(x) = 1 - f(1 - x).
|
||||
* In practice, this means that if f is an interpolator used to model a value animating between
|
||||
* m and n, g is the interpolator to use to obtain the specular behavior when animating from n
|
||||
* to m.
|
||||
*/
|
||||
public static Interpolator reverse(Interpolator interpolator) {
|
||||
return t -> 1 - interpolator.getInterpolation(1 - t);
|
||||
}
|
||||
}
|
||||
+10
-5
@@ -13,10 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.flags;
|
||||
|
||||
/**
|
||||
* Place holder class for developer options.
|
||||
*/
|
||||
public class DeveloperOptionsFragment {
|
||||
package com.android.app.animation;
|
||||
|
||||
public final class MathUtils {
|
||||
public static float log(float a) {
|
||||
return (float) Math.log(a);
|
||||
}
|
||||
|
||||
public static float max(float a, float b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2023 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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.app.animation.tests">
|
||||
|
||||
<instrumentation
|
||||
android:name="android.testing.TestableInstrumentation"
|
||||
android:label="Tests for public Animation Lib"
|
||||
android:targetPackage="com.android.app.animation.tests"/>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,2 @@
|
||||
sdk=NEWEST_SDK
|
||||
shadows=com.android.app.animation.robolectric.ShadowAnimationUtils2
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.android.app.animation.robolectric
|
||||
|
||||
import android.view.animation.AnimationUtils
|
||||
import org.robolectric.annotation.Implements
|
||||
import org.robolectric.shadows.ShadowAnimationUtils
|
||||
|
||||
/**
|
||||
* This shadow overwrites [ShadowAnimationUtils] and ensures that the real implementation of
|
||||
* [AnimationUtils] is used in tests.
|
||||
*/
|
||||
@Implements(AnimationUtils::class)
|
||||
class ShadowAnimationUtils2
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.android.app.animation
|
||||
|
||||
import android.annotation.InterpolatorRes
|
||||
import android.content.Context
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import junit.framework.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class InterpolatorResourcesTest {
|
||||
|
||||
private lateinit var context: Context
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResourceInterpolatorsMatchCodeInterpolators() {
|
||||
var progress = 0f
|
||||
while (progress < +1f) {
|
||||
assertEquals(
|
||||
InterpolatorsAndroidX.EMPHASIZED.getInterpolation(progress),
|
||||
loadInterpolator(R.interpolator.emphasized_interpolator).getInterpolation(progress)
|
||||
)
|
||||
assertEquals(
|
||||
InterpolatorsAndroidX.EMPHASIZED_ACCELERATE.getInterpolation(progress),
|
||||
loadInterpolator(R.interpolator.emphasized_accelerate_interpolator)
|
||||
.getInterpolation(progress)
|
||||
)
|
||||
assertEquals(
|
||||
InterpolatorsAndroidX.EMPHASIZED_DECELERATE.getInterpolation(progress),
|
||||
loadInterpolator(R.interpolator.emphasized_decelerate_interpolator)
|
||||
.getInterpolation(progress)
|
||||
)
|
||||
assertEquals(
|
||||
InterpolatorsAndroidX.STANDARD.getInterpolation(progress),
|
||||
loadInterpolator(R.interpolator.standard_interpolator).getInterpolation(progress)
|
||||
)
|
||||
assertEquals(
|
||||
InterpolatorsAndroidX.STANDARD_ACCELERATE.getInterpolation(progress),
|
||||
loadInterpolator(R.interpolator.standard_accelerate_interpolator)
|
||||
.getInterpolation(progress)
|
||||
)
|
||||
assertEquals(
|
||||
InterpolatorsAndroidX.STANDARD_DECELERATE.getInterpolation(progress),
|
||||
loadInterpolator(R.interpolator.standard_decelerate_interpolator)
|
||||
.getInterpolation(progress)
|
||||
)
|
||||
progress += 0.1f
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadInterpolator(@InterpolatorRes resourceInt: Int) =
|
||||
AnimationUtils.loadInterpolator(context, resourceInt)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.app.animation
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import java.lang.reflect.Modifier
|
||||
import junit.framework.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
private const val ANDROIDX_ANIM_PACKAGE_NAME = "androidx.core.animation."
|
||||
private const val ANDROID_ANIM_PACKAGE_NAME = "android.view.animation."
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class InterpolatorsAndroidXTest {
|
||||
|
||||
@Test
|
||||
fun testInterpolatorsAndInterpolatorsAndroidXPublicMethodsAreEqual() {
|
||||
assertEquals(
|
||||
Interpolators::class.java.getPublicMethods(),
|
||||
InterpolatorsAndroidX::class.java.getPublicMethods()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInterpolatorsAndInterpolatorsAndroidXPublicFieldsAreEqual() {
|
||||
assertEquals(
|
||||
Interpolators::class.java.getPublicFields(),
|
||||
InterpolatorsAndroidX::class.java.getPublicFields()
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T> Class<T>.getPublicMethods() =
|
||||
declaredMethods
|
||||
.filter { Modifier.isPublic(it.modifiers) }
|
||||
.map { it.toString().replace(name, "")
|
||||
.replace(ANDROIDX_ANIM_PACKAGE_NAME, "")
|
||||
.replace(ANDROID_ANIM_PACKAGE_NAME, "") }
|
||||
.toSet()
|
||||
|
||||
private fun <T> Class<T>.getPublicFields() =
|
||||
fields.filter { Modifier.isPublic(it.modifiers) }.map { it.name }.toSet()
|
||||
}
|
||||
+9
-2
@@ -28,13 +28,16 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 34
|
||||
targetSdkVersion 35
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
buildConfigField "boolean", "IS_STUDIO_BUILD", "false"
|
||||
buildConfigField "boolean", "QSB_ON_FIRST_SCREEN", "true"
|
||||
buildConfigField "boolean", "IS_DEBUG_DEVICE", "false"
|
||||
buildConfigField "boolean", "WIDGET_ON_FIRST_SCREEN", "true"
|
||||
buildConfigField "boolean", "WIDGETS_ENABLED", "true"
|
||||
buildConfigField "boolean", "NOTIFICATION_DOTS_ENABLED", "true"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@@ -88,7 +91,7 @@ android {
|
||||
sourceSets {
|
||||
main {
|
||||
res.srcDirs = ['res']
|
||||
java.srcDirs = ['src', 'src_plugins', 'tests/shared']
|
||||
java.srcDirs = ['src', 'src_plugins', 'tests/shared', 'system_ext', 'tests/multivalentTests/shared', 'systemui_core/shared']
|
||||
manifest.srcFile 'AndroidManifest-common.xml'
|
||||
proto {
|
||||
srcDirs = ['protos/', 'protos_overrides/']
|
||||
@@ -110,6 +113,7 @@ android {
|
||||
}
|
||||
|
||||
aospWithoutQuickstep {
|
||||
java.srcDirs = ['src_no_quickstep']
|
||||
manifest.srcFile "AndroidManifest.xml"
|
||||
}
|
||||
|
||||
@@ -171,6 +175,7 @@ dependencies {
|
||||
implementation "androidx.preference:preference:${ANDROID_X_VERSION}"
|
||||
implementation project(':IconLoader')
|
||||
implementation project(':systemUIPluginCore')
|
||||
implementation project(':animationlib')
|
||||
// implementation project(':UiTestsLibLauncher')
|
||||
// withQuickstepImplementation project(':SharedLibWrapper')
|
||||
implementation 'com.google.protobuf:protobuf-javalite:4.26.1'
|
||||
@@ -195,6 +200,8 @@ dependencies {
|
||||
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
implementation 'androidx.slice:slice-builders:1.0.0'
|
||||
|
||||
implementation "androidx.window:window:1.3.0"
|
||||
}
|
||||
|
||||
def protocVersion = '4.26.1'//'3.8.0'
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="test_information_handler_class" translatable="false">com.android.launcher3.testing.DebugTestInformationHandler</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.launcher3.testing;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.system.Os;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Class to handle requests from tests, including debug ones.
|
||||
*/
|
||||
public class DebugTestInformationHandler extends TestInformationHandler {
|
||||
private static Collection<String> sEvents;
|
||||
private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks;
|
||||
private static final Map<Activity, Boolean> sActivities =
|
||||
Collections.synchronizedMap(new WeakHashMap<>());
|
||||
private static int sActivitiesCreatedCount = 0;
|
||||
|
||||
public DebugTestInformationHandler(Context context) {
|
||||
init(context);
|
||||
if (sActivityLifecycleCallbacks == null) {
|
||||
sActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle bundle) {
|
||||
sActivities.put(activity, true);
|
||||
++sActivitiesCreatedCount;
|
||||
Log.d(TestProtocol.FLAKY_ACTIVITY_COUNT, "onActivityCreated", new Exception());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
}
|
||||
};
|
||||
((Application) context.getApplicationContext())
|
||||
.registerActivityLifecycleCallbacks(sActivityLifecycleCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
private static void runGcAndFinalizersSync() {
|
||||
Runtime.getRuntime().gc();
|
||||
Runtime.getRuntime().runFinalization();
|
||||
|
||||
final CountDownLatch fence = new CountDownLatch(1);
|
||||
createFinalizationObserver(fence);
|
||||
try {
|
||||
do {
|
||||
Runtime.getRuntime().gc();
|
||||
Runtime.getRuntime().runFinalization();
|
||||
} while (!fence.await(100, TimeUnit.MILLISECONDS));
|
||||
} catch (InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the observer in the scope of a method to minimize the chance that
|
||||
// it remains live in a DEX/machine register at the point of the fence guard.
|
||||
// This must be kept to avoid R8 inlining it.
|
||||
@Keep
|
||||
private static void createFinalizationObserver(CountDownLatch fence) {
|
||||
new Object() {
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
fence.countDown();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String method, String arg, @Nullable Bundle extras) {
|
||||
final Bundle response = new Bundle();
|
||||
switch (method) {
|
||||
case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: {
|
||||
return getLauncherUIProperty(Bundle::putInt,
|
||||
l -> l.getAppsView().getAppsStore().getDeferUpdatesFlags());
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
|
||||
TestProtocol.sDebugTracing = true;
|
||||
return response;
|
||||
|
||||
case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
|
||||
TestProtocol.sDebugTracing = false;
|
||||
return response;
|
||||
|
||||
case TestProtocol.REQUEST_PID: {
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid());
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_FORCE_GC: {
|
||||
runGcAndFinalizersSync();
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_START_EVENT_LOGGING: {
|
||||
sEvents = new ArrayList<>();
|
||||
TestLogging.setEventConsumer(
|
||||
(sequence, event) -> {
|
||||
final Collection<String> events = sEvents;
|
||||
if (events != null) {
|
||||
synchronized (events) {
|
||||
events.add(sequence + '/' + event);
|
||||
}
|
||||
}
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_STOP_EVENT_LOGGING: {
|
||||
TestLogging.setEventConsumer(null);
|
||||
sEvents = null;
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_GET_TEST_EVENTS: {
|
||||
if (sEvents == null) {
|
||||
// sEvents can be null if Launcher died and restarted after
|
||||
// REQUEST_START_EVENT_LOGGING.
|
||||
return response;
|
||||
}
|
||||
|
||||
synchronized (sEvents) {
|
||||
response.putStringArrayList(
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents));
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_CLEAR_DATA: {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
LauncherSettings.Settings.call(mContext.getContentResolver(),
|
||||
LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
|
||||
MAIN_EXECUTOR.submit(() ->
|
||||
LauncherAppState.getInstance(mContext).getModel().forceReload());
|
||||
return response;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: {
|
||||
return getLauncherUIProperty(Bundle::putStringArrayList, l -> {
|
||||
ShortcutAndWidgetContainer hotseatIconsContainer =
|
||||
l.getHotseat().getShortcutsAndWidgets();
|
||||
ArrayList<String> hotseatIconNames = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) {
|
||||
// Use unchecked cast to catch changes in hotseat layout
|
||||
BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i);
|
||||
hotseatIconNames.add((String) icon.getText());
|
||||
}
|
||||
|
||||
return hotseatIconNames;
|
||||
});
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: {
|
||||
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount);
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_GET_ACTIVITIES: {
|
||||
response.putStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD,
|
||||
sActivities.keySet().stream().map(
|
||||
a -> a.getClass().getSimpleName() + " ("
|
||||
+ (a.isDestroyed() ? "destroyed" : "current") + ")")
|
||||
.toArray(String[]::new));
|
||||
return response;
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_MODEL_QUEUE_CLEARED:
|
||||
return getFromExecutorSync(MODEL_EXECUTOR, Bundle::new);
|
||||
|
||||
default:
|
||||
return super.call(method, arg, extras);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/quickstep/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice" />
|
||||
<orderEntry type="module" module-name="quickstep" />
|
||||
<orderEntry type="module" module-name="tests1" />
|
||||
<orderEntry type="module" module-name="Launcher3-refs_heads_android15-s1-release" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="multivalentTests1" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="quickstep" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="tests1" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="multivalentTests1" />
|
||||
<orderEntry type="module" module-name="Launcher3-refs_heads_android15-s1-release" />
|
||||
<orderEntry type="module" module-name="quickstep" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice" />
|
||||
<orderEntry type="module" module-name="multivalentTests1" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="Launcher3-refs_heads_android15-s1-release" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="tests1" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -120,6 +120,19 @@
|
||||
android:layout_height="1dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Unused. Included only for compatibility with parent class. -->
|
||||
<Button
|
||||
android:id="@+id/action_save_app_pair"
|
||||
style="@style/GoOverviewActionButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:drawableStart="@drawable/ic_save_app_pair_up_down"
|
||||
android:text="@string/action_save_app_pair"
|
||||
android:theme="@style/ThemeControlHighlightWorkspaceColor"
|
||||
android:visibility="gone" />
|
||||
|
||||
</com.android.quickstep.views.GoOverviewActionsView>
|
||||
@@ -14,7 +14,7 @@
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"Για να ακούσετε ή να μεταφράσετε κείμενο στην οθόνη σας, επιλέξτε μια εφαρμογή ψηφιακού βοηθού στις Ρυθμίσεις."</string>
|
||||
<string name="assistant_not_supported_title" msgid="1675788067597484142">"Αλλάξτε τον βοηθό σας για να χρησιμοποιήσετε αυτήν τη λειτουργία"</string>
|
||||
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Για να ακούσετε ή να μεταφράσετε κείμενο στην οθόνη σας, αλλάξτε την εφαρμογή ψηφιακού βοηθού στις Ρυθμίσεις."</string>
|
||||
<string name="tooltip_listen" msgid="7634466447860989102">"Πατήστε εδώ για να ακούσετε το κείμενο σε αυτήν την οθόνη"</string>
|
||||
<string name="tooltip_translate" msgid="4184845868901542567">"Πατήστε εδώ για να μεταφράσετε το κείμενο σε αυτήν την οθόνη"</string>
|
||||
<string name="tooltip_listen" msgid="7634466447860989102">"Πατήστε εδώ για να ακούσετε το κείμενο σε αυτή την οθόνη"</string>
|
||||
<string name="tooltip_translate" msgid="4184845868901542567">"Πατήστε εδώ για να μεταφράσετε το κείμενο σε αυτή την οθόνη"</string>
|
||||
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Δεν είναι δυνατή η κοινή χρήση της εφαρμογής"</string>
|
||||
</resources>
|
||||
@@ -14,7 +14,7 @@
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"برای گوش کردن به نوشتار در صفحهنمایشتان یا ترجمه کردن آن، یکی از برنامههای دستیار دیجیتالی را در «تنظیمات» انتخاب کنید"</string>
|
||||
<string name="assistant_not_supported_title" msgid="1675788067597484142">"برای استفاده از این ویژگی، دستیارتان را تغییر دهید"</string>
|
||||
<string name="assistant_not_supported_text" msgid="1708031078549268884">"برای گوش کردن به نوشتار در صفحهنمایشتان یا ترجمه کردن آن، برنامه دستیار دیجیتالیتان را در «تنظیمات» تغییر دهید"</string>
|
||||
<string name="tooltip_listen" msgid="7634466447860989102">"برای گوش کردن به نوشتار در این صفحه، اینجا ضربه بزنید"</string>
|
||||
<string name="tooltip_translate" msgid="4184845868901542567">"برای ترجمه نوشتار در این صفحه، اینجا ضربه بزنید"</string>
|
||||
<string name="tooltip_listen" msgid="7634466447860989102">"برای گوش کردن به نوشتار در این صفحه، اینجا تکضرب بزنید"</string>
|
||||
<string name="tooltip_translate" msgid="4184845868901542567">"برای ترجمه نوشتار در این صفحه، اینجا تکضرب بزنید"</string>
|
||||
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"نمیتوان این برنامه را همرسانی کرد"</string>
|
||||
</resources>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="app_share_drop_target_label" msgid="5804774105974539508">"Partager application"</string>
|
||||
<string name="app_share_drop_target_label" msgid="5804774105974539508">"Partager appli"</string>
|
||||
<string name="action_listen" msgid="2370304050784689486">"Écouter"</string>
|
||||
<string name="action_translate" msgid="8028378961867277746">"Traduire"</string>
|
||||
<string name="action_search" msgid="6269564710943755464">"Lentille"</string>
|
||||
@@ -9,12 +9,12 @@
|
||||
<string name="dialog_cancel" msgid="6464336969134856366">"ANNULER"</string>
|
||||
<string name="dialog_settings" msgid="6564397136021186148">"PARAMÈTRES"</string>
|
||||
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Traduire ou écouter le texte à l\'écran"</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Des renseignements comme du texte sur votre écran, des adresses Web et des captures d\'écran peuvent être partagés avec Google.\n\nPour modifier les renseignements que vous partagez, accédez à "<b>"Paramètres > Applications > Applications par défaut > Application d\'assistant numérique"</b>"."</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Des renseignements comme du texte sur votre écran, des adresses Web et des captures d\'écran peuvent être partagés avec Google.\n\nPour modifier les renseignements que vous partagez, accédez à "<b>"Paramètres > Applis > Applis par défaut > Appli d\'assistant numérique"</b>"."</string>
|
||||
<string name="assistant_not_selected_title" msgid="5017072974603345228">"Choisir un assistant pour utiliser cette fonctionnalité"</string>
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"Pour écouter ou traduire le texte affiché sur votre écran, choisissez l\'application d\'un assistant numérique dans les paramètres"</string>
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"Pour écouter ou traduire le texte affiché sur votre écran, choisissez l\'appli d\'un assistant numérique dans les paramètres"</string>
|
||||
<string name="assistant_not_supported_title" msgid="1675788067597484142">"Modifier votre assistant pour utiliser cette fonctionnalité"</string>
|
||||
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Pour écouter ou traduire le texte affiché sur votre écran, modifiez l\'application de votre assistant numérique dans les paramètres"</string>
|
||||
<string name="assistant_not_supported_text" msgid="1708031078549268884">"Pour écouter ou traduire le texte affiché sur votre écran, modifiez l\'appli de votre assistant numérique dans les paramètres"</string>
|
||||
<string name="tooltip_listen" msgid="7634466447860989102">"Touchez ce bouton pour écouter le texte affiché sur cet écran"</string>
|
||||
<string name="tooltip_translate" msgid="4184845868901542567">"Touchez ce bouton pour traduire le texte affiché sur cet écran"</string>
|
||||
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Cette application ne peut pas être partagée"</string>
|
||||
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"Cette appli ne peut pas être partagée"</string>
|
||||
</resources>
|
||||
@@ -9,11 +9,11 @@
|
||||
<string name="dialog_cancel" msgid="6464336969134856366">"မလုပ်တော့"</string>
|
||||
<string name="dialog_settings" msgid="6564397136021186148">"ဆက်တင်များ"</string>
|
||||
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"ဖန်သားပြင်ပေါ်ရှိ စာသားကို ဘာသာပြန်ပါ (သို့) နားထောင်ပါ"</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"သင့်ဖန်သားပြင်ပေါ်ရှိ စာသား၊ ဝဘ်လိပ်စာနှင့် ဖန်သားပြင်ဓာတ်ပုံများကဲ့သို့ အချက်အလက်များကို Google နှင့် မျှဝေနိုင်သည်။\n\nသင်မျှဝေသည့် အချက်အလက်များကို ပြောင်းရန် "<b>"ဆက်တင်များ > အက်ပ်များ > မူရင်းအက်ပ်များ > ဒစ်ဂျစ်တယ် Assistant အက်ပ်"</b>" သို့ သွားပါ။"</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"သင့်ဖန်သားပြင်ပေါ်ရှိ စာသား၊ ဝဘ်လိပ်စာနှင့် ဖန်သားပြင်ဓာတ်ပုံများကဲ့သို့ အချက်အလက်များကို Google နှင့် မျှဝေနိုင်သည်။\n\nသင်မျှဝေသည့် အချက်အလက်များကို ပြောင်းရန် "<b>"ဆက်တင်များ > အက်ပ်များ > မူရင်းအက်ပ်များ > ဒစ်ဂျစ်တယ်အထောက်အကူ အက်ပ်"</b>" သို့ သွားပါ။"</string>
|
||||
<string name="assistant_not_selected_title" msgid="5017072974603345228">"ဤဝန်ဆောင်မှုကို အသုံးပြုရန် assistant ရွေးပါ"</string>
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"ဖန်သားပြင်ပေါ်ရှိ စာသားကို နားထောင်ရန် (သို့) ဘာသာပြန်ဆိုရန် ‘ဆက်တင်များ’ တွင် ဒစ်ဂျစ်တယ် assistant အက်ပ် ရွေးပါ"</string>
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"ဖန်သားပြင်ပေါ်ရှိ စာသားကို နားထောင်ရန် (သို့) ဘာသာပြန်ဆိုရန် ‘ဆက်တင်များ’ တွင် ဒစ်ဂျစ်တယ်အထောက်အကူ အက်ပ် ရွေးပါ"</string>
|
||||
<string name="assistant_not_supported_title" msgid="1675788067597484142">"ဤဝန်ဆောင်မှုကို သုံးရန် assistant ကို ပြောင်းပါ"</string>
|
||||
<string name="assistant_not_supported_text" msgid="1708031078549268884">"ဖန်သားပြင်ပေါ်ရှိ စာသားကို နားထောင်ရန် (သို့) ဘာသာပြန်ဆိုရန် ‘ဆက်တင်များ’ တွင် ဒစ်ဂျစ်တယ် assistant အက်ပ်ကို ပြောင်းပါ"</string>
|
||||
<string name="assistant_not_supported_text" msgid="1708031078549268884">"ဖန်သားပြင်ပေါ်ရှိ စာသားကို နားထောင်ရန် (သို့) ဘာသာပြန်ဆိုရန် ‘ဆက်တင်များ’ တွင် ဒစ်ဂျစ်တယ်အထောက်အကူ အက်ပ်ကို ပြောင်းပါ"</string>
|
||||
<string name="tooltip_listen" msgid="7634466447860989102">"ဤဖန်သားပြင်ပေါ်ရှိ စာသားကို နားထောင်ရန် ဤနေရာကို တို့ပါ"</string>
|
||||
<string name="tooltip_translate" msgid="4184845868901542567">"ဤဖန်သားပြင်ပေါ်ရှိ စာသားကို ဘာသာပြန်ဆိုရန် ဤနေရာကို တို့ပါ"</string>
|
||||
<string name="toast_p2p_app_not_shareable" msgid="7229739094132131536">"ဤအက်ပ်ကို မျှဝေ၍မရပါ"</string>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<string name="dialog_cancel" msgid="6464336969134856366">"AVBRYT"</string>
|
||||
<string name="dialog_settings" msgid="6564397136021186148">"INNSTILLINGER"</string>
|
||||
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"Oversett eller lytt til tekst på skjermen"</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Informasjon som tekst på skjermen, nettadresser og skjermdumper kan deles med Google.\n\nFor å endre hvilken informasjon du deler, gå til "<b>"Innstillinger > Apper > Standardapper > Digital assistent-app"</b>"."</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"Informasjon som tekst på skjermen, nettadresser og skjermbilder kan deles med Google.\n\nFor å endre hvilken informasjon du deler, gå til "<b>"Innstillinger > Apper > Standardapper > Digital assistent-app"</b>"."</string>
|
||||
<string name="assistant_not_selected_title" msgid="5017072974603345228">"Velg en assistent for å bruke denne funksjonen"</string>
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"For å høre eller oversette tekst på skjermen, velg en digital assistent-app i innstillingene"</string>
|
||||
<string name="assistant_not_supported_title" msgid="1675788067597484142">"Endre assistenten for å bruke denne funksjonen"</string>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<string name="dialog_acknowledge" msgid="2804025517675853172">"बुझेँ"</string>
|
||||
<string name="dialog_cancel" msgid="6464336969134856366">"रद्द गर्नुहोस्"</string>
|
||||
<string name="dialog_settings" msgid="6564397136021186148">"सेटिङ"</string>
|
||||
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"स्क्रिनमा देखिने पाठ अनुवाद गरियोस् वा पढेर सुनाइयोस्"</string>
|
||||
<string name="niu_actions_confirmation_title" msgid="3863451714863526143">"स्क्रिनमा देखिने पाठ अनुवाद गर्नुहोस् वा पढेर सुनाउनुहोस्"</string>
|
||||
<string name="niu_actions_confirmation_text" msgid="2105271481950866089">"तपाईंको स्क्रिनमा देखिने पाठ, वेब ठेगाना र स्क्रिनसटलगायतका जानकारी Google सँग सेयर गर्न सकिन्छ।\n\nकुन कुन जानकारी सेयर गर्न दिने भन्ने सेटिङ बदल्न "<b>"सेटिङ > एप > डिफल्ट एप > डिजिटल सहायक एप"</b>" मा जानुहोस्।"</string>
|
||||
<string name="assistant_not_selected_title" msgid="5017072974603345228">"तपाईं यो सुविधा चलाउन चाहनुहुन्छ भने कुनै सहायक छनौट गर्नुहोस्"</string>
|
||||
<string name="assistant_not_selected_text" msgid="3244613673884359276">"तपाईं आफ्नो स्क्रिनमा देखिने पाठ सुन्न वा अनुवाद गर्न चाहनुहुन्छ भने सेटिङमा गई कुनै डिजिटल सहायक एप छनौट गर्नुहोस्"</string>
|
||||
|
||||
@@ -21,4 +21,7 @@
|
||||
<bool name="enable_niu_actions">true</bool>
|
||||
|
||||
<string name="task_overlay_factory_class" translatable="false">com.android.quickstep.TaskOverlayFactoryGo</string>
|
||||
|
||||
<!-- String representing the intent to delete a package. -->
|
||||
<string name="delete_package_intent" translatable="false">#Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;B.android.intent.extra.RETURN_RESULT=true;end</string>
|
||||
</resources>
|
||||
File renamed without changes.
@@ -27,9 +27,12 @@ import android.net.Uri;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.content.FileProvider;
|
||||
@@ -44,6 +47,9 @@ import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* Defines the Share system shortcut and its factory.
|
||||
@@ -64,14 +70,17 @@ public final class AppSharing {
|
||||
|
||||
private static final String TAG = "AppSharing";
|
||||
private static final String FILE_PROVIDER_SUFFIX = ".overview.fileprovider";
|
||||
private static final String APP_EXSTENSION = ".apk";
|
||||
private static final String APP_EXTENSION = ".apk";
|
||||
private static final String APP_MIME_TYPE = "application/application";
|
||||
|
||||
private final String mSharingComponent;
|
||||
private AppShareabilityManager mShareabilityMgr;
|
||||
|
||||
private AppSharing(Launcher launcher) {
|
||||
mSharingComponent = launcher.getText(R.string.app_sharing_component).toString();
|
||||
String sharingComponent = Settings.Secure.getString(launcher.getContentResolver(),
|
||||
Settings.Secure.NEARBY_SHARING_COMPONENT);
|
||||
mSharingComponent = TextUtils.isEmpty(sharingComponent) ? launcher.getText(
|
||||
R.string.app_sharing_component).toString() : sharingComponent;
|
||||
}
|
||||
|
||||
private Uri getShareableUri(Context context, String path, String displayName) {
|
||||
@@ -108,6 +117,9 @@ public final class AppSharing {
|
||||
private final PopupDataProvider mPopupDataProvider;
|
||||
private final boolean mSharingEnabledForUser;
|
||||
|
||||
private final Set<View> mBoundViews = Collections.newSetFromMap(new WeakHashMap<>());
|
||||
private boolean mIsEnabled = true;
|
||||
|
||||
public Share(Launcher target, ItemInfo itemInfo, View originalView) {
|
||||
super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo,
|
||||
originalView);
|
||||
@@ -123,11 +135,24 @@ public final class AppSharing {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIconAndLabelFor(View iconView, TextView labelView) {
|
||||
super.setIconAndLabelFor(iconView, labelView);
|
||||
mBoundViews.add(iconView);
|
||||
mBoundViews.add(labelView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIconAndContentDescriptionFor(ImageView view) {
|
||||
super.setIconAndContentDescriptionFor(view);
|
||||
mBoundViews.add(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
ActivityContext.lookupContext(view.getContext())
|
||||
.getStatsLogManager().logger().log(LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP);
|
||||
if (!isEnabled()) {
|
||||
if (!mIsEnabled) {
|
||||
showCannotShareToast(view.getContext());
|
||||
return;
|
||||
}
|
||||
@@ -147,7 +172,7 @@ public final class AppSharing {
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
|
||||
sourceDir = packageInfo.applicationInfo.sourceDir;
|
||||
appLabel = packageManager.getApplicationLabel(packageInfo.applicationInfo)
|
||||
.toString() + APP_EXSTENSION;
|
||||
+ APP_EXTENSION;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Could not find info for package \"" + packageName + "\"");
|
||||
return;
|
||||
@@ -175,9 +200,6 @@ public final class AppSharing {
|
||||
return;
|
||||
}
|
||||
checkShareability(/* requestUpdateIfUnknown */ false);
|
||||
mTarget.runOnUiThread(() -> {
|
||||
mPopupDataProvider.redrawSystemShortcuts();
|
||||
});
|
||||
}
|
||||
|
||||
private void checkShareability(boolean requestUpdateIfUnknown) {
|
||||
@@ -207,6 +229,17 @@ public final class AppSharing {
|
||||
int duration = Toast.LENGTH_SHORT;
|
||||
Toast.makeText(context, text, duration).show();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean isEnabled) {
|
||||
if (mIsEnabled != isEnabled) {
|
||||
mIsEnabled = isEnabled;
|
||||
mBoundViews.forEach(v -> v.setEnabled(isEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return mIsEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.launcher3;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final String APPLICATION_ID = "com.android.launcher3";
|
||||
|
||||
public static final boolean IS_STUDIO_BUILD = false;
|
||||
/**
|
||||
* Flag to state if the QSB is on the first screen and placed on the top,
|
||||
* this can be overwritten in other launchers with a different value, if needed.
|
||||
*/
|
||||
public static final boolean QSB_ON_FIRST_SCREEN = true;
|
||||
|
||||
/**
|
||||
* Flag to state if the widget on the top of the first screen should be shown.
|
||||
*/
|
||||
public static final boolean WIDGET_ON_FIRST_SCREEN = false;
|
||||
|
||||
/**
|
||||
* Flag to control various developer centric features
|
||||
*/
|
||||
public static final boolean IS_DEBUG_DEVICE = false;
|
||||
|
||||
// Flag to control widgets support in Launcher
|
||||
public static final boolean WIDGETS_ENABLED = false;
|
||||
// Flag to control notification dots support in Launcher
|
||||
public static final boolean NOTIFICATION_DOTS_ENABLED = false;
|
||||
}
|
||||
@@ -35,6 +35,7 @@ import androidx.room.Room;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.launcher3.model.AppShareabilityDatabase.ShareabilityDao;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.ArrayList;
|
||||
@@ -47,7 +48,7 @@ import java.util.function.Consumer;
|
||||
* Each app's status is retrieved from the Play Store's API. Statuses are cached in order
|
||||
* to limit extraneous calls to that API (which can be time-consuming).
|
||||
*/
|
||||
public class AppShareabilityManager {
|
||||
public class AppShareabilityManager implements SafeCloseable {
|
||||
@Retention(SOURCE)
|
||||
@IntDef({
|
||||
ShareabilityStatus.UNKNOWN,
|
||||
@@ -194,6 +195,11 @@ public class AppShareabilityManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mDatabase.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a testable instance of this class
|
||||
* This instance allows database queries on the main thread
|
||||
|
||||
@@ -56,7 +56,7 @@ import com.android.launcher3.views.ArrowTipView;
|
||||
import com.android.quickstep.util.AssistContentRequester;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.views.GoOverviewActionsView;
|
||||
import com.android.quickstep.views.TaskThumbnailView;
|
||||
import com.android.quickstep.views.TaskView.TaskContainer;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
@@ -101,8 +101,8 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
/**
|
||||
* Create a new overlay instance for the given View
|
||||
*/
|
||||
public TaskOverlayGo createOverlay(TaskThumbnailView thumbnailView) {
|
||||
return new TaskOverlayGo(thumbnailView, mContentRequester);
|
||||
public TaskOverlayGo createOverlay(TaskContainer taskContainer) {
|
||||
return new TaskOverlayGo(taskContainer, mContentRequester);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,9 +120,9 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
private OverlayDialogGo mDialog;
|
||||
private ArrowTipView mArrowTipView;
|
||||
|
||||
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
|
||||
private TaskOverlayGo(TaskContainer taskContainer,
|
||||
AssistContentRequester assistContentRequester) {
|
||||
super(taskThumbnailView);
|
||||
super(taskContainer);
|
||||
mFactoryContentRequester = assistContentRequester;
|
||||
mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
|
||||
}
|
||||
@@ -148,7 +148,8 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
// Disable Overview Actions for Work Profile apps
|
||||
boolean isManagedProfileTask =
|
||||
UserManager.get(mApplicationContext).isManagedProfile(task.key.userId);
|
||||
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot() && !isManagedProfileTask;
|
||||
boolean isAllowedByPolicy = mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot()
|
||||
&& !isManagedProfileTask;
|
||||
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
|
||||
mTaskPackageName = task.key.getPackageName();
|
||||
mSharedPreferences = LauncherPrefs.getPrefs(mApplicationContext);
|
||||
@@ -162,8 +163,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
int taskId = task.key.id;
|
||||
mFactoryContentRequester.requestAssistContent(taskId, this::onAssistContentReceived);
|
||||
|
||||
RecentsOrientedState orientedState =
|
||||
mThumbnailView.getTaskView().getRecentsView().getPagedViewOrientedState();
|
||||
RecentsOrientedState orientedState = mTaskContainer.getTaskView().getOrientedState();
|
||||
boolean isInLandscape = orientedState.getDisplayRotation() != ROTATION_0;
|
||||
|
||||
// show tooltips in portrait mode only
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/* Copyright 2017, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<bool name="notification_dots_enabled">false</bool>
|
||||
</resources>
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
|
||||
/**
|
||||
* Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
|
||||
*/
|
||||
public class LauncherBinder extends BaseLauncherBinder {
|
||||
|
||||
public LauncherBinder(LauncherAppState app, BgDataModel dataModel,
|
||||
AllAppsList allAppsList, Callbacks[] callbacks) {
|
||||
super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindDeepShortcuts() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWidgets() {
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Widgets data model that is used by the adapters of the widget views and controllers.
|
||||
*
|
||||
* <p> The widgets and shortcuts are organized using package name as its index.
|
||||
*/
|
||||
public class WidgetsModel {
|
||||
|
||||
// True is the widget support is disabled.
|
||||
public static final boolean GO_DISABLE_WIDGETS = true;
|
||||
public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
|
||||
|
||||
private static final ArrayList<WidgetsListBaseEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Returns a list of {@link WidgetsListBaseEntry}. All {@link WidgetItem} in a single row are
|
||||
* sorted (based on label and user), but the overall list of {@link WidgetsListBaseEntry}s is
|
||||
* not sorted. This list is sorted at the UI when using
|
||||
* {@link com.android.launcher3.widget.picker.WidgetsDiffReporter}
|
||||
*
|
||||
* @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
|
||||
*/
|
||||
public synchronized ArrayList<WidgetsListBaseEntry> getWidgetsListForPicker(Context context) {
|
||||
return EMPTY_WIDGET_LIST;
|
||||
}
|
||||
|
||||
/** Returns a mapping of packages to their widgets without static shortcuts. */
|
||||
public synchronized Map<PackageUserKey, List<WidgetItem>> getAllWidgetsWithoutShortcuts() {
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise
|
||||
* only widgets and shortcuts associated with the package/user are.
|
||||
*/
|
||||
public List<ComponentWithLabelAndIcon> update(LauncherAppState app,
|
||||
@Nullable PackageUserKey packageUser) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
|
||||
LauncherAppState app) {
|
||||
}
|
||||
|
||||
public WidgetItem getWidgetProviderInfoByProviderName(
|
||||
ComponentName providerName, UserHandle user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns {@link PackageItemInfo} of a pending widget. */
|
||||
public static PackageItemInfo newPendingItemInfo(
|
||||
Context context, ComponentName provider, UserHandle userHandle) {
|
||||
return new PackageItemInfo(provider.getPackageName(), userHandle);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.launcher3.util;
|
||||
|
||||
/**
|
||||
* Defines method to find the next vacant cell on a grid.
|
||||
* This uses the default top-down, left-right approach and can be over-written through
|
||||
* code swaps in different launchers.
|
||||
*/
|
||||
public abstract class AbsGridOccupancy {
|
||||
|
||||
/**
|
||||
* Find the first vacant cell, if there is one.
|
||||
*
|
||||
* @param vacantOut Holds the x and y coordinate of the vacant cell
|
||||
* @param spanX Horizontal cell span.
|
||||
* @param spanY Vertical cell span.
|
||||
*
|
||||
* @return true if a vacant cell was found
|
||||
*/
|
||||
protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY,
|
||||
int spanX, int spanY) {
|
||||
for (int y = 0; (y + spanY) <= countY; y++) {
|
||||
for (int x = 0; (x + spanX) <= countX; x++) {
|
||||
boolean available = !cells[x][y];
|
||||
out:
|
||||
for (int i = x; i < x + spanX; i++) {
|
||||
for (int j = y; j < y + spanY; j++) {
|
||||
available = available && !cells[i][j];
|
||||
if (!available) break out;
|
||||
}
|
||||
}
|
||||
if (available) {
|
||||
vacantOut[0] = x;
|
||||
vacantOut[1] = y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -16,6 +16,6 @@ PROTOBUF_CLASS_PATH=com.google.protobuf:protobuf-gradle-plugin:0.9.4
|
||||
PROTOBUF_DEPENDENCY=com.google.protobuf.nano:protobuf-javanano:3.1.0
|
||||
|
||||
BUILD_TOOLS_VERSION=28.0.3
|
||||
COMPILE_SDK=android-34
|
||||
COMPILE_SDK=android-35
|
||||
#KOTLIN=org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10
|
||||
KOTLIN=org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0
|
||||
@@ -3,19 +3,14 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion COMPILE_SDK
|
||||
|
||||
namespace = "com.android.launcher3.icons"
|
||||
compileSdkVersion COMPILE_SDK
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 26
|
||||
targetSdkVersion 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
targetSdkVersion 35
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java.srcDirs = ['src', 'src_full_lib']
|
||||
@@ -26,6 +21,10 @@ android {
|
||||
lint {
|
||||
abortOnError false
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
||||
@@ -34,5 +33,4 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.core:core:1.13.1"
|
||||
implementation "androidx.annotation:annotation:1.8.1"
|
||||
}
|
||||
@@ -17,27 +17,16 @@
|
||||
android:width="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#11000000"
|
||||
android:pathData="M.5,12.25
|
||||
A11.5,11.5 0 1,1 23.5,12.25
|
||||
A11.5,11.5 0 1,1 .5,12.25" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M1,12
|
||||
A11,11 0 1,1 23,12
|
||||
A11,11 0 1,1 1,12" />
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/badge_tint_clone">
|
||||
|
||||
<group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12">
|
||||
<path
|
||||
android:pathData="M22,9.5C22,13.642 18.642,17 14.5,17C10.358,17 7,13.642 7,9.5C7,5.358 10.358,2 14.5,2C18.642,2 22,5.358 22,9.5Z"
|
||||
android:fillColor="#ff3C4043"/>
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"/>
|
||||
<path
|
||||
android:pathData="M9.5,20.333C12.722,20.333 15.333,17.722 15.333,14.5C15.333,11.278 12.722,8.667 9.5,8.667C6.278,8.667 3.667,11.278 3.667,14.5C3.667,17.722 6.278,20.333 9.5,20.333ZM9.5,22C13.642,22 17,18.642 17,14.5C17,10.358 13.642,7 9.5,7C5.358,7 2,10.358 2,14.5C2,18.642 5.358,22 9.5,22Z"
|
||||
android:fillColor="#ff3C4043"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 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="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#11000000"
|
||||
android:pathData="M.5,12.25
|
||||
A11.5,11.5 0 1,1 23.5,12.25
|
||||
A11.5,11.5 0 1,1 .5,12.25" />
|
||||
|
||||
<path
|
||||
android:fillColor="@color/themed_icon_background_color"
|
||||
android:pathData="M1,12
|
||||
A11,11 0 1,1 23,12
|
||||
A11,11 0 1,1 1,12" />
|
||||
|
||||
<group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12">
|
||||
<path
|
||||
android:pathData="M22,9.5C22,13.642 18.642,17 14.5,17C10.358,17 7,13.642 7,9.5C7,5.358 10.358,2 14.5,2C18.642,2 22,5.358 22,9.5Z"
|
||||
android:fillColor="@color/themed_badge_icon_color"/>
|
||||
<path
|
||||
android:pathData="M9.5,20.333C12.722,20.333 15.333,17.722 15.333,14.5C15.333,11.278 12.722,8.667 9.5,8.667C6.278,8.667 3.667,11.278 3.667,14.5C3.667,17.722 6.278,20.333 9.5,20.333ZM9.5,22C13.642,22 17,18.642 17,14.5C17,10.358 13.642,7 9.5,7C5.358,7 2,10.358 2,14.5C2,18.642 5.358,22 9.5,22Z"
|
||||
android:fillColor="@color/themed_badge_icon_color"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -17,14 +17,11 @@
|
||||
android:width="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="18"
|
||||
android:viewportHeight="18">
|
||||
android:viewportHeight="18"
|
||||
android:tint="@color/badge_tint_instant">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M 9 0 C 13.9705627485 0 18 4.02943725152 18 9 C 18 13.9705627485 13.9705627485 18 9 18 C 4.02943725152 18 0 13.9705627485 0 9 C 0 4.02943725152 4.02943725152 0 9 0 Z" />
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M 6 10.4123279 L 8.63934949 10.4123279 L 8.63934949 15.6 L 12.5577168 7.84517705 L 9.94547194 7.84517705 L 9.94547194 2 Z" />
|
||||
</vector>
|
||||
@@ -1,30 +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="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="18"
|
||||
android:viewportHeight="18">
|
||||
|
||||
<path
|
||||
android:fillColor="@color/themed_badge_icon_background_color"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M 9 0 C 13.9705627485 0 18 4.02943725152 18 9 C 18 13.9705627485 13.9705627485 18 9 18 C 4.02943725152 18 0 13.9705627485 0 9 C 0 4.02943725152 4.02943725152 0 9 0 Z" />
|
||||
<path
|
||||
android:fillColor="@color/themed_badge_icon_color"
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M 6 10.4123279 L 8.63934949 10.4123279 L 8.63934949 15.6 L 12.5577168 7.84517705 L 9.94547194 7.84517705 L 9.94547194 2 Z" />
|
||||
</vector>
|
||||
@@ -0,0 +1,32 @@
|
||||
<!--
|
||||
~ Copyright (C) 2023 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="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/badge_tint_private">
|
||||
<group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12">
|
||||
<path
|
||||
android:pathData="M12,2L4,5V11.09C4,16.14 7.41,20.85 12,22C16.59,20.85 20,16.14 20,11.09V5L12,2ZM15,15V17H13V18H11V12.84C9.56,12.41 8.5,11.09 8.5,9.5C8.5,7.57 10.07,6 12,6C13.93,6 15.5,7.57 15.5,9.5C15.5,11.08 14.44,12.41 13,12.84V15H15Z"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M12,11C12.828,11 13.5,10.328 13.5,9.5C13.5,8.672 12.828,8 12,8C11.172,8 10.5,8.672 10.5,9.5C10.5,10.328 11.172,11 12,11Z"
|
||||
android:fillColor="#FFFFFFFF"/>
|
||||
</group>
|
||||
</vector>
|
||||
|
||||
@@ -17,23 +17,12 @@
|
||||
android:width="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#11000000"
|
||||
android:pathData="M.5,12.25
|
||||
A11.5,11.5 0 1,1 23.5,12.25
|
||||
A11.5,11.5 0 1,1 .5,12.25" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M1,12
|
||||
A11,11 0 1,1 23,12
|
||||
A11,11 0 1,1 1,12" />
|
||||
android:viewportHeight="24"
|
||||
android:tint="@color/badge_tint_work">
|
||||
|
||||
<group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12">
|
||||
<path
|
||||
android:fillColor="#1A73E8"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM14,6h-4L10,4h4v2z" />
|
||||
</group>
|
||||
</vector>
|
||||
@@ -1,39 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 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="@dimen/profile_badge_size"
|
||||
android:height="@dimen/profile_badge_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="#11000000"
|
||||
android:pathData="M.5,12.25
|
||||
A11.5,11.5 0 1,1 23.5,12.25
|
||||
A11.5,11.5 0 1,1 .5,12.25" />
|
||||
|
||||
<path
|
||||
android:fillColor="@color/themed_badge_icon_background_color"
|
||||
android:pathData="M1,12
|
||||
A11,11 0 1,1 23,12
|
||||
A11,11 0 1,1 1,12" />
|
||||
|
||||
<group android:scaleX=".6" android:scaleY=".6" android:pivotX="12" android:pivotY="12">
|
||||
<path
|
||||
android:fillColor="@color/themed_badge_icon_color"
|
||||
android:pathData="M20,6h-4L16,4c0,-1.11 -0.89,-2 -2,-2h-4c-1.11,0 -2,0.89 -2,2v2L4,6c-1.11,0 -1.99,0.89 -1.99,2L2,19c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2zM14,6h-4L10,4h4v2z" />
|
||||
</group>
|
||||
</vector>
|
||||
@@ -21,7 +21,11 @@
|
||||
<color name="themed_icon_background_color">#D3E3FD</color>
|
||||
<color name="themed_badge_icon_color">#0842A0</color>
|
||||
<color name="themed_badge_icon_background_color">#D3E3FD</color>
|
||||
<color name="legacy_icon_background">#FFFFFF</color>
|
||||
|
||||
<color name="badge_tint_instant">@android:color/black</color>
|
||||
<color name="badge_tint_work">#1A73E8</color>
|
||||
<color name="badge_tint_private">#3C4043</color>
|
||||
<color name="badge_tint_clone">#ff3C4043</color>
|
||||
|
||||
<!-- Yellow 600, used for highlighting "important" conversations in settings & notifications -->
|
||||
<color name="important_conversation">#f9ab00</color>
|
||||
|
||||
@@ -5,9 +5,7 @@ import static android.graphics.Paint.DITHER_FLAG;
|
||||
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
|
||||
import static android.graphics.drawable.AdaptiveIconDrawable.getExtraInsetFraction;
|
||||
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_CLONE;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_INSTANT;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_WORK;
|
||||
import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
@@ -29,10 +27,11 @@ import android.graphics.drawable.AdaptiveIconDrawable;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.DrawableWrapper;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.UserHandle;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.IntDef;
|
||||
@@ -41,6 +40,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.icons.BitmapInfo.Extender;
|
||||
import com.android.launcher3.util.FlagOp;
|
||||
import com.android.launcher3.util.UserIconInfo;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.Objects;
|
||||
@@ -52,6 +52,7 @@ import java.util.Objects;
|
||||
public class BaseIconFactory implements AutoCloseable {
|
||||
|
||||
private static final int DEFAULT_WRAPPER_BACKGROUND = Color.WHITE;
|
||||
private static final float LEGACY_ICON_SCALE = .7f * (1f / (1 + 2 * getExtraInsetFraction()));
|
||||
|
||||
public static final int MODE_DEFAULT = 0;
|
||||
public static final int MODE_ALPHA = 1;
|
||||
@@ -61,7 +62,8 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({MODE_DEFAULT, MODE_ALPHA, MODE_WITH_SHADOW, MODE_HARDWARE_WITH_SHADOW, MODE_HARDWARE})
|
||||
@interface BitmapGenerationMode {}
|
||||
@interface BitmapGenerationMode {
|
||||
}
|
||||
|
||||
private static final float ICON_BADGE_SCALE = 0.444f;
|
||||
|
||||
@@ -69,7 +71,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
private final Rect mOldBounds = new Rect();
|
||||
|
||||
@NonNull
|
||||
private final SparseBooleanArray mIsUserBadged = new SparseBooleanArray();
|
||||
private final SparseArray<UserIconInfo> mCachedUserInfo = new SparseArray<>();
|
||||
|
||||
@NonNull
|
||||
protected final Context mContext;
|
||||
@@ -162,8 +164,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
* Create a placeholder icon using the passed in text.
|
||||
*
|
||||
* @param placeholder used for foreground element in the icon bitmap
|
||||
* @param color used for the foreground text color
|
||||
* @return
|
||||
* @param color used for the foreground text color
|
||||
*/
|
||||
public BitmapInfo createIconBitmap(String placeholder, int color) {
|
||||
AdaptiveIconDrawable drawable = new AdaptiveIconDrawable(
|
||||
@@ -203,27 +204,26 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
* Creates bitmap using the source drawable and various parameters.
|
||||
* The bitmap is visually normalized with other icons and has enough spacing to add shadow.
|
||||
*
|
||||
* @param icon source of the icon
|
||||
* @param icon source of the icon
|
||||
* @return a bitmap suitable for disaplaying as an icon at various system UIs.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.TIRAMISU)
|
||||
@NonNull
|
||||
public BitmapInfo createBadgedIconBitmap(@NonNull Drawable icon,
|
||||
@Nullable IconOptions options) {
|
||||
boolean shrinkNonAdaptiveIcons = options == null || options.mShrinkNonAdaptiveIcons;
|
||||
float[] scale = new float[1];
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, shrinkNonAdaptiveIcons, null, scale);
|
||||
Bitmap bitmap = createIconBitmap(icon, scale[0],
|
||||
AdaptiveIconDrawable adaptiveIcon = normalizeAndWrapToAdaptiveIcon(icon, null, scale);
|
||||
Bitmap bitmap = createIconBitmap(adaptiveIcon, scale[0],
|
||||
options == null ? MODE_WITH_SHADOW : options.mGenerationMode);
|
||||
|
||||
int color = (options != null && options.mExtractedColor != null)
|
||||
? options.mExtractedColor : mColorExtractor.findDominantColorByHue(bitmap);
|
||||
BitmapInfo info = BitmapInfo.of(bitmap, color);
|
||||
|
||||
if (icon instanceof BitmapInfo.Extender) {
|
||||
info = ((BitmapInfo.Extender) icon).getExtendedInfo(bitmap, color, this, scale[0]);
|
||||
if (adaptiveIcon instanceof BitmapInfo.Extender extender) {
|
||||
info = extender.getExtendedInfo(bitmap, color, this, scale[0]);
|
||||
} else if (IconProvider.ATLEAST_T && mMonoIconEnabled) {
|
||||
Drawable mono = getMonochromeDrawable(icon);
|
||||
Drawable mono = getMonochromeDrawable(adaptiveIcon);
|
||||
if (mono != null) {
|
||||
info.setMonoIcon(createIconBitmap(mono, scale[0], MODE_ALPHA), this);
|
||||
}
|
||||
@@ -234,15 +234,14 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
|
||||
/**
|
||||
* Returns a monochromatic version of the given drawable or null, if it is not supported
|
||||
*
|
||||
* @param base the original icon
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.TIRAMISU)
|
||||
protected Drawable getMonochromeDrawable(Drawable base) {
|
||||
if (base instanceof AdaptiveIconDrawable) {
|
||||
Drawable mono = ((AdaptiveIconDrawable) base).getMonochrome();
|
||||
if (mono != null) {
|
||||
return new ClippedMonoDrawable(mono);
|
||||
}
|
||||
protected Drawable getMonochromeDrawable(AdaptiveIconDrawable base) {
|
||||
Drawable mono = base.getMonochrome();
|
||||
if (mono != null) {
|
||||
return new ClippedMonoDrawable(mono);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -255,27 +254,35 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
op = op.addFlag(FLAG_INSTANT);
|
||||
}
|
||||
|
||||
if (options.mUserHandle != null) {
|
||||
int key = options.mUserHandle.hashCode();
|
||||
boolean isBadged;
|
||||
int index;
|
||||
if ((index = mIsUserBadged.indexOfKey(key)) >= 0) {
|
||||
isBadged = mIsUserBadged.valueAt(index);
|
||||
} else {
|
||||
// Check packageManager if the provided user needs a badge
|
||||
NoopDrawable d = new NoopDrawable();
|
||||
isBadged = (d != mPm.getUserBadgedIcon(d, options.mUserHandle));
|
||||
mIsUserBadged.put(key, isBadged);
|
||||
}
|
||||
// Set the clone profile badge flag in case it is present.
|
||||
op = op.setFlag(FLAG_CLONE, isBadged && options.mIsCloneProfile);
|
||||
// Set the Work profile badge for all other cases.
|
||||
op = op.setFlag(FLAG_WORK, isBadged && !options.mIsCloneProfile);
|
||||
UserIconInfo info = options.mUserIconInfo;
|
||||
if (info == null && options.mUserHandle != null) {
|
||||
info = getUserInfo(options.mUserHandle);
|
||||
}
|
||||
if (info != null) {
|
||||
op = info.applyBitmapInfoFlags(op);
|
||||
}
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected UserIconInfo getUserInfo(@NonNull UserHandle user) {
|
||||
int key = user.hashCode();
|
||||
UserIconInfo info = mCachedUserInfo.get(key);
|
||||
/*
|
||||
* We do not have the ability to distinguish between different badged users here.
|
||||
* As such all badged users will have the work profile badge applied.
|
||||
*/
|
||||
if (info == null) {
|
||||
// Simple check to check if the provided user is work profile or not based on badging
|
||||
NoopDrawable d = new NoopDrawable();
|
||||
boolean isWork = (d != mPm.getUserBadgedIcon(d, user));
|
||||
info = new UserIconInfo(user, isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN);
|
||||
mCachedUserInfo.put(key, info);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Bitmap getWhiteShadowLayer() {
|
||||
if (mWhiteShadowLayer == null) {
|
||||
@@ -290,7 +297,7 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
public Bitmap createScaledBitmap(@NonNull Drawable icon, @BitmapGenerationMode int mode) {
|
||||
RectF iconBounds = new RectF();
|
||||
float[] scale = new float[1];
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, true, iconBounds, scale);
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon, iconBounds, scale);
|
||||
return createIconBitmap(icon,
|
||||
Math.min(scale[0], ShadowGenerator.getScaleForBounds(iconBounds)), mode);
|
||||
}
|
||||
@@ -303,37 +310,59 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Drawable normalizeAndWrapToAdaptiveIcon(@Nullable Drawable icon,
|
||||
final boolean shrinkNonAdaptiveIcons, @Nullable final RectF outIconBounds,
|
||||
@NonNull final float[] outScale) {
|
||||
protected AdaptiveIconDrawable normalizeAndWrapToAdaptiveIcon(@Nullable Drawable icon,
|
||||
@Nullable final RectF outIconBounds, @NonNull final float[] outScale) {
|
||||
if (icon == null) {
|
||||
return null;
|
||||
}
|
||||
float scale = 1f;
|
||||
|
||||
if (shrinkNonAdaptiveIcons && !(icon instanceof AdaptiveIconDrawable)) {
|
||||
if (mWrapperIcon == null) {
|
||||
mWrapperIcon = mContext.getDrawable(R.drawable.adaptive_icon_drawable_wrapper)
|
||||
.mutate();
|
||||
}
|
||||
AdaptiveIconDrawable dr = (AdaptiveIconDrawable) mWrapperIcon;
|
||||
AdaptiveIconDrawable adaptiveIcon;
|
||||
float scale;
|
||||
adaptiveIcon = wrapToAdaptiveIcon(icon, outIconBounds);
|
||||
scale = getNormalizer().getScale(adaptiveIcon, outIconBounds, null, null);
|
||||
outScale[0] = scale;
|
||||
return adaptiveIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a drawable which draws the original drawable at a fixed scale
|
||||
*/
|
||||
private Drawable createScaledDrawable(@NonNull Drawable main, float scale) {
|
||||
float h = main.getIntrinsicHeight();
|
||||
float w = main.getIntrinsicWidth();
|
||||
float scaleX = scale;
|
||||
float scaleY = scale;
|
||||
if (h > w && w > 0) {
|
||||
scaleX *= w / h;
|
||||
} else if (w > h && h > 0) {
|
||||
scaleY *= h / w;
|
||||
}
|
||||
scaleX = (1 - scaleX) / 2;
|
||||
scaleY = (1 - scaleY) / 2;
|
||||
return new InsetDrawable(main, scaleX, scaleY, scaleX, scaleY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the provided icon in an adaptive icon drawable
|
||||
*/
|
||||
public AdaptiveIconDrawable wrapToAdaptiveIcon(@NonNull Drawable icon,
|
||||
@Nullable final RectF outIconBounds) {
|
||||
if (icon instanceof AdaptiveIconDrawable aid) {
|
||||
return aid;
|
||||
} else {
|
||||
EmptyWrapper foreground = new EmptyWrapper();
|
||||
AdaptiveIconDrawable dr = new AdaptiveIconDrawable(
|
||||
new ColorDrawable(mWrapperBackgroundColor), foreground);
|
||||
dr.setBounds(0, 0, 1, 1);
|
||||
boolean[] outShape = new boolean[1];
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
|
||||
float scale = getNormalizer().getScale(icon, outIconBounds, dr.getIconMask(), outShape);
|
||||
if (!outShape[0]) {
|
||||
FixedScaleDrawable fsd = ((FixedScaleDrawable) dr.getForeground());
|
||||
fsd.setDrawable(icon);
|
||||
fsd.setScale(scale);
|
||||
icon = dr;
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
((ColorDrawable) dr.getBackground()).setColor(mWrapperBackgroundColor);
|
||||
foreground.setDrawable(createScaledDrawable(icon, scale * LEGACY_ICON_SCALE));
|
||||
} else {
|
||||
foreground.setDrawable(createScaledDrawable(icon, 1 - getExtraInsetFraction()));
|
||||
}
|
||||
} else {
|
||||
scale = getNormalizer().getScale(icon, outIconBounds, null, null);
|
||||
return dr;
|
||||
}
|
||||
|
||||
outScale[0] = scale;
|
||||
return icon;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -376,6 +405,8 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
mOldBounds.set(icon.getBounds());
|
||||
|
||||
if (icon instanceof AdaptiveIconDrawable) {
|
||||
// We are ignoring KEY_SHADOW_DISTANCE because regular icons ignore this at the
|
||||
// moment b/298203449
|
||||
int offset = Math.max((int) Math.ceil(BLUR_FACTOR * size),
|
||||
Math.round(size * (1 - scale) / 2));
|
||||
// b/211896569: AdaptiveIconDrawable do not work properly for non top-left bounds
|
||||
@@ -464,28 +495,20 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
|
||||
public static class IconOptions {
|
||||
|
||||
boolean mShrinkNonAdaptiveIcons = true;
|
||||
|
||||
boolean mIsInstantApp;
|
||||
|
||||
boolean mIsCloneProfile;
|
||||
|
||||
@BitmapGenerationMode
|
||||
int mGenerationMode = MODE_WITH_SHADOW;
|
||||
|
||||
@Nullable UserHandle mUserHandle;
|
||||
@Nullable
|
||||
UserHandle mUserHandle;
|
||||
@Nullable
|
||||
UserIconInfo mUserIconInfo;
|
||||
|
||||
@ColorInt
|
||||
@Nullable Integer mExtractedColor;
|
||||
@Nullable
|
||||
Integer mExtractedColor;
|
||||
|
||||
/**
|
||||
* Set to false if non-adaptive icons should not be treated
|
||||
*/
|
||||
@NonNull
|
||||
public IconOptions setShrinkNonAdaptiveIcons(final boolean shrink) {
|
||||
mShrinkNonAdaptiveIcons = shrink;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* User for this icon, in case of badging
|
||||
@@ -496,6 +519,15 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* User for this icon, in case of badging
|
||||
*/
|
||||
@NonNull
|
||||
public IconOptions setUser(@Nullable final UserIconInfo user) {
|
||||
mUserIconInfo = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this icon represents an instant app
|
||||
*/
|
||||
@@ -523,15 +555,6 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
mGenerationMode = generationMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine the badge type for this icon.
|
||||
*/
|
||||
@NonNull
|
||||
public IconOptions setIsCloneProfile(boolean isCloneProfile) {
|
||||
mIsCloneProfile = isCloneProfile;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,4 +638,17 @@ public class BaseIconFactory implements AutoCloseable {
|
||||
mTextPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private static class EmptyWrapper extends DrawableWrapper {
|
||||
|
||||
EmptyWrapper() {
|
||||
super(new ColorDrawable());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
Drawable d = getDrawable();
|
||||
return d == null ? null : d.getConstantState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,10 @@
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -29,21 +29,25 @@ import com.android.launcher3.util.FlagOp;
|
||||
|
||||
public class BitmapInfo {
|
||||
|
||||
static final int FLAG_WORK = 1 << 0;
|
||||
static final int FLAG_INSTANT = 1 << 1;
|
||||
static final int FLAG_CLONE = 1 << 2;
|
||||
public static final int FLAG_WORK = 1 << 0;
|
||||
public static final int FLAG_INSTANT = 1 << 1;
|
||||
public static final int FLAG_CLONE = 1 << 2;
|
||||
public static final int FLAG_PRIVATE = 1 << 3;
|
||||
@IntDef(flag = true, value = {
|
||||
FLAG_WORK,
|
||||
FLAG_INSTANT,
|
||||
FLAG_CLONE
|
||||
FLAG_CLONE,
|
||||
FLAG_PRIVATE
|
||||
})
|
||||
@interface BitmapInfoFlags {}
|
||||
|
||||
public static final int FLAG_THEMED = 1 << 0;
|
||||
public static final int FLAG_NO_BADGE = 1 << 1;
|
||||
public static final int FLAG_SKIP_USER_BADGE = 1 << 2;
|
||||
@IntDef(flag = true, value = {
|
||||
FLAG_THEMED,
|
||||
FLAG_NO_BADGE,
|
||||
FLAG_SKIP_USER_BADGE,
|
||||
})
|
||||
public @interface DrawableCreationFlags {}
|
||||
|
||||
@@ -151,25 +155,50 @@ public class BitmapInfo {
|
||||
protected void applyFlags(Context context, FastBitmapDrawable drawable,
|
||||
@DrawableCreationFlags int creationFlags) {
|
||||
drawable.mDisabledAlpha = GraphicsUtils.getFloat(context, R.attr.disabledIconAlpha, 1f);
|
||||
drawable.mCreationFlags = creationFlags;
|
||||
if ((creationFlags & FLAG_NO_BADGE) == 0) {
|
||||
if (badgeInfo != null) {
|
||||
drawable.setBadge(badgeInfo.newIcon(context, creationFlags));
|
||||
} else if ((flags & FLAG_INSTANT) != 0) {
|
||||
drawable.setBadge(context.getDrawable(drawable.isThemed()
|
||||
? R.drawable.ic_instant_app_badge_themed
|
||||
: R.drawable.ic_instant_app_badge));
|
||||
} else if ((flags & FLAG_WORK) != 0) {
|
||||
drawable.setBadge(context.getDrawable(drawable.isThemed()
|
||||
? R.drawable.ic_work_app_badge_themed
|
||||
: R.drawable.ic_work_app_badge));
|
||||
} else if ((flags & FLAG_CLONE) != 0) {
|
||||
drawable.setBadge(context.getDrawable(drawable.isThemed()
|
||||
? R.drawable.ic_clone_app_badge_themed
|
||||
: R.drawable.ic_clone_app_badge));
|
||||
Drawable badge = getBadgeDrawable(context, (creationFlags & FLAG_THEMED) != 0,
|
||||
(creationFlags & FLAG_SKIP_USER_BADGE) != 0);
|
||||
if (badge != null) {
|
||||
drawable.setBadge(badge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Drawable getBadgeDrawable(Context context, boolean isThemed) {
|
||||
return getBadgeDrawable(context, isThemed, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a drawable representing the badge for this info
|
||||
*/
|
||||
@Nullable
|
||||
private Drawable getBadgeDrawable(Context context, boolean isThemed, boolean skipUserBadge) {
|
||||
if (badgeInfo != null) {
|
||||
int creationFlag = isThemed ? FLAG_THEMED : 0;
|
||||
if (skipUserBadge) {
|
||||
creationFlag |= FLAG_SKIP_USER_BADGE;
|
||||
}
|
||||
return badgeInfo.newIcon(context, creationFlag);
|
||||
}
|
||||
if (skipUserBadge) {
|
||||
return null;
|
||||
} else if ((flags & FLAG_INSTANT) != 0) {
|
||||
return new UserBadgeDrawable(context, R.drawable.ic_instant_app_badge,
|
||||
R.color.badge_tint_instant, isThemed);
|
||||
} else if ((flags & FLAG_WORK) != 0) {
|
||||
return new UserBadgeDrawable(context, R.drawable.ic_work_app_badge,
|
||||
R.color.badge_tint_work, isThemed);
|
||||
} else if ((flags & FLAG_CLONE) != 0) {
|
||||
return new UserBadgeDrawable(context, R.drawable.ic_clone_app_badge,
|
||||
R.color.badge_tint_clone, isThemed);
|
||||
} else if ((flags & FLAG_PRIVATE) != 0) {
|
||||
return new UserBadgeDrawable(context, R.drawable.ic_private_profile_app_badge,
|
||||
R.color.badge_tint_private, isThemed);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static BitmapInfo fromBitmap(@NonNull Bitmap bitmap) {
|
||||
return of(bitmap, 0);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ public class BubbleIconFactory extends BaseIconFactory {
|
||||
outScale = new float[1];
|
||||
}
|
||||
icon = normalizeAndWrapToAdaptiveIcon(icon,
|
||||
true /* shrinkNonAdaptiveIcons */,
|
||||
null /* outscale */,
|
||||
outScale);
|
||||
return createIconBitmap(icon, outScale[0], MODE_WITH_SHADOW);
|
||||
|
||||
@@ -56,6 +56,8 @@ import java.util.function.IntFunction;
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class ClockDrawableWrapper extends AdaptiveIconDrawable implements BitmapInfo.Extender {
|
||||
|
||||
public static boolean sRunningInTest = false;
|
||||
|
||||
private static final String TAG = "ClockDrawableWrapper";
|
||||
|
||||
private static final boolean DISABLE_SECONDS = true;
|
||||
@@ -477,7 +479,6 @@ public class ClockDrawableWrapper extends AdaptiveIconDrawable implements Bitmap
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
unscheduleSelf(this);
|
||||
final long upTime = SystemClock.uptimeMillis();
|
||||
final long step = TICK_MS; /* tick every 200 ms */
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import static com.android.launcher3.icons.BaseIconFactory.getBadgeSizeForIconSize;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
@@ -34,16 +36,23 @@ import android.util.FloatProperty;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.icons.BitmapInfo.DrawableCreationFlags;
|
||||
|
||||
public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
private static final Interpolator ACCEL = new AccelerateInterpolator();
|
||||
private static final Interpolator DEACCEL = new DecelerateInterpolator();
|
||||
private static final Interpolator HOVER_EMPHASIZED_DECELERATE_INTERPOLATOR =
|
||||
new PathInterpolator(0.05f, 0.7f, 0.1f, 1.0f);
|
||||
|
||||
private static final float PRESSED_SCALE = 1.1f;
|
||||
@VisibleForTesting protected static final float PRESSED_SCALE = 1.1f;
|
||||
@VisibleForTesting protected static final float HOVERED_SCALE = 1.1f;
|
||||
public static final int WHITE_SCRIM_ALPHA = 138;
|
||||
|
||||
private static final float DISABLED_DESATURATION = 1f;
|
||||
@@ -51,6 +60,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
protected static final int FULLY_OPAQUE = 255;
|
||||
|
||||
public static final int CLICK_FEEDBACK_DURATION = 200;
|
||||
public static final int HOVER_FEEDBACK_DURATION = 300;
|
||||
|
||||
private static boolean sFlagHoverEnabled = false;
|
||||
|
||||
protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
|
||||
protected final Bitmap mBitmap;
|
||||
@@ -58,12 +70,15 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
|
||||
@Nullable private ColorFilter mColorFilter;
|
||||
|
||||
private boolean mIsPressed;
|
||||
@VisibleForTesting protected boolean mIsPressed;
|
||||
@VisibleForTesting protected boolean mIsHovered;
|
||||
protected boolean mIsDisabled;
|
||||
float mDisabledAlpha = 1f;
|
||||
|
||||
@DrawableCreationFlags int mCreationFlags = 0;
|
||||
|
||||
// Animator and properties for the fast bitmap drawable's scale
|
||||
private static final FloatProperty<FastBitmapDrawable> SCALE
|
||||
@VisibleForTesting protected static final FloatProperty<FastBitmapDrawable> SCALE
|
||||
= new FloatProperty<FastBitmapDrawable>("scale") {
|
||||
@Override
|
||||
public Float get(FastBitmapDrawable fastBitmapDrawable) {
|
||||
@@ -76,7 +91,7 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
fastBitmapDrawable.invalidateSelf();
|
||||
}
|
||||
};
|
||||
private ObjectAnimator mScaleAnimation;
|
||||
@VisibleForTesting protected ObjectAnimator mScaleAnimation;
|
||||
private float mScale = 1;
|
||||
private int mAlpha = 255;
|
||||
|
||||
@@ -146,6 +161,14 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the drawable was created with theme, even if it doesn't
|
||||
* support theming itself.
|
||||
*/
|
||||
public boolean isCreatedForTheme() {
|
||||
return isThemed() || (mCreationFlags & FLAG_THEMED) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
mColorFilter = cf;
|
||||
@@ -163,6 +186,9 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
mAlpha = alpha;
|
||||
mPaint.setAlpha(alpha);
|
||||
invalidateSelf();
|
||||
if (mBadge != null) {
|
||||
mBadge.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,37 +249,41 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
@Override
|
||||
protected boolean onStateChange(int[] state) {
|
||||
boolean isPressed = false;
|
||||
boolean isHovered = false;
|
||||
for (int s : state) {
|
||||
if (s == android.R.attr.state_pressed) {
|
||||
isPressed = true;
|
||||
break;
|
||||
} else if (sFlagHoverEnabled && s == android.R.attr.state_hovered) {
|
||||
isHovered = true;
|
||||
// Do not break on hovered state, as pressed state should take precedence.
|
||||
}
|
||||
}
|
||||
if (mIsPressed != isPressed) {
|
||||
mIsPressed = isPressed;
|
||||
|
||||
if (mIsPressed != isPressed || mIsHovered != isHovered) {
|
||||
if (mScaleAnimation != null) {
|
||||
mScaleAnimation.cancel();
|
||||
mScaleAnimation = null;
|
||||
}
|
||||
|
||||
if (mIsPressed) {
|
||||
// Animate when going to pressed state
|
||||
mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, PRESSED_SCALE);
|
||||
mScaleAnimation.setDuration(CLICK_FEEDBACK_DURATION);
|
||||
mScaleAnimation.setInterpolator(ACCEL);
|
||||
mScaleAnimation.start();
|
||||
} else {
|
||||
float endScale = isPressed ? PRESSED_SCALE : (isHovered ? HOVERED_SCALE : 1f);
|
||||
if (mScale != endScale) {
|
||||
if (isVisible()) {
|
||||
mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, 1f);
|
||||
mScaleAnimation.setDuration(CLICK_FEEDBACK_DURATION);
|
||||
mScaleAnimation.setInterpolator(DEACCEL);
|
||||
Interpolator interpolator =
|
||||
isPressed != mIsPressed ? (isPressed ? ACCEL : DEACCEL)
|
||||
: HOVER_EMPHASIZED_DECELERATE_INTERPOLATOR;
|
||||
int duration =
|
||||
isPressed != mIsPressed ? CLICK_FEEDBACK_DURATION
|
||||
: HOVER_FEEDBACK_DURATION;
|
||||
mScaleAnimation = ObjectAnimator.ofFloat(this, SCALE, endScale);
|
||||
mScaleAnimation.setDuration(duration);
|
||||
mScaleAnimation.setInterpolator(interpolator);
|
||||
mScaleAnimation.start();
|
||||
} else {
|
||||
mScale = 1f;
|
||||
mScale = endScale;
|
||||
invalidateSelf();
|
||||
}
|
||||
}
|
||||
mIsPressed = isPressed;
|
||||
mIsHovered = isHovered;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -282,6 +312,11 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
updateFilter();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Drawable getBadge() {
|
||||
return mBadge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the paint to reflect the current brightness and saturation.
|
||||
*/
|
||||
@@ -304,6 +339,7 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
if (mBadge != null) {
|
||||
cs.mBadgeConstantState = mBadge.getConstantState();
|
||||
}
|
||||
cs.mCreationFlags = mCreationFlags;
|
||||
return cs;
|
||||
}
|
||||
|
||||
@@ -311,6 +347,11 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
return getDisabledColorFilter(1);
|
||||
}
|
||||
|
||||
// Returns if the FastBitmapDrawable contains a badge.
|
||||
public boolean hasBadge() {
|
||||
return (mCreationFlags & FLAG_NO_BADGE) == 0;
|
||||
}
|
||||
|
||||
private static ColorFilter getDisabledColorFilter(float disabledAlpha) {
|
||||
ColorMatrix tempBrightnessMatrix = new ColorMatrix();
|
||||
ColorMatrix tempFilterMatrix = new ColorMatrix();
|
||||
@@ -366,6 +407,13 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
unscheduleSelf(what);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether hover state functionality is enabled.
|
||||
*/
|
||||
public static void setFlagHoverEnabled(boolean isFlagHoverEnabled) {
|
||||
sFlagHoverEnabled = isFlagHoverEnabled;
|
||||
}
|
||||
|
||||
protected static class FastBitmapConstantState extends ConstantState {
|
||||
protected final Bitmap mBitmap;
|
||||
protected final int mIconColor;
|
||||
@@ -375,6 +423,8 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
protected boolean mIsDisabled;
|
||||
private ConstantState mBadgeConstantState;
|
||||
|
||||
@DrawableCreationFlags int mCreationFlags = 0;
|
||||
|
||||
public FastBitmapConstantState(Bitmap bitmap, int color) {
|
||||
mBitmap = bitmap;
|
||||
mIconColor = color;
|
||||
@@ -391,6 +441,7 @@ public class FastBitmapDrawable extends Drawable implements Drawable.Callback {
|
||||
if (mBadgeConstantState != null) {
|
||||
drawable.setBadge(mBadgeConstantState.newDrawable());
|
||||
}
|
||||
drawable.mCreationFlags = mCreationFlags;
|
||||
return drawable;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.DrawableWrapper;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Extension of {@link DrawableWrapper} which scales the child drawables by a fixed amount.
|
||||
*/
|
||||
public class FixedScaleDrawable extends DrawableWrapper {
|
||||
|
||||
// TODO b/33553066 use the constant defined in MaskableIconDrawable
|
||||
private static final float LEGACY_ICON_SCALE = .7f * .6667f;
|
||||
private float mScaleX, mScaleY;
|
||||
|
||||
public FixedScaleDrawable() {
|
||||
super(new ColorDrawable());
|
||||
mScaleX = LEGACY_ICON_SCALE;
|
||||
mScaleY = LEGACY_ICON_SCALE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
int saveCount = canvas.save();
|
||||
canvas.scale(mScaleX, mScaleY,
|
||||
getBounds().exactCenterX(), getBounds().exactCenterY());
|
||||
super.draw(canvas);
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) { }
|
||||
|
||||
@Override
|
||||
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) { }
|
||||
|
||||
public void setScale(float scale) {
|
||||
float h = getIntrinsicHeight();
|
||||
float w = getIntrinsicWidth();
|
||||
mScaleX = scale * LEGACY_ICON_SCALE;
|
||||
mScaleY = scale * LEGACY_ICON_SCALE;
|
||||
if (h > w && w > 0) {
|
||||
mScaleX *= w / h;
|
||||
} else if (w > h && h > 0) {
|
||||
mScaleY *= h / w;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,8 @@ public class ShadowGenerator {
|
||||
scale = (HALF_DISTANCE - BLUR_FACTOR) / (HALF_DISTANCE - minSide);
|
||||
}
|
||||
|
||||
float bottomSpace = BLUR_FACTOR + KEY_SHADOW_DISTANCE;
|
||||
// We are ignoring KEY_SHADOW_DISTANCE because regular icons ignore this at the moment b/298203449
|
||||
float bottomSpace = BLUR_FACTOR;
|
||||
if (bounds.bottom < bottomSpace) {
|
||||
scale = Math.min(scale,
|
||||
(HALF_DISTANCE - bottomSpace) / (HALF_DISTANCE - bounds.bottom));
|
||||
|
||||
@@ -15,16 +15,12 @@
|
||||
*/
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import static android.content.res.Configuration.UI_MODE_NIGHT_MASK;
|
||||
import static android.content.res.Configuration.UI_MODE_NIGHT_YES;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BlendMode;
|
||||
import android.graphics.BlendModeColorFilter;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
@@ -93,13 +89,6 @@ public class ThemedIconDrawable extends FastBitmapDrawable {
|
||||
return new ThemedConstantState(bitmapInfo, colorBg, colorFg);
|
||||
}
|
||||
|
||||
public void changeBackgroundColor(int colorBg) {
|
||||
if (mIsDisabled) return;
|
||||
|
||||
mBgPaint.setColorFilter(new BlendModeColorFilter(colorBg, BlendMode.SRC_IN));
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
static class ThemedConstantState extends FastBitmapConstantState {
|
||||
|
||||
final BitmapInfo bitmapInfo;
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.launcher3.icons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.DrawableWrapper;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
/**
|
||||
* A drawable used for drawing user badge. It draws a circle around the actual badge,
|
||||
* and has support for theming.
|
||||
*/
|
||||
public class UserBadgeDrawable extends DrawableWrapper {
|
||||
|
||||
private static final float VIEWPORT_SIZE = 24;
|
||||
private static final float CENTER = VIEWPORT_SIZE / 2;
|
||||
|
||||
private static final float BG_RADIUS = 11;
|
||||
private static final float SHADOW_RADIUS = 11.5f;
|
||||
private static final float SHADOW_OFFSET_Y = 0.25f;
|
||||
|
||||
@VisibleForTesting
|
||||
static final int SHADOW_COLOR = 0x11000000;
|
||||
|
||||
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private final int mBaseColor;
|
||||
private final int mBgColor;
|
||||
private boolean mShouldDrawBackground = true;
|
||||
|
||||
@VisibleForTesting
|
||||
public final boolean mIsThemed;
|
||||
|
||||
public UserBadgeDrawable(Context context, int badgeRes, int colorRes, boolean isThemed) {
|
||||
super(context.getDrawable(badgeRes));
|
||||
|
||||
mIsThemed = isThemed;
|
||||
if (isThemed) {
|
||||
mutate();
|
||||
mBaseColor = context.getColor(R.color.themed_badge_icon_color);
|
||||
mBgColor = context.getColor(R.color.themed_badge_icon_background_color);
|
||||
} else {
|
||||
mBaseColor = context.getColor(colorRes);
|
||||
mBgColor = Color.WHITE;
|
||||
}
|
||||
setTint(mBaseColor);
|
||||
}
|
||||
|
||||
private UserBadgeDrawable(Drawable base, int bgColor, int baseColor,
|
||||
boolean shouldDrawBackground) {
|
||||
super(base);
|
||||
mIsThemed = false;
|
||||
mBgColor = bgColor;
|
||||
mBaseColor = baseColor;
|
||||
mShouldDrawBackground = shouldDrawBackground;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas) {
|
||||
if (mShouldDrawBackground) {
|
||||
Rect b = getBounds();
|
||||
int saveCount = canvas.save();
|
||||
canvas.translate(b.left, b.top);
|
||||
canvas.scale(b.width() / VIEWPORT_SIZE, b.height() / VIEWPORT_SIZE);
|
||||
|
||||
mPaint.setColor(blendDrawableAlpha(SHADOW_COLOR));
|
||||
canvas.drawCircle(CENTER, CENTER + SHADOW_OFFSET_Y, SHADOW_RADIUS, mPaint);
|
||||
|
||||
mPaint.setColor(blendDrawableAlpha(mBgColor));
|
||||
canvas.drawCircle(CENTER, CENTER, BG_RADIUS, mPaint);
|
||||
|
||||
canvas.restoreToCount(saveCount);
|
||||
}
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
private @ColorInt int blendDrawableAlpha(@ColorInt int color) {
|
||||
int alpha = (int) (Color.valueOf(color).alpha() * getAlpha());
|
||||
return ColorUtils.setAlphaComponent(color, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(@Nullable ColorFilter filter) {
|
||||
if (filter == null) {
|
||||
super.setTint(mBaseColor);
|
||||
} else if (filter instanceof ColorMatrixColorFilter cf) {
|
||||
ColorMatrix cm = new ColorMatrix();
|
||||
cf.getColorMatrix(cm);
|
||||
|
||||
ColorMatrix cm2 = new ColorMatrix();
|
||||
float[] base = cm2.getArray();
|
||||
base[0] = Color.red(mBaseColor) / 255f;
|
||||
base[6] = Color.green(mBaseColor) / 255f;
|
||||
base[12] = Color.blue(mBaseColor) / 255f;
|
||||
base[18] = Color.alpha(mBaseColor) / 255f;
|
||||
cm2.postConcat(cm);
|
||||
|
||||
super.setColorFilter(new ColorMatrixColorFilter(cm2));
|
||||
} else {
|
||||
// fail safe
|
||||
Paint p = new Paint();
|
||||
p.setColorFilter(filter);
|
||||
Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
|
||||
new Canvas(b).drawPaint(p);
|
||||
super.setTint(b.getPixel(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void setShouldDrawBackground(boolean shouldDrawBackground) {
|
||||
mutate();
|
||||
mShouldDrawBackground = shouldDrawBackground;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantState getConstantState() {
|
||||
return new MyConstantState(
|
||||
getDrawable().getConstantState(), mBgColor, mBaseColor, mShouldDrawBackground);
|
||||
}
|
||||
|
||||
private static class MyConstantState extends ConstantState {
|
||||
|
||||
private final ConstantState mBase;
|
||||
private final int mBgColor;
|
||||
private final int mBaseColor;
|
||||
private final boolean mShouldDrawBackground;
|
||||
|
||||
MyConstantState(ConstantState base, int bgColor, int baseColor,
|
||||
boolean shouldDrawBackground) {
|
||||
mBase = base;
|
||||
mBgColor = bgColor;
|
||||
mBaseColor = baseColor;
|
||||
mShouldDrawBackground = shouldDrawBackground;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
return mBase.getChangingConfigurations();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Drawable newDrawable() {
|
||||
return new UserBadgeDrawable(
|
||||
mBase.newDrawable(), mBgColor, mBaseColor, mShouldDrawBackground);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Drawable newDrawable(Resources res) {
|
||||
return new UserBadgeDrawable(
|
||||
mBase.newDrawable(res), mBgColor, mBaseColor, mShouldDrawBackground);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Drawable newDrawable(Resources res, Theme theme) {
|
||||
return new UserBadgeDrawable(
|
||||
mBase.newDrawable(res, theme), mBgColor, mBaseColor, mShouldDrawBackground);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,6 @@ import android.os.Handler;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
@@ -133,6 +132,8 @@ public abstract class BaseIconCache {
|
||||
@NonNull
|
||||
private final Looper mBgLooper;
|
||||
|
||||
private volatile boolean mIconUpdateInProgress = false;
|
||||
|
||||
public BaseIconCache(@NonNull final Context context, @Nullable final String dbFileName,
|
||||
@NonNull final Looper bgLooper, final int iconDpi, final int iconPixelSize,
|
||||
final boolean inMemoryCache) {
|
||||
@@ -200,7 +201,8 @@ public abstract class BaseIconCache {
|
||||
if (resources != null && iconId != 0) {
|
||||
try {
|
||||
return resources.getDrawableForDensity(iconId, mIconDpi);
|
||||
} catch (Resources.NotFoundException e) { }
|
||||
} catch (Resources.NotFoundException e) {
|
||||
}
|
||||
}
|
||||
return getFullResDefaultActivityIcon(mIconDpi);
|
||||
}
|
||||
@@ -209,7 +211,8 @@ public abstract class BaseIconCache {
|
||||
public Drawable getFullResIcon(@NonNull final String packageName, final int iconId) {
|
||||
try {
|
||||
return getFullResIcon(mPackageManager.getResourcesForApplication(packageName), iconId);
|
||||
} catch (PackageManager.NameNotFoundException e) { }
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
return getFullResDefaultActivityIcon(mIconDpi);
|
||||
}
|
||||
|
||||
@@ -218,10 +221,19 @@ public abstract class BaseIconCache {
|
||||
try {
|
||||
return getFullResIcon(mPackageManager.getResourcesForApplication(info.applicationInfo),
|
||||
info.getIconResource());
|
||||
} catch (PackageManager.NameNotFoundException e) { }
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
return getFullResDefaultActivityIcon(mIconDpi);
|
||||
}
|
||||
|
||||
public void setIconUpdateInProgress(boolean updating) {
|
||||
mIconUpdateInProgress = updating;
|
||||
}
|
||||
|
||||
public boolean isIconUpdateInProgress() {
|
||||
return mIconUpdateInProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any records for the supplied ComponentName.
|
||||
*/
|
||||
@@ -236,13 +248,13 @@ public abstract class BaseIconCache {
|
||||
private void removeFromMemCacheLocked(@Nullable final String packageName,
|
||||
@Nullable final UserHandle user) {
|
||||
HashSet<ComponentKey> forDeletion = new HashSet<>();
|
||||
for (ComponentKey key: mCache.keySet()) {
|
||||
for (ComponentKey key : mCache.keySet()) {
|
||||
if (key.componentName.getPackageName().equals(packageName)
|
||||
&& key.user.equals(user)) {
|
||||
forDeletion.add(key);
|
||||
}
|
||||
}
|
||||
for (ComponentKey condemned: forDeletion) {
|
||||
for (ComponentKey condemned : forDeletion) {
|
||||
mCache.remove(condemned);
|
||||
}
|
||||
}
|
||||
@@ -299,6 +311,7 @@ public abstract class BaseIconCache {
|
||||
|
||||
/**
|
||||
* Adds an entry into the DB and the in-memory cache.
|
||||
*
|
||||
* @param replaceExisting if true, it will recreate the bitmap even if it already exists in
|
||||
* the memory. This is useful then the previous bitmap was created using
|
||||
* old data.
|
||||
@@ -329,9 +342,11 @@ public abstract class BaseIconCache {
|
||||
if (entry.bitmap.isNullOrLowRes()) return;
|
||||
|
||||
CharSequence entryTitle = cachingLogic.getLabel(object);
|
||||
if (entryTitle == null) {
|
||||
Log.wtf(TAG, "No label returned from caching logic instance: " + cachingLogic);
|
||||
entryTitle = "";
|
||||
if (TextUtils.isEmpty(entryTitle)) {
|
||||
if (entryTitle == null) {
|
||||
Log.wtf(TAG, "No label returned from caching logic instance: " + cachingLogic);
|
||||
}
|
||||
entryTitle = componentName.getPackageName();
|
||||
}
|
||||
entry.title = entryTitle;
|
||||
|
||||
@@ -346,6 +361,7 @@ public abstract class BaseIconCache {
|
||||
|
||||
/**
|
||||
* Updates {@param values} to contain versioning information and adds it to the DB.
|
||||
*
|
||||
* @param values {@link ContentValues} containing icon & title
|
||||
*/
|
||||
private void addIconToDB(@NonNull final ContentValues values, @NonNull final ComponentName key,
|
||||
@@ -466,8 +482,10 @@ public abstract class BaseIconCache {
|
||||
if (usePackageIcon) {
|
||||
CacheEntry packageEntry = getEntryForPackageLocked(
|
||||
componentName.getPackageName(), user, false);
|
||||
if (DEBUG) Log.d(TAG, "using package default icon for " +
|
||||
componentName.toShortString());
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "using package default icon for "
|
||||
+ componentName.toShortString());
|
||||
}
|
||||
entry.bitmap = packageEntry.bitmap;
|
||||
entry.contentDescription = packageEntry.contentDescription;
|
||||
|
||||
@@ -490,13 +508,16 @@ public abstract class BaseIconCache {
|
||||
@NonNull final T object, @NonNull final CacheEntry entry,
|
||||
@NonNull final CachingLogic<T> cachingLogic, @NonNull final UserHandle user) {
|
||||
entry.title = cachingLogic.getLabel(object);
|
||||
if (TextUtils.isEmpty(entry.title)) {
|
||||
entry.title = cachingLogic.getComponent(object).getPackageName();
|
||||
}
|
||||
entry.contentDescription = getUserBadgedLabel(
|
||||
cachingLogic.getDescription(object, entry.title), user);
|
||||
}
|
||||
|
||||
public synchronized void clear() {
|
||||
public synchronized void clearMemoryCache() {
|
||||
assertWorkerThread();
|
||||
mIconDb.clear();
|
||||
mCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,6 +562,7 @@ public abstract class BaseIconCache {
|
||||
*/
|
||||
@WorkerThread
|
||||
@NonNull
|
||||
@SuppressWarnings("NewApi")
|
||||
protected CacheEntry getEntryForPackageLocked(@NonNull final String packageName,
|
||||
@NonNull final UserHandle user, final boolean useLowResIcon) {
|
||||
assertWorkerThread();
|
||||
@@ -554,26 +576,39 @@ public abstract class BaseIconCache {
|
||||
// Check the DB first.
|
||||
if (!getEntryFromDBLocked(cacheKey, entry, useLowResIcon)) {
|
||||
try {
|
||||
int flags = Process.myUserHandle().equals(user) ? 0 :
|
||||
long flags = Process.myUserHandle().equals(user) ? 0 :
|
||||
PackageManager.GET_UNINSTALLED_PACKAGES;
|
||||
PackageInfo info = mPackageManager.getPackageInfo(packageName, flags);
|
||||
flags |= PackageManager.MATCH_ARCHIVED_PACKAGES;
|
||||
PackageInfo info = mPackageManager.getPackageInfo(packageName,
|
||||
PackageManager.PackageInfoFlags.of(flags));
|
||||
ApplicationInfo appInfo = info.applicationInfo;
|
||||
if (appInfo == null) {
|
||||
throw new NameNotFoundException("ApplicationInfo is null");
|
||||
NameNotFoundException e = new NameNotFoundException(
|
||||
"ApplicationInfo is null");
|
||||
logdPersistently(TAG,
|
||||
String.format("ApplicationInfo is null for %s", packageName),
|
||||
e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
BaseIconFactory li = getIconFactory();
|
||||
// Load the full res icon for the application, but if useLowResIcon is set, then
|
||||
// only keep the low resolution icon instead of the larger full-sized icon
|
||||
BitmapInfo iconInfo = li.createBadgedIconBitmap(
|
||||
appInfo.loadIcon(mPackageManager),
|
||||
Drawable appIcon = appInfo.loadIcon(mPackageManager);
|
||||
if (mPackageManager.isDefaultApplicationIcon(appIcon)) {
|
||||
logdPersistently(TAG,
|
||||
String.format("Default icon returned for %s", packageName),
|
||||
null);
|
||||
}
|
||||
BitmapInfo iconInfo = li.createBadgedIconBitmap(appIcon,
|
||||
new IconOptions().setUser(user).setInstantApp(isInstantApp(appInfo)));
|
||||
li.close();
|
||||
|
||||
entry.title = appInfo.loadLabel(mPackageManager);
|
||||
entry.contentDescription = getUserBadgedLabel(entry.title, user);
|
||||
entry.bitmap = BitmapInfo.of(
|
||||
useLowResIcon ? LOW_RES_ICON : iconInfo.icon, iconInfo.color);
|
||||
entry.bitmap = useLowResIcon
|
||||
? BitmapInfo.of(LOW_RES_ICON, iconInfo.color)
|
||||
: iconInfo;
|
||||
|
||||
// Add the icon in the DB here, since these do not get written during
|
||||
// package updates.
|
||||
@@ -700,17 +735,19 @@ public abstract class BaseIconCache {
|
||||
public static final String COLUMN_SYSTEM_STATE = "system_state";
|
||||
public static final String COLUMN_KEYWORDS = "keywords";
|
||||
|
||||
public static final String[] COLUMNS_LOW_RES = new String[] {
|
||||
public static final String[] COLUMNS_LOW_RES = new String[]{
|
||||
COLUMN_COMPONENT,
|
||||
COLUMN_LABEL,
|
||||
COLUMN_ICON_COLOR,
|
||||
COLUMN_FLAGS};
|
||||
public static final String[] COLUMNS_HIGH_RES = Arrays.copyOf(COLUMNS_LOW_RES,
|
||||
COLUMNS_LOW_RES.length + 2, String[].class);
|
||||
|
||||
static {
|
||||
COLUMNS_HIGH_RES[COLUMNS_LOW_RES.length] = COLUMN_ICON;
|
||||
COLUMNS_HIGH_RES[COLUMNS_LOW_RES.length + 1] = COLUMN_MONO_ICON;
|
||||
}
|
||||
|
||||
private static final int INDEX_TITLE = Arrays.asList(COLUMNS_LOW_RES).indexOf(COLUMN_LABEL);
|
||||
private static final int INDEX_COLOR = Arrays.asList(COLUMNS_LOW_RES)
|
||||
.indexOf(COLUMN_ICON_COLOR);
|
||||
@@ -778,4 +815,9 @@ public abstract class BaseIconCache {
|
||||
throw new IllegalStateException("Cache accessed on wrong thread " + Looper.myLooper());
|
||||
}
|
||||
}
|
||||
|
||||
/** Log to Log.d. Subclasses can override this method to log persistently for debugging. */
|
||||
protected void logdPersistently(String tag, String message, @Nullable Exception e) {
|
||||
Log.d(tag, message, e);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.icons.cache;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A runnable that can be posted to a {@link Handler} which can be canceled.
|
||||
*/
|
||||
public class HandlerRunnable<T> implements Runnable {
|
||||
|
||||
private final Handler mWorkerHandler;
|
||||
private final Supplier<T> mTask;
|
||||
|
||||
private final Executor mCallbackExecutor;
|
||||
private final Consumer<T> mCallback;
|
||||
private final Runnable mEndRunnable;
|
||||
|
||||
private boolean mEnded = false;
|
||||
private boolean mCanceled = false;
|
||||
|
||||
public HandlerRunnable(Handler workerHandler, Supplier<T> task, Executor callbackExecutor,
|
||||
Consumer<T> callback) {
|
||||
this(workerHandler, task, callbackExecutor, callback, () -> { });
|
||||
}
|
||||
|
||||
public HandlerRunnable(Handler workerHandler, Supplier<T> task, Executor callbackExecutor,
|
||||
Consumer<T> callback, Runnable endRunnable) {
|
||||
mWorkerHandler = workerHandler;
|
||||
mTask = task;
|
||||
mCallbackExecutor = callbackExecutor;
|
||||
mCallback = callback;
|
||||
mEndRunnable = endRunnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels this runnable from being run, only if it has not already run.
|
||||
*/
|
||||
public void cancel() {
|
||||
mWorkerHandler.removeCallbacks(this);
|
||||
mCanceled = true;
|
||||
mCallbackExecutor.execute(this::onEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
T value = mTask.get();
|
||||
mCallbackExecutor.execute(() -> {
|
||||
if (!mCanceled) {
|
||||
mCallback.accept(value);
|
||||
}
|
||||
onEnd();
|
||||
});
|
||||
}
|
||||
|
||||
private void onEnd() {
|
||||
if (!mEnded) {
|
||||
mEnded = true;
|
||||
mEndRunnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-12
@@ -30,13 +30,13 @@ import android.util.SparseBooleanArray;
|
||||
|
||||
import com.android.launcher3.icons.cache.BaseIconCache.IconDB;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Utility class to handle updating the Icon cache
|
||||
@@ -57,7 +57,7 @@ public class IconCacheUpdateHandler {
|
||||
*/
|
||||
private static final boolean MODE_CLEAR_VALID_ITEMS = false;
|
||||
|
||||
private static final Object ICON_UPDATE_TOKEN = new Object();
|
||||
static final Object ICON_UPDATE_TOKEN = new Object();
|
||||
|
||||
private final HashMap<String, PackageInfo> mPkgInfoMap;
|
||||
private final BaseIconCache mIconCache;
|
||||
@@ -101,6 +101,7 @@ public class IconCacheUpdateHandler {
|
||||
/**
|
||||
* Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
|
||||
* the DB and are updated.
|
||||
*
|
||||
* @return The set of packages for which icons have updated.
|
||||
*/
|
||||
public <T> void updateIcons(List<T> apps, CachingLogic<T> cachingLogic,
|
||||
@@ -130,6 +131,7 @@ public class IconCacheUpdateHandler {
|
||||
/**
|
||||
* Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
|
||||
* the DB and are updated.
|
||||
*
|
||||
* @return The set of packages for which icons have updated.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -141,7 +143,7 @@ public class IconCacheUpdateHandler {
|
||||
}
|
||||
long userSerial = mIconCache.getSerialNumberForUser(user);
|
||||
|
||||
Stack<T> appsToUpdate = new Stack<>();
|
||||
ArrayDeque<T> appsToUpdate = new ArrayDeque<>();
|
||||
|
||||
try (Cursor c = mIconCache.mIconDb.query(
|
||||
new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
|
||||
@@ -183,7 +185,7 @@ public class IconCacheUpdateHandler {
|
||||
if (version == info.versionCode
|
||||
&& updateTime == cachingLogic.getLastUpdatedTime(app, info)
|
||||
&& TextUtils.equals(c.getString(systemStateIndex),
|
||||
mIconCache.getIconSystemState(info.packageName))) {
|
||||
mIconCache.getIconSystemState(info.packageName))) {
|
||||
|
||||
if (mFilterMode == MODE_CLEAR_VALID_ITEMS) {
|
||||
mItemsToDelete.put(rowId, false);
|
||||
@@ -207,8 +209,9 @@ public class IconCacheUpdateHandler {
|
||||
|
||||
// Insert remaining apps.
|
||||
if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
|
||||
Stack<T> appsToAdd = new Stack<>();
|
||||
ArrayDeque<T> appsToAdd = new ArrayDeque<>();
|
||||
appsToAdd.addAll(componentMap.values());
|
||||
mIconCache.setIconUpdateInProgress(true);
|
||||
new SerializedIconUpdateTask(userSerial, user, appsToAdd, appsToUpdate, cachingLogic,
|
||||
onUpdateCallback).scheduleNext();
|
||||
}
|
||||
@@ -226,7 +229,7 @@ public class IconCacheUpdateHandler {
|
||||
.append(" IN (");
|
||||
|
||||
int count = mItemsToDelete.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (mItemsToDelete.valueAt(i)) {
|
||||
if (deleteCount > 0) {
|
||||
queryBuilder.append(", ");
|
||||
@@ -250,14 +253,14 @@ public class IconCacheUpdateHandler {
|
||||
private class SerializedIconUpdateTask<T> implements Runnable {
|
||||
private final long mUserSerial;
|
||||
private final UserHandle mUserHandle;
|
||||
private final Stack<T> mAppsToAdd;
|
||||
private final Stack<T> mAppsToUpdate;
|
||||
private final ArrayDeque<T> mAppsToAdd;
|
||||
private final ArrayDeque<T> mAppsToUpdate;
|
||||
private final CachingLogic<T> mCachingLogic;
|
||||
private final HashSet<String> mUpdatedPackages = new HashSet<>();
|
||||
private final OnUpdateCallback mOnUpdateCallback;
|
||||
|
||||
SerializedIconUpdateTask(long userSerial, UserHandle userHandle,
|
||||
Stack<T> appsToAdd, Stack<T> appsToUpdate, CachingLogic<T> cachingLogic,
|
||||
ArrayDeque<T> appsToAdd, ArrayDeque<T> appsToUpdate, CachingLogic<T> cachingLogic,
|
||||
OnUpdateCallback onUpdateCallback) {
|
||||
mUserHandle = userHandle;
|
||||
mUserSerial = userSerial;
|
||||
@@ -270,7 +273,7 @@ public class IconCacheUpdateHandler {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!mAppsToUpdate.isEmpty()) {
|
||||
T app = mAppsToUpdate.pop();
|
||||
T app = mAppsToUpdate.removeLast();
|
||||
String pkg = mCachingLogic.getComponent(app).getPackageName();
|
||||
PackageInfo info = mPkgInfoMap.get(pkg);
|
||||
|
||||
@@ -286,8 +289,9 @@ public class IconCacheUpdateHandler {
|
||||
// Let it run one more time.
|
||||
scheduleNext();
|
||||
} else if (!mAppsToAdd.isEmpty()) {
|
||||
T app = mAppsToAdd.pop();
|
||||
PackageInfo info = mPkgInfoMap.get(mCachingLogic.getComponent(app).getPackageName());
|
||||
T app = mAppsToAdd.removeLast();
|
||||
PackageInfo info = mPkgInfoMap.get(
|
||||
mCachingLogic.getComponent(app).getPackageName());
|
||||
// We do not check the mPkgInfoMap when generating the mAppsToAdd. Although every
|
||||
// app should have package info, this is not guaranteed by the api
|
||||
if (info != null) {
|
||||
@@ -297,6 +301,10 @@ public class IconCacheUpdateHandler {
|
||||
|
||||
if (!mAppsToAdd.isEmpty()) {
|
||||
scheduleNext();
|
||||
} else if (!mIconCache.mWorkerHandler.hasMessages(0, ICON_UPDATE_TOKEN)) {
|
||||
// This checks if there is a second icon update process happening
|
||||
// before notifying BaseIconCache that the updates are over
|
||||
mIconCache.setIconUpdateInProgress(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.launcher3.util;
|
||||
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_CLONE;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_PRIVATE;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_WORK;
|
||||
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Data class which stores various properties of a {@link android.os.UserHandle}
|
||||
* which affects rendering
|
||||
*/
|
||||
public class UserIconInfo {
|
||||
|
||||
public static final int TYPE_MAIN = 0;
|
||||
public static final int TYPE_WORK = 1;
|
||||
public static final int TYPE_CLONED = 2;
|
||||
|
||||
public static final int TYPE_PRIVATE = 3;
|
||||
|
||||
@IntDef({TYPE_MAIN, TYPE_WORK, TYPE_CLONED, TYPE_PRIVATE})
|
||||
public @interface UserType { }
|
||||
|
||||
public final UserHandle user;
|
||||
@UserType
|
||||
public final int type;
|
||||
|
||||
public final long userSerial;
|
||||
|
||||
public UserIconInfo(UserHandle user, @UserType int type) {
|
||||
this(user, type, user != null ? user.hashCode() : 0);
|
||||
}
|
||||
|
||||
public UserIconInfo(UserHandle user, @UserType int type, long userSerial) {
|
||||
this.user = user;
|
||||
this.type = type;
|
||||
this.userSerial = userSerial;
|
||||
}
|
||||
|
||||
public boolean isMain() {
|
||||
return type == TYPE_MAIN;
|
||||
}
|
||||
|
||||
public boolean isWork() {
|
||||
return type == TYPE_WORK;
|
||||
}
|
||||
|
||||
public boolean isCloned() {
|
||||
return type == TYPE_CLONED;
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return type == TYPE_PRIVATE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public FlagOp applyBitmapInfoFlags(@NonNull FlagOp op) {
|
||||
return op.setFlag(FLAG_WORK, isWork())
|
||||
.setFlag(FLAG_CLONE, isCloned())
|
||||
.setFlag(FLAG_PRIVATE, isPrivate());
|
||||
}
|
||||
}
|
||||
@@ -68,14 +68,14 @@ public class SimpleIconCache extends BaseIconCache {
|
||||
@Override
|
||||
protected long getSerialNumberForUser(@NonNull UserHandle user) {
|
||||
synchronized (mUserSerialMap) {
|
||||
int index = mUserSerialMap.indexOfKey(user.hashCode());
|
||||
// int index = mUserSerialMap.indexOfKey(user.getIdentifier());
|
||||
int index = mUserSerialMap.indexOfKey(0);
|
||||
if (index >= 0) {
|
||||
return mUserSerialMap.valueAt(index);
|
||||
}
|
||||
long serial = mUserManager.getSerialNumberForUser(user);
|
||||
mUserSerialMap.put(user.hashCode(), serial);
|
||||
// mUserSerialMap.put(user.getIdentifier(), serial);
|
||||
mUserSerialMap.put(0, serial);
|
||||
return serial;
|
||||
}
|
||||
}
|
||||
@@ -88,8 +88,8 @@ public class SimpleIconCache extends BaseIconCache {
|
||||
|
||||
@Override
|
||||
protected boolean isInstantApp(@NonNull ApplicationInfo info) {
|
||||
// return info.isInstantApp();
|
||||
return false;
|
||||
// return info.isInstantApp();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
+28
-139
@@ -1,148 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
|
||||
<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01">
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 28 (current min is 26): `android.app.Person#getKey`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/notification/NotificationKeyData.java"
|
||||
line="72"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 29 (current min is 26): `android.content.res.Resources#getFloat`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/util/DynamicResource.java"
|
||||
line="73"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 30 (current min is 26): `android.graphics.Outline#setPath`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/popup/RoundedArrowDrawable.java"
|
||||
line="114"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 30 (current min is 26): `android.view.View#getWindowInsetsController`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java"
|
||||
line="902"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 30 (current min is 26): `android.view.WindowInsets.Type#ime`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java"
|
||||
line="902"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 30 (current min is 26): `android.view.WindowInsetsController#hide`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java"
|
||||
line="902"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 31 (current min is 26): `android.appwidget.AppWidgetHostView#resetColorResources`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java"
|
||||
line="114"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 31 (current min is 30): `android.appwidget.AppWidgetHostView#setColorResources`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java"
|
||||
line="415"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Field requires API level 28 (current min is 26): `android.appwidget.AppWidgetProviderInfo#widgetFeatures`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/widget/WidgetAddFlowHandler.java"
|
||||
line="93"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_LEFT`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
|
||||
line="1814"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_LEFT`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
|
||||
line="1824"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_RIGHT`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
|
||||
line="1815"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_RIGHT`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
|
||||
line="1823"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Method reference requires API level 28 (current min is 26): `Person::getKey`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/model/data/WorkspaceItemInfo.java"
|
||||
line="195"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Method reference requires API level 28 (current min is 26): `Person::getKey`">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/notification/NotificationKeyData.java"
|
||||
line="73"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="`?android:attr/dialogCornerRadius` requires API level 28 (current min is 26)">
|
||||
<location
|
||||
file="packages/apps/Launcher3/res/drawable/add_item_dialog_background.xml"
|
||||
line="6"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="`?android:attr/dialogCornerRadius` requires API level 28 (current min is 26)">
|
||||
<location
|
||||
file="packages/apps/Launcher3/res/drawable/add_item_dialog_background.xml"
|
||||
line="7"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="`@android:dimen/system_app_widget_background_radius` requires API level 31 (current min is 26)">
|
||||
message="`@android:dimen/system_app_widget_background_radius` requires API level 31 (current min is 26)"
|
||||
errorLine1=' <corners android:radius="@android:dimen/system_app_widget_background_radius" />'
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="packages/apps/Launcher3/res/drawable/widget_resize_frame.xml"
|
||||
line="20"/>
|
||||
line="20"
|
||||
column="14"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 31 (current min is 26): `android.appwidget.AppWidgetHostView#resetColorResources`"
|
||||
errorLine1=" resetColorResources();"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java"
|
||||
line="117"
|
||||
column="13"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 31 (current min is 30): `android.appwidget.AppWidgetHostView#setColorResources`"
|
||||
errorLine1=" view.setColorResources(mWallpaperColorResources);"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java"
|
||||
line="433"
|
||||
column="18"/>
|
||||
</issue>
|
||||
|
||||
</issues>
|
||||
@@ -38,7 +38,7 @@ message ItemInfo {
|
||||
optional int32 rank = 5;
|
||||
|
||||
// Stores whether the Item belows to non primary user
|
||||
optional bool is_work = 6;
|
||||
optional bool is_work = 6 [deprecated = true];
|
||||
|
||||
// Item can be child node to parent container or parent containers (nested)
|
||||
optional ContainerInfo container_info = 7;
|
||||
@@ -48,6 +48,9 @@ message ItemInfo {
|
||||
|
||||
// Stores whether the navigation bar is in kids mode.
|
||||
optional bool is_kids_mode = 13;
|
||||
|
||||
// Stores type of the user the Item belong to
|
||||
optional int32 user_type = 14;
|
||||
}
|
||||
|
||||
message LauncherAttributes{
|
||||
@@ -118,6 +121,20 @@ message SettingsContainer {
|
||||
}
|
||||
|
||||
message TaskSwitcherContainer {
|
||||
/**
|
||||
* Indicates the current OrientationHandler in use in Overview.
|
||||
* In fake landscape, the value will be
|
||||
* {@link com.android.quickstep.orientation.LandscapePagedViewHandler} and in real landscape,
|
||||
* the value will be {@link com.android.quickstep.orientation.PortraitPagedViewHandler} for
|
||||
* example.
|
||||
*/
|
||||
optional OrientationHandler orientation_handler = 1;
|
||||
|
||||
enum OrientationHandler {
|
||||
PORTRAIT = 0;
|
||||
LANDSCAPE = 1;
|
||||
SEASCAPE = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Container for taskbar.
|
||||
@@ -135,7 +152,7 @@ message TaskBarContainer {
|
||||
}
|
||||
}
|
||||
|
||||
// Next value 51
|
||||
// Next value 54
|
||||
enum Attribute {
|
||||
option allow_alias = true;
|
||||
|
||||
@@ -180,13 +197,16 @@ enum Attribute {
|
||||
ALL_APPS_SEARCH_RESULT_CHROMETAB = 24;
|
||||
ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25 [deprecated = true];
|
||||
ALL_APPS_SEARCH_RESULT_TIPS = 26;
|
||||
ALL_APPS_SEARCH_RESULT_PEOPLE_TILE = 27;
|
||||
ALL_APPS_SEARCH_RESULT_QS_TILE = 27;
|
||||
ALL_APPS_SEARCH_RESULT_PEOPLE_TILE = 27 [deprecated = true];
|
||||
ALL_APPS_SEARCH_RESULT_LEGACY_SHORTCUT = 30;
|
||||
ALL_APPS_SEARCH_RESULT_ASSISTANT_MEMORY = 31;
|
||||
ALL_APPS_SEARCH_RESULT_VIDEO = 41;
|
||||
ALL_APPS_SEARCH_RESULT_SYSTEM_POINTER = 42;
|
||||
ALL_APPS_SEARCH_RESULT_EDUCARD = 43;
|
||||
ALL_APPS_SEARCH_RESULT_LOCATION = 50;
|
||||
ALL_APPS_SEARCH_RESULT_TEXT_HEADER = 51;
|
||||
ALL_APPS_SEARCH_RESULT_NO_FULFILLMENT = 52;
|
||||
|
||||
// Result sources
|
||||
DATA_SOURCE_APPSEARCH_APP_PREVIEW = 45;
|
||||
@@ -194,6 +214,7 @@ enum Attribute {
|
||||
DATA_SOURCE_APPSEARCH_CATEGORY_SRP_PREVIEW = 48;
|
||||
DATA_SOURCE_APPSEARCH_ENTITY_SRP_PREVIEW = 49;
|
||||
DATA_SOURCE_AIAI_SEARCH_ROOT = 47;
|
||||
DATA_SOURCE_LAUNCHER = 53;
|
||||
|
||||
// Web suggestions provided by AGA
|
||||
ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39;
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+16
-5
@@ -23,15 +23,23 @@ filegroup {
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "launcher3-quickstep-robolectric-src",
|
||||
path: "robolectric_tests",
|
||||
srcs: ["robolectric_tests/src/**/*.java"],
|
||||
name: "launcher3-quickstep-robo-src",
|
||||
path: "tests/multivalentTests",
|
||||
srcs: [
|
||||
"tests/multivalentTests/src/**/*.java",
|
||||
"tests/multivalentTests/src/**/*.kt",
|
||||
],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "launcher3-quickstep-tests-src",
|
||||
path: "tests",
|
||||
srcs: ["tests/src/**/*.java", "tests/src/**/*.kt"],
|
||||
srcs: [
|
||||
"tests/multivalentTests/src/**/*.java",
|
||||
"tests/multivalentTests/src/**/*.kt",
|
||||
"tests/src/**/*.java",
|
||||
"tests/src/**/*.kt",
|
||||
],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
@@ -41,6 +49,9 @@ filegroup {
|
||||
"tests/src/com/android/quickstep/TaskbarModeSwitchRule.java",
|
||||
"tests/src/com/android/quickstep/NavigationModeSwitchRule.java",
|
||||
"tests/src/com/android/quickstep/AbstractQuickStepTest.java",
|
||||
"tests/src/com/android/quickstep/TaplOverviewIconTest.java",
|
||||
"tests/src/com/android/quickstep/TaplTestsQuickstep.java",
|
||||
]
|
||||
"tests/src/com/android/quickstep/TaplTestsSplitscreen.java",
|
||||
"tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java"
|
||||
],
|
||||
}
|
||||
@@ -20,7 +20,6 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.launcher3">
|
||||
<uses-sdk android:targetSdkVersion="33" android:minSdkVersion="26"/>
|
||||
<!--
|
||||
Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
|
||||
Refer comments around specific entries on how to extend individual components.
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
<uses-permission android:name="android.permission.REMOVE_TASKS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
|
||||
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
|
||||
<uses-permission android:name="android.permission.STATUS_BAR"/>
|
||||
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.STOP_APP_SWITCHES"/>
|
||||
<uses-permission android:name="android.permission.SET_ORIENTATION"/>
|
||||
<uses-permission android:name="android.permission.READ_FRAME_BUFFER"/>
|
||||
@@ -41,6 +43,16 @@
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY" />
|
||||
|
||||
<!--
|
||||
Permission required to access profiles which are otherwise hidden
|
||||
from being visible via APIs, e.g. private profile.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.ACCESS_HIDDEN_PROFILES_FULL" />
|
||||
|
||||
<!-- Permission required to start a WidgetPickerActivity. -->
|
||||
<permission android:name="${applicationId}.permission.START_WIDGET_PICKER_ACTIVITY"
|
||||
android:protectionLevel="signature|privileged" />
|
||||
|
||||
<application android:backupAgent="com.android.launcher3.LauncherBackupAgent"
|
||||
android:fullBackupOnly="true"
|
||||
android:fullBackupContent="@xml/backupscheme"
|
||||
@@ -67,15 +79,16 @@
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:stateNotNeeded="true"
|
||||
android:theme="@style/LauncherTheme"
|
||||
android:screenOrientation="unspecified"
|
||||
android:screenOrientation="behind"
|
||||
android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
|
||||
android:resizeableActivity="true"
|
||||
android:resumeWhilePausing="true"
|
||||
android:enableOnBackInvokedCallback="false"
|
||||
android:taskAffinity=""/>
|
||||
|
||||
<!-- Content provider to settings search. The autority should be same as the packageName -->
|
||||
<provider android:name="com.android.quickstep.LauncherSearchIndexablesProvider"
|
||||
android:authorities="${packageName}"
|
||||
android:authorities="${applicationId}"
|
||||
android:grantUriPermissions="true"
|
||||
android:multiprocess="true"
|
||||
android:permission="android.permission.READ_SEARCH_INDEXABLES"
|
||||
@@ -87,7 +100,7 @@
|
||||
|
||||
<!-- FileProvider used for sharing images. -->
|
||||
<provider android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${packageName}.overview.fileprovider"
|
||||
android:authorities="${applicationId}.overview.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
@@ -95,10 +108,11 @@
|
||||
</provider>
|
||||
|
||||
<activity android:name="com.android.launcher3.proxy.ProxyActivityStarter"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTask"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:exported="false"/>
|
||||
android:theme="@style/ProxyActivityStarterTheme"
|
||||
android:launchMode="singleTask"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:exported="false"
|
||||
/>
|
||||
|
||||
<activity android:name="com.android.quickstep.interaction.GestureSandboxActivity"
|
||||
android:autoRemoveFromRecents="true"
|
||||
@@ -130,6 +144,20 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="com.android.launcher3.WidgetPickerActivity"
|
||||
android:theme="@style/WidgetPickerActivityTheme"
|
||||
android:excludeFromRecents="true"
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:showOnLockScreen="true"
|
||||
android:launchMode="singleTop"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.START_WIDGET_PICKER_ACTIVITY">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PICK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.quickstep;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.testing.DebugTestInformationHandler;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
|
||||
/**
|
||||
* Class to handle requests from tests, including debug ones, to Quickstep Launcher builds.
|
||||
*/
|
||||
public abstract class DebugQuickstepTestInformationHandler extends QuickstepTestInformationHandler {
|
||||
|
||||
private final DebugTestInformationHandler mDebugTestInformationHandler;
|
||||
|
||||
public DebugQuickstepTestInformationHandler(Context context) {
|
||||
super(context);
|
||||
mDebugTestInformationHandler = new DebugTestInformationHandler(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String method, String arg, @Nullable Bundle extras) {
|
||||
Bundle response = new Bundle();
|
||||
if (TestProtocol.REQUEST_RECREATE_TASKBAR.equals(method)) {
|
||||
// Allow null-pointer to catch illegal states.
|
||||
runOnTISBinder(tisBinder -> tisBinder.getTaskbarManager().recreateTaskbar());
|
||||
return response;
|
||||
}
|
||||
response = super.call(method, arg, extras);
|
||||
if (response != null) return response;
|
||||
return mDebugTestInformationHandler.call(method, arg, extras);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ message DeviceSearchResultContainer{
|
||||
// For application, it will be the column number in the apps row.
|
||||
optional int32 grid_x = 3;
|
||||
|
||||
// LINT.IfChange
|
||||
// Next ID = 4
|
||||
message SearchAttributes{
|
||||
|
||||
@@ -61,6 +62,13 @@ message DeviceSearchResultContainer{
|
||||
|
||||
// User entered by tapping on QSB bar on homescreen.
|
||||
QSB = 2;
|
||||
|
||||
// User entered by swiping up from overview (using Rocket Gesture).
|
||||
OVERVIEW = 3;
|
||||
|
||||
// User entered by tapping the search box in the Taskbar AllApps drawer.
|
||||
TASKBAR = 4;
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(//quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="Launcher3-refs_heads_android15-s1-release" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="Launcher3-refs_heads_android15-s1-release" />
|
||||
<orderEntry type="module" module-name="multivalentTests" />
|
||||
<orderEntry type="module" module-name="multivalentTestsForDevice1" />
|
||||
<orderEntry type="module" module-name="Launcher3-refs_heads_android15-s1-release" />
|
||||
<orderEntry type="module" module-name="tests" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2024 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
<item android:alpha="0.35" android:color="?androidprv:attr/materialColorPrimaryContainer" />
|
||||
</selector>
|
||||
@@ -16,7 +16,8 @@
|
||||
android:width="84dp"
|
||||
android:height="208dp"
|
||||
android:viewportWidth="84"
|
||||
android:viewportHeight="208">
|
||||
android:viewportHeight="208"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:pathData="M24.53,169.2L32.09,165.56C77.7,143.55 77.7,64.45 32.09,42.35L24.53,38.71C14.55,33.95 6.06,25.56 0,14.92V193.08C6.06,182.44 14.55,174.05 24.53,169.2Z"
|
||||
android:fillColor="?attr/onSurfaceBack"/>
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
android:width="122dp"
|
||||
android:height="303dp"
|
||||
android:viewportWidth="122"
|
||||
android:viewportHeight="303">
|
||||
android:viewportHeight="303"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:pathData="M35.65,245.9L46.63,240.61C112.92,208.62 112.92,93.67 46.63,61.54L35.65,56.26C21.15,49.34 8.81,37.14 0,21.69V280.6C8.81,265.15 21.15,252.95 35.65,245.9Z"
|
||||
android:fillColor="?attr/onSurfaceBack"/>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2024 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.
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="@dimen/bubblebar_drop_target_corner_radius" />
|
||||
<solid android:color="@color/bubblebar_drop_target_bg_color" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="?androidprv:attr/materialColorPrimaryContainer" />
|
||||
</shape>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2023 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.
|
||||
-->
|
||||
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@android:color/system_accent1_600" />
|
||||
|
||||
<solid android:color="@android:color/system_accent1_600" />
|
||||
</shape>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2024 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.
|
||||
-->
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:inset="@dimen/bubble_expanded_view_drop_target_padding">
|
||||
<shape
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="@dimen/bubble_expanded_view_drop_target_corner_radius" />
|
||||
<solid android:color="@color/bubblebar_drop_target_bg_color" />
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="?androidprv:attr/materialColorPrimaryContainer" />
|
||||
</shape>
|
||||
</inset>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Copyright (C) 2023 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.
|
||||
-->
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners android:radius="@dimen/rounded_button_radius" />
|
||||
<solid android:color="?androidprv:attr/materialColorPrimaryContainer" />
|
||||
</shape>
|
||||
@@ -20,7 +20,7 @@
|
||||
<item>
|
||||
<shape android:shape="rectangle"
|
||||
android:tint="?colorButtonNormal">
|
||||
<corners android:radius="24dp" />
|
||||
<corners android:radius="@dimen/recents_clear_all_outline_radius" />
|
||||
<solid android:color="?androidprv:attr/materialColorSurfaceBright"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
android:color="?android:attr/colorControlHighlight">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="16dp"/>
|
||||
<corners android:radius="28dp"/>
|
||||
<solid android:color="@color/taskbar_edu_button_color"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
android:width="83dp"
|
||||
android:height="208dp"
|
||||
android:viewportWidth="83"
|
||||
android:viewportHeight="208">
|
||||
android:viewportHeight="208"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:pathData="M23.53,169.2L31.09,165.56C76.7,143.55 76.7,64.45 31.09,42.35L23.53,38.71C13.55,33.95 5.06,25.56 -1,14.92V193.08C5.06,182.44 13.55,174.05 23.53,169.2Z"
|
||||
android:fillColor="?attr/onSurfaceBack"/>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2023 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="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
|
||||
android:fillColor="@android:color/system_neutral1_50"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 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"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:autoMirrored="true"
|
||||
android:tint="?androidprv:attr/materialColorOnSurface"
|
||||
android:viewportHeight="48"
|
||||
android:viewportWidth="48">
|
||||
<group
|
||||
android:name="scaleGroup"
|
||||
android:pivotX="24"
|
||||
android:pivotY="24"
|
||||
android:rotation="90">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18.75,36 L16.6,33.85 26.5,23.95 16.6,14.05 18.75,11.9 30.8,23.95Z" />
|
||||
</group>
|
||||
</vector>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2023 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.329,2.305H4.242C2.751,2.305 1.542,3.514 1.542,5.005V13.005C1.542,14.496 2.751,15.705 4.242,15.705H7.875V19.011C7.875,20.502 9.084,21.711 10.575,21.711H19.662C21.153,21.711 22.362,20.502 22.362,19.011V10.011C22.362,8.52 21.153,7.311 19.662,7.311H16.029V5.005C16.029,3.514 14.821,2.305 13.329,2.305ZM14.329,7.311V5.005C14.329,4.452 13.882,4.005 13.329,4.005H4.242C3.69,4.005 3.242,4.452 3.242,5.005V13.005C3.242,13.557 3.69,14.005 4.242,14.005H7.875V10.011C7.875,8.52 9.084,7.311 10.575,7.311H14.329ZM9.575,14.005V10.011C9.575,9.611 9.81,9.266 10.15,9.106C10.285,9.037 10.438,8.999 10.6,8.999H19.687C20.239,8.999 20.687,9.447 20.687,9.999V18.999C20.687,19.399 20.452,19.744 20.113,19.904C19.977,19.972 19.824,20.011 19.662,20.011H10.575C10.023,20.011 9.575,19.563 9.575,19.011V15.705H9.6V14.005H9.575ZM15.542,11.996V14H17.588V15H15.542V16.996H14.542V15H12.464V14H14.542V11.996H15.542Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2024 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="M8.5,4.5H3.5C2.4,4.5 1.5,5.4 1.5,6.5V18.5C1.5,19.6 2.4,20.5 3.5,20.5H8.5C9.6,20.5 10.5,19.6 10.5,18.5V6.5C10.5,5.4 9.6,4.5 8.5,4.5ZM8.5,18.5H3.5V6.5H8.5V18.5ZM14.5,6.5H19.5V13.5H21.5V6.5C21.5,5.4 20.6,4.5 19.5,4.5H14.5C13.4,4.5 12.5,5.4 12.5,6.5V18.5C12.5,19.6 13.4,20.5 14.5,20.5H15.5V18.5H14.5V6.5ZM20.5,14.5V16.5H22.5V18.5H20.5V20.5H18.5V18.5H16.5V16.5H18.5V14.5H20.5Z"
|
||||
android:fillColor="#48473A"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2024 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="M18,2L6,2C4.9,2 4,2.9 4,4L4,9C4,10.1 4.9,11 6,11L18,11C19.1,11 20,10.1 20,9L20,4C20,2.9 19.1,2 18,2ZM18,9L6,9L6,4L18,4L18,9ZM18,13L6,13C4.9,13 4,13.9 4,15L4,20C4,21.1 4.9,22 6,22L13,22L13,20L6,20L6,15L18,15L18,16L20,16L20,15C20,13.9 19.1,13 18,13ZM16,17L18,17L18,19L20,19L20,21L18,21L18,23L16,23L16,21L14,21L14,19L16,19L16,17Z"
|
||||
android:fillColor="#48473A"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
+6
-8
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 The Android Open Source Project
|
||||
<!-- Copyright (C) 2024 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.
|
||||
@@ -13,11 +13,9 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.popup.PopupContainerWithArrow
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/popup_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"/>
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/white" />
|
||||
<corners android:radius="@dimen/keyboard_quick_switch_task_view_radius" />
|
||||
</shape>
|
||||
Loaded 100 of 1624 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user