diff --git a/Android.bp b/Android.bp index 0bbb3d2c1e..e730c9d57c 100644 --- a/Android.bp +++ b/Android.bp @@ -80,10 +80,10 @@ android_library { "androidx.preference_preference", "SystemUISharedLib", "SystemUIAnimationLib", + "launcher-testing-shared", ], srcs: [ "tests/tapl/**/*.java", - "src/com/android/launcher3/testing/shared/**/*.java", ], resource_dirs: [ ], manifest: "tests/tapl/AndroidManifest.xml", @@ -169,7 +169,10 @@ android_library { android_library { name: "Launcher3CommonDepsLib", srcs: ["src_build_config/**/*.java"], - static_libs: ["Launcher3ResLib"], + static_libs: [ + "Launcher3ResLib", + "launcher-testing-shared", + ], sdk_version: "current", min_sdk_version: min_launcher3_sdk_version, manifest: "AndroidManifest-common.xml", diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index 951be4e54e..0c7b48fe66 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -40,6 +40,7 @@ + diff --git a/OWNERS b/OWNERS index 560b5629fb..2d7a014ce9 100644 --- a/OWNERS +++ b/OWNERS @@ -4,31 +4,37 @@ # People who can approve changes for submission # -alexchau@google.com -andraskloczl@google.com -patmanning@google.com adamcohen@google.com -hyunyoungs@google.com -mrcasey@google.com -sunnygoyal@google.com +alexchau@google.com +andonian@google.com awickham@google.com -twickham@google.com -winsonc@google.com -zakcohen@google.com -santie@google.com -vadimt@google.com -jonmiranda@google.com -pinyaoting@google.com -gwasserman@google.com -jamesoleary@google.com -joshtrask@google.com -mrenouf@google.com -mkephart@google.com -hwwang@google.com -tracyzhou@google.com -peanutbutter@google.com -xuqiu@google.com +brdayauon@google.com brianji@google.com +captaincole@google.com +charlander@google.com +fbaron@google.com +ganjam@google.com +hwwang@google.com +hyunyoungs@google.com +jagrutdesai@google.com +jeremysim@google.com +jiuyu@google.com +jonmiranda@google.com +kylim@google.com +patmanning@google.com +peanutbutter@google.com +pinyaoting@google.com +randypfohl@google.com +saumyaprakash@google.com +sihua@google.com +sunnygoyal@google.com +tracyzhou@google.com +tsuharesu@google.com +twickham@google.com +vadimt@google.com +victortulias@google.com +winsonc@google.com +xuqiu@google.com per-file FeatureFlags.java, globs = set noparent -per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, zakcohen@google.com, mrcasey@google.com, adamcohen@google.com, hyunyoungs@google.com +per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com, captaincole@google.com diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 912395970f..a77791f78b 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -1,2 +1,4 @@ [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} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 68ed73d60a..090bafe68c 100644 --- a/build.gradle +++ b/build.gradle @@ -147,6 +147,7 @@ dependencies { implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}" implementation "androidx.preference:preference:${ANDROID_X_VERSION}" implementation project(':IconLoader') + implementation project(':UiTestsLibLauncher') withQuickstepImplementation project(':SharedLibWrapper') // Recents lib dependency diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java index a645e58ecc..4f9c32ade5 100644 --- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java +++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java @@ -16,6 +16,7 @@ package com.android.launcher3.testing; +import static com.android.launcher3.testing.shared.TestProtocol.VIEW_AND_ACTIVITY_LEAKS; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; @@ -24,7 +25,9 @@ import android.app.Application; import android.content.Context; import android.os.Binder; import android.os.Bundle; +import android.os.Process; import android.system.Os; +import android.util.Log; import android.view.View; import androidx.annotation.Keep; @@ -157,11 +160,17 @@ public class DebugTestInformationHandler extends TestInformationHandler { case TestProtocol.REQUEST_VIEW_LEAK: { if (sLeaks == null) sLeaks = new LinkedList(); + Log.d(VIEW_AND_ACTIVITY_LEAKS, "forcefully leaking 2 views"); sLeaks.add(new View(mContext)); sLeaks.add(new View(mContext)); return response; } + case TestProtocol.PRINT_VIEW_LEAK: { + Log.d(VIEW_AND_ACTIVITY_LEAKS, "(pid=" + Process.myPid() + ") sLeaks=" + sLeaks); + return response; + } + case TestProtocol.REQUEST_START_EVENT_LOGGING: { sEvents = new ArrayList<>(); TestLogging.setEventConsumer( @@ -221,6 +230,12 @@ public class DebugTestInformationHandler extends TestInformationHandler { return response; } + case TestProtocol.REQUEST_USE_TAPL_WORKSPACE_LAYOUT: { + useTestWorkspaceLayout( + LauncherSettings.Settings.ARG_DEFAULT_WORKSPACE_LAYOUT_TAPL); + return response; + } + case TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT: { useTestWorkspaceLayout(null); return response; diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml index 196541f0a9..48650aac20 100644 --- a/go/quickstep/res/layout/overview_actions_container.xml +++ b/go/quickstep/res/layout/overview_actions_container.xml @@ -109,7 +109,7 @@ style="@style/GoOverviewActionButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:drawableStart="@drawable/ic_split_screen" + android:drawableStart="@drawable/ic_split_vertical" android:text="@string/action_split" android:theme="@style/ThemeControlHighlightWorkspaceColor" android:visibility="gone" /> diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LauncherBinder.java similarity index 82% rename from go/src/com/android/launcher3/model/LoaderResults.java rename to go/src/com/android/launcher3/model/LauncherBinder.java index 5f71061a6e..437d8caf94 100644 --- a/go/src/com/android/launcher3/model/LoaderResults.java +++ b/go/src/com/android/launcher3/model/LauncherBinder.java @@ -22,11 +22,11 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.model.BgDataModel.Callbacks; /** - * Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}. + * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects. */ -public class LoaderResults extends BaseLoaderResults { +public class LauncherBinder extends BaseLauncherBinder { - public LoaderResults(LauncherAppState app, BgDataModel dataModel, + public LauncherBinder(LauncherAppState app, BgDataModel dataModel, AllAppsList allAppsList, Callbacks[] callbacks) { super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR); } diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto index 677c9921a0..b1064f73db 100644 --- a/protos/launcher_atom.proto +++ b/protos/launcher_atom.proto @@ -128,10 +128,17 @@ message TaskBarContainer { // Bit encoded value to capture pinned and predicted taskbar positions. optional int32 cardinality = 2; + + // Container where taskbar was invoked. + oneof ParentContainer { + TaskSwitcherContainer task_switcher_container = 3; + } } -// Next value 41 +// Next value 44 enum Attribute { + option allow_alias = true; + UNKNOWN = 0; DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat BACKUP_RESTORE = 2; // icon layout restored from backup @@ -166,7 +173,8 @@ enum Attribute { ALL_APPS_SEARCH_RESULT_SLICE = 19; ALL_APPS_SEARCH_RESULT_WIDGETS = 20; ALL_APPS_SEARCH_RESULT_PLAY = 21; - ALL_APPS_SEARCH_RESULT_SUGGEST = 22; + ALL_APPS_SEARCH_RESULT_FALLBACK = 22; + ALL_APPS_SEARCH_RESULT_SUGGEST = 22 [deprecated = true]; ALL_APPS_SEARCH_RESULT_ASSISTANT = 23; ALL_APPS_SEARCH_RESULT_CHROMETAB = 24; ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25; @@ -174,6 +182,9 @@ enum Attribute { ALL_APPS_SEARCH_RESULT_PEOPLE_TILE = 27; 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; // Web suggestions provided by AGA ALL_APPS_SEARCH_RESULT_WEB_SUGGEST = 39; diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 3647e05f0a..8e1baba956 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -103,6 +103,7 @@ diff --git a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_back_step_shape.xml b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_back_step_shape.xml new file mode 100644 index 0000000000..0f2650b83f --- /dev/null +++ b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_back_step_shape.xml @@ -0,0 +1,23 @@ + + + + diff --git a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml new file mode 100644 index 0000000000..4cccd09bf5 --- /dev/null +++ b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_home_step_shape.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml new file mode 100644 index 0000000000..7011f6c263 --- /dev/null +++ b/quickstep/res/drawable-sw600dp-land/gesture_tutorial_overview_step_shape.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_back_step_shape.xml b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_back_step_shape.xml new file mode 100644 index 0000000000..02f6ff9e38 --- /dev/null +++ b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_back_step_shape.xml @@ -0,0 +1,23 @@ + + + + diff --git a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml new file mode 100644 index 0000000000..5becb8b0fe --- /dev/null +++ b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_home_step_shape.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml new file mode 100644 index 0000000000..7143089d48 --- /dev/null +++ b/quickstep/res/drawable-sw720dp-land/gesture_tutorial_overview_step_shape.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/quickstep/res/drawable/bg_taskbar_edu_tooltip.xml b/quickstep/res/drawable/bg_taskbar_edu_tooltip.xml new file mode 100644 index 0000000000..a20f7daf2c --- /dev/null +++ b/quickstep/res/drawable/bg_taskbar_edu_tooltip.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/close_icon.xml b/quickstep/res/drawable/close_icon.xml deleted file mode 100644 index 07f4336882..0000000000 --- a/quickstep/res/drawable/close_icon.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml b/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml new file mode 100644 index 0000000000..68c5eb1fbd --- /dev/null +++ b/quickstep/res/drawable/gesture_tutorial_back_step_shape.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/res/drawable/ic_split_screen.xml b/quickstep/res/drawable/gesture_tutorial_complete_checkmark.xml similarity index 52% rename from res/drawable/ic_split_screen.xml rename to quickstep/res/drawable/gesture_tutorial_complete_checkmark.xml index 108006929c..254d6d5ce5 100644 --- a/res/drawable/ic_split_screen.xml +++ b/quickstep/res/drawable/gesture_tutorial_complete_checkmark.xml @@ -1,12 +1,10 @@ - - + android:width="48dp" + android:height="48dp" + android:tint="?attr/colorControlNormal" + android:viewportHeight="24" + android:viewportWidth="24"> - + android:fillColor="@android:color/black" + android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41L9,16.17z" /> diff --git a/quickstep/res/drawable/gesture_tutorial_complete_checkmark_bg.xml b/quickstep/res/drawable/gesture_tutorial_complete_checkmark_bg.xml new file mode 100644 index 0000000000..d6a6686766 --- /dev/null +++ b/quickstep/res/drawable/gesture_tutorial_complete_checkmark_bg.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/quickstep/res/drawable/gesture_tutorial_home_step_shape.xml b/quickstep/res/drawable/gesture_tutorial_home_step_shape.xml new file mode 100644 index 0000000000..698cba140b --- /dev/null +++ b/quickstep/res/drawable/gesture_tutorial_home_step_shape.xml @@ -0,0 +1,23 @@ + + + + diff --git a/quickstep/res/drawable/gesture_tutorial_menu_button_background.xml b/quickstep/res/drawable/gesture_tutorial_menu_button_background.xml new file mode 100644 index 0000000000..1ab776bd6e --- /dev/null +++ b/quickstep/res/drawable/gesture_tutorial_menu_button_background.xml @@ -0,0 +1,19 @@ + + + + diff --git a/quickstep/res/drawable/gesture_tutorial_overview_step_shape.xml b/quickstep/res/drawable/gesture_tutorial_overview_step_shape.xml new file mode 100644 index 0000000000..cc2c491ef3 --- /dev/null +++ b/quickstep/res/drawable/gesture_tutorial_overview_step_shape.xml @@ -0,0 +1,23 @@ + + + + diff --git a/quickstep/res/drawable/hotseat_icon.xml b/quickstep/res/drawable/hotseat_icon.xml new file mode 100644 index 0000000000..b849fe90ce --- /dev/null +++ b/quickstep/res/drawable/hotseat_icon.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/hotseat_icon_home.xml b/quickstep/res/drawable/hotseat_icon_home.xml new file mode 100644 index 0000000000..d59dd4a88e --- /dev/null +++ b/quickstep/res/drawable/hotseat_icon_home.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/hotseat_search_bar.xml b/quickstep/res/drawable/hotseat_search_bar.xml new file mode 100644 index 0000000000..ea332e9462 --- /dev/null +++ b/quickstep/res/drawable/hotseat_search_bar.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/ic_desktop.xml b/quickstep/res/drawable/ic_desktop.xml new file mode 100644 index 0000000000..8de275df5c --- /dev/null +++ b/quickstep/res/drawable/ic_desktop.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/quickstep/res/drawable/ic_sysbar_back.xml b/quickstep/res/drawable/ic_sysbar_back.xml index 1eea6774b1..7d2bdee6e0 100644 --- a/quickstep/res/drawable/ic_sysbar_back.xml +++ b/quickstep/res/drawable/ic_sysbar_back.xml @@ -16,13 +16,13 @@ --> + android:viewportWidth="20" + android:viewportHeight="20"> + android:pathData="M15.5417 1.66669C15.1833 1.66669 14.8417 1.76669 14.5333 1.94169L3.21667 8.74169C2.775 9.00002 2.5 9.48335 2.5 10C2.5 10.5167 2.775 11 3.21667 11.2584L14.5333 18.05C14.8417 18.2334 15.1833 18.325 15.5417 18.325C16.625 18.325 17.5 17.45 17.5 16.3667V3.62502C17.5 2.54169 16.625 1.66669 15.5417 1.66669Z" /> \ No newline at end of file diff --git a/quickstep/res/drawable/ic_sysbar_back_kids.xml b/quickstep/res/drawable/ic_sysbar_back_kids.xml index ac6d49b7f3..e7bba671e8 100644 --- a/quickstep/res/drawable/ic_sysbar_back_kids.xml +++ b/quickstep/res/drawable/ic_sysbar_back_kids.xml @@ -1,6 +1,7 @@ + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> + android:pathData="M10.0001 18.3334C5.40008 18.3334 1.66675 14.6 1.66675 10C1.66675 5.40002 5.40008 1.66669 10.0001 1.66669C14.6001 1.66669 18.3334 5.40002 18.3334 10C18.3334 14.6 14.6001 18.3334 10.0001 18.3334Z" /> \ No newline at end of file diff --git a/quickstep/res/drawable/ic_sysbar_recent.xml b/quickstep/res/drawable/ic_sysbar_recent.xml index f8c4778a2b..26c4dc813c 100644 --- a/quickstep/res/drawable/ic_sysbar_recent.xml +++ b/quickstep/res/drawable/ic_sysbar_recent.xml @@ -16,12 +16,12 @@ --> + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> + android:pathData="M4.47634 2.5H15.5241C16.6164 2.5 17.5002 3.38382 17.5002 4.4761V15.5239C17.5002 16.6162 16.6164 17.5 15.5241 17.5H4.47634C3.38407 17.5 2.50024 16.6162 2.50024 15.5239V4.4761C2.50024 3.38382 3.38407 2.5 4.47634 2.5Z" /> \ No newline at end of file diff --git a/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml b/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml new file mode 100644 index 0000000000..286a3c4e4f --- /dev/null +++ b/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/quickstep/res/drawable/keyboard_quick_switch_task_view_background.xml b/quickstep/res/drawable/keyboard_quick_switch_task_view_background.xml new file mode 100644 index 0000000000..d0aac8c364 --- /dev/null +++ b/quickstep/res/drawable/keyboard_quick_switch_task_view_background.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/quickstep/res/drawable/keyboard_quick_switch_view_background.xml b/quickstep/res/drawable/keyboard_quick_switch_view_background.xml new file mode 100644 index 0000000000..19aaed46b0 --- /dev/null +++ b/quickstep/res/drawable/keyboard_quick_switch_view_background.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/quickstep/res/drawable/mock_app_icon.xml b/quickstep/res/drawable/mock_app_icon.xml new file mode 100644 index 0000000000..92cdea3044 --- /dev/null +++ b/quickstep/res/drawable/mock_app_icon.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/mock_taskbar_background.xml b/quickstep/res/drawable/mock_taskbar_background.xml new file mode 100644 index 0000000000..8ac9080f2f --- /dev/null +++ b/quickstep/res/drawable/mock_taskbar_background.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/redesigned_default_sandbox_app_icon.xml b/quickstep/res/drawable/redesigned_default_sandbox_app_icon.xml new file mode 100644 index 0000000000..cb94d9a8fc --- /dev/null +++ b/quickstep/res/drawable/redesigned_default_sandbox_app_icon.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/quickstep/res/drawable/top_task_view.xml b/quickstep/res/drawable/top_task_view.xml new file mode 100644 index 0000000000..d2176c3cb4 --- /dev/null +++ b/quickstep/res/drawable/top_task_view.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml b/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml index 20d2ecc59f..c7e176ac2e 100644 --- a/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml +++ b/quickstep/res/layout-land/gesture_tutorial_mock_hotseat.xml @@ -24,54 +24,50 @@ android:paddingStart="56dp" android:paddingEnd="56dp"> - - - - - - - - - - - - \ No newline at end of file diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml new file mode 100644 index 0000000000..18c0e1f444 --- /dev/null +++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml @@ -0,0 +1,52 @@ + + + + + + + + + diff --git a/quickstep/res/layout-land/redesigned_gesture_tutorial_mock_hotseat.xml b/quickstep/res/layout-land/redesigned_gesture_tutorial_mock_hotseat.xml new file mode 100644 index 0000000000..6c08d14b6b --- /dev/null +++ b/quickstep/res/layout-land/redesigned_gesture_tutorial_mock_hotseat.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml new file mode 100644 index 0000000000..39c7e73d2d --- /dev/null +++ b/quickstep/res/layout-sw600dp-land/gesture_tutorial_step_menu.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +