From 5d80c28161ed9b9f664bf8d2df359ec0f6910c3d Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 26 Jul 2017 06:40:17 -0700 Subject: [PATCH 01/38] Updating fade-effect parameters: > Shifting the effect at the edge in the presence of padding > Removing fade effect at the bottom > Fixing wrong call for translating children Bug: 63003761 Change-Id: Ia9d030de60e933a2e688496109d62977885c2c0d --- .../allapps/AllAppsRecyclerView.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index ab589d83b9..22e295e76e 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -202,8 +202,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine @Override public void onDraw(Canvas c) { - c.translate(0, mContentTranslationY); - // Draw the background if (mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) { mEmptySearchBackground.draw(c); @@ -212,6 +210,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine super.onDraw(c); } + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.translate(0, mContentTranslationY); + super.dispatchDraw(canvas); + canvas.translate(0, -mContentTranslationY); + } + public float getContentTranslationY() { return mContentTranslationY; } @@ -336,6 +341,22 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine mFastScrollHelper.onSetAdapter((AllAppsGridAdapter) adapter); } + @Override + protected float getBottomFadingEdgeStrength() { + // No bottom fading edge. + return 0; + } + + @Override + protected boolean isPaddingOffsetRequired() { + return true; + } + + @Override + protected int getTopPaddingOffset() { + return -getPaddingTop(); + } + /** * Updates the bounds for the scrollbar. */ From 6d1e9a1012262b64646c6f765d3d9179c1700cac Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 27 Jul 2017 10:21:50 -0700 Subject: [PATCH 02/38] Moving GradientView background alpha to resources Bug: 63072570 Change-Id: Ie982a5a33ece72942ebee79e4eb81f83da7b31c4 --- res/values/config.xml | 2 ++ .../launcher3/graphics/GradientView.java | 17 ++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/res/values/config.xml b/res/values/config.xml index e9c62a783d..e7ec0a0b1c 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -9,6 +9,8 @@ false false + 191 + @string/app_name diff --git a/src/com/android/launcher3/graphics/GradientView.java b/src/com/android/launcher3/graphics/GradientView.java index 678396df1f..5455b43ec6 100644 --- a/src/com/android/launcher3/graphics/GradientView.java +++ b/src/com/android/launcher3/graphics/GradientView.java @@ -27,6 +27,7 @@ import android.graphics.RectF; import android.graphics.Shader; import android.support.v4.graphics.ColorUtils; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.view.View; import android.view.animation.AccelerateInterpolator; import android.view.animation.Interpolator; @@ -46,7 +47,6 @@ public class GradientView extends View implements WallpaperColorInfo.OnChangeLis private static final int DEFAULT_COLOR = Color.WHITE; private static final int ALPHA_MASK_HEIGHT_DP = 500; private static final int ALPHA_MASK_WIDTH_DP = 2; - private static final int ALPHA_COLORS = 0xBF; private static final boolean DEBUG = false; private final Bitmap mAlphaGradientMask; @@ -62,7 +62,7 @@ public class GradientView extends View implements WallpaperColorInfo.OnChangeLis private final Paint mPaintNoScrim = new Paint(); private float mProgress; private final int mMaskHeight, mMaskWidth; - private final Context mAppContext; + private final int mAlphaColors; private final Paint mDebugPaint = DEBUG ? new Paint() : null; private final Interpolator mAccelerator = new AccelerateInterpolator(); private final float mAlphaStart; @@ -71,15 +71,14 @@ public class GradientView extends View implements WallpaperColorInfo.OnChangeLis public GradientView(Context context, AttributeSet attrs) { super(context, attrs); - this.mAppContext = context.getApplicationContext(); - this.mMaskHeight = Utilities.pxFromDp(ALPHA_MASK_HEIGHT_DP, - mAppContext.getResources().getDisplayMetrics()); - this.mMaskWidth = Utilities.pxFromDp(ALPHA_MASK_WIDTH_DP, - mAppContext.getResources().getDisplayMetrics()); + DisplayMetrics dm = getResources().getDisplayMetrics(); + this.mMaskHeight = Utilities.pxFromDp(ALPHA_MASK_HEIGHT_DP, dm); + this.mMaskWidth = Utilities.pxFromDp(ALPHA_MASK_WIDTH_DP, dm); Launcher launcher = Launcher.getLauncher(context); this.mAlphaStart = launcher.getDeviceProfile().isVerticalBarLayout() ? 0 : 100; this.mScrimColor = Themes.getAttrColor(context, R.attr.allAppsScrimColor); this.mWallpaperColorInfo = WallpaperColorInfo.getInstance(launcher); + mAlphaColors = getResources().getInteger(R.integer.extracted_color_gradient_alpha); updateColors(); mAlphaGradientMask = createDitheredAlphaMask(); } @@ -104,9 +103,9 @@ public class GradientView extends View implements WallpaperColorInfo.OnChangeLis private void updateColors() { this.mColor1 = ColorUtils.setAlphaComponent(mWallpaperColorInfo.getMainColor(), - ALPHA_COLORS); + mAlphaColors); this.mColor2 = ColorUtils.setAlphaComponent(mWallpaperColorInfo.getSecondaryColor(), - ALPHA_COLORS); + mAlphaColors); if (mWidth + mHeight > 0) { createRadialShader(); } From 3f9bab2fe4ec0a9c5d4414c7a1acb413f1d70ded Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Fri, 28 Jul 2017 14:50:17 -0700 Subject: [PATCH 03/38] More launcher grid updates. * Increase padding when in All Apps landscape. * Calculate aspectRatio using width/height instead of availableWidth/Height. * Instead of increasing page indicator size, we add the extra height to the Hotseat. Bug: 63996463 Bug: 63149981 Change-Id: I1ee3549b4089b277704d5d72e1b7cb5a2abdbd5a --- src/com/android/launcher3/DeviceProfile.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 031bfe115b..6dfb1901e4 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -63,7 +63,7 @@ public class DeviceProfile { */ private static final float MAX_HORIZONTAL_PADDING_PERCENT = 0.14f; - private static final float TALL_DEVICE_ASPECT_RATIO_THRESHOLD = 1.82f; + private static final float TALL_DEVICE_ASPECT_RATIO_THRESHOLD = 2.0f; // Overview mode private final int overviewModeMinIconZoneHeightPx; @@ -238,17 +238,17 @@ public class DeviceProfile { updateAvailableDimensions(dm, res); // Now that we have all of the variables calculated, we can tune certain sizes. - float aspectRatio = ((float) Math.max(availableWidthPx, availableHeightPx)) - / Math.min(availableWidthPx, availableHeightPx); + float aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx); boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0; if (!isVerticalBarLayout() && isPhone && isTallDevice) { - // We increase the page indicator size when there is extra space. + // We increase the hotseat size when there is extra space. // ie. For a display with a large aspect ratio, we can keep the icons on the workspace - // in portrait mode closer together by increasing the page indicator size. + // in portrait mode closer together by adding more height to the hotseat. // Note: This calculation was created after noticing a pattern in the design spec. - pageIndicatorSizePx = getCellSize().y - iconSizePx - iconDrawablePaddingPx; + int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx; + hotseatBarHeightPx += extraSpace - pageIndicatorSizePx; - // Recalculate the available dimensions using the new page indicator size. + // Recalculate the available dimensions using the new hotseat size. updateAvailableDimensions(dm, res); } @@ -301,10 +301,10 @@ public class DeviceProfile { // In normal cases, All Apps cell height should equal the Workspace cell height. // Since we are removing labels from the Workspace, we need to manually compute the // All Apps cell height. + int topBottomPadding = allAppsIconDrawablePaddingPx * (isVerticalBarLayout() ? 2 : 1); allAppsCellHeightPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx + Utilities.calculateTextHeight(allAppsIconTextSizePx) - // Top and bottom padding is equal to the drawable padding - + allAppsIconDrawablePaddingPx * 2; + + topBottomPadding * 2; } /** From 7653a60c74e9babfda1c3754eb4f3060b6e40990 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Fri, 28 Jul 2017 10:09:34 -0700 Subject: [PATCH 04/38] Optimize updating All Apps Predictions. * Prefetch existing predictions in onResume. * Only update predictions if something has been changed. * Swap predictions in place (if possible) -- this avoids having to relayout all of All Apps when just the predictions change. Bug: 64126588 Bug: 63711551 Change-Id: Iffa0d9d7d6f99f606dd68b7df5893d6eba1574f5 --- src/com/android/launcher3/Launcher.java | 3 + .../allapps/AllAppsContainerView.java | 2 + .../allapps/AlphabeticalAppsList.java | 81 +++++++++++++++---- 3 files changed, 69 insertions(+), 17 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7b7177e54e..7e9c5a332a 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -958,6 +958,9 @@ public class Launcher extends BaseActivity } else if (mOnResumeState == State.WIDGETS) { showWidgetsView(false, false); } + if (mOnResumeState != State.APPS) { + tryAndUpdatePredictedApps(); + } mOnResumeState = State.NONE; mPaused = false; diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 0083d47f2a..ede3bea725 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -224,6 +224,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc mAppsRecyclerView.setLayoutManager(mLayoutManager); mAppsRecyclerView.setAdapter(mAdapter); mAppsRecyclerView.setHasFixedSize(true); + // Removes the animation that can occur when updating the predicted apps in place. + mAppsRecyclerView.getItemAnimator().setChangeDuration(0); if (FeatureFlags.LAUNCHER3_PHYSICS) { mAppsRecyclerView.setSpringAnimationHandler(mSpringAnimationHandler); } diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 608e898ae8..ee2756f2cb 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -298,14 +298,74 @@ public class AlphabeticalAppsList { updateAdapterItems(); } + private List processPredictedAppComponents(List components) { + if (mComponentToAppMap.isEmpty()) { + // Apps have not been bound yet. + return Collections.emptyList(); + } + + List predictedApps = new ArrayList<>(); + for (ComponentKey ck : components) { + AppInfo info = mComponentToAppMap.get(ck); + if (info != null) { + predictedApps.add(info); + } else { + if (FeatureFlags.IS_DOGFOOD_BUILD) { + Log.e(TAG, "Predicted app not found: " + ck); + } + } + // Stop at the number of predicted apps + if (predictedApps.size() == mNumPredictedAppsPerRow) { + break; + } + } + return predictedApps; + } + /** - * Sets the current set of predicted apps. Since this can be called before we get the full set - * of applications, we should merge the results only in onAppsUpdated() which is idempotent. + * Sets the current set of predicted apps. + * + * This can be called before we get the full set of applications, we should merge the results + * only in onAppsUpdated() which is idempotent. + * + * If the number of predicted apps is the same as the previous list of predicted apps, + * we can optimize by swapping them in place. */ public void setPredictedApps(List apps) { mPredictedAppComponents.clear(); mPredictedAppComponents.addAll(apps); - onAppsUpdated(); + + List newPredictedApps = processPredictedAppComponents(apps); + // We only need to do work if any of the visible predicted apps have changed. + if (!newPredictedApps.equals(mPredictedApps)) { + if (newPredictedApps.size() == mPredictedApps.size()) { + swapInNewPredictedApps(newPredictedApps); + } else { + // We need to update the appIndex of all the items. + onAppsUpdated(); + } + } + } + + /** + * Swaps out the old predicted apps with the new predicted apps, in place. This optimization + * allows us to skip an entire relayout that would otherwise be called by notifyDataSetChanged. + * + * Note: This should only be called if the # of predicted apps is the same. + * This method assumes that predicted apps are the first items in the adapter. + */ + private void swapInNewPredictedApps(List apps) { + mPredictedApps.clear(); + mPredictedApps.addAll(apps); + + int size = apps.size(); + for (int i = 0; i < size; ++i) { + AppInfo info = apps.get(i); + AdapterItem appItem = AdapterItem.asPredictedApp(i, "", info, i); + mAdapterItems.set(i, appItem); + mFilteredApps.set(i, info); + mAdapter.notifyItemChanged(i); + } } /** @@ -432,20 +492,7 @@ public class AlphabeticalAppsList { // Process the predicted app components mPredictedApps.clear(); if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { - for (ComponentKey ck : mPredictedAppComponents) { - AppInfo info = mComponentToAppMap.get(ck); - if (info != null) { - mPredictedApps.add(info); - } else { - if (FeatureFlags.IS_DOGFOOD_BUILD) { - Log.e(TAG, "Predicted app not found: " + ck); - } - } - // Stop at the number of predicted apps - if (mPredictedApps.size() == mNumPredictedAppsPerRow) { - break; - } - } + mPredictedApps.addAll(processPredictedAppComponents(mPredictedAppComponents)); if (!mPredictedApps.isEmpty()) { // Add a section for the predictions From 14b3240ecaeb066c6f3fa9cc61d0cc6d5c481c2c Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 31 Jul 2017 10:03:28 -0700 Subject: [PATCH 05/38] Sending onCreate to the callbacks after our call is complete Bug: Bug: 63381480 Change-Id: Ib5fcd9ef500a91fef93c9e5af657b23723748ccc --- src/com/android/launcher3/Launcher.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7b7177e54e..000c516dad 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -464,9 +464,6 @@ public class Launcher extends BaseActivity setOrientation(); setContentView(mLauncherView); - if (mLauncherCallbacks != null) { - mLauncherCallbacks.onCreate(savedInstanceState); - } // Listen for broadcasts IntentFilter filter = new IntentFilter(); @@ -477,6 +474,10 @@ public class Launcher extends BaseActivity getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); + + if (mLauncherCallbacks != null) { + mLauncherCallbacks.onCreate(savedInstanceState); + } } @Override From 1d7f45d8f8fafc46f23963e3b43c95a2c2120079 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 31 Jul 2017 10:59:52 -0700 Subject: [PATCH 06/38] Fixing various tests > Migrating UI tests to AndroidJUnit4 for better support > Removing obsolete RotationPreference test > Fixing broken FileLogTest and AndroidJUnit4 > Removing InvariantDeviceProfileTest as it does not work well with resource overlays Change-Id: I0abb1df6765d76d86c1c6c84e8ac35eb9a6bcdaa --- .../search/DefaultAppSearchAlgorithm.java | 4 - .../android/launcher3/logging/FileLog.java | 10 +- .../launcher3/InvariantDeviceProfileTest.java | 119 ---------------- .../search/DefaultAppSearchAlgorithmTest.java | 99 ++++++------- .../launcher3/logging/FileLogTest.java | 6 + .../model/AddWorkspaceItemsTaskTest.java | 4 +- ...tCase.java => AbstractLauncherUiTest.java} | 86 +++--------- .../launcher3/ui/AllAppsAppLaunchTest.java | 35 ++--- .../launcher3/ui/AllAppsIconToHomeTest.java | 40 +++--- .../launcher3/ui/RotationPreferenceTest.java | 77 ---------- .../launcher3/ui/ShortcutsLaunchTest.java | 38 ++--- .../launcher3/ui/ShortcutsToHomeTest.java | 39 +++--- .../ui/widget/AddConfigWidgetTest.java | 71 ++++------ .../launcher3/ui/widget/AddWidgetTest.java | 39 +++--- .../launcher3/ui/widget/BindWidgetTest.java | 44 ++++-- .../ui/widget/RequestPinItemTest.java | 75 ++++------ .../launcher3/util/SimpleActivityMonitor.java | 65 --------- .../util/rule/LauncherActivityRule.java | 132 ++++++++++++++++++ .../launcher3/util/rule/ShellCommandRule.java | 90 ++++++++++++ 19 files changed, 503 insertions(+), 570 deletions(-) delete mode 100644 tests/src/com/android/launcher3/InvariantDeviceProfileTest.java rename tests/src/com/android/launcher3/ui/{LauncherInstrumentationTestCase.java => AbstractLauncherUiTest.java} (80%) delete mode 100644 tests/src/com/android/launcher3/ui/RotationPreferenceTest.java delete mode 100644 tests/src/com/android/launcher3/util/SimpleActivityMonitor.java create mode 100644 tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java create mode 100644 tests/src/com/android/launcher3/util/rule/ShellCommandRule.java diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java index 21eb3fba05..26f6ec3572 100644 --- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java +++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java @@ -71,10 +71,6 @@ public class DefaultAppSearchAlgorithm implements SearchAlgorithm { return result; } - public static boolean matches(AppInfo info, String query) { - return matches(info, query, StringMatcher.getInstance()); - } - public static boolean matches(AppInfo info, String query, StringMatcher matcher) { int queryLength = query.length(); diff --git a/src/com/android/launcher3/logging/FileLog.java b/src/com/android/launcher3/logging/FileLog.java index 4c83e9ac22..f7f8ef18f6 100644 --- a/src/com/android/launcher3/logging/FileLog.java +++ b/src/com/android/launcher3/logging/FileLog.java @@ -29,6 +29,8 @@ import java.util.concurrent.TimeUnit; */ public final class FileLog { + protected static final boolean ENABLED = + FeatureFlags.IS_DOGFOOD_BUILD || Utilities.IS_DEBUG_DEVICE; private static final String FILE_NAME_PREFIX = "log-"; private static final DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); @@ -39,7 +41,7 @@ public final class FileLog { private static File sLogsDirectory = null; public static void setDir(File logsDir) { - if (FeatureFlags.IS_DOGFOOD_BUILD || Utilities.IS_DEBUG_DEVICE) { + if (ENABLED) { synchronized (DATE_FORMAT) { // If the target directory changes, stop any active thread. if (sHandler != null && !logsDir.equals(sLogsDirectory)) { @@ -76,7 +78,7 @@ public final class FileLog { } public static void print(String tag, String msg, Exception e) { - if (!FeatureFlags.IS_DOGFOOD_BUILD) { + if (!ENABLED) { return; } String out = String.format("%s %s %s", DATE_FORMAT.format(new Date()), tag, msg); @@ -102,7 +104,7 @@ public final class FileLog { * @param out if not null, all the persisted logs are copied to the writer. */ public static void flushAll(PrintWriter out) throws InterruptedException { - if (!FeatureFlags.IS_DOGFOOD_BUILD) { + if (!ENABLED) { return; } CountDownLatch latch = new CountDownLatch(1); @@ -135,7 +137,7 @@ public final class FileLog { @Override public boolean handleMessage(Message msg) { - if (sLogsDirectory == null || !FeatureFlags.IS_DOGFOOD_BUILD) { + if (sLogsDirectory == null || !ENABLED) { return true; } switch (msg.what) { diff --git a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java b/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java deleted file mode 100644 index 230d623e90..0000000000 --- a/tests/src/com/android/launcher3/InvariantDeviceProfileTest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.android.launcher3; - -import android.content.res.Resources; -import android.graphics.Point; -import android.graphics.PointF; -import android.graphics.Rect; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; -import android.util.Log; - -import java.util.ArrayList; - -/** - * Tests the {@link DeviceProfile} and {@link InvariantDeviceProfile}. - */ -@SmallTest -public class InvariantDeviceProfileTest extends AndroidTestCase { - - private static final String TAG = "DeviceProfileTest"; - private static final boolean DEBUG = false; - - private InvariantDeviceProfile mInvariantProfile; - private ArrayList mPredefinedDeviceProfiles; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mInvariantProfile = new InvariantDeviceProfile(getContext()); - mPredefinedDeviceProfiles = mInvariantProfile.getPredefinedDeviceProfiles(getContext()); - } - - @Override - protected void tearDown() throws Exception { - // Nothing to tear down as this class only tests static methods. - } - - public void testFindClosestDeviceProfile2() { - for (InvariantDeviceProfile idf: mPredefinedDeviceProfiles) { - ArrayList predefinedProfilesCopy = - new ArrayList<>(mPredefinedDeviceProfiles); - ArrayList closestProfiles = - mInvariantProfile.findClosestDeviceProfiles( - idf.minWidthDps, idf.minHeightDps, predefinedProfilesCopy - ); - assertTrue(closestProfiles.get(0).equals(idf)); - } - } - - /** - * Used to print out how the invDistWeightedInterpolate works between device profiles to - * tweak the two constants that control how the interpolation curve is shaped. - */ - public void testInvInterpolation() { - - InvariantDeviceProfile p1 = mPredefinedDeviceProfiles.get(7); // e.g., Large Phone - InvariantDeviceProfile p2 = mPredefinedDeviceProfiles.get(8); // e.g., Nexus 7 - - ArrayList pts = createInterpolatedPoints( - new PointF(p1.minWidthDps, p1.minHeightDps), - new PointF(p2.minWidthDps, p2.minHeightDps), - 20f); - - for (int i = 0; i < pts.size(); i++) { - ArrayList closestProfiles = - mInvariantProfile.findClosestDeviceProfiles( - pts.get(i).x, pts.get(i).y, mPredefinedDeviceProfiles); - InvariantDeviceProfile result = - mInvariantProfile.invDistWeightedInterpolate( - pts.get(i).x, pts.get(i).y, closestProfiles); - if (DEBUG) { - Log.d(TAG, String.format("width x height = (%f, %f)] iconSize = %f", - pts.get(i).x, pts.get(i).y, result.iconSize)); - } - } - } - - private ArrayList createInterpolatedPoints(PointF a, PointF b, float numPts) { - ArrayList result = new ArrayList(); - result.add(a); - for (float i = 1; i < numPts; i = i + 1.0f) { - result.add(new PointF((b.x * i + a.x * (numPts - i)) / numPts, - (b.y * i + a.y * (numPts - i)) / numPts)); - } - result.add(b); - return result; - } - - /** - * Ensures that system calls (e.g., WindowManager, DisplayMetrics) that require contexts are - * properly working to generate minimum width and height of the display. - */ - public void test_hammerhead() { - if (!android.os.Build.DEVICE.equals("hammerhead")) { - return; - } - assertEquals(4, mInvariantProfile.numRows); - assertEquals(4, mInvariantProfile.numColumns); - assertEquals(5, mInvariantProfile.numHotseatIcons); - } - - // Add more tests for other devices, however, running them once on a single device is enough - // for verifying that for a platform version, the WindowManager and DisplayMetrics is - // working as intended. -} diff --git a/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java b/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java index 26ec69b1c7..846a163700 100644 --- a/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java +++ b/tests/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithmTest.java @@ -16,85 +16,78 @@ package com.android.launcher3.allapps.search; import android.content.ComponentName; -import android.test.InstrumentationTestCase; +import android.support.test.runner.AndroidJUnit4; import com.android.launcher3.AppInfo; import com.android.launcher3.Utilities; -import java.util.ArrayList; -import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; /** * Unit tests for {@link DefaultAppSearchAlgorithm} */ -public class DefaultAppSearchAlgorithmTest extends InstrumentationTestCase { - - private List mAppsList; - private DefaultAppSearchAlgorithm mAlgorithm; - - @Override - protected void setUp() throws Exception { - super.setUp(); - mAppsList = new ArrayList<>(); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - mAlgorithm = new DefaultAppSearchAlgorithm(mAppsList); - } - }); - } +@RunWith(AndroidJUnit4.class) +public class DefaultAppSearchAlgorithmTest { + private static final DefaultAppSearchAlgorithm.StringMatcher MATCHER = + DefaultAppSearchAlgorithm.StringMatcher.getInstance(); + @Test public void testMatches() { - assertTrue(mAlgorithm.matches(getInfo("white cow"), "cow")); - assertTrue(mAlgorithm.matches(getInfo("whiteCow"), "cow")); - assertTrue(mAlgorithm.matches(getInfo("whiteCOW"), "cow")); - assertTrue(mAlgorithm.matches(getInfo("whitecowCOW"), "cow")); - assertTrue(mAlgorithm.matches(getInfo("white2cow"), "cow")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("white cow"), "cow", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("whiteCow"), "cow", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("whiteCOW"), "cow", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("whitecowCOW"), "cow", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("white2cow"), "cow", MATCHER)); - assertFalse(mAlgorithm.matches(getInfo("whitecow"), "cow")); - assertFalse(mAlgorithm.matches(getInfo("whitEcow"), "cow")); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("whitecow"), "cow", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("whitEcow"), "cow", MATCHER)); - assertTrue(mAlgorithm.matches(getInfo("whitecowCow"), "cow")); - assertTrue(mAlgorithm.matches(getInfo("whitecow cow"), "cow")); - assertFalse(mAlgorithm.matches(getInfo("whitecowcow"), "cow")); - assertFalse(mAlgorithm.matches(getInfo("whit ecowcow"), "cow")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("whitecowCow"), "cow", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("whitecow cow"), "cow", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("whitecowcow"), "cow", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("whit ecowcow"), "cow", MATCHER)); - assertTrue(mAlgorithm.matches(getInfo("cats&dogs"), "dog")); - assertTrue(mAlgorithm.matches(getInfo("cats&Dogs"), "dog")); - assertTrue(mAlgorithm.matches(getInfo("cats&Dogs"), "&")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("cats&dogs"), "dog", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("cats&Dogs"), "dog", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("cats&Dogs"), "&", MATCHER)); - assertTrue(mAlgorithm.matches(getInfo("2+43"), "43")); - assertFalse(mAlgorithm.matches(getInfo("2+43"), "3")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("2+43"), "43", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("2+43"), "3", MATCHER)); - assertTrue(mAlgorithm.matches(getInfo("Q"), "q")); - assertTrue(mAlgorithm.matches(getInfo(" Q"), "q")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("Q"), "q", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo(" Q"), "q", MATCHER)); // match lower case words - assertTrue(mAlgorithm.matches(getInfo("elephant"), "e")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("elephant"), "e", MATCHER)); - assertTrue(mAlgorithm.matches(getInfo("电子邮件"), "电")); - assertTrue(mAlgorithm.matches(getInfo("电子邮件"), "电子")); - assertFalse(mAlgorithm.matches(getInfo("电子邮件"), "子")); - assertFalse(mAlgorithm.matches(getInfo("电子邮件"), "邮件")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("电子邮件"), "电", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("电子邮件"), "电子", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("电子邮件"), "子", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("电子邮件"), "邮件", MATCHER)); - assertFalse(mAlgorithm.matches(getInfo("Bot"), "ba")); - assertFalse(mAlgorithm.matches(getInfo("bot"), "ba")); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("Bot"), "ba", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("bot"), "ba", MATCHER)); } + @Test public void testMatchesVN() { if (!Utilities.ATLEAST_NOUGAT) { return; } - assertTrue(mAlgorithm.matches(getInfo("다운로드"), "다")); - assertTrue(mAlgorithm.matches(getInfo("드라이브"), "드")); - assertTrue(mAlgorithm.matches(getInfo("다운로드 드라이브"), "ㄷ")); - assertTrue(mAlgorithm.matches(getInfo("운로 드라이브"), "ㄷ")); - assertTrue(mAlgorithm.matches(getInfo("abc"), "åbç")); - assertTrue(mAlgorithm.matches(getInfo("Alpha"), "ål")); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("다운로드"), "다", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("드라이브"), "드", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("다운로드 드라이브"), "ㄷ", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("운로 드라이브"), "ㄷ", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("abc"), "åbç", MATCHER)); + assertTrue(DefaultAppSearchAlgorithm.matches(getInfo("Alpha"), "ål", MATCHER)); - assertFalse(mAlgorithm.matches(getInfo("다운로드 드라이브"), "ㄷㄷ")); - assertFalse(mAlgorithm.matches(getInfo("로드라이브"), "ㄷ")); - assertFalse(mAlgorithm.matches(getInfo("abc"), "åç")); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("다운로드 드라이브"), "ㄷㄷ", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("로드라이브"), "ㄷ", MATCHER)); + assertFalse(DefaultAppSearchAlgorithm.matches(getInfo("abc"), "åç", MATCHER)); } private AppInfo getInfo(String title) { diff --git a/tests/src/com/android/launcher3/logging/FileLogTest.java b/tests/src/com/android/launcher3/logging/FileLogTest.java index c24cc3fb77..7048c2868c 100644 --- a/tests/src/com/android/launcher3/logging/FileLogTest.java +++ b/tests/src/com/android/launcher3/logging/FileLogTest.java @@ -37,6 +37,9 @@ public class FileLogTest extends AndroidTestCase { } public void testPrintLog() throws Exception { + if (!FileLog.ENABLED) { + return; + } FileLog.print("Testing", "hoolalala"); StringWriter writer = new StringWriter(); FileLog.flushAll(new PrintWriter(writer)); @@ -54,6 +57,9 @@ public class FileLogTest extends AndroidTestCase { } public void testOldFileTruncated() throws Exception { + if (!FileLog.ENABLED) { + return; + } FileLog.print("Testing", "hoolalala"); StringWriter writer = new StringWriter(); FileLog.flushAll(new PrintWriter(writer)); diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java index 4c80902f00..ae15f086f3 100644 --- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java +++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java @@ -20,9 +20,9 @@ import com.android.launcher3.util.Provider; import org.mockito.ArgumentCaptor; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import static org.mockito.Matchers.isNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -131,7 +131,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { // only info2 should be added because info was already added to the workspace // in setupWorkspaceWithHoles() verify(callbacks).bindAppsAdded(any(ArrayList.class), notAnimated.capture(), - animated.capture(), any(ArrayList.class)); + animated.capture(), isNull(ArrayList.class)); assertTrue(notAnimated.getValue().isEmpty()); assertEquals(1, animated.getValue().size()); diff --git a/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java similarity index 80% rename from tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java rename to tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 47b43f530e..7fb5d85212 100644 --- a/tests/src/com/android/launcher3/ui/LauncherInstrumentationTestCase.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -15,29 +15,26 @@ */ package com.android.launcher3.ui; +import android.app.Instrumentation; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; +import android.content.pm.LauncherActivityInfo; import android.graphics.Point; -import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; +import android.support.test.InstrumentationRegistry; import android.support.test.uiautomator.By; import android.support.test.uiautomator.BySelector; import android.support.test.uiautomator.Direction; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; -import android.test.InstrumentationTestCase; import android.view.MotionEvent; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherSettings; @@ -45,25 +42,26 @@ import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.compat.AppWidgetManagerCompat; +import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.testcomponent.AppWidgetNoConfig; import com.android.launcher3.testcomponent.AppWidgetWithConfig; import com.android.launcher3.util.ManagedProfileHeuristic; -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; +import org.junit.Before; + import java.util.Locale; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + /** * Base class for all instrumentation tests providing various utility methods. */ -public class LauncherInstrumentationTestCase extends InstrumentationTestCase { +public abstract class AbstractLauncherUiTest { public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10); public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5; @@ -71,16 +69,15 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { public static final long DEFAULT_UI_TIMEOUT = 3000; public static final long DEFAULT_WORKER_TIMEOUT_SECS = 5; + protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); protected UiDevice mDevice; protected Context mTargetContext; protected String mTargetPackage; - @Override - protected void setUp() throws Exception { - super.setUp(); - + @Before + public void setUp() throws Exception { mDevice = UiDevice.getInstance(getInstrumentation()); - mTargetContext = getInstrumentation().getTargetContext(); + mTargetContext = InstrumentationRegistry.getTargetContext(); mTargetPackage = mTargetContext.getPackageName(); } @@ -97,56 +94,15 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { } } - /** - * Starts the launcher activity in the target package and returns the Launcher instance. - */ - protected Launcher startLauncher() { - return (Launcher) getInstrumentation().startActivitySync(getHomeIntent()); - } - - protected Intent getHomeIntent() { - return new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_HOME) - .setPackage(mTargetPackage) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - } - - /** - * Grants the launcher permission to bind widgets. - */ - protected void grantWidgetPermission() throws IOException { - // Check bind widget permission - if (mTargetContext.getPackageManager().checkPermission( - mTargetPackage, android.Manifest.permission.BIND_APPWIDGET) - != PackageManager.PERMISSION_GRANTED) { - runShellCommand("appwidget grantbind --package " + mTargetPackage); - } - } - - /** - * Sets the target launcher as default launcher. - */ - protected void setDefaultLauncher() throws IOException { - ActivityInfo launcher = mTargetContext.getPackageManager() - .queryIntentActivities(getHomeIntent(), 0).get(0).activityInfo; - runShellCommand("cmd package set-home-activity " + - new ComponentName(launcher.packageName, launcher.name).flattenToString()); - } - - protected void runShellCommand(String command) throws IOException { - ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation() - .executeShellCommand(command); - - // Read the input stream fully. - FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); - while (fis.read() != -1); - fis.close(); + protected Instrumentation getInstrumentation() { + return InstrumentationRegistry.getInstrumentation(); } /** * Opens all apps and returns the recycler view */ protected UiObject2 openAllApps() { + mDevice.waitForIdle(); if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { // clicking on the page indicator brings up all apps tray on non tablets. findViewById(R.id.page_indicator).click(); @@ -262,7 +218,7 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { protected void resetLoaderState() { try { - runTestOnUiThread(new Runnable() { + mMainThreadExecutor.execute(new Runnable() { @Override public void run() { ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mTargetContext); @@ -279,7 +235,7 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { */ protected T getOnUiThread(final Callable callback) { try { - return new MainThreadExecutor().submit(callback).get(); + return mMainThreadExecutor.submit(callback).get(); } catch (Exception e) { throw new RuntimeException(e); } @@ -315,6 +271,10 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase { return By.res(mTargetPackage, name); } + protected LauncherActivityInfo getSettingsApp() { + return LauncherAppsCompat.getInstance(mTargetContext) + .getActivityList("com.android.settings", Process.myUserHandle()).get(0); + } /** * Broadcast receiver which blocks until the result is received. diff --git a/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java b/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java index 0ced7cf33a..46343a3894 100644 --- a/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java +++ b/tests/src/com/android/launcher3/ui/AllAppsAppLaunchTest.java @@ -1,52 +1,55 @@ package com.android.launcher3.ui; import android.content.pm.LauncherActivityInfo; -import android.os.Process; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; -import android.test.suitebuilder.annotation.LargeTest; -import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.util.Condition; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertTrue; /** * Test for verifying apps is launched from all-apps */ @LargeTest -public class AllAppsAppLaunchTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class AllAppsAppLaunchTest extends AbstractLauncherUiTest { - private LauncherActivityInfo mSettingsApp; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) - .getActivityList("com.android.settings", Process.myUserHandle()).get(0); - } + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Test public void testAppLauncher_portrait() throws Exception { lockRotation(true); performTest(); } + @Test public void testAppLauncher_landscape() throws Exception { lockRotation(false); performTest(); } private void performTest() throws Exception { - startLauncher(); + mActivityMonitor.startLauncher(); + + LauncherActivityInfo settingsApp = getSettingsApp(); // Open all apps and wait for load complete final UiObject2 appsContainer = openAllApps(); assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT)); // Open settings app and verify app launched - scrollAndFind(appsContainer, By.text(mSettingsApp.getLabel().toString())).click(); + scrollAndFind(appsContainer, By.text(settingsApp.getLabel().toString())).click(); assertTrue(mDevice.wait(Until.hasObject(By.pkg( - mSettingsApp.getComponentName().getPackageName()).depth(0)), DEFAULT_UI_TIMEOUT)); + settingsApp.getComponentName().getPackageName()).depth(0)), DEFAULT_UI_TIMEOUT)); } } diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java index 9361750873..00f30ada9d 100644 --- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java +++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java @@ -1,58 +1,62 @@ package com.android.launcher3.ui; import android.content.pm.LauncherActivityInfo; -import android.os.Process; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; -import android.test.suitebuilder.annotation.LargeTest; -import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.util.Condition; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertTrue; /** * Test for dragging an icon from all-apps to homescreen. */ @LargeTest -public class AllAppsIconToHomeTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class AllAppsIconToHomeTest extends AbstractLauncherUiTest { - private LauncherActivityInfo mSettingsApp; - - @Override - protected void setUp() throws Exception { - super.setUp(); - setDefaultLauncher(); - - mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) - .getActivityList("com.android.settings", Process.myUserHandle()).get(0); - } + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher(); + @Test public void testDragIcon_portrait() throws Throwable { lockRotation(true); performTest(); } + @Test public void testDragIcon_landscape() throws Throwable { lockRotation(false); performTest(); } private void performTest() throws Throwable { + LauncherActivityInfo settingsApp = getSettingsApp(); + clearHomescreen(); - startLauncher(); + mActivityMonitor.startLauncher(); // Open all apps and wait for load complete. final UiObject2 appsContainer = openAllApps(); assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT)); // Drag icon to homescreen. - UiObject2 icon = scrollAndFind(appsContainer, By.text(mSettingsApp.getLabel().toString())); + UiObject2 icon = scrollAndFind(appsContainer, By.text(settingsApp.getLabel().toString())); dragToWorkspace(icon, true); // Verify that the icon works on homescreen. - mDevice.findObject(By.text(mSettingsApp.getLabel().toString())).click(); + mDevice.findObject(By.text(settingsApp.getLabel().toString())).click(); assertTrue(mDevice.wait(Until.hasObject(By.pkg( - mSettingsApp.getComponentName().getPackageName()).depth(0)), DEFAULT_UI_TIMEOUT)); + settingsApp.getComponentName().getPackageName()).depth(0)), DEFAULT_UI_TIMEOUT)); } } diff --git a/tests/src/com/android/launcher3/ui/RotationPreferenceTest.java b/tests/src/com/android/launcher3/ui/RotationPreferenceTest.java deleted file mode 100644 index e84ad047f1..0000000000 --- a/tests/src/com/android/launcher3/ui/RotationPreferenceTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.android.launcher3.ui; - -import android.content.SharedPreferences; -import android.graphics.Rect; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject; -import android.support.test.uiautomator.UiSelector; -import android.test.suitebuilder.annotation.MediumTest; - -import com.android.launcher3.R; -import com.android.launcher3.Utilities; - -/** - * Test for auto rotate preference. - */ -@MediumTest -public class RotationPreferenceTest extends LauncherInstrumentationTestCase { - - private SharedPreferences mPrefs; - private boolean mOriginalRotationValue; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - mDevice = UiDevice.getInstance(getInstrumentation()); - mTargetContext = getInstrumentation().getTargetContext(); - mTargetPackage = mTargetContext.getPackageName(); - mPrefs = Utilities.getPrefs(mTargetContext); - mOriginalRotationValue = mPrefs.getBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, false); - } - - @Override - protected void tearDown() throws Exception { - setRotationEnabled(mOriginalRotationValue); - super.tearDown(); - } - - public void testRotation_disabled() throws Exception { - if (mTargetContext.getResources().getBoolean(R.bool.allow_rotation)) { - // This is a tablet. The test is only valid to mobile devices. - return; - } - - setRotationEnabled(false); - mDevice.setOrientationRight(); - startLauncher(); - - Rect hotseat = getHotseatBounds(); - assertTrue(hotseat.width() > hotseat.height()); - } - - public void testRotation_enabled() throws Exception { - if (mTargetContext.getResources().getBoolean(R.bool.allow_rotation)) { - // This is a tablet. The test is only valid to mobile devices. - return; - } - - setRotationEnabled(true); - mDevice.setOrientationRight(); - startLauncher(); - - Rect hotseat = getHotseatBounds(); - assertTrue(hotseat.width() < hotseat.height()); - } - - private void setRotationEnabled(boolean enabled) { - mPrefs.edit().putBoolean(Utilities.ALLOW_ROTATION_PREFERENCE_KEY, enabled).commit(); - } - - private Rect getHotseatBounds() throws Exception { - UiObject hotseat = mDevice.findObject( - new UiSelector().resourceId(mTargetPackage + ":id/hotseat")); - hotseat.waitForExists(6000); - return hotseat.getVisibleBounds(); - } -} diff --git a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java index 3a0b6132c6..a40ad7fadc 100644 --- a/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java +++ b/tests/src/com/android/launcher3/ui/ShortcutsLaunchTest.java @@ -2,54 +2,58 @@ package com.android.launcher3.ui; import android.content.pm.LauncherActivityInfo; import android.graphics.Point; -import android.os.Process; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; -import android.test.suitebuilder.annotation.LargeTest; import android.view.MotionEvent; import com.android.launcher3.R; -import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.util.Condition; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * Test for verifying that shortcuts are shown and can be launched after long pressing an app */ @LargeTest -public class ShortcutsLaunchTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class ShortcutsLaunchTest extends AbstractLauncherUiTest { - private LauncherActivityInfo mSettingsApp; - - @Override - protected void setUp() throws Exception { - super.setUp(); - setDefaultLauncher(); - - mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) - .getActivityList("com.android.settings", Process.myUserHandle()).get(0); - } + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher(); + @Test public void testAppLauncher_portrait() throws Exception { lockRotation(true); performTest(); } + @Test public void testAppLauncher_landscape() throws Exception { lockRotation(false); performTest(); } private void performTest() throws Exception { - startLauncher(); + mActivityMonitor.startLauncher(); + LauncherActivityInfo settingsApp = getSettingsApp(); // Open all apps and wait for load complete final UiObject2 appsContainer = openAllApps(); assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT)); // Find settings app and verify shortcuts appear when long pressed - UiObject2 icon = scrollAndFind(appsContainer, By.text(mSettingsApp.getLabel().toString())); + UiObject2 icon = scrollAndFind(appsContainer, By.text(settingsApp.getLabel().toString())); // Press icon center until shortcuts appear Point iconCenter = icon.getVisibleCenter(); sendPointer(MotionEvent.ACTION_DOWN, iconCenter); @@ -63,7 +67,7 @@ public class ShortcutsLaunchTest extends LauncherInstrumentationTestCase { .findObject(getSelectorForId(R.id.bubble_text)); shortcut.click(); assertTrue(mDevice.wait(Until.hasObject(By.pkg( - mSettingsApp.getComponentName().getPackageName()) + settingsApp.getComponentName().getPackageName()) .text(shortcut.getText())), DEFAULT_UI_TIMEOUT)); } } diff --git a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java index 5d86d1ec68..434311dd6f 100644 --- a/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java +++ b/tests/src/com/android/launcher3/ui/ShortcutsToHomeTest.java @@ -2,40 +2,43 @@ package com.android.launcher3.ui; import android.content.pm.LauncherActivityInfo; import android.graphics.Point; -import android.os.Process; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; -import android.test.suitebuilder.annotation.LargeTest; import android.view.MotionEvent; import com.android.launcher3.R; -import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.util.Condition; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * Test for dragging a deep shortcut to the home screen. */ @LargeTest -public class ShortcutsToHomeTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class ShortcutsToHomeTest extends AbstractLauncherUiTest { - private LauncherActivityInfo mSettingsApp; - - @Override - protected void setUp() throws Exception { - super.setUp(); - setDefaultLauncher(); - - mSettingsApp = LauncherAppsCompat.getInstance(mTargetContext) - .getActivityList("com.android.settings", Process.myUserHandle()).get(0); - } + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher(); + @Test public void testDragIcon_portrait() throws Throwable { lockRotation(true); performTest(); } + @Test public void testDragIcon_landscape() throws Throwable { lockRotation(false); performTest(); @@ -43,14 +46,16 @@ public class ShortcutsToHomeTest extends LauncherInstrumentationTestCase { private void performTest() throws Throwable { clearHomescreen(); - startLauncher(); + mActivityMonitor.startLauncher(); + + LauncherActivityInfo settingsApp = getSettingsApp(); // Open all apps and wait for load complete. final UiObject2 appsContainer = openAllApps(); assertTrue(Wait.atMost(Condition.minChildCount(appsContainer, 2), DEFAULT_UI_TIMEOUT)); // Find the app and long press it to show shortcuts. - UiObject2 icon = scrollAndFind(appsContainer, By.text(mSettingsApp.getLabel().toString())); + UiObject2 icon = scrollAndFind(appsContainer, By.text(settingsApp.getLabel().toString())); // Press icon center until shortcuts appear Point iconCenter = icon.getVisibleCenter(); sendPointer(MotionEvent.ACTION_DOWN, iconCenter); @@ -69,7 +74,7 @@ public class ShortcutsToHomeTest extends LauncherInstrumentationTestCase { // (the app opens and has the same text as the shortcut). mDevice.findObject(By.text(shortcutName)).click(); assertTrue(mDevice.wait(Until.hasObject(By.pkg( - mSettingsApp.getComponentName().getPackageName()) + settingsApp.getComponentName().getPackageName()) .text(shortcutName)), DEFAULT_UI_TIMEOUT)); } } diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java index 0b4e34f94c..a5c2e69af7 100644 --- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java @@ -15,75 +15,75 @@ */ package com.android.launcher3.ui.widget; -import android.app.Activity; -import android.app.Application; import android.appwidget.AppWidgetManager; import android.content.Intent; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; -import android.test.suitebuilder.annotation.LargeTest; import android.view.View; import com.android.launcher3.ItemInfo; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherAppWidgetProviderInfo; -import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.Workspace; import com.android.launcher3.testcomponent.WidgetConfigActivity; -import com.android.launcher3.ui.LauncherInstrumentationTestCase; +import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.util.Condition; -import com.android.launcher3.util.SimpleActivityMonitor; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.widget.WidgetCell; -import java.util.concurrent.Callable; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; /** * Test to verify widget configuration is properly shown. */ @LargeTest -public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class AddConfigWidgetTest extends AbstractLauncherUiTest { + + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind(); private LauncherAppWidgetProviderInfo mWidgetInfo; - private SimpleActivityMonitor mActivityMonitor; - private MainThreadExecutor mMainThreadExecutor; private AppWidgetManager mAppWidgetManager; private int mWidgetId; @Override - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { super.setUp(); mWidgetInfo = findWidgetProvider(true /* hasConfigureScreen */); - mActivityMonitor = new SimpleActivityMonitor(); - ((Application) getInstrumentation().getTargetContext().getApplicationContext()) - .registerActivityLifecycleCallbacks(mActivityMonitor); - mMainThreadExecutor = new MainThreadExecutor(); mAppWidgetManager = AppWidgetManager.getInstance(mTargetContext); - - grantWidgetPermission(); - } - - @Override - protected void tearDown() throws Exception { - ((Application) getInstrumentation().getTargetContext().getApplicationContext()) - .unregisterActivityLifecycleCallbacks(mActivityMonitor); - super.tearDown(); } + @Test public void testWidgetConfig() throws Throwable { runTest(false, true); } + @Test public void testWidgetConfig_rotate() throws Throwable { runTest(true, true); } + @Test public void testConfigCancelled() throws Throwable { runTest(false, false); } + @Test public void testConfigCancelled_rotate() throws Throwable { runTest(true, false); } @@ -96,7 +96,7 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { lockRotation(true); clearHomescreen(); - startLauncher(); + mActivityMonitor.startLauncher(); // Open widget tray and wait for load complete. final UiObject2 widgetContainer = openWidgetsTray(); @@ -146,11 +146,11 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { * Condition for searching widget id */ private class WidgetSearchCondition extends Condition - implements Callable, Workspace.ItemOperator { + implements Workspace.ItemOperator { @Override public boolean isTrue() throws Throwable { - return mMainThreadExecutor.submit(this).get(); + return mMainThreadExecutor.submit(mActivityMonitor.itemExists(this)).get(); } @Override @@ -159,21 +159,6 @@ public class AddConfigWidgetTest extends LauncherInstrumentationTestCase { ((LauncherAppWidgetInfo) info).providerName.equals(mWidgetInfo.provider) && ((LauncherAppWidgetInfo) info).appWidgetId == mWidgetId; } - - @Override - public Boolean call() throws Exception { - // Find the resumed launcher - Launcher launcher = null; - for (Activity a : mActivityMonitor.resumed) { - if (a instanceof Launcher) { - launcher = (Launcher) a; - } - } - if (launcher == null) { - return false; - } - return launcher.getWorkspace().getFirstMatch(this) != null; - } } /** diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java index 3c92c578d5..19f7db72bf 100644 --- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java @@ -15,42 +15,46 @@ */ package com.android.launcher3.ui.widget; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; -import android.test.suitebuilder.annotation.LargeTest; import android.view.View; import com.android.launcher3.ItemInfo; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.Workspace.ItemOperator; -import com.android.launcher3.ui.LauncherInstrumentationTestCase; +import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.util.Condition; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.widget.WidgetCell; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertTrue; + /** * Test to add widget from widget tray */ @LargeTest -public class AddWidgetTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class AddWidgetTest extends AbstractLauncherUiTest { - private LauncherAppWidgetProviderInfo widgetInfo; - - @Override - protected void setUp() throws Exception { - super.setUp(); - grantWidgetPermission(); - - widgetInfo = findWidgetProvider(false /* hasConfigureScreen */); - } + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind(); + @Test public void testDragIcon_portrait() throws Throwable { lockRotation(true); performTest(); } + @Test public void testDragIcon_landscape() throws Throwable { lockRotation(false); performTest(); @@ -58,7 +62,10 @@ public class AddWidgetTest extends LauncherInstrumentationTestCase { private void performTest() throws Throwable { clearHomescreen(); - Launcher launcher = startLauncher(); + mActivityMonitor.startLauncher(); + + final LauncherAppWidgetProviderInfo widgetInfo = + findWidgetProvider(false /* hasConfigureScreen */); // Open widget tray and wait for load complete. final UiObject2 widgetContainer = openWidgetsTray(); @@ -69,12 +76,12 @@ public class AddWidgetTest extends LauncherInstrumentationTestCase { .hasDescendant(By.text(widgetInfo.getLabel(mTargetContext.getPackageManager())))); dragToWorkspace(widget, false); - assertNotNull(launcher.getWorkspace().getFirstMatch(new ItemOperator() { + assertTrue(mActivityMonitor.itemExists(new ItemOperator() { @Override public boolean evaluate(ItemInfo info, View view) { return info instanceof LauncherAppWidgetInfo && ((LauncherAppWidgetInfo) info).providerName.equals(widgetInfo.provider); } - })); + }).call()); } } diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java index 221fed1fc5..d4d517a22c 100644 --- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java @@ -24,10 +24,10 @@ import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageManager; import android.database.Cursor; import android.os.Bundle; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.UiSelector; -import android.test.suitebuilder.annotation.LargeTest; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetHost; import com.android.launcher3.LauncherAppWidgetHostView; import com.android.launcher3.LauncherAppWidgetInfo; @@ -38,23 +38,40 @@ import com.android.launcher3.PendingAppWidgetHostView; import com.android.launcher3.Workspace; import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.compat.PackageInstallerCompat; -import com.android.launcher3.ui.LauncherInstrumentationTestCase; +import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.LooperExecutor; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.widget.PendingAddWidgetInfo; import com.android.launcher3.widget.WidgetHostViewLoader; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + /** * Tests for bind widget flow. * * Note running these tests will clear the workspace on the device. */ @LargeTest -public class BindWidgetTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class BindWidgetTest extends AbstractLauncherUiTest { + + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind(); private ContentResolver mResolver; private AppWidgetManagerCompat mWidgetManager; @@ -65,21 +82,20 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { private int mSessionId = -1; @Override - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { super.setUp(); mResolver = mTargetContext.getContentResolver(); mWidgetManager = AppWidgetManagerCompat.getInstance(mTargetContext); - grantWidgetPermission(); // Clear all existing data LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB); LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG); } - @Override - protected void tearDown() throws Exception { - super.tearDown(); + @After + public void tearDown() throws Exception { if (mCursor != null) { mCursor.close(); } @@ -89,6 +105,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { } } + @Test public void testBindNormalWidget_withConfig() { LauncherAppWidgetProviderInfo info = findWidgetProvider(true); LauncherAppWidgetInfo item = createWidgetInfo(info, true); @@ -96,6 +113,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { setupAndVerifyContents(item, LauncherAppWidgetHostView.class, info.label); } + @Test public void testBindNormalWidget_withoutConfig() { LauncherAppWidgetProviderInfo info = findWidgetProvider(false); LauncherAppWidgetInfo item = createWidgetInfo(info, true); @@ -103,6 +121,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { setupAndVerifyContents(item, LauncherAppWidgetHostView.class, info.label); } + @Test public void testUnboundWidget_removed() throws Exception { LauncherAppWidgetProviderInfo info = findWidgetProvider(false); LauncherAppWidgetInfo item = createWidgetInfo(info, false); @@ -121,6 +140,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { assertFalse(mDevice.findObject(new UiSelector().description(info.label)).exists()); } + @Test public void testPendingWidget_autoRestored() { // A non-restored widget with no config screen gets restored automatically. LauncherAppWidgetProviderInfo info = findWidgetProvider(false); @@ -132,6 +152,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { setupAndVerifyContents(item, LauncherAppWidgetHostView.class, info.label); } + @Test public void testPendingWidget_withConfigScreen() throws Exception { // A non-restored widget with config screen get bound and shows a 'Click to setup' UI. LauncherAppWidgetProviderInfo info = findWidgetProvider(true); @@ -154,6 +175,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { LauncherSettings.Favorites.APPWIDGET_ID)))); } + @Test public void testPendingWidget_notRestored_removed() throws Exception { LauncherAppWidgetInfo item = getInvalidWidgetInfo(); item.restoreStatus = LauncherAppWidgetInfo.FLAG_ID_NOT_VALID @@ -170,6 +192,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { assertEquals(0, mCursor.getCount()); } + @Test public void testPendingWidget_notRestored_brokenInstall() throws Exception { // A widget which is was being installed once, even if its not being // installed at the moment is not removed. @@ -192,6 +215,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID); } + @Test public void testPendingWidget_notRestored_activeInstall() throws Exception { // A widget which is being installed is not removed LauncherAppWidgetInfo item = getInvalidWidgetInfo(); @@ -250,7 +274,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { resetLoaderState(); // Launch the home activity - startLauncher(); + mActivityMonitor.startLauncher(); // Verify UI UiSelector selector = new UiSelector().packageName(mTargetContext.getPackageName()) .className(widgetClass); diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java index b798dfa88d..4b9d83f8ae 100644 --- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java +++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java @@ -15,23 +15,20 @@ */ package com.android.launcher3.ui.widget; -import android.app.Activity; -import android.app.Application; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.Intent; import android.graphics.Color; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiObject2; import android.support.test.uiautomator.Until; -import android.test.suitebuilder.annotation.LargeTest; import android.view.View; import com.android.launcher3.ItemInfo; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherSettings.Favorites; -import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; import com.android.launcher3.Utilities; @@ -40,50 +37,48 @@ import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.testcomponent.AppWidgetNoConfig; import com.android.launcher3.testcomponent.AppWidgetWithConfig; import com.android.launcher3.testcomponent.RequestPinItemActivity; -import com.android.launcher3.ui.LauncherInstrumentationTestCase; +import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.util.Condition; -import com.android.launcher3.util.SimpleActivityMonitor; import com.android.launcher3.util.Wait; +import com.android.launcher3.util.rule.LauncherActivityRule; +import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.widget.WidgetCell; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.util.UUID; -import java.util.concurrent.Callable; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; /** * Test to verify pin item request flow. */ @LargeTest -public class RequestPinItemTest extends LauncherInstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class RequestPinItemTest extends AbstractLauncherUiTest { - private SimpleActivityMonitor mActivityMonitor; - private MainThreadExecutor mMainThreadExecutor; + @Rule public LauncherActivityRule mActivityMonitor = new LauncherActivityRule(); + @Rule public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grandWidgetBind(); + @Rule public ShellCommandRule mDefaultLauncherRule = ShellCommandRule.setDefaultLauncher(); private String mCallbackAction; private String mShortcutId; private int mAppWidgetId; @Override - protected void setUp() throws Exception { + @Before + public void setUp() throws Exception { super.setUp(); - grantWidgetPermission(); - setDefaultLauncher(); - - mActivityMonitor = new SimpleActivityMonitor(); - ((Application) getInstrumentation().getTargetContext().getApplicationContext()) - .registerActivityLifecycleCallbacks(mActivityMonitor); - mMainThreadExecutor = new MainThreadExecutor(); - mCallbackAction = UUID.randomUUID().toString(); mShortcutId = UUID.randomUUID().toString(); } - @Override - protected void tearDown() throws Exception { - ((Application) getInstrumentation().getTargetContext().getApplicationContext()) - .unregisterActivityLifecycleCallbacks(mActivityMonitor); - super.tearDown(); - } - + @Test public void testPinWidgetNoConfig() throws Throwable { runTest("pinWidgetNoConfig", true, new ItemOperator() { @Override @@ -96,6 +91,7 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase { }); } + @Test public void testPinWidgetNoConfig_customPreview() throws Throwable { // Command to set custom preview Intent command = RequestPinItemActivity.getCommandIntent( @@ -113,6 +109,7 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase { }, command); } + @Test public void testPinWidgetWithConfig() throws Throwable { runTest("pinWidgetWithConfig", true, new ItemOperator() { @Override @@ -125,6 +122,7 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase { }); } + @Test public void testPinShortcut() throws Throwable { // Command to set the shortcut id Intent command = RequestPinItemActivity.getCommandIntent( @@ -149,7 +147,7 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase { lockRotation(true); clearHomescreen(); - startLauncher(); + mActivityMonitor.startLauncher(); // Open all apps and wait for load complete final UiObject2 appsContainer = openAllApps(); @@ -191,14 +189,14 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase { } // Go back to home - mTargetContext.startActivity(getHomeIntent()); + mActivityMonitor.returnToHome(); assertTrue(Wait.atMost(new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT)); } /** * Condition for for an item */ - private class ItemSearchCondition extends Condition implements Callable { + private class ItemSearchCondition extends Condition { private final ItemOperator mOp; @@ -208,22 +206,7 @@ public class RequestPinItemTest extends LauncherInstrumentationTestCase { @Override public boolean isTrue() throws Throwable { - return mMainThreadExecutor.submit(this).get(); - } - - @Override - public Boolean call() throws Exception { - // Find the resumed launcher - Launcher launcher = null; - for (Activity a : mActivityMonitor.resumed) { - if (a instanceof Launcher) { - launcher = (Launcher) a; - } - } - if (launcher == null) { - return false; - } - return launcher.getWorkspace().getFirstMatch(mOp) != null; + return mMainThreadExecutor.submit(mActivityMonitor.itemExists(mOp)).get(); } } } diff --git a/tests/src/com/android/launcher3/util/SimpleActivityMonitor.java b/tests/src/com/android/launcher3/util/SimpleActivityMonitor.java deleted file mode 100644 index 6154ab6c58..0000000000 --- a/tests/src/com/android/launcher3/util/SimpleActivityMonitor.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.android.launcher3.util; - -import android.app.Activity; -import android.app.Application.*; -import android.os.Bundle; - -import java.util.ArrayList; - -/** - * Simple monitor to keep a list of active activities. - */ -public class SimpleActivityMonitor implements ActivityLifecycleCallbacks { - - public final ArrayList created = new ArrayList<>(); - public final ArrayList started = new ArrayList<>(); - public final ArrayList resumed = new ArrayList<>(); - - @Override - public void onActivityCreated(Activity activity, Bundle bundle) { - created.add(activity); - } - - @Override - public void onActivityStarted(Activity activity) { - started.add(activity); - } - - @Override - public void onActivityResumed(Activity activity) { - resumed.add(activity); - } - - @Override - public void onActivityPaused(Activity activity) { - resumed.remove(activity); - } - - @Override - public void onActivityStopped(Activity activity) { - started.remove(activity); - } - - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { } - - @Override - public void onActivityDestroyed(Activity activity) { - created.remove(activity); - } -} diff --git a/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java new file mode 100644 index 0000000000..edd152a2c7 --- /dev/null +++ b/tests/src/com/android/launcher3/util/rule/LauncherActivityRule.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.android.launcher3.util.rule; + +import android.app.Activity; +import android.app.Application; +import android.app.Application.ActivityLifecycleCallbacks; +import android.content.Intent; +import android.os.Bundle; +import android.support.test.InstrumentationRegistry; + +import com.android.launcher3.Launcher; +import com.android.launcher3.Workspace.ItemOperator; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.util.concurrent.Callable; + +/** + * Test rule to get the current Launcher activity. + */ +public class LauncherActivityRule implements TestRule { + + private Launcher mActivity; + + @Override + public Statement apply(Statement base, Description description) { + return new MyStatement(base); + } + + public Launcher getActivity() { + return mActivity; + } + + public Callable itemExists(final ItemOperator op) { + return new Callable() { + + @Override + public Boolean call() throws Exception { + Launcher launcher = getActivity(); + if (launcher == null) { + return false; + } + return launcher.getWorkspace().getFirstMatch(op) != null; + } + }; + } + + /** + * Starts the launcher activity in the target package. + */ + public void startLauncher() { + InstrumentationRegistry.getInstrumentation().startActivitySync(getHomeIntent()); + } + + public void returnToHome() { + InstrumentationRegistry.getTargetContext().startActivity(getHomeIntent()); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + + public static Intent getHomeIntent() { + return new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME) + .setPackage(InstrumentationRegistry.getTargetContext().getPackageName()) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + + private class MyStatement extends Statement implements ActivityLifecycleCallbacks { + + private final Statement mBase; + + public MyStatement(Statement base) { + mBase = base; + } + + @Override + public void evaluate() throws Throwable { + Application app = (Application) + InstrumentationRegistry.getTargetContext().getApplicationContext(); + app.registerActivityLifecycleCallbacks(this); + try { + mBase.evaluate(); + } finally { + app.unregisterActivityLifecycleCallbacks(this); + } + } + + @Override + public void onActivityCreated(Activity activity, Bundle bundle) { + if (activity instanceof Launcher) { + mActivity = (Launcher) activity; + } + } + + @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) { + if (activity == mActivity) { + mActivity = null; + } + } + } +} diff --git a/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java b/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java new file mode 100644 index 0000000000..dba2d71003 --- /dev/null +++ b/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.android.launcher3.util.rule; + +import android.content.ComponentName; +import android.content.pm.ActivityInfo; +import android.os.ParcelFileDescriptor; +import android.support.test.InstrumentationRegistry; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.io.FileInputStream; +import java.io.IOException; + +/** + * Test rule which executes a shell command at the start of the test. + */ +public class ShellCommandRule implements TestRule { + + private final String mCmd; + + public ShellCommandRule(String cmd) { + mCmd = cmd; + } + + @Override + public Statement apply(Statement base, Description description) { + return new MyStatement(base, mCmd); + } + + public static void runShellCommand(String command) throws IOException { + ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand(command); + + // Read the input stream fully. + FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + while (fis.read() != -1); + fis.close(); + } + + private static class MyStatement extends Statement { + private final Statement mBase; + private final String mCmd; + + public MyStatement(Statement base, String cmd) { + mBase = base; + mCmd = cmd; + } + + @Override + public void evaluate() throws Throwable { + runShellCommand(mCmd); + mBase.evaluate(); + } + } + + /** + * Grants the launcher permission to bind widgets. + */ + public static ShellCommandRule grandWidgetBind() { + return new ShellCommandRule("appwidget grantbind --package " + + InstrumentationRegistry.getTargetContext().getPackageName()); + } + + /** + * Sets the target launcher as default launcher. + */ + public static ShellCommandRule setDefaultLauncher() { + ActivityInfo launcher = InstrumentationRegistry.getTargetContext().getPackageManager() + .queryIntentActivities(LauncherActivityRule.getHomeIntent(), 0).get(0) + .activityInfo; + return new ShellCommandRule("cmd package set-home-activity " + + new ComponentName(launcher.packageName, launcher.name).flattenToString()); + } +} From b65e13ca837376e9712f31fdf947bad23b1107ef Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 1 Aug 2017 11:04:15 -0700 Subject: [PATCH 07/38] Making the whole preference entry a single tap target when notification access is not available Bug: 64232287 Change-Id: I93dadfb88ee5d008dee7582c5f37ea3d354330cd --- res/layout/notification_pref_warning.xml | 3 +-- src/com/android/launcher3/SettingsActivity.java | 9 +++++---- .../android/launcher3/views/ButtonPreference.java | 15 +++++---------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/res/layout/notification_pref_warning.xml b/res/layout/notification_pref_warning.xml index 795699e99d..100fac5e41 100644 --- a/res/layout/notification_pref_warning.xml +++ b/res/layout/notification_pref_warning.xml @@ -17,8 +17,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="48dp" android:layout_height="match_parent" - android:background="?android:attr/selectableItemBackgroundBorderless" - android:contentDescription="@string/title_missing_notification_access" + android:importantForAccessibility="no" android:scaleType="center" android:src="@drawable/ic_warning" android:tint="?android:attr/textColorSecondary" /> diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java index d5d5eab761..fa7769e3f6 100644 --- a/src/com/android/launcher3/SettingsActivity.java +++ b/src/com/android/launcher3/SettingsActivity.java @@ -34,7 +34,6 @@ import android.preference.Preference; import android.preference.PreferenceFragment; import android.provider.Settings; import android.provider.Settings.System; -import android.view.View; import com.android.launcher3.graphics.IconShapeOverride; import com.android.launcher3.notification.NotificationListener; @@ -172,7 +171,7 @@ public class SettingsActivity extends Activity { * and updates the launcher badging setting subtext accordingly. */ private static class IconBadgingObserver extends ContentObserver - implements View.OnClickListener { + implements Preference.OnPreferenceClickListener { private final ButtonPreference mBadgingPref; private final ContentResolver mResolver; @@ -205,14 +204,16 @@ public class SettingsActivity extends Activity { summary = R.string.title_missing_notification_access; } } - mBadgingPref.setButtonOnClickListener(serviceEnabled ? null : this); + mBadgingPref.setWidgetFrameVisible(!serviceEnabled); + mBadgingPref.setOnPreferenceClickListener(serviceEnabled ? null : this); mBadgingPref.setSummary(summary); } @Override - public void onClick(View view) { + public boolean onPreferenceClick(Preference preference) { new NotificationAccessConfirmation().show(mFragmentManager, "notification_access"); + return true; } } diff --git a/src/com/android/launcher3/views/ButtonPreference.java b/src/com/android/launcher3/views/ButtonPreference.java index 4697e25e44..fdcf2ca5ba 100644 --- a/src/com/android/launcher3/views/ButtonPreference.java +++ b/src/com/android/launcher3/views/ButtonPreference.java @@ -28,7 +28,7 @@ import android.view.ViewGroup; */ public class ButtonPreference extends Preference { - private View.OnClickListener mClickListener; + private boolean mWidgetFrameVisible = false; public ButtonPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); @@ -46,9 +46,9 @@ public class ButtonPreference extends Preference { super(context); } - public void setButtonOnClickListener(View.OnClickListener clickListener) { - if (mClickListener != clickListener) { - mClickListener = clickListener; + public void setWidgetFrameVisible(boolean isVisible) { + if (mWidgetFrameVisible != isVisible) { + mWidgetFrameVisible = isVisible; notifyChanged(); } } @@ -59,12 +59,7 @@ public class ButtonPreference extends Preference { ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame); if (widgetFrame != null) { - View button = widgetFrame.getChildAt(0); - if (button != null) { - button.setOnClickListener(mClickListener); - } - widgetFrame.setVisibility( - (mClickListener == null || button == null) ? View.GONE : View.VISIBLE); + widgetFrame.setVisibility(mWidgetFrameVisible ? View.VISIBLE : View.GONE); } } } From 9749b3a93dc43cb75c133160107d20f1fb3b2fea Mon Sep 17 00:00:00 2001 From: Mario Bertschler Date: Tue, 1 Aug 2017 15:19:59 -0700 Subject: [PATCH 08/38] disabling feature flag LAUNCHER3_UPDATE_SOFT_INPUT_MODE Change-Id: I10d0a19487331f8e6c19c2cce659f670849caab8 --- src/com/android/launcher3/config/BaseFlags.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 9e0a3b3b5c..7964dd15d3 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -39,7 +39,7 @@ abstract class BaseFlags { // When enabled allows to use any point on the fast scrollbar to start dragging. public static final boolean LAUNCHER3_DIRECT_SCROLL = true; // When enabled while all-apps open, the soft input will be set to adjust resize . - public static final boolean LAUNCHER3_UPDATE_SOFT_INPUT_MODE = true; + public static final boolean LAUNCHER3_UPDATE_SOFT_INPUT_MODE = false; // When enabled the promise icon is visible in all apps while installation an app. public static final boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false; // When enabled uses the AllAppsRadialGradientAndScrimDrawable for all apps From 43387914ca599e7227adae1344659aa8c66a42f2 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 1 Aug 2017 15:22:18 -0700 Subject: [PATCH 09/38] Import translations. DO NOT MERGE Change-Id: Ief09f14606e61d02e2439d535158b95306510b75 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- res/values-az/strings.xml | 24 +++++++++++++++++------- res/values-be/strings.xml | 26 ++++++++++++++++++-------- res/values-bn/strings.xml | 17 +++++++++++++++-- res/values-bs/strings.xml | 38 ++++++++++++++++++++++++-------------- res/values-et/strings.xml | 24 +++++++++++++++++------- res/values-eu/strings.xml | 24 +++++++++++++++++------- res/values-gl/strings.xml | 24 +++++++++++++++++------- res/values-gu/strings.xml | 17 +++++++++++++++-- res/values-hy/strings.xml | 24 +++++++++++++++++------- res/values-is/strings.xml | 24 +++++++++++++++++------- res/values-ka/strings.xml | 24 +++++++++++++++++------- res/values-kk/strings.xml | 24 +++++++++++++++++------- res/values-km/strings.xml | 24 +++++++++++++++++------- res/values-kn/strings.xml | 17 +++++++++++++++-- res/values-ky/strings.xml | 24 +++++++++++++++++------- res/values-lo/strings.xml | 24 +++++++++++++++++------- res/values-mk/strings.xml | 24 +++++++++++++++++------- res/values-ml/strings.xml | 19 ++++++++++++++++--- res/values-mn/strings.xml | 24 +++++++++++++++++------- res/values-mr/strings.xml | 17 +++++++++++++++-- res/values-ms/strings.xml | 24 +++++++++++++++++------- res/values-my/strings.xml | 24 +++++++++++++++++------- res/values-nb/strings.xml | 4 ++-- res/values-ne/strings.xml | 17 +++++++++++++++-- res/values-pa/strings.xml | 17 +++++++++++++++-- res/values-ru/strings.xml | 6 +++--- res/values-si/strings.xml | 24 +++++++++++++++++------- res/values-sq/strings.xml | 24 +++++++++++++++++------- res/values-ta/strings.xml | 24 +++++++++++++++++------- res/values-te/strings.xml | 17 +++++++++++++++-- res/values-ur/strings.xml | 17 +++++++++++++++-- res/values-uz/strings.xml | 24 +++++++++++++++++------- 32 files changed, 506 insertions(+), 179 deletions(-) diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 5cbe408522..6b50e4daea 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -70,20 +70,27 @@ "Qovluq: %1$s" "Vidcet" "Divar kağızları" - "Ayarlar" + "Home ayarları" "Admininiz tərəfindən deaktiv edilib" "İcmal" "Əsas ekranın firlanmağına icazə verin" "Telefon çevrilən zaman" "Cari Ekran ayarı fırlatmağa icazə vermir" + "Bildiriş nişanı" + "Aktiv" + "Deaktiv" + "Bildiriş girişi tələb edilir" + "Bildiriş Nöqtələrini göstərmək üçün %1$s bildirişlərini aktiv edin" + "Ayarları dəyişin" "Əsas ekrana ikona əlavə edin" "Yeni tətbiqlər üçün" - - - - - - + "İkona formasını dəyişin" + "Sistem defoltu istifadə edin" + "Kvadrat" + "Kənarları dairəvi kvadrat" + "Çevrə" + "Gözyaşı damlası" + "İkona formasına etdiyiniz dəyişikliklər tətbiq edilir" "Naməlum" "Yığışdır" "Axtarış" @@ -118,4 +125,7 @@ "Vidcetin eni %1$s hündürlüyü %2$s kimi ölçüləndirildi" "Qısa yollar" "%1$d üçün %2$s qısa yolu" + "%3$s üçün %1$d qısayol və %2$d bildiriş" + "Rədd edin" + "Bildiriş rədd edildi" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 8eb7e8423d..b2ec143696 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -46,7 +46,7 @@ "Галоўная" "Выдаліць" "Выдаліць" - "Звесткі пра праграму" + "Звесткі пра праграмы" "усталёўваць ярлыкі" "Дазваляе праграмам дадаваць ярлыкі без умяшання карыстальніка." "счытваць налады і ярлыкі на Галоўнай старонцы" @@ -70,20 +70,27 @@ "Папка: %1$s" "Віджэты" "Шпалеры" - "Налады" + "Налады галоўнага экрана" "Адключаная адміністратарам" "Агляд" "Дазволіць паварот галоўнага экрана" "Пры павароце тэлефона" "Бягучая налада дысплэя не прадугледжвае паварот" + "Значкі апавяшчэнняў" + "Уключана" + "Выключана" + "Патрабуецца доступ да апавяшчэнняў" + "Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для %1$s" + "Змяніць налады" "Дадаць значок на Галоўны экран" "Для новых праграм" - - - - - - + "Змяніць форму значка" + "Выкарыстоўваць стандартныя формы" + "Квадрат" + "Прамавугольнік са скругленымі вугламі" + "Круг" + "Сляза" + "Змены формы значка прымяняюцца" "Невядома" "Выдаліць" "Шукаць" @@ -118,4 +125,7 @@ "Памеры віджэта зменены на: шырыня %1$s, вышыня %2$s" "Ярлыкі" "Ярлыкі (%1$d) для %2$s" + "Ярлыкі (%1$d) і апавяшчэнні (%2$d) для %3$s" + "Адхіліць" + "Апавяшчэнне адхілена" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 065019a29f..02a95f2365 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -70,16 +70,26 @@ "ফোল্ডার: %1$s" "উইজেটগুলি" "ওয়ালপেপারগুলি" - "সেটিংস" + "হোম এর সেটিংস" "আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে" "এক নজরে" "হোমস্ক্রীন ঘোরানোর অনুমতি দিন" "যখন ফোনটি ঘোরানো হয়" "বর্তমান প্রদর্শনের সেটিংস ঘোরানোর মঞ্জুরি দেয় না" + "বিজ্ঞপ্তি ডট" + "চালু হয়েছে" + "বন্ধ আছে" + "বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন" + "বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, %1$s এর অ্যাপ বিজ্ঞপ্তি চালু করুন" + "সেটিংস পরিবর্তন করুন" "হোম স্ক্রিনে আইকন যোগ করুন" "নতুন অ্যাপ্লিকেশানগুলির জন্যে" "আইকনের আকৃতি পরিবর্তন করুন" - "পরিবর্তন করবেন না" + "সিস্টেমের ডিফল্ট মান ব্যবহার করুন" + "চৌকো" + "চৌকো-গোলাকার" + "গোলাকার" + "চোখের জল" "আইকনের আকৃতি পরিবর্তন করা হচ্ছে" "অজানা" "সরান" @@ -115,4 +125,7 @@ "উইজেটের আকার প্রস্থ %1$s উচ্চতা %2$s তে পরিবর্তন করা হয়েছে" "শর্টকাট" "%2$s এর %1$dটি শর্টকার্ট" + "%3$s এর জন্য %1$dটি শর্টকাট এবং %2$dটি বিজ্ঞপ্তি" + "খারিজ করুন" + "বিজ্ঞপ্তি খারিজ করা হয়েছে" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 8e1234edc8..10cf2f960a 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -43,7 +43,7 @@ "Na ovom početnom ekranu nema više prostora." "Nema više prostora u ladici Favoriti" "Spisak aplikacija" - "Tipka za početak" + "Početna" "Ukloni" "Deinstaliraj" "Informacije o aplikaciji" @@ -57,33 +57,40 @@ "Problem pri učitavanju dodatka" "Postavljanje" "Ovo je sistemska aplikacija i ne može se deinstalirati." - "Neimenovana fascikla" + "Neimenovani folder" "Aplikacija %1$s je onemogućena" "Strana %1$d od %2$d" "Početni ekran %1$d od %2$d" "Nova stranica početnog ekrana" - "Fascikla je otvorena, (š) %1$d (v) %2$d" + "Folder je otvoren, (š) %1$d (v) %2$d" "Dodirnite da zatvorite folder" "Dodirnite da sačuvate promjenu imena" - "Fascikla je zatvorena" - "Ime fascikle je promijenjeno u %1$s" - "Fascikla: %1$s" + "Folder je zatvoren" + "Ime foldera je promijenjeno u %1$s" + "Folder: %1$s" "Dodaci" - "Pozadine" - "Postavke" + "Pozadinske slike" + "Postavke za Home" "Onemogućio vaš administrator" "Pregled" "Dozvoli rotiranje početnog ekrana" "Kada se telefon zarotira" "Trenutne postavke ekrana ne dozvoljavaju rotiranje" + "Tačke za obavještenja" + "Uključeno" + "Isključeno" + "Potreban je pristup obavještenjima" + "Za prikaz tačaka obavještenja, uključite obavještenja za aplikacije za aplikaciju %1$s" + "Promijeni postavke" "Dodajte ikonu na početni ekran" "Za nove aplikacije" - - - - - - + "Promjena oblika ikona" + "Koristite sistemski zadano" + "Kvadrat" + "Zaobljeni kvadrat" + "Krug" + "Suza" + "Primjenjivanje promjena oblika ikona" "Nepoznato" "Ukloni" "Traži" @@ -118,4 +125,7 @@ "Veličina vidžeta je promijenjena na širinu %1$s visinu %2$s" "Prečice" "%1$d prečica za aplikaciju %2$s" + "Za aplikaciju %3$s broj prečica je %1$d, a broj obavještenja je %2$d" + "Odbaci" + "Obavještenje je odbačeno" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 91a7333186..28daf6c717 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -70,20 +70,27 @@ "Kaust: %1$s" "Vidinad" "Taustapildid" - "Seaded" + "Avalehe seaded" "Keelas administraator" "Ülevaade" "Luba avaekraani pööramine" "Kui telefoni pööratakse" "Praegune kuvaseade ei luba pööramist" + "Märguandetäpid" + "Sees" + "Väljas" + "Vaja on juurdepääsu märguannetele" + "Märguandetäppide kuvamiseks lülitage sisse rakenduse %1$s märguanded" + "Seadete muutmine" "Lisa ikoon avaekraanile" "Uute rakenduste puhul" - - - - - - + "Ikooni kuju muutmine" + "Kasuta süsteemi vaikeseadet" + "Ruut" + "Ümarate nurkadega ruut" + "Ring" + "Tilk" + "Ikooni kuju muudatuste rakendamine" "Teadmata" "Eemalda" "Otsing" @@ -118,4 +125,7 @@ "Vidina suurust muudeti. Laius: %1$s. Kõrgus: %2$s" "Otseteed" "%1$d otseteed rakenduse %2$s jaoks" + "%1$d otseteed ja %2$d märguannet rakendusele %3$s" + "Loobu" + "Märguandest loobuti" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 1a4d809432..09a5f84382 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -70,20 +70,27 @@ "Karpeta: %1$s" "Widgetak" "Horma-paperak" - "Ezarpenak" + "Hasierako pantailaren ezarpenak" "Administratzaileak desgaitu du" "Ikuspegi orokorra" "Baimendu hasierako pantaila biratzea" "Telefonoa biratzen denean" "Uneko pantaila-ezarpenak ez du onartzen ikuspegia biratzea" + "Jakinarazteko biribiltxoak" + "Aktibatuta" + "Desaktibatuta" + "Jakinarazpenetarako sarbidea behar da" + "Jakinarazteko biribiltxoak ikusteko, aktibatu %1$s aplikazioaren jakinarazpenak" + "Aldatu ezarpenak" "Gehitu ikonoa hasierako pantailan" "Aplikazio berrietan" - - - - - - + "Aldatu ikonoaren forma" + "Erabili sistemaren balio lehenetsiak" + "Karratua" + "Ertz biribilduko karratua" + "Zirkulua" + "Malkoa" + "Ikonoaren forman egindako aldaketak aplikatzen" "Ezezaguna" "Kendu" "Bilatu" @@ -118,4 +125,7 @@ "Aldatu da widgetaren tamaina. Zabalera: %1$s. Altuera: %2$s." "Lasterbideak" "%2$s aplikazioaren %1$d lasterbide" + "%3$s aplikazioaren %1$d lasterbide eta %2$d jakinarazpen" + "Baztertu" + "Baztertu egin da jakinarazpena" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index e8213b51d2..4be320398e 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -70,20 +70,27 @@ "Cartafol: %1$s" "Widgets" "Fondos de pantalla" - "Configuración" + "Configuración de inicio" "Función desactivada polo administrador" "Visión xeral" "Permitir xirar a pantalla de inicio" "Ao xirar o teléfono" "A configuración de visualización actual non permite xirar a pantalla" + "Puntos de notificacións" + "Activado" + "Desactivado" + "Necesítase acceso ás notificacións" + "Para que se mostren os puntos de notificacións, activa as notificacións da aplicación %1$s" + "Cambiar configuración" "Engadir icona á pantalla de inicio" "Para novas aplicacións" - - - - - - + "Cambiar forma das iconas" + "Usar valores predeterminados do sistema" + "Cadrado" + "Cadrado de bordos redondeados" + "Círculo" + "Bágoa" + "Aplicando cambios na forma das iconas" "Descoñecido" "Eliminar" "Buscar" @@ -118,4 +125,7 @@ "Cambiouse o tamaño do widget polo ancho %1$s e a altura %2$s" "Atallos" "%1$d atallos para %2$s" + "%1$d atallos e %2$d notificacións para a aplicación %3$s" + "Ignorar" + "Ignorouse a notificación" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index aa4992db7a..587d16eb4e 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -70,16 +70,26 @@ "ફોલ્ડર: %1$s" "વિજેટ્સ" "વૉલપેપર્સ" - "સેટિંગ્સ" + "હોમ સેટિંગ્સ" "તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ" "વિહંગાવલોકન" "હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો" "જ્યારે ફોન ફેરવવામાં આવે ત્યારે" "વર્તમાન પ્રદર્શન સેટિંગ ફેરવવાની પરવાનગી આપતી નથી" + "સૂચના બિંદુઓ" + "ચાલુ" + "બંધ" + "નોટિફિકેશનનો ઍક્સેસની જરૂરી છે" + "નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, %1$s માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો" + "સેટિંગ્સ બદલો" "હોમ સ્ક્રીન પર આઇકન ઉમેરો" "નવી ઍપ્લિકેશનો માટે" "આઇકનનો આકાર બદલો" - "બદલશો નહીં" + "સિસ્ટમ ડિફૉલ્ટનો ઉપયોગ કરો" + "ચોરસ" + "ચોરસ જેવું ગોળ" + "વર્તુળ" + "ટિઅરડ્રોપ" "આઇકનના આકારમાં કરેલ ફેરફારો લાગુ કરી રહ્યા છીએ" "અજાણ્યો" "દૂર કરો" @@ -115,4 +125,7 @@ "વિજેટનો આકાર બદલીને %1$s પહોળાઈ %2$s ઊંચાઈ કર્યો" "શૉર્ટકટ્સ" "%2$s માટે %1$d શૉર્ટકટ" + "%3$s માટે %1$d શૉર્ટકટ અને %2$d સૂચનાઓ" + "છોડી દો" + "સૂચના છોડી દીધી" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 7c39a3f182..413f51fb3f 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -70,20 +70,27 @@ "Պանակ՝ %1$s" "Վիջեթներ" "Պաստառներ" - "Կարգավորումներ" + "Գլխավոր էջի կարգավորումներ" "Անջատվել է ձեր ադմինիստրատորի կողմից" "Համատեսք" "Թույլ տալ հիմնական էկրանի պտտումը" "Հեռախոսը պտտելու դեպքում" "Ցուցադրման ընթացիկ կարգավորումներն արգելում են պտտումը" + "Ծանուցման կետեր" + "Միացված է" + "Անջատված է" + "Անհրաժեշտ է ծանուցման թույլտվություն" + "Ծանուցման կետերը ցուցադրելու համար միացրեք հավելվածի ծանուցումները %1$s-ի համար" + "Փոխել կարգավորումները" "Ավելացնել պատկերակը Հիմնական էկրանին" "Նոր հավելվածների համար" - - - - - - + "Փոխել պատկերակների տեսքը" + "Օգտագործել համակարգի կանխադրված կարգավորումը" + "Քառակուսի" + "Քառանկյուն" + "Օղակ" + "Արցունքաձև" + "Պատկերակների տեսքի փոփոխությունները կիրառվում են" "Անհայտ է" "Հեռացնել" "Գտնել" @@ -118,4 +125,7 @@ "Վիջեթի լայնությունը փոխվել է %1$s-ի, իսկ բարձրությունը՝ %2$s-ի" "Դյուրանցումներ" "%1$d դյուրանցումներ %2$s հավելվածի համար" + "%1$d դյուրացում և %2$d ծանուցում %3$s-ի համար" + "Անտեսել" + "Ծանուցումը մերժված է" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 3694a10e43..3c54fc2e4b 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -70,20 +70,27 @@ "Mappa: %1$s" "Græjur" "Veggfóður" - "Stillingar" + "Heimastillingar" "Gert óvirkt af kerfisstjóra" "Yfirlit" "Leyfa snúning fyrir heimaskjá" "Þegar símanum er snúið" "Núverandi skjástilling leyfir ekki snúning" + "Tilkynningapunktar" + "Kveikt" + "Slökkt" + "Aðgangs að tilkynningum er krafist" + "Til að sýna tilkynningarpunkta skaltu kveikja á forritstilkynningum fyrir %1$s" + "Breyta stillingum" "Bæta tákni á heimaskjáinn" "Fyrir ný forrit" - - - - - - + "Breyta formi tákns" + "Nota sjálfgildi kerfis" + "Ferningur" + "Ferhringur" + "Hringur" + "Dropi" + "Breytir formi tákns" "Óþekkt" "Fjarlægja" "Leita" @@ -118,4 +125,7 @@ "Stærð græju breytt í %1$s á breidd og %2$s á hæð" "Flýtileiðir" "%1$d flýtileiðir fyrir %2$s" + "%1$d flýtileiðir og %2$d tilkynningar fyrir %3$s" + "Hunsa" + "Tilkynningu lokað" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index 197944936a..12171083fb 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -70,20 +70,27 @@ "საქაღალდე: %1$s" "ვიჯეტები" "ფონები" - "პარამეტრები" + "მთავარი გვერდის პარამეტრები" "გათიშულია თქვენი ადმინისტრატორის მიერ" "მიმოხილვა" "მთავარი ეკრანის შეტრიალების დაშვება" "ტელეფონის შეტრიალებისას" "ბრუნვა დაუშვებელია ჩვენების მიმდინარე პარამეტრებით" + "შეტყობინების ნიშნულები" + "ჩართული" + "გამორთული" + "საჭიროა შეტყობინებებზე წვდომა" + "შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები %1$s-ისთვის" + "პარამეტრების შეცვლა" "ხატულას მთავარ ეკრანზე დამატება" "ახალი აპებისთვის" - - - - - - + "ხატულას ფორმის შეცვლა" + "ნაგულისხმევი სისტემური პარამეტრების გამოყენება" + "კვადრატი" + "წრეკუთხედი" + "წრე" + "წვეთი" + "მიმდინარეობს ხატულას ფორმის ცვლილებების მიყენება" "უცნობი" "ამოშლა" "ძიება" @@ -118,4 +125,7 @@ "ვიჯეტის ზომები შეიცვალა: სიგანე %1$s სიმაღლე %2$s" "მალსახმობები" "%2$s-ს აქვს %1$d მალსახმობი" + "%3$s-ის %1$d მალსახმობი და %2$d შეტყობინება" + "დახურვა" + "შეტყობინება დაიხურა" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 5df503a103..6cb4fa74e8 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -70,20 +70,27 @@ "Қалта: %1$s" "Виджеттер" "Тұсқағаздар" - "Параметрлер" + "Негізгі экран параметрлері" "Әкімші өшірді" "Шолу" "Негізгі экранның бұрылуына рұқсат ету" "Телефон бұрылғанда" "Экранның ағымдағы параметрі айналуға рұқсат бермейді" + "Хабарландыру белгілері" + "Қосулы" + "Өшірулі" + "Хабарландыруға кіру рұқсаты қажет" + "Хабарландыру белгілерін көрсету үшін %1$s қолданбасының қолданба хабарландыруларын қосыңыз" + "Параметрлерді өзгерту" "Негізгі экранға белгіше енгізу" "Жаңа қолданбаларға арналған" - - - - - - + "Белгіше пішінін өзгерту" + "Жүйенің әдепкі параметрін пайдалану" + "Шаршы" + "Жұмыр төртбұрыш" + "Шеңбер" + "Тамшы" + "Белгіше пішіні өзгерістері күшіне енуде" "Белгісіз" "Алып тастау" "Іздеу" @@ -118,4 +125,7 @@ "Виджет өлшемінің ені %1$s, биіктігі %2$s болып өзгертілді" "Таңбашалар" "%2$s қолданбасына арналған %1$d таңбаша" + "%3$s қолданбасының %1$d таңбашасы мен %2$d хабарландыруы" + "Бас тарту" + "Хабарландырудан бас тартылды" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index a64b604cb1..8782230bb5 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -70,20 +70,27 @@ "ថត៖ %1$s" "ធាតុ​ក្រាហ្វិក" "ផ្ទាំង​រូបភាព" - "ការកំណត់" + "ការកំណត់​ទំព័រដើម" "បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក" "សង្ខេប" "អនុញ្ញាតការបងិ្វលអេក្រង់ដើម" "នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក" "ការកំណត់អេក្រង់បច្ចុប្បន្នមិនអនុញ្ញាតការបង្វិលទេ" + "ស្លាកជូនដំណឹង" + "បើក" + "បិទ" + "តម្រូវ​ឲ្យមាន​សិទ្ធិចូល​ប្រើប្រាស់​ការជូនដំណឹង" + "ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ %1$s" + "ប្ដូរ​ការកំណត់" "បញ្ចូល​រូបតំណាង​ទៅ​អេក្រង់​ដើម" "សម្រាប់កម្មវិធីថ្មី" - - - - - - + "ប្តូររូបរាងរូបតំណាង" + "ប្រើលំនាំដើមរបស់ប្រព័ន្ធ" + "ការ៉េ" + "ការ៉េជ្រុងកោង" + "រង្វង់" + "តំណក់​ទឹកភ្នែក" + "កំពុងអនុវត្ត​ការប្តូររូបរាងរូបតំណាង" "មិន​ស្គាល់" "លុបចេញ" "ស្វែងរក" @@ -118,4 +125,7 @@ "ធាតុក្រាហ្វិកដែលបានប្តូរទំហំទៅទទឹងប្រវែង %1$s កម្ពស់ប្រវែង %2$s" "ផ្លូវកាត់" "%1$d ផ្លូវកាត់សម្រាប់ %2$s" + "ផ្លូវកាត់ចំនួន %1$d និង​ការជូនដំណឹងចំនួន %2$d សម្រាប់ %3$s" + "បដិសេធ" + "បាន​បដិសេធ​ការជូនដំណឹង" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index b22af0de8b..7566503b0b 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -70,16 +70,26 @@ "ಫೋಲ್ಡರ್: %1$s" "ವಿಜೆಟ್‌ಗಳು" "ವಾಲ್‌ಪೇಪರ್‌ಗಳು" - "ಸೆಟ್ಟಿಂಗ್‌ಗಳು" + "ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ" "ಅವಲೋಕನ" "ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ" "ಫೋನ್‌ ತಿರುಗಿಸಿದಾಗ" "ಪ್ರಸ್ತುತ ಪ್ರದರ್ಶನ ಸೆಟ್ಟಿಂಗ್ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ" + "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳು" + "ಆನ್" + "ಆಫ್" + "ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ" + "ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, %1$s ಗೆ ಅಪ್ಲಿಕೇಶನ್‌ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್‌ ಮಾಡಿ" + "ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ" "ಮುಖಪುಟದ ಪರದೆಗೆ ಐಕಾನ್ ಸೇರಿಸಿ" "ಹೊಸ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ" "ಐಕಾನ್ ಆಕಾರವನ್ನು ಬದಲಿಸಿ" - "ಬದಲಿಸಬೇಡಿ" + "ಸಿಸ್ಟಂ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ" + "ಚೌಕ" + "ಚೌಕವೃತ್ತ" + "ವೃತ್ತ" + "ಕಂಬನಿ" "ಐಕಾನ್ ಆಕಾರ ಬದಲಾವಣೆಯನ್ನು ಅನ್ವಯಿಸಲಾಗುತ್ತಿದೆ" "ಅಪರಿಚಿತ" "ತೆಗೆದುಹಾಕಿ" @@ -115,4 +125,7 @@ "ವಿಜೆಟ್ ಅನ್ನು %1$s ಅಗಲ %2$s ಎತ್ತರಕ್ಕೆ ಮರುಗಾತ್ರಗೊಳಿಸಲಾಗಿದೆ" "ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" "%2$s ಗೆ %1$d ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + "%3$s ಗಾಗಿ %1$d ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು ಮತ್ತು %2$d ಅಧಿಸೂಚನೆಗಳು" + "ವಜಾಗೊಳಿಸಿ" + "ಅಧಿಸೂಚನೆಯನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 21622924d4..7d19b30311 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -70,20 +70,27 @@ "Фолдер: %1$s" "Виджеттер" "Тушкагаздар" - "Тууралоолор" + "Башкы беттин жөндөөлөрү" "Администраторуңуз өчүрүп койгон" "Көз жүгүртүү" "Башкы экранды айлантууга уруксат берүү" "Телефон айланганда" "Экранды айлантуу параметри өчүрүлгөн" + "Эскертме белгилери" + "Күйүк" + "Өчүк" + "Эскертмелерге уруксат берилиши керек" + "Эскертме белгилерин көрсөтүү максатында, %1$s үчүн колдонмонун эскертмелерин күйгүзүү керек" + "Жөндөөлөрдү өзгөртүү" "Башкы экранга сүрөтчө кошуу" "Жаңы колдонмолор үчүн" - - - - - - + "Сүрөтчөнүн формасын өзгөртүү" + "Тутум сушунтаган демейкисин колдонуу" + "Чарчы" + "Бурчтары жумуру төрт бурчтук" + "Тегерек" + "Тамчы" + "Өзгөртүлгөн сүрөтчөнүн формасы колдонулууда" "Белгисиз" "Алып салуу" "Издөө" @@ -118,4 +125,7 @@ "Виджеттин кеңдиги %1$s бийиктиги %2$s болду" "Кыска жолдор" "%2$s колдонмосуна %1$d кыска жол бар" + "%3$s колдонмосу үчүн %1$d кыска жол жана %2$d эскертме бар" + "Этибарга албоо" + "Эскертме көз жаздымда калтырылды" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index 334305afe1..e31584d2e1 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -70,20 +70,27 @@ "ໂຟນເດີ: %1$s" "ວິດເຈັດ" "ພາບພື້ນຫຼັງ" - "ການຕັ້ງຄ່າ" + "ການຕັ້ງຄ່າ Home" "ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ" "ພາບຮວມ" "ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້" "ເມື່ອໝຸນໂທລະສັບ" "ການຕັ້ງຄ່າສະແດງຜົນປັດຈຸບັນບໍ່ອະນຸຍາດໃຫ້ໝຸນໄດ້" + "ຈຸດການແຈ້ງເຕືອນ" + "ເປີດ" + "ປິດ" + "ຕ້ອງໃຊ້ການເຂົ້າເຖິງການແຈ້ງເຕືອນ" + "ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ %1$s" + "ບັນທຶກການຕັ້ງຄ່າ" "ເພີ່ມໄອຄອນໃສ່ໜ້າຈໍຫຼັກ" "ສຳລັບແອັບໃໝ່" - - - - - - + "ປ່ຽນຮູບຮ່າງໄອຄອນ" + "ໃຊ້ຄ່າເລີ່ມຕົ້ນລະບົບ" + "ສີ່ຫຼ່ຽມຈັດຕຸລັດ" + "ສີ່ຫຼ່ຽມຂອບມົນ" + "ວົງມົນ" + "ນ້ຳຢອດ" + "ນຳໃຊ້ການປ່ຽນແປງຮູບຮ່າງໄອຄອນ" "​ບໍ່​ຮູ້​ຈັກ" "ລຶບ​" "ຊອກຫາ" @@ -118,4 +125,7 @@ "ປ່ຽນ​ຂະ​ໜາດ​ວິດ​ເຈັດ​ເປັນ​ລວງ​ກ້​ວາງ %1$s ລວງ​ສູງ %2$s ແລ້ວ" "ທາງລັດ" "%1$d ທາງລັດສຳລັບ %2$s" + "%1$d ທາງລັດ ແລະ %2$d ການແຈ້ງເຕືອນສຳລັບ %3$s" + "ປິດໄວ້" + "ປິດການແຈ້ງເຕືອນແລ້ວ" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 267e75b98d..1061ebf207 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -70,20 +70,27 @@ "Папка: %1$s" "Додатоци" "Позадини" - "Поставки" + "Поставки за Home" "Оневозможено од администраторот" "Краток преглед" "Дозволете ротација на Почетниот екран" "Кога телефонот се ротира" "Тековната поставка на Екранот не дозволува ротација" + "Точки за известување" + "Вклучено" + "Исклучено" + "Потребен е пристап до известувањата" + "За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата %1$s" + "Промени ги поставките" "Додајте икона на почетниот екран" "За нови апликации" - - - - - - + "Променете ја формата на иконата" + "Користи ја стандардната поставка на системот" + "Квадрат" + "Заоблен квадрат" + "Круг" + "Солза" + "Се применуваат промените на формата на иконата" "Непознато" "Отстрани" "Барај" @@ -118,4 +125,7 @@ "Големината на виџетот е променета на ширина %1$s висина %2$s" "Кратенки" "%1$d кратенки за %2$s" + "%1$d кратенки и %2$d известувања за %3$s" + "Отфрли" + "Известувањето е отфрлено" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index a92fc03568..62bcc8cbe2 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -36,7 +36,7 @@ "സ്വമേധയാ സ്ഥാപിക്കുന്നതിന് സ്‌പർശിച്ചുപിടിക്കുക" "സ്വയമേവ ചേർക്കുക" "ആപ്പുകളെ തിരയുക" - "ആപ്പ്‌സ് ലോഡുചെയ്യുന്നു..." + "ആപ്പുകൾ ലോഡുചെയ്യുന്നു..." "\"%1$s\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പ്‌സൊന്നും കണ്ടെത്തിയില്ല" "കൂടുതൽ ആപ്പുകൾക്ക് തിരയുക" "അറിയിപ്പുകൾ" @@ -70,16 +70,26 @@ "ഫോൾഡർ: %1$s" "വിജറ്റുകൾ" "വാൾപേപ്പർ" - "ക്രമീകരണം" + "ഹോം ക്രമീകരണം" "അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു" "കാഴ്ച" "ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക" "ഫോൺ തിരിച്ച നിലയിലായിരിക്കുമ്പോൾ" "നിലവിലെ ഡിസ്പ്ലേ ക്രമീകരണം തിരിക്കൽ അനുവദിക്കുന്നില്ല" + "അറിയിപ്പ് ഡോട്ടുകൾ" + "ഓൺ" + "ഓഫ്" + "അറിയിപ്പിനായുള്ള ആക്‌സസ് ആവശ്യമാണ്" + "അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുന്നതിന്, %1$s എന്നയാളിനായുള്ള ആപ്പ് അറിയിപ്പുകൾ ഓണാക്കുക" + "ക്രമീകരണം മാറ്റുക" "ഹോം സ്ക്രീനിലേക്ക് ഐക്കൺ ചേർക്കുക" "പുതിയ ആപ്പുകൾക്ക്" "ഐക്കണിന്റെ ആകാരം മാറ്റുക" - "മാറ്റരുത്" + "സിസ്‌റ്റം ഡിഫോൾട്ട് ഉപയോഗിക്കുക" + "ചതുരം" + "ചതുരവൃത്തം" + "വൃത്തം" + "കണ്ണുനീര്‍ തുള്ളി" "ഐക്കൺ ആകാര മാറ്റങ്ങൾ പ്രയോഗിക്കുന്നു" "അജ്ഞാതം" "നീക്കംചെയ്യുക" @@ -115,4 +125,7 @@ "വീതി %1$s ഉയരം %2$s-ലേക്ക് വിഡ്‌ജെറ്റിന്റെ വലുപ്പം മാറ്റി" "കുറുക്കുവഴികൾ" "%2$s ആപ്പിനുള്ള %1$d കുറുക്കുവഴികൾ" + "%3$s ആപ്പിനായുള്ള %1$d കുറുക്കുവഴികളും %2$d അറിയിപ്പുകളും" + "നിരസിക്കുക" + "അറിയിപ്പ് നിരസിച്ചു" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 5b74fd2049..b350570646 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -70,20 +70,27 @@ "Фолдер: %1$s" "Виджет" "Ханын зураг" - "Тохиргоо" + "Нүүр хуудасны тохиргоо" "Таны админ идэвхгүй болгосон" "Тойм" "Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх" "Утсыг эргүүлсэн үед" "Дэлгэцийн одоогийн тохиргоогоор эргүүлэх боломжгүй" + "Мэдэгдлийн цэг" + "Асаалттай" + "Унтраалттай" + "Мэдэгдлийн хандалт шаардлагатай" + "Мэдэгдлийн цэгийг харуулахын тулд %1$s-д аппын мэдэгдлийг асаана уу" + "Тохиргоог өөрчлөх" "Нүүр хуудаст дүрс тэмдэг нэмэх" "Шинэ аппад зориулсан" - - - - - - + "Дүрс тэмдгийн хэлбэрийг өөрчлөх" + "Системийн өгөгдмөл тохиргоог ашиглах" + "Дөрвөлжин" + "Мохоо өнцөгтэй дөрвөлжин" + "Дугуй" + "Дусал" + "Дүрс тэмдгийн хэлбэрийг өөрчилж байна" "Тодорхойгүй" "Устгах" "Хайх" @@ -118,4 +125,7 @@ "Виджэтийн өргөн %1$s, өндөр %2$s болсон" "Товчлол" "%2$s%1$d товчлол" + "%1$d товчлол болон %3$s%2$d мэдэгдэл" + "Хаах" + "Мэдэгдлийг хаасан" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 1a10e4b571..3435061b84 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -70,16 +70,26 @@ "फोल्डर: %1$s" "विजेट" "वॉलपेपर" - "सेटिंग्ज" + "होम सेटिंग्‍ज" "आपल्या प्रशासकाने अक्षम केले" "विहंगावलोकन" "मुख्यस्क्रीन फिरविण्‍यास अनुमती द्या" "फोन फिरविला जातो तेव्हा" "वर्तमान प्रदर्शन सेटिंग फिरविण्यास परवानगी देत नाही" + "सूचना बिंदू" + "चालू" + "बंद" + "सूचनांच्या अ‍ॅक्सेसची आवश्यकता आहे" + "सूचना बिंदू दाखवण्यासाठी, %1$s साठी अ‍ॅप सूचना चालू करा" + "सेटिंग्ज बदला" "मुख्य स्क्रीनवर चिन्ह जोडा" "नवीन अॅप्ससाठी" "चिन्हाचा आकार बदला" - "बदलू नका" + "सिस्‍टमचे डीफॉल्‍ट वापरा" + "चौरस" + "गोलाकार चौरस" + "वर्तुळ" + "अश्रू" "चिन्हाचा आकार बदल लागू करत आहे" "अज्ञात" "काढा" @@ -115,4 +125,7 @@ "विजेटचा आकार रुंदी %1$s उंची %2$s मध्ये बदलला" "शॉर्टकट" "%2$s साठी %1$d शॉर्टकट" + "%3$sसाठी %1$d शॉर्टकट आणि %2$d सूचना" + "डिसमिस करा" + "सूचना डिसमिस केली" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 756a2cf2f2..0dfe81af79 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -70,20 +70,27 @@ "Folder: %1$s" "Widget" "Kertas dinding" - "Tetapan" + "Tetapan laman utama" "Dilumpuhkan oleh pentadbir anda" "Ikhtisar" "Benarkan putaran Skrin Utama" "Apabila telefon diputar" "Tetapan Paparan semasa tidak membenarkan putaran" + "Titik pemberitahuan" + "Hidup" + "Mati" + "Akses pemberitahuan diperlukan" + "Untuk menunjukkan Titik Pemberitahuan, hidupkan pemberitahuan apl untuk %1$s" + "Tukar tetapan" "Tambahkan ikon pada Skrin Utama" "Untuk apl baharu" - - - - - - + "Tukar bentuk ikon" + "Gunakan lalai sistem" + "Segi empat sama" + "Segi empat berbucu bulat" + "Bulatan" + "Titisan air mata" + "Menggunakan perubahan bentuk ikon" "Tidak diketahui" "Alih keluar" "Carian" @@ -118,4 +125,7 @@ "Saiz widget diubah menjadi %1$s lebar %2$s tinggi" "Pintasan" "%1$d pintasan untuk %2$s" + "%1$d pintasan dan %2$d pemberitahuan untuk %3$s" + "Ketepikan" + "Pemberitahuan diketepikan" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 449aae8e02..3d1311f557 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -70,20 +70,27 @@ "အကန့်အမည်: %1$s" "ဝိဂျက်များ" "နောက်ခံများ" - "ဆက်တင်များ" + "ပင်မဆက်တင်များ" "သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်" "ခြုံငုံသုံးသပ်ချက်" "ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ" "ဖုန်းကိုလှည့်ထားစဉ်" "လက်ရှိ မြင်ကွင်းဆက်တင်တွင် မြင်ကွင်းကို လှည့်ခွင့်မပေးပါ" + "အကြောင်းကြားချက်အမှတ်အသားများ" + "ဖွင့်ထားသည်" + "ပိတ်ထားသည်" + "အကြောင်းကြားချက် အသုံးပြုခွင့် လိုအပ်သည်" + "အကြောင်းကြားချက် အစက်များကို ပြသရန် %1$s အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ" + "ဆက်တင်များ ပြောင်းရန်" "ပင်မစာမျက်နှာသို့ သင်္ကေတပုံ ထည့်ရန်" "အက်ပ်အသစ်များအတွက်" - - - - - - + "သင်္ကေတပုံစံကို ပြောင်းရန်" + "စနစ်၏ မူရင်းပုံကို အသုံးပြုရန်" + "လေးထောင့်" + "စတုရန်းမကျ စက်ဝိုင်းမကျပုံ" + "စက်ဝိုင်း" + "မျက်ရည်စက်ပုံ" + "သင်္ကေတပုံစံကို ပြောင်းလဲနေသည်" "မသိရ" "ဖယ်ရှားရန်" "ရှာဖွေရန်" @@ -118,4 +125,7 @@ "Widget အား အကျယ် %1$s အမြင့် %2$s အရွယ်အစားပြန်လည်ချိန်ညှိပြီး၏" "ဖြတ်လမ်းများ" "%2$s အတွက် အမြန်နည်း %1$d ခု" + "%3$s အတွက် ဖြတ်လမ်းလင့်ခ် %1$d နှင့် အကြောင်းကြားချက် %2$d ခု" + "ပယ်ရန်" + "အသိပေးချက်ကို ဖယ်ထုတ်ပြီးပါပြီ" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index e6534740e3..5503451455 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -84,13 +84,13 @@ "Endre innstillingene" "Legg til ikon på startsiden" "For nye apper" - "Endre ikonets form" + "Endre formen på ikonet" "Bruk systemstandard" "Kvadrat" "Superellipse" "Sirkel" "Dråpe" - "Aktiverer endringer av ikonets form" + "Aktiverer endringer av formen på ikonet" "Ukjent" "Fjern" "Søk" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 46c8f9ceae..b28e0e2b46 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -70,16 +70,26 @@ "फोल्डर: %1$s" "विजेटहरू" "वालपेपरहरु" - "सेटिंङहरू" + "गृहपृष्ठका सेटिङहरू" "तपाईँको प्रशासकद्वारा असक्षम गरिएको" "परिदृश्य" "गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्" "फोनलाई घुमाइँदा" "हालको प्रदर्शन सम्बन्धी सेटिङले घुमाउने सुविधालाई अनुमति दिँदैन" + "सूचनाको प्रतीक जनाउने थोप्लोहरू" + "सक्रिय छ" + "निष्क्रिय छ" + "सूचनासम्बन्धी पहुँच आवश्यक हुन्छ" + "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन %1$s को अनुप्रयोगसम्बन्धी सूचनाहरूलाई सक्रिय गर्नुहोस्" + "सेटिङहरू बदल्नुहोस्" "गृह स्क्रिनमा आइकन थप्नुहोस्" "नयाँ अनुप्रयोगका लागि" "आइकनको आकार परिवर्तन गर्नुहोस्" - "परिवर्तन नगर्नुहोस्" + "प्रणालीको पूर्वनिर्धारित सेटिङ प्रयोग गर्नुहोस्" + "वर्ग" + "वर्गाकार वृत्त" + "वृत्त" + "आँसुको थोपा" "आइकनको आकारमा गरिएका परिवर्तनहरू लागू गरिँदैछन्" "अज्ञात" "हटाउनुहोस्" @@ -115,4 +125,7 @@ "विजेट चौडाइ %1$s उचाइ %2$s मा पुनः आकार मिलाइयो" "सर्टकटहरू" "%2$s का %1$d सर्टकटहरू" + "%3$s का %1$d सर्टकट र %2$d सूचनाहरू" + "खारेज गर्नुहोस्" + "सूचना खारेज गरियो" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index c4c11ce04e..aaf4c92cb2 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -70,16 +70,26 @@ "ਫੋਲਡਰ: %1$s" "ਵਿਜਿਟ" "ਵਾਲਪੇਪਰ" - "ਸੈਟਿੰਗਾਂ" + "ਹੋਮ ਸੈਟਿੰਗਾਂ" "ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ" "ਰੂਪ-ਰੇਖਾ" "ਮੁੱਖ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁੰਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ" "ਜਦੋਂ ਫ਼ੋਨ ਘੁੰਮਾਇਆ ਜਾਂਦਾ ਹੈ" "ਵਰਤਮਾਨ ਡਿਸਪਲੇ ਸੈਟਿੰਗ ਘੁੰਮਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੰਦੀ ਹੈ" + "ਸੂਚਨਾ ਬਿੰਦੂ" + "ਚਾਲੂ" + "ਬੰਦ" + "ਸੂਚਨਾ ਪਹੁੰਚ ਲੋੜੀਂਦੀ ਹੈ" + "ਸੂਚਨਾ ਬਿੰਦੀਆਂ ਦਿਖਾਉਣ ਲਈ, %1$s ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ" + "ਸੈਟਿੰਗਾਂ ਬਦਲੋ" "ਮੁੱਖ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰਤੀਕ ਸ਼ਾਮਲ ਕਰੋ" "ਨਵੀਆਂ ਐਪਾਂ ਲਈ" "ਆਈਕਨ ਦੀ ਆਕ੍ਰਿਤੀ ਬਦਲੋ" - "ਨਾ ਬਦਲੋ" + "ਸਿਸਟਮ ਦੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗ ਵਰਤੋ" + "ਵਰਗ" + "ਵਰਗਾਕਾਰ-ਚੱਕਰ" + "ਚੱਕਰ" + "ਹੰਝੂ ਦੀ ਬੂੰਦ" "ਆਈਕਨ ਦੀ ਆਕ੍ਰਿਤੀ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਨੂੰ ਲਾਗੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" "ਅਗਿਆਤ" "ਹਟਾਓ" @@ -115,4 +125,7 @@ "ਵਿਜੈਟ ਨੂੰ ਚੌੜਾਈ %1$s ਉਂਚਾਈ %2$s ਨੂੰ ਮੁੜ ਆਕਾਰ ਦਿੱਤਾ" "ਸ਼ਾਰਟਕੱਟ" "%2$s ਲਈ %1$d ਸ਼ਾਰਟਕੱਟ" + "%3$s ਲਈ %1$d ਸ਼ਾਰਟਕੱਟ ਅਤੇ %2$d ਸੂਚਨਾਵਾਂ" + "ਖਾਰਜ ਕਰੋ" + "ਸੂਚਨਾ ਖਾਰਜ ਕੀਤੀ ਗਈ" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 4ad962fa08..06278925bf 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -28,9 +28,9 @@ "Виджеты отключены в безопасном режиме" "Ярлык недоступен" "Главный экран" - "Пользовательские действия" + "Специальные действия" "Чтобы выбрать виджет, нажмите на значок и удерживайте его." - "Чтобы выбрать виджет, нажмите на него дважды и не отпускайте или выполните предложенные действия." + "Чтобы выбрать виджет или использовать специальные действия, нажмите на него дважды и не отпускайте." "%1$d x %2$d" "Ширина %1$d, высота %2$d" "Нажмите и удерживайте, чтобы добавить вручную" @@ -90,7 +90,7 @@ "Квадрат с закругленными краями" "Круг" "Капля" - "Применение изменений..." + "Применение изменений…" "Неизвестно" "Удалить" "Найти" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 569a77f003..fcb3bc0a77 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -70,20 +70,27 @@ "ෆෝල්ඩරය: %1$s" "විජට්" "වෝල්පේපර" - "සැකසීම්" + "Home සැකසීම්" "ඔබගේ පරිපාලක විසින් අබල කරන ලදී" "දළ විශ්ලේෂණය" "මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න" "දුරකථනය කරකවන විට" "වත්මන් සංදර්ශක සැකසීම් කරකැවීමට සහාය නොදක්වයි" + "දැනුම්දීම් තිත්" + "ක්‍රියාත්මකයි" + "ක්‍රියාවිරහිතයි" + "දැනුම්දීම් ප්‍රවේශය අවශ්‍යයි" + "දැනුම්දීම් තිත් පෙන්වීමට, %1$s සඳහා යෙදුම් දැනුම්දීම් සබල කරන්න" + "සැකසීම් වෙනස් කරන්න" "මුල් පිටු තිරය වෙත අයිකනය එක් කරන්න" "නව යෙදුම් සඳහා" - - - - - - + "නිරූපක හැඩය වෙනස් කරන්න" + "පද්ධති පෙරනිමි භාවිත කරන්න" + "සමචතුරස්‍රය" + "හතරැස් කවය" + "කවය" + "කඳුළු බිංදුව" + "නිරූපක හැඩය වෙනස් කිරීම් යොදමින්" "නොදනී" "ඉවත් කරන්න" "සොයන්න" @@ -118,4 +125,7 @@ "විජට් පළල %1$s උස %2$s වෙත ප්‍රමාණකරණය කරන ලදි" "කෙටිමං" "%2$s සඳහා කෙටි මං %1$d" + "%3$s සඳහා කෙටි මං %1$dක් සහ දැනුම්දීම් %2$dක්" + "ඉවතලන්න" + "දැනුම්දීම ඉවතලන ලදී" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index 2b656840d7..4ec5dc1ada 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -70,20 +70,27 @@ "Dosja: %1$s" "Miniaplikacionet" "Imazhet e sfondit" - "Cilësimet" + "Cilësimet e Home" "Çaktivizuar nga administratori" "Përmbledhje" "Lejo rrotullimin e ekranit kryesor" "Kur telefoni rrotullohet" "Cilësimi aktuali i afishimit nuk lejon rrotullimin" + "Pikat e njoftimeve" + "Aktiv" + "Joaktiv" + "Nevojitet qasja në njoftime" + "Për të shfaqur \"Pikat e njoftimeve\", aktivizo njoftimet e aplikacionit për %1$s" + "Ndrysho cilësimet" "Shto ikonë në ekranin bazë" "Për aplikacionet e reja" - - - - - - + "Ndrysho formën e ikonës" + "Përdor parazgjedhjen e sisteit" + "Katror" + "Katror me kënde të rrumbullakëta" + "Rreth" + "Pikë loti" + "Po zbatohen ndryshimet e formës së ikonës" "I panjohur" "Hiq" "Kërko" @@ -118,4 +125,7 @@ "Madhësia e miniaplikacionit u ndryshua me gjerësinë %1$s dhe lartësinë %2$s" "Shkurtoret" "%1$d shkurtesa për %2$s" + "%1$d shkurtore dhe %2$d njoftime për %3$s" + "Hiqe" + "Njoftimi u hoq" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index a1e00a11dc..156a49e37f 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -70,20 +70,27 @@ "கோப்புறை: %1$s" "ஷார்ட்கட்ஸ்" "வால்பேப்பர்கள்" - "அமைப்பு" + "முகப்பு அமைப்புகள்" "உங்கள் நிர்வாகி முடக்கியுள்ளார்" "மேலோட்டப் பார்வை" "முகப்புத் திரை சுழற்சியை அனுமதி" "மொபைலைச் சுழற்றும் போது" "தற்போதைய திரை அமைப்பு சுழற்றுவதை அனுமதிக்கவில்லை" + "அறிவிப்புப் புள்ளிகள்" + "இயக்கப்பட்டுள்ளது" + "முடக்கப்பட்டுள்ளது" + "அறிவிப்பிற்கான அணுகல் தேவை" + "அறிவிப்புப் புள்ளிகளைக் காட்ட, %1$s இன் பயன்பாட்டு அறிவிப்புகளை இயக்கவும்" + "அமைப்புகளை மாற்று" "முகப்புத் திரையில் ஐகானைச் சேர்" "புதிய பயன்பாடுகளுக்கு" - - - - - - + "ஐகான் வடிவத்தை மாற்று" + "அமைப்பின் இயல்புநிலையைப் பயன்படுத்து" + "சதுரம்" + "சதுரவட்டம்" + "வட்டம்" + "கண்ணீர்துளி" + "ஐகான் வடிவத்தை மாற்றுகிறது" "தெரியாதது" "அகற்று" "தேடு" @@ -118,4 +125,7 @@ "அகலம் %1$s மற்றும் உயரம் %2$sக்கு விட்ஜெட் அளவு மாற்றப்பட்டது" "குறுக்குவழிகள்" "%2$sக்கான %1$d குறுக்குவழிகள்" + "%3$s பயன்பாட்டிற்கான %1$d குறுக்குவழிகளும் %2$d அறிவிப்புகளும் உள்ளன" + "நிராகரி" + "அறிவிப்பு நிராகரிக்கப்பட்டது" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 65ca927753..94e09d8660 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -70,16 +70,26 @@ "ఫోల్డర్: %1$s" "విడ్జెట్‌లు" "వాల్‌పేపర్‌లు" - "సెట్టింగ్‌లు" + "హోమ్ సెట్టింగ్‌లు" "మీ నిర్వాహకులు నిలిపివేసారు" "స్థూలదృష్టి" "హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి" "ఫోన్‌‌ను తిప్పినప్పుడు" "ప్రస్తుత డిస్‌ప్లే సెట్టింగ్ భ్రమణాన్ని అనుమతించలేదు" + "నోటిఫికేషన్ డాట్‌లు" + "ఆన్" + "ఆఫ్" + "నోటిఫికేషన్ యాక్సెస్ అవసరం" + "నోటిఫికేషన్ డాట్‌లను చూపించడానికి %1$sకు యాప్ నోటిఫికేషన్‌లను ఆన్ చేయండి" + "సెట్టింగ్‌లను మార్చు" "హోమ్ స్క్రీన్‌కి చిహ్నాన్ని జోడించు" "కొత్త అనువర్తనాల కోసం" "చిహ్న ఆకారాన్ని మార్చు" - "మార్చవద్దు" + "సిస్టమ్ డిఫాల్ట్‌ను ఉపయోగించండి" + "చతురస్రం" + "చతురస్రాకార వృత్తం" + "వృత్తం" + "కన్నీటి చుక్క" "చిహ్న ఆకార మార్పులను వర్తింపజేస్తోంది" "తెలియదు" "తీసివేయి" @@ -115,4 +125,7 @@ "విడ్జెట్ పరిమాణం వెడల్పు %1$sకి, ఎత్తు %2$sకి మార్చబడింది" "సత్వరమార్గాలు" "%2$s కోసం %1$d సత్వరమార్గాలు" + "%3$s కోసం %1$d సత్వరమార్గాలు మరియు %2$d నోటిఫికేషన్‌లు" + "తీసివేయి" + "నోటిఫికేషన్ తీసివేయబడింది" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 29d1cd53cd..f3d6d3f3cb 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -70,16 +70,26 @@ "فولڈر: %1$s" "ویجیٹس" "وال پیپرز" - "ترتیبات" + "ہوم ترتیبات" "آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا" "مجموعی جائزہ" "ہوم اسکرین گھمانے کی اجازت دیں" "جب فون گھمایا جاتا ہے" "موجودہ ڈسپلے ترتیب گھمانے کی اجازت نہیں دیتی" + "اطلاعاتی ڈاٹس" + "آن" + "آف" + "اطلاعاتی رسائی درکار ہے" + "اطلاعاتی ڈاٹس دکھانے کی خاطر %1$s کیلئے ایپ کی اطلاعات آن کریں" + "ترتیبات تبدیل کریں" "آئیکن کو ہوم اسکرین میں شامل کریں" "نئی ایپس کیلئے" "آئیکن کی شکل تبدیل کریں" - "تبدیل نہ کریں" + "سسٹم ڈیفالٹ کا استعمال کریں" + "مربع" + "اسکورکل" + "حلقہ" + "آنسو کا قطرہ" "آئيکن کی شکل کی تبدیلیاں لاگو ہو رہی ہیں" "نامعلوم" "ہٹائیں" @@ -115,4 +125,7 @@ "ویجیٹ کے سائز کو چوڑائی %1$s اونچائی %2$s میں تبدیل کر دیا گیا" "شارٹ کٹس" "%2$s کیلئے %1$d شارٹ کٹس" + "%3$s کے %1$d شارٹ کٹس اور %2$d اطلاعات" + "برخاست کریں" + "اطلاع مسترد ہو گئی" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 81be979cc6..aa288560c3 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -70,20 +70,27 @@ "Jild: %1$s" "Vidjetlar" "Fon rasmlari" - "Sozlamalar" + "Home sozlamalari" "Administrator tomonidan o‘chirilgan" "Umumiy ko‘rinish" "Asosiy ekranni aylantirishga ruxsat berish" "Telefon burilganda" "Ekran sozlamalariga ko‘ra uni aylantirib bo‘lmaydi" + "Bildirishnoma nuqtalari" + "Yoniq" + "O‘chiq" + "Bildirishnomalarga ruxsat berilmagan" + "Bildirishnoma nuqtalarini ko‘rsatish uchun %1$s ilovasida bildirishnomalarni yoqing" + "Sozlamalarni o‘zgartirish" "Bosh ekranga ikonka qo‘shish" "Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish" - - - - - - + "Ikonka shaklini o‘zgartirish" + "Standart tizim parametrlaridan foydalanish" + "Kvadrat" + "Qirralari aylana kvadrat" + "Aylana" + "Tomchi" + "Ikonka shakli o‘zgartirilmoqda" "Noma’lum" "O‘chirish" "Qidirish" @@ -118,4 +125,7 @@ "Vidjetning eni %1$s, bo‘yi %2$s qilib o‘zgartirildi" "Tezkor tugmalar" "%2$s ilovasi uchun %1$d ta tezkor tugma" + "%3$s ilovasi uchun %1$d ta yorliq va %2$d ta bildirishnoma" + "Yopish" + "Bildirishnoma yopildi" From 561ba6f75ea9657647290319fb4d38a68f4c1c1a Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 1 Aug 2017 15:23:26 -0700 Subject: [PATCH 10/38] Import translations. DO NOT MERGE Change-Id: Ia9d31a97df9a90afdeb62b63c53142d2ebe302c1 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- go/res/values-az/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-be/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-bg/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-bn/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-bs/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ca/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-cs/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-de/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-el/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-es-rUS/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-es/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-et/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-eu/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-fi/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-fr-rCA/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-fr/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-gl/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-gu/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-hi/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-hu/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-hy/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-is/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-iw/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ka/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-kk/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-km/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-kn/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ko/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ky/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-lo/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-lv/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-mk/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ml/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-mn/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-mr/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ms/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-my/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-nb/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ne/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-pa/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ro/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ru/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-si/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-sq/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ta/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-te/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-th/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-tl/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-ur/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-uz/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-vi/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-zh-rCN/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-zh-rHK/strings.xml | 26 ++++++++++++++++++++++++++ go/res/values-zh-rTW/strings.xml | 26 ++++++++++++++++++++++++++ res/values-az/strings.xml | 15 ++++++++------- res/values-be/strings.xml | 15 ++++++++------- res/values-bn/strings.xml | 9 ++++++--- res/values-bs/strings.xml | 15 ++++++++------- res/values-et/strings.xml | 15 ++++++++------- res/values-eu/strings.xml | 15 ++++++++------- res/values-gl/strings.xml | 15 ++++++++------- res/values-gu/strings.xml | 9 ++++++--- res/values-hy/strings.xml | 15 ++++++++------- res/values-is/strings.xml | 15 ++++++++------- res/values-ka/strings.xml | 15 ++++++++------- res/values-kk/strings.xml | 15 ++++++++------- res/values-km/strings.xml | 15 ++++++++------- res/values-kn/strings.xml | 9 ++++++--- res/values-ky/strings.xml | 15 ++++++++------- res/values-lo/strings.xml | 15 ++++++++------- res/values-mk/strings.xml | 15 ++++++++------- res/values-ml/strings.xml | 9 ++++++--- res/values-mn/strings.xml | 15 ++++++++------- res/values-mr/strings.xml | 9 ++++++--- res/values-ms/strings.xml | 15 ++++++++------- res/values-my/strings.xml | 15 ++++++++------- res/values-nb/strings.xml | 4 ++-- res/values-ne/strings.xml | 9 ++++++--- res/values-pa/strings.xml | 9 ++++++--- res/values-ru/strings.xml | 6 +++--- res/values-si/strings.xml | 15 ++++++++------- res/values-sq/strings.xml | 15 ++++++++------- res/values-ta/strings.xml | 15 ++++++++------- res/values-te/strings.xml | 9 ++++++--- res/values-ur/strings.xml | 9 ++++++--- res/values-uz/strings.xml | 15 ++++++++------- 86 files changed, 1631 insertions(+), 179 deletions(-) create mode 100644 go/res/values-az/strings.xml create mode 100644 go/res/values-be/strings.xml create mode 100644 go/res/values-bg/strings.xml create mode 100644 go/res/values-bn/strings.xml create mode 100644 go/res/values-bs/strings.xml create mode 100644 go/res/values-ca/strings.xml create mode 100644 go/res/values-cs/strings.xml create mode 100644 go/res/values-de/strings.xml create mode 100644 go/res/values-el/strings.xml create mode 100644 go/res/values-es-rUS/strings.xml create mode 100644 go/res/values-es/strings.xml create mode 100644 go/res/values-et/strings.xml create mode 100644 go/res/values-eu/strings.xml create mode 100644 go/res/values-fi/strings.xml create mode 100644 go/res/values-fr-rCA/strings.xml create mode 100644 go/res/values-fr/strings.xml create mode 100644 go/res/values-gl/strings.xml create mode 100644 go/res/values-gu/strings.xml create mode 100644 go/res/values-hi/strings.xml create mode 100644 go/res/values-hu/strings.xml create mode 100644 go/res/values-hy/strings.xml create mode 100644 go/res/values-is/strings.xml create mode 100644 go/res/values-iw/strings.xml create mode 100644 go/res/values-ka/strings.xml create mode 100644 go/res/values-kk/strings.xml create mode 100644 go/res/values-km/strings.xml create mode 100644 go/res/values-kn/strings.xml create mode 100644 go/res/values-ko/strings.xml create mode 100644 go/res/values-ky/strings.xml create mode 100644 go/res/values-lo/strings.xml create mode 100644 go/res/values-lv/strings.xml create mode 100644 go/res/values-mk/strings.xml create mode 100644 go/res/values-ml/strings.xml create mode 100644 go/res/values-mn/strings.xml create mode 100644 go/res/values-mr/strings.xml create mode 100644 go/res/values-ms/strings.xml create mode 100644 go/res/values-my/strings.xml create mode 100644 go/res/values-nb/strings.xml create mode 100644 go/res/values-ne/strings.xml create mode 100644 go/res/values-pa/strings.xml create mode 100644 go/res/values-ro/strings.xml create mode 100644 go/res/values-ru/strings.xml create mode 100644 go/res/values-si/strings.xml create mode 100644 go/res/values-sq/strings.xml create mode 100644 go/res/values-ta/strings.xml create mode 100644 go/res/values-te/strings.xml create mode 100644 go/res/values-th/strings.xml create mode 100644 go/res/values-tl/strings.xml create mode 100644 go/res/values-ur/strings.xml create mode 100644 go/res/values-uz/strings.xml create mode 100644 go/res/values-vi/strings.xml create mode 100644 go/res/values-zh-rCN/strings.xml create mode 100644 go/res/values-zh-rHK/strings.xml create mode 100644 go/res/values-zh-rTW/strings.xml diff --git a/go/res/values-az/strings.xml b/go/res/values-az/strings.xml new file mode 100644 index 0000000000..c4b8cb7801 --- /dev/null +++ b/go/res/values-az/strings.xml @@ -0,0 +1,26 @@ + + + + + "Qısayolu seçmək üçün toxunub saxlayın." + "Qısayolu seçmək üçün iki dəfə basıb saxlayın və ya fərdi əməliyyatlardan istifadə edin." + "Qısayollar" + "%1$s qısayolları" + diff --git a/go/res/values-be/strings.xml b/go/res/values-be/strings.xml new file mode 100644 index 0000000000..4189e35fa0 --- /dev/null +++ b/go/res/values-be/strings.xml @@ -0,0 +1,26 @@ + + + + + "Дакраніцеся і ўтрымлiвайце ярлык, каб дадаць яго." + "Дакраніцеся двойчы і ўтрымлівайце, каб выбраць ярлык або выкарыстоўваць спецыяльныя дзеянні." + "Ярлыкі" + "Ярлыкі %1$s" + diff --git a/go/res/values-bg/strings.xml b/go/res/values-bg/strings.xml new file mode 100644 index 0000000000..1b85992d99 --- /dev/null +++ b/go/res/values-bg/strings.xml @@ -0,0 +1,26 @@ + + + + + "Докоснете и задръжте за избор на пряк път." + "Докоснете двукратно и задръжте за избор на пряк път или използвайте персонализирани действия." + "Преки пътища" + "Преки пътища за %1$s" + diff --git a/go/res/values-bn/strings.xml b/go/res/values-bn/strings.xml new file mode 100644 index 0000000000..c56c925a29 --- /dev/null +++ b/go/res/values-bn/strings.xml @@ -0,0 +1,26 @@ + + + + + "কোনও শর্টকাট বেছে নিতে টাচ করে ধরে রাখুন।" + "কোনও শর্টকাট বেছে নিতে ডাবল ট্যাপ করে ধরে রাখুন অথবা কাস্টম ক্রিয়াগুলি ব্যবহার করুন।" + "শর্টকাট" + "%1$s এর শর্টকাট" + diff --git a/go/res/values-bs/strings.xml b/go/res/values-bs/strings.xml new file mode 100644 index 0000000000..7042468b47 --- /dev/null +++ b/go/res/values-bs/strings.xml @@ -0,0 +1,26 @@ + + + + + "Dodirnite i držite da uzmete prečicu." + "Dvaput dodirnite i držite da uzmete prečicu ili koristite prilagođene akcije." + "Prečice" + "Prečice aplikacije %1$s" + diff --git a/go/res/values-ca/strings.xml b/go/res/values-ca/strings.xml new file mode 100644 index 0000000000..3b5c3f7b56 --- /dev/null +++ b/go/res/values-ca/strings.xml @@ -0,0 +1,26 @@ + + + + + "Mantén premuda una drecera per seleccionar-la." + "Fes doble toc i mantén premut per seleccionar una drecera o per utilitzar accions personalitzades." + "Dreceres" + "Dreceres de l\'aplicació %1$s" + diff --git a/go/res/values-cs/strings.xml b/go/res/values-cs/strings.xml new file mode 100644 index 0000000000..e4018f2c0f --- /dev/null +++ b/go/res/values-cs/strings.xml @@ -0,0 +1,26 @@ + + + + + "Zkratku vyberete podržením." + "Dvojitým klepnutím a podržením vyberte zkratku, případně použijte vlastní akce." + "Zkratky" + "Zkratky aplikace %1$s" + diff --git a/go/res/values-de/strings.xml b/go/res/values-de/strings.xml new file mode 100644 index 0000000000..43a1b3a9e1 --- /dev/null +++ b/go/res/values-de/strings.xml @@ -0,0 +1,26 @@ + + + + + "Doppeltippen und halten, um eine Verknüpfung auszuwählen." + "Doppeltippen und halten, um eine Verknüpfung auszuwählen oder benutzerdefinierte Aktionen zu nutzen." + "Verknüpfungen" + "%1$s-Verknüpfungen" + diff --git a/go/res/values-el/strings.xml b/go/res/values-el/strings.xml new file mode 100644 index 0000000000..ae59907d16 --- /dev/null +++ b/go/res/values-el/strings.xml @@ -0,0 +1,26 @@ + + + + + "Αγγίξτε παρατεταμένα για να σηκώσετε μια συντόμευση." + "Πατήσετε δύο φορές παρατεταμένα για να σηκώσετε μια συντόμευση ή για να χρησιμοποιήσετε προσαρμοσμένες ενέργειες." + "Συντομεύσεις" + "Συντομεύσεις %1$s" + diff --git a/go/res/values-es-rUS/strings.xml b/go/res/values-es-rUS/strings.xml new file mode 100644 index 0000000000..5212c035d3 --- /dev/null +++ b/go/res/values-es-rUS/strings.xml @@ -0,0 +1,26 @@ + + + + + "Mantén presionado para elegir un acceso directo." + "Presiona dos veces y mantén presionado para elegir un acceso directo o usar acciones personalizadas." + "Accesos directos" + "Accesos directos de %1$s" + diff --git a/go/res/values-es/strings.xml b/go/res/values-es/strings.xml new file mode 100644 index 0000000000..3ae45889cf --- /dev/null +++ b/go/res/values-es/strings.xml @@ -0,0 +1,26 @@ + + + + + "Mantén pulsado el acceso directo que quieras." + "Toca dos veces y mantén pulsado el acceso directo o utiliza acciones personalizadas." + "Accesos directos" + "Accesos directos de %1$s" + diff --git a/go/res/values-et/strings.xml b/go/res/values-et/strings.xml new file mode 100644 index 0000000000..2513e65a33 --- /dev/null +++ b/go/res/values-et/strings.xml @@ -0,0 +1,26 @@ + + + + + "Otsetee valimiseks puudutage seda pikalt." + "Topeltpuudutage ja hoidke otsetee valimiseks või kohandatud toimingute kasutamiseks." + "Otseteed" + "Rakenduse %1$s otseteed" + diff --git a/go/res/values-eu/strings.xml b/go/res/values-eu/strings.xml new file mode 100644 index 0000000000..9949ef091d --- /dev/null +++ b/go/res/values-eu/strings.xml @@ -0,0 +1,26 @@ + + + + + "Eduki sakatuta lasterbide bat aukeratzeko." + "Sakatu birritan eta eduki sakatuta lasterbide bat aukeratzeko edo ekintza pertsonalizatuak erabiltzeko." + "Lasterbideak" + "%1$s aplikazioaren lasterbidea" + diff --git a/go/res/values-fi/strings.xml b/go/res/values-fi/strings.xml new file mode 100644 index 0000000000..da9b0e1c42 --- /dev/null +++ b/go/res/values-fi/strings.xml @@ -0,0 +1,26 @@ + + + + + "Valitse pikakuvake painamalla sitä pitkään." + "Valitse pikakuvake tai käytä muokattuja toimintoja kaksoisnapauttamalla ja painamalla pitkään." + "Pikakuvakkeet" + "Kohteen %1$s pikakuvakkeet" + diff --git a/go/res/values-fr-rCA/strings.xml b/go/res/values-fr-rCA/strings.xml new file mode 100644 index 0000000000..c7fd6d6423 --- /dev/null +++ b/go/res/values-fr-rCA/strings.xml @@ -0,0 +1,26 @@ + + + + + "Maintenez un doigt sur le raccourci pour l\'ajouter" + "Touchez 2x un raccourci et maintenez doigt dessus pour l’aj. ou utiliser des actions personnalisées." + "Raccourcis" + "Raccourcis : %1$s" + diff --git a/go/res/values-fr/strings.xml b/go/res/values-fr/strings.xml new file mode 100644 index 0000000000..238fe73d75 --- /dev/null +++ b/go/res/values-fr/strings.xml @@ -0,0 +1,26 @@ + + + + + "Appui prolongé pour sélectionner raccourci." + "Appuyez 2 fois et maintenez pression pour sélectionner raccourci ou utilisez actions personnalisées." + "Raccourcis" + "Raccourcis %1$s" + diff --git a/go/res/values-gl/strings.xml b/go/res/values-gl/strings.xml new file mode 100644 index 0000000000..31621d5c2c --- /dev/null +++ b/go/res/values-gl/strings.xml @@ -0,0 +1,26 @@ + + + + + "Mantén premido un atallo para seleccionalo." + "Toca dúas veces e mantén premido para seleccionar un atallo ou utiliza accións personalizadas." + "Atallos" + "Atallos da aplicación %1$s" + diff --git a/go/res/values-gu/strings.xml b/go/res/values-gu/strings.xml new file mode 100644 index 0000000000..bdb549ff7f --- /dev/null +++ b/go/res/values-gu/strings.xml @@ -0,0 +1,26 @@ + + + + + "એક શૉર્ટકટ ચૂંટવા ટૅપ કરી રાખો." + "એક શૉર્ટકટ ચૂંટવા અથવા કોઈ કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટૅપ કરી રાખો." + "શૉર્ટકટ" + "%1$s શૉર્ટકટ" + diff --git a/go/res/values-hi/strings.xml b/go/res/values-hi/strings.xml new file mode 100644 index 0000000000..bc057760fb --- /dev/null +++ b/go/res/values-hi/strings.xml @@ -0,0 +1,26 @@ + + + + + "शॉर्टकट चुनने के लिए छूकर रखें." + "शॉर्टकट चुनने के लिए डबल टैप करके रखें या कस्टम कार्रवाइयों का उपयोग करें." + "शॉर्टकट" + "%1$s शॉर्टकट" + diff --git a/go/res/values-hu/strings.xml b/go/res/values-hu/strings.xml new file mode 100644 index 0000000000..369c22745a --- /dev/null +++ b/go/res/values-hu/strings.xml @@ -0,0 +1,26 @@ + + + + + "Felvételhez tartsa nyomva a parancsikont." + "Parancsikon felvételéhez koppintson rá duplán és tartsa nyomva, vagy használjon egyéni műveleteket." + "Parancsikonok" + "%1$s-parancsikonok" + diff --git a/go/res/values-hy/strings.xml b/go/res/values-hy/strings.xml new file mode 100644 index 0000000000..4747f6df35 --- /dev/null +++ b/go/res/values-hy/strings.xml @@ -0,0 +1,26 @@ + + + + + "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար։" + "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար կամ օգտվեք հարմարեցրած գործողություններից:" + "Դյուրանցումներ" + "%1$s դյուրանցումներ" + diff --git a/go/res/values-is/strings.xml b/go/res/values-is/strings.xml new file mode 100644 index 0000000000..b8bb923746 --- /dev/null +++ b/go/res/values-is/strings.xml @@ -0,0 +1,26 @@ + + + + + "Haltu fingri á flýtileið til að grípa hana." + "Ýttu tvisvar og haltu fingri á flýtileið til að grípa hana eða notaðu sérsniðnar aðgerðir." + "Flýtileiðir" + "%1$s flýtileiðir" + diff --git a/go/res/values-iw/strings.xml b/go/res/values-iw/strings.xml new file mode 100644 index 0000000000..f541d4d316 --- /dev/null +++ b/go/res/values-iw/strings.xml @@ -0,0 +1,26 @@ + + + + + "כדי להוסיף קיצור דרך, מקישים עליו פעמיים ומחזיקים." + "כדי להוסיף קיצור דרך או להשתמש בפעולות מותאמות אישית, מקישים על קיצור הדרך פעמיים ומחזיקים." + "קיצורי דרך" + "קיצורי דרך לאפליקציה %1$s" + diff --git a/go/res/values-ka/strings.xml b/go/res/values-ka/strings.xml new file mode 100644 index 0000000000..1b46534788 --- /dev/null +++ b/go/res/values-ka/strings.xml @@ -0,0 +1,26 @@ + + + + + "შეეხეთ და დააყოვნეთ მალსახმობის ასარჩევად." + "ორმაგად შეეხეთ და გეჭიროთ მალსახმობის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად." + "მალსახმობები" + "%1$s-ის მალსახმობები" + diff --git a/go/res/values-kk/strings.xml b/go/res/values-kk/strings.xml new file mode 100644 index 0000000000..e909818afc --- /dev/null +++ b/go/res/values-kk/strings.xml @@ -0,0 +1,26 @@ + + + + + "Таңбашаны таңдау үшін оны түртіп, ұстап тұрыңыз." + "Таңбашаны таңдау немесе арнаулы әрекеттерді пайдалану үшін екі рет түртіп, ұстап тұрыңыз." + "Таңбашалар" + "%1$s таңбаша" + diff --git a/go/res/values-km/strings.xml b/go/res/values-km/strings.xml new file mode 100644 index 0000000000..40082a4b9d --- /dev/null +++ b/go/res/values-km/strings.xml @@ -0,0 +1,26 @@ + + + + + "ប៉ះ ហើយចុចឲ្យជាប់ដើម្បីរើសផ្លូវកាត់មួយ។" + "ប៉ះពីរដង ហើយចុចឱ្យជាប់ដើម្បីរើសផ្លូវកាត់មួយ ឬប្រើសកម្មភាពផ្ទាល់ខ្លួន។" + "ផ្លូវកាត់" + "ផ្លូវកាត់សម្រាប់ %1$s" + diff --git a/go/res/values-kn/strings.xml b/go/res/values-kn/strings.xml new file mode 100644 index 0000000000..9c121fd294 --- /dev/null +++ b/go/res/values-kn/strings.xml @@ -0,0 +1,26 @@ + + + + + "ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ." + "ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ." + "ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + "%1$s ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + diff --git a/go/res/values-ko/strings.xml b/go/res/values-ko/strings.xml new file mode 100644 index 0000000000..60f925e36b --- /dev/null +++ b/go/res/values-ko/strings.xml @@ -0,0 +1,26 @@ + + + + + "바로가기를 선택하려면 길게 터치하세요." + "바로가기를 선택하려면 두 번 탭한 다음 길게 터치하거나 맞춤 액션을 사용합니다." + "바로가기" + "%1$s 바로가기" + diff --git a/go/res/values-ky/strings.xml b/go/res/values-ky/strings.xml new file mode 100644 index 0000000000..4c7e973cef --- /dev/null +++ b/go/res/values-ky/strings.xml @@ -0,0 +1,26 @@ + + + + + "Кыска жолду тандоо үчүн басып туруңуз." + "Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." + "Кыска жолдор" + "%1$s кыска жол" + diff --git a/go/res/values-lo/strings.xml b/go/res/values-lo/strings.xml new file mode 100644 index 0000000000..7864884acc --- /dev/null +++ b/go/res/values-lo/strings.xml @@ -0,0 +1,26 @@ + + + + + "ແຕະຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ." + "ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ ຫຼື ໃຊ້ຄຳສັ່ງແບບກຳນົດເອງ." + "ປຸ່ມລັດ" + "ປຸ່ມລັດ %1$s" + diff --git a/go/res/values-lv/strings.xml b/go/res/values-lv/strings.xml new file mode 100644 index 0000000000..04315ebaa0 --- /dev/null +++ b/go/res/values-lv/strings.xml @@ -0,0 +1,26 @@ + + + + + "Lai izvēlētos saīsni, pieskarieties un turiet to." + "Lai atlasītu saīsni, veiciet dubultskārienu uz tās un turiet to vai arī veiciet pielāgotas darbības." + "Saīsnes" + "Lietotnes %1$s saīsnes" + diff --git a/go/res/values-mk/strings.xml b/go/res/values-mk/strings.xml new file mode 100644 index 0000000000..52d66b5e28 --- /dev/null +++ b/go/res/values-mk/strings.xml @@ -0,0 +1,26 @@ + + + + + "Допрете двапати и задржете за да изберете кратенка." + "Допрете двапати и задржете за да изберете кратенка или да користите приспособени дејства." + "Кратенки" + "Кратенки за %1$s" + diff --git a/go/res/values-ml/strings.xml b/go/res/values-ml/strings.xml new file mode 100644 index 0000000000..b3c12e16e1 --- /dev/null +++ b/go/res/values-ml/strings.xml @@ -0,0 +1,26 @@ + + + + + "ഒരു കുറുക്കുവഴി ചേർക്കുന്നതിന് അത് സ്‌പർശിച്ച് പിടിക്കുക." + "ഒരു കുറുക്കുവഴി തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ രണ്ടുതവണ ടാപ്പുചെയ്ത് പിടിക്കുക." + "കുറുക്കുവഴികൾ" + "%1$s കുറുക്കുവഴികൾ" + diff --git a/go/res/values-mn/strings.xml b/go/res/values-mn/strings.xml new file mode 100644 index 0000000000..c89dfd1bdc --- /dev/null +++ b/go/res/values-mn/strings.xml @@ -0,0 +1,26 @@ + + + + + "Товчлол авах бол удаан дарна уу." + "Товчлол авах болон тохируулсан үйлдлийг ашиглахын тулд хоёр товшоод хүлээнэ үү." + "Товчлол" + "%1$s-н товчлол" + diff --git a/go/res/values-mr/strings.xml b/go/res/values-mr/strings.xml new file mode 100644 index 0000000000..2c767b4f19 --- /dev/null +++ b/go/res/values-mr/strings.xml @@ -0,0 +1,26 @@ + + + + + "शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." + "शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा." + "शॉर्टकट" + "%1$s शॉर्टकट" + diff --git a/go/res/values-ms/strings.xml b/go/res/values-ms/strings.xml new file mode 100644 index 0000000000..42add9a197 --- /dev/null +++ b/go/res/values-ms/strings.xml @@ -0,0 +1,26 @@ + + + + + "Sentuh & tahan untuk mengambil pintasan." + "Ketik dua kali & tahan untuk mengambil pintasan atau menggunakan tindakan tersuai." + "Pintasan" + "Pintasan %1$s" + diff --git a/go/res/values-my/strings.xml b/go/res/values-my/strings.xml new file mode 100644 index 0000000000..5784df63bf --- /dev/null +++ b/go/res/values-my/strings.xml @@ -0,0 +1,26 @@ + + + + + "လက်ကွက်ဖြတ်လမ်းတစ်ခုကို ရွေးရန် ထိပြီး ဖိထားပါ" + "လက်ကွက်ဖြတ်လမ်းကို ရွေးရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန်နှစ်ချက်တို့ပြီး ဖိထားပါ။" + "ဖြတ်လမ်းလင့်ခ်များ" + "%1$s ဖြတ်လမ်းလင့်ခ်များ" + diff --git a/go/res/values-nb/strings.xml b/go/res/values-nb/strings.xml new file mode 100644 index 0000000000..2a5ffb6e7c --- /dev/null +++ b/go/res/values-nb/strings.xml @@ -0,0 +1,26 @@ + + + + + "Trykk og hold for å velge en snarvei." + "Dobbelttrykk og hold for å velge en snarvei eller bruke tilpassede handlinger." + "Snarveier" + "%1$s-snarveier" + diff --git a/go/res/values-ne/strings.xml b/go/res/values-ne/strings.xml new file mode 100644 index 0000000000..0be0375f3a --- /dev/null +++ b/go/res/values-ne/strings.xml @@ -0,0 +1,26 @@ + + + + + "कुनै सटकर्ट छनौट गर्न छोइराख्नुहोस्।" + "कुनै सर्टकट छनौट गर्न दुईपटक ट्याप गरेर होल्ड गर्नुहोस् वा रोजेका कारबाहीहरू प्रयोग गर्नुहोस्।" + "सर्टकटहरू" + "%1$s सर्टकटहरू" + diff --git a/go/res/values-pa/strings.xml b/go/res/values-pa/strings.xml new file mode 100644 index 0000000000..fdb3c74152 --- /dev/null +++ b/go/res/values-pa/strings.xml @@ -0,0 +1,26 @@ + + + + + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਜਾਂ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਡਬਲ-ਟੈਪ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + "ਸ਼ਾਰਟਕੱਟ" + "%1$s ਸ਼ਾਰਟਕੱਟ" + diff --git a/go/res/values-ro/strings.xml b/go/res/values-ro/strings.xml new file mode 100644 index 0000000000..75d1796b57 --- /dev/null +++ b/go/res/values-ro/strings.xml @@ -0,0 +1,26 @@ + + + + + "Atingeți și țineți apăsat pentru a selecta o comandă rapidă." + "Atingeți de două ori și țineți apăsat pentru comandă rapidă sau folosiți acțiuni personalizate." + "Comenzi rapide" + "Comenzi rapide pentru %1$s" + diff --git a/go/res/values-ru/strings.xml b/go/res/values-ru/strings.xml new file mode 100644 index 0000000000..9c5c8cd340 --- /dev/null +++ b/go/res/values-ru/strings.xml @@ -0,0 +1,26 @@ + + + + + "Чтобы выбрать ярлык, нажмите на него и удерживайте." + "Чтобы выбрать ярлык или использовать специальные действия, нажмите на него дважды и не отпускайте." + "Ярлыки" + "%1$s: ярлыки" + diff --git a/go/res/values-si/strings.xml b/go/res/values-si/strings.xml new file mode 100644 index 0000000000..4b25c90b0b --- /dev/null +++ b/go/res/values-si/strings.xml @@ -0,0 +1,26 @@ + + + + + "කෙටි මගක් තෝරා ගැනීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න." + "විජට් එකක් තෝරා ගැනීමට හෝ අභිරුචි භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න." + "කෙටි මං" + "කෙටි මං %1$s" + diff --git a/go/res/values-sq/strings.xml b/go/res/values-sq/strings.xml new file mode 100644 index 0000000000..bb74db6b55 --- /dev/null +++ b/go/res/values-sq/strings.xml @@ -0,0 +1,26 @@ + + + + + "Prek dhe mbaj prekur për të zgjedhur një shkurtore." + "Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara." + "Shkurtoret" + "%1$s shkurtore" + diff --git a/go/res/values-ta/strings.xml b/go/res/values-ta/strings.xml new file mode 100644 index 0000000000..50059b65f9 --- /dev/null +++ b/go/res/values-ta/strings.xml @@ -0,0 +1,26 @@ + + + + + "குறுக்குவழியைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்." + "குறுக்குவழியை சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் அல்லது தனிப்பயன் செயல்களைப் பயன்படுத்தவும்." + "குறுக்குவழிகள்" + "%1$s குறுக்குவழிகள்" + diff --git a/go/res/values-te/strings.xml b/go/res/values-te/strings.xml new file mode 100644 index 0000000000..0bdf743342 --- /dev/null +++ b/go/res/values-te/strings.xml @@ -0,0 +1,26 @@ + + + + + "సత్వరమార్గాన్ని ఎంచుకోవడానికి తాకి & నొక్కి ఉంచండి." + "సత్వరమార్గాన్ని ఎంచుకోవడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కి &ఉంచండి." + "సత్వరమార్గాలు" + "%1$s సత్వరమార్గాలు" + diff --git a/go/res/values-th/strings.xml b/go/res/values-th/strings.xml new file mode 100644 index 0000000000..e73d89fb0e --- /dev/null +++ b/go/res/values-th/strings.xml @@ -0,0 +1,26 @@ + + + + + "แตะค้างไว้เพื่อเลือกทางลัด" + "แตะสองครั้งค้างไว้เพื่อเลือกทางลัดหรือใช้การกระทำที่กำหนดเอง" + "ทางลัด" + "ทางลัด %1$s" + diff --git a/go/res/values-tl/strings.xml b/go/res/values-tl/strings.xml new file mode 100644 index 0000000000..8f44ec5742 --- /dev/null +++ b/go/res/values-tl/strings.xml @@ -0,0 +1,26 @@ + + + + + "Pindutin nang matagal upang kumuha ng shortcut." + "I-double tap nang matagal upang kumuha ng shortcut o gumamit ng mga custom na pagkilos." + "Mga Shortcut" + "Mga shortcut sa %1$s" + diff --git a/go/res/values-ur/strings.xml b/go/res/values-ur/strings.xml new file mode 100644 index 0000000000..46bd823d8e --- /dev/null +++ b/go/res/values-ur/strings.xml @@ -0,0 +1,26 @@ + + + + + "کوئی شارٹ کٹ منتخب کرنے کیلئے ٹچ کریں اور دبائے رکھیں۔" + "کوئی شارٹ کٹ منتخب کرنے یا حسب ضرورت کاروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور دبائے رکھیں۔" + "شارٹ کٹس" + "%1$s شارٹ کٹس" + diff --git a/go/res/values-uz/strings.xml b/go/res/values-uz/strings.xml new file mode 100644 index 0000000000..318bc15722 --- /dev/null +++ b/go/res/values-uz/strings.xml @@ -0,0 +1,26 @@ + + + + + "Yorliqni tanlab olish uchun bosib turing." + "Ikki marta bosib va bosib turgan holatda yorliqni tanlang yoki maxsus amaldan foydalaning." + "Yorliqlar" + "%1$s ilovasi yorliqlari" + diff --git a/go/res/values-vi/strings.xml b/go/res/values-vi/strings.xml new file mode 100644 index 0000000000..84ed627964 --- /dev/null +++ b/go/res/values-vi/strings.xml @@ -0,0 +1,26 @@ + + + + + "Chạm và giữ để chọn lối tắt." + "Nhấn đúp và giữ để chọn lối tắt hoặc sử dụng tác vụ tùy chỉnh." + "Lối tắt" + "Lối tắt %1$s" + diff --git a/go/res/values-zh-rCN/strings.xml b/go/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..57351d37f5 --- /dev/null +++ b/go/res/values-zh-rCN/strings.xml @@ -0,0 +1,26 @@ + + + + + "触摸并按住快捷方式即可选择快捷方式。" + "点按两次并按住快捷方式即可选择快捷方式,您也可以使用自定义操作。" + "快捷方式" + "%1$s快捷方式" + diff --git a/go/res/values-zh-rHK/strings.xml b/go/res/values-zh-rHK/strings.xml new file mode 100644 index 0000000000..dea7749f68 --- /dev/null +++ b/go/res/values-zh-rHK/strings.xml @@ -0,0 +1,26 @@ + + + + + "按住捷徑即可選取捷徑。" + "扲兩下然後扲住就可以揀選捷徑,或者用自訂嘅操作。" + "捷徑" + "%1$s 捷徑" + diff --git a/go/res/values-zh-rTW/strings.xml b/go/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..07ae2ed5b4 --- /dev/null +++ b/go/res/values-zh-rTW/strings.xml @@ -0,0 +1,26 @@ + + + + + "按住捷徑即可選取。" + "輕觸兩下並按住捷徑即可選取,你也可以使用自訂動作。" + "捷徑" + "「%1$s」捷徑" + diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index a8791b7353..18f87bcf33 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -35,9 +35,9 @@ "%2$d hündürlük %1$d enində" "Manual olaraq yerləşdirmək üçün toxunaraq basıb saxlayın" "Avtomatik əlavə edin" - "Tətbiq Axtarın" - "Tətbiqlər endirilir..." - "\"%1$s\" sorğusuna uyğun Tətbiqlər tapılmadı" + "Tətbiqləri axtarın" + "Tətbiqlər yüklənir…" + "%1$s sorğusuna uyğun tətbiq tapılmadı" "Daha çox tətbiq üçün axtarış edin" "Bildirişlər" "Bu Əsas ekranda boş yer yoxdur." @@ -79,17 +79,18 @@ "Bildiriş nişanı" "Aktiv" "Deaktiv" + "Bildiriş girişi tələb edilir" + "Bildiriş Nöqtələrini göstərmək üçün %1$s bildirişlərini aktiv edin" + "Ayarları dəyişin" "Əsas ekrana ikona əlavə edin" "Yeni tətbiqlər üçün" - - + "İkona formasını dəyişin" "Sistem defoltu istifadə edin" "Kvadrat" "Kənarları dairəvi kvadrat" "Çevrə" "Gözyaşı damlası" - - + "İkona formasına etdiyiniz dəyişikliklər tətbiq edilir" "Naməlum" "Yığışdır" "Axtarış" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 0a055a4413..0a31ddf7c1 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -35,9 +35,9 @@ "Шырына: %1$d, вышыня: %2$d" "Каб размясціць уручную, дакраніцеся і ўтрымлівайце" "Дадаць аўтаматычна" - "Пошук у Праграмах" - "Ідзе загрузка праграм…" - "Праграм, якія адпавядаюць запыту \"%1$s\", не знойдзена" + "Пошук праграм" + "Праграмы загружаюцца…" + "Праграм, якія адпавядаюць запыту \"%1$s\", не знойдзена" "Шукаць іншыя праграмы" "Апавяшчэнні" "На гэтым Галоўным экране больш няма месца." @@ -79,17 +79,18 @@ "Значкі апавяшчэнняў" "Уключана" "Выключана" + "Патрабуецца доступ да апавяшчэнняў" + "Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для %1$s" + "Змяніць налады" "Дадаць значок на Галоўны экран" "Для новых праграм" - - + "Змяніць форму значка" "Выкарыстоўваць стандартныя формы" "Квадрат" "Прамавугольнік са скругленымі вугламі" "Круг" "Сляза" - - + "Змены формы значка прымяняюцца" "Невядома" "Выдаліць" "Шукаць" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index d4c5210593..92f1affb69 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -35,9 +35,9 @@ "%2$d উচ্চতা অনুযায়ী %1$d প্রস্থ" "নিজে যোগ করতে টাচ করে ধরে রাখুন" "স্বয়ংক্রিয়ভাবে যোগ করুন" - "অ্যাপ্লিকেশানগুলি অনুসন্ধান করুন" - "অ্যাপ্লিকেশানগুলি লোড হচ্ছে..." - "\"%1$s\" এর সাথে মেলে এমন কোনো অ্যাপ্লিকেশান পাওয়া যায়নি" + "অ্যাপ অনুসন্ধান করুন" + "অ্যাপ লোড হচ্ছে…" + "\"%1$s\" এর সাথে মেলে এমন কোনো অ্যাপ পাওয়া যায়নি" "আরো অ্যাপ্লিকেশানের জন্য অনুসন্ধান করুন" "বিজ্ঞপ্তি" "এই হোম স্ক্রীনে আর কোনো জায়গা নেই৷" @@ -79,6 +79,9 @@ "বিজ্ঞপ্তি ডট" "চালু হয়েছে" "বন্ধ আছে" + "বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন" + "বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, %1$s এর অ্যাপ বিজ্ঞপ্তি চালু করুন" + "সেটিংস পরিবর্তন করুন" "হোম স্ক্রিনে আইকন যোগ করুন" "নতুন অ্যাপ্লিকেশানগুলির জন্যে" "আইকনের আকৃতি পরিবর্তন করুন" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index d91106bb20..49c862a8cd 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -35,9 +35,9 @@ "Širina %1$d, visina %2$d" "Dodirnite i držite da postavite ručno" "Dodaj automatski" - "Pretraži aplikacije" - "Aplikacije se učitavaju…" - "Nije pronađena nijedna aplikacija koja odgovara upitu \"%1$s\"" + "Pretražite aplikacije" + "Aplikacije se učitavaju…" + "Nije pronađena nijedna aplikacija za upit \"%1$s\"" "Pretraži više aplikacija" "Obavještenja" "Na ovom početnom ekranu nema više prostora." @@ -79,17 +79,18 @@ "Tačke za obavještenja" "Uključeno" "Isključeno" + "Potreban je pristup obavještenjima" + "Za prikaz tačaka obavještenja, uključite obavještenja za aplikacije za aplikaciju %1$s" + "Promijeni postavke" "Dodajte ikonu na početni ekran" "Za nove aplikacije" - - + "Promjena oblika ikona" "Koristite sistemski zadano" "Kvadrat" "Zaobljeni kvadrat" "Krug" "Suza" - - + "Primjenjivanje promjena oblika ikona" "Nepoznato" "Ukloni" "Traži" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index f5ea4564d2..9d9991ddce 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -35,9 +35,9 @@ "%1$d lai ja %2$d kõrge" "Puudutage pikalt, et käsitsi asetada" "Lisa automaatselt" - "Otsige rakendustest" - "Rakenduste laadimine ..." - "Päringule „%1$s” ei vastanud ükski rakendus" + "Otsige rakendusi" + "Rakenduste laadimine …" + "Päringule „%1$s” ei vastanud ükski rakendus" "Otsi rohkem rakendusi" "Märguanded" "Sellel avaekraanil pole enam ruumi." @@ -79,17 +79,18 @@ "Märguandetäpid" "Sees" "Väljas" + "Vaja on juurdepääsu märguannetele" + "Märguandetäppide kuvamiseks lülitage sisse rakenduse %1$s märguanded" + "Seadete muutmine" "Lisa ikoon avaekraanile" "Uute rakenduste puhul" - - + "Ikooni kuju muutmine" "Kasuta süsteemi vaikeseadet" "Ruut" "Ümarate nurkadega ruut" "Ring" "Tilk" - - + "Ikooni kuju muudatuste rakendamine" "Teadmata" "Eemalda" "Otsing" diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 59fc221566..b6082fadab 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -35,9 +35,9 @@ "%1$d zabal eta %2$d luze" "Eduki sakatuta eskuz gehitzeko" "Gehitu automatikoki" - "Bilatu aplikazioetan" - "Aplikazioak kargatzen…" - "Ez da aurkitu \"%1$s\" bilaketarekin bat datorren aplikaziorik" + "Bilatu aplikazioetan" + "Aplikazioak kargatzen…" + "Ez da aurkitu \"%1$s\" bilaketaren emaitzarik" "Bilatu aplikazio gehiago" "Jakinarazpenak" "Hasierako pantaila honetan ez dago toki gehiago." @@ -79,17 +79,18 @@ "Jakinarazteko biribiltxoak" "Aktibatuta" "Desaktibatuta" + "Jakinarazpenetarako sarbidea behar da" + "Jakinarazteko biribiltxoak ikusteko, aktibatu %1$s aplikazioaren jakinarazpenak" + "Aldatu ezarpenak" "Gehitu ikonoa hasierako pantailan" "Aplikazio berrietan" - - + "Aldatu ikonoaren forma" "Erabili sistemaren balio lehenetsiak" "Karratua" "Ertz biribilduko karratua" "Zirkulua" "Malkoa" - - + "Ikonoaren forman egindako aldaketak aplikatzen" "Ezezaguna" "Kendu" "Bilatu" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 9211ba1a15..d55514d1e9 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -35,9 +35,9 @@ "%1$d de largo por %2$d de alto" "Mantén premido o elemento para colocalo manualmente" "Engadir automaticamente" - "Aplicacións de busca" - "Cargando aplicacións..." - "Non se atoparon aplicacións que coincidan con \"%1$s\"" + "Buscar aplicacións" + "Cargando aplicacións…" + "Non se atoparon aplicacións que coincidan con \"%1$s\"" "Buscar máis aplicacións" "Notificacións" "Non hai máis espazo nesta pantalla de inicio." @@ -79,17 +79,18 @@ "Puntos de notificacións" "Activado" "Desactivado" + "Necesítase acceso ás notificacións" + "Para que se mostren os puntos de notificacións, activa as notificacións da aplicación %1$s" + "Cambiar configuración" "Engadir icona á pantalla de inicio" "Para novas aplicacións" - - + "Cambiar forma das iconas" "Usar valores predeterminados do sistema" "Cadrado" "Cadrado de bordos redondeados" "Círculo" "Bágoa" - - + "Aplicando cambios na forma das iconas" "Descoñecido" "Eliminar" "Buscar" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index b491e42984..808c04756f 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -35,9 +35,9 @@ "%1$d પહોળાઈ X %2$d ઊંચાઈ" "મેન્યુઅલી મૂકવા માટે ટચ કરી દબાવી રાખો" "આપમેળે ઉમેરો" - "શોધ ઍપ્લિકેશનો" - "ઍપ્લિકેશનો લોડ કરી રહ્યું છે…" - "\"%1$s\" થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી" + "શોધ ઍપ્લિકેશનો" + "ઍપ્લિકેશનો લોડ કરી રહ્યું છે…" + "\"%1$s\"થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી" "વધુ ઍપ્લિકેશનો શોધો" "સૂચનાઓ" "આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી." @@ -79,6 +79,9 @@ "સૂચના બિંદુઓ" "ચાલુ" "બંધ" + "નોટિફિકેશનનો ઍક્સેસની જરૂરી છે" + "નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, %1$s માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો" + "સેટિંગ્સ બદલો" "હોમ સ્ક્રીન પર આઇકન ઉમેરો" "નવી ઍપ્લિકેશનો માટે" "આઇકનનો આકાર બદલો" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 1646f9e33e..2b55e966a4 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -35,9 +35,9 @@ "Լայնությունը՝ %1$d, բարձրությունը՝ %2$d" "Հպեք և պահեք՝ ձեռքով տեղադրելու համար" "Ավելացնել ավտոմատ կերպով" - "Հավելվածների որոնում" - "Հավելվածների բեռնում…" - %1$s» հարցմանը համապատասխանող հավելվածներ չեն գտնվել" + "Որոնել հավելվածներ" + "Հավելվածների բեռնում…" + %1$s» հարցմանը համապատասխանող հավելվածներ չեն գտնվել" "Որոնել այլ հավելվածներ" "Ծանուցումներ" "Այլևս տեղ չկա այս հիմնական էկրանին:" @@ -79,17 +79,18 @@ "Ծանուցման կետեր" "Միացված է" "Անջատված է" + "Անհրաժեշտ է ծանուցման թույլտվություն" + "Ծանուցման կետերը ցուցադրելու համար միացրեք հավելվածի ծանուցումները %1$s-ի համար" + "Փոխել կարգավորումները" "Ավելացնել պատկերակը Հիմնական էկրանին" "Նոր հավելվածների համար" - - + "Փոխել պատկերակների տեսքը" "Օգտագործել համակարգի կանխադրված կարգավորումը" "Քառակուսի" "Քառանկյուն" "Օղակ" "Արցունքաձև" - - + "Պատկերակների տեսքի փոփոխությունները կիրառվում են" "Անհայտ է" "Հեռացնել" "Գտնել" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 853cd3b41c..cf178a56ad 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -35,9 +35,9 @@ "%1$d á breidd og %2$d á hæð" "Haltu inni til að staðsetja handvirkt" "Bæta sjálfkrafa við" - "Leita í forritum" - "Hleður forrit…" - "Ekki fundust forrit sem samsvara „%1$s“" + "Leita í forritum" + "Hleður forrit…" + "Ekki fundust forrit sem samsvara „%1$s“" "Leita að fleiri forritum" "Tilkynningar" "Ekki meira pláss á þessum heimaskjá." @@ -79,17 +79,18 @@ "Tilkynningapunktar" "Kveikt" "Slökkt" + "Aðgangs að tilkynningum er krafist" + "Til að sýna tilkynningarpunkta skaltu kveikja á forritstilkynningum fyrir %1$s" + "Breyta stillingum" "Bæta tákni á heimaskjáinn" "Fyrir ný forrit" - - + "Breyta formi tákns" "Nota sjálfgildi kerfis" "Ferningur" "Ferhringur" "Hringur" "Dropi" - - + "Breytir formi tákns" "Óþekkt" "Fjarlægja" "Leita" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index 2634cdf431..7e8b46ce88 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -35,9 +35,9 @@ "სიგრძე: %1$d, სიგანე: %2$d" "ხანგრძლივად შეეხეთ ხელით განსათავსებლად" "ავტომატურად დამატება" - "აპების ძიება" - "აპები იტვირთება..." - "„%1$s“-ის თანხვედრი აპები არ მოიძებნა" + "აპების ძიება" + "აპები იტვირთება…" + "„%1$s“-ის თანხვედრი აპები არ მოიძებნა" "მეტი აპის პოვნა" "შეტყობინებები" "ამ მთავარ ეკრანზე ადგილი აღარ არის." @@ -79,17 +79,18 @@ "შეტყობინების ნიშნულები" "ჩართული" "გამორთული" + "საჭიროა შეტყობინებებზე წვდომა" + "შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები %1$s-ისთვის" + "პარამეტრების შეცვლა" "ხატულას მთავარ ეკრანზე დამატება" "ახალი აპებისთვის" - - + "ხატულას ფორმის შეცვლა" "ნაგულისხმევი სისტემური პარამეტრების გამოყენება" "კვადრატი" "წრეკუთხედი" "წრე" "წვეთი" - - + "მიმდინარეობს ხატულას ფორმის ცვლილებების მიყენება" "უცნობი" "ამოშლა" "ძიება" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 66766b6dba..50ed9aa680 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -35,9 +35,9 @@ "Ені: %1$d, биіктігі: %2$d" "Қолмен қою үшін басып тұрыңыз" "Автоматты енгізу" - "Қолданбаларды іздеу" - "Қолданбалар жүктелуде…" - %1$s» сұрауына сәйкес келетін қолданбалар жоқ" + "Қолданбаларды іздеу" + "Қолданбалар жүктелуде…" + "\"%1$s\" сұрауына сәйкес келетін қолданбалар жоқ" "Қосымша қолданбалар іздеу" "Хабарландырулар" "Бұл Негізгі экранда орын қалмады." @@ -79,17 +79,18 @@ "Хабарландыру белгілері" "Қосулы" "Өшірулі" + "Хабарландыруға кіру рұқсаты қажет" + "Хабарландыру белгілерін көрсету үшін %1$s қолданбасының қолданба хабарландыруларын қосыңыз" + "Параметрлерді өзгерту" "Негізгі экранға белгіше енгізу" "Жаңа қолданбаларға арналған" - - + "Белгіше пішінін өзгерту" "Жүйенің әдепкі параметрін пайдалану" "Шаршы" "Жұмыр төртбұрыш" "Шеңбер" "Тамшы" - - + "Белгіше пішіні өзгерістері күшіне енуде" "Белгісіз" "Алып тастау" "Іздеу" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index ee44302eaf..7028f7e3ae 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -35,9 +35,9 @@ "ទទឺង %1$d គុណនឹងកម្ពស់ %2$d" "ចុច​ឲ្យជាប់​ដើម្បី​បញ្ចូលវា​ដោយផ្ទាល់" "បញ្ចូល​ដោយ​ស្វ័យ​ប្រវត្តិ" - "ស្វែងរកកម្មវិធី" - "កំពុងដំណើរការកម្មវិធី..." - "គ្មានកម្មវិធីដែលត្រូវជាមួយ \"%1$s\" ទេ" + "ស្វែងរក​កម្មវិធី" + "កំពុងផ្ទុកកម្មវិធី…" + "រកមិនឃើញកម្មវិធី​ដែលត្រូវគ្នាជាមួយ \"%1$s\" ទេ" "ស្វែងរកកម្មវិធីច្រើនទៀត" "ការ​ជូនដំណឹង" "គ្មាន​បន្ទប់​នៅ​លើ​អេក្រង់​ដើម​នេះ​ទៀត​ទេ។" @@ -79,17 +79,18 @@ "ស្លាកជូនដំណឹង" "បើក" "បិទ" + "តម្រូវ​ឲ្យមាន​សិទ្ធិចូល​ប្រើប្រាស់​ការជូនដំណឹង" + "ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ %1$s" + "ប្ដូរ​ការកំណត់" "បញ្ចូល​រូបតំណាង​ទៅ​អេក្រង់​ដើម" "សម្រាប់កម្មវិធីថ្មី" - - + "ប្តូររូបរាងរូបតំណាង" "ប្រើលំនាំដើមរបស់ប្រព័ន្ធ" "ការ៉េ" "ការ៉េជ្រុងកោង" "រង្វង់" "តំណក់​ទឹកភ្នែក" - - + "កំពុងអនុវត្ត​ការប្តូររូបរាងរូបតំណាង" "មិន​ស្គាល់" "លុបចេញ" "ស្វែងរក" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 6c89b7bd13..9a31649be3 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -35,9 +35,9 @@ "%1$d ಅಗಲ ಮತ್ತು %2$d ಎತ್ತರ" "ಹಸ್ತಚಾಲಿತವಾಗಿ ಸೇರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ" "ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸೇರಿಸಿ" - "ಅಪ್ಲಿಕೇಷನ್‌ಗಳನ್ನು ಹುಡುಕಿ" - "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..." - "\"%1$s\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ" + "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹುಡುಕಿ" + "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..." + "\"%1$s\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ" "ಮತ್ತಷ್ಟು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹುಡುಕಿ" "ಅಧಿಸೂಚನೆಗಳು" "ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಹೆಚ್ಚು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ." @@ -79,6 +79,9 @@ "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳು" "ಆನ್" "ಆಫ್" + "ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ" + "ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, %1$s ಗೆ ಅಪ್ಲಿಕೇಶನ್‌ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್‌ ಮಾಡಿ" + "ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ" "ಮುಖಪುಟದ ಪರದೆಗೆ ಐಕಾನ್ ಸೇರಿಸಿ" "ಹೊಸ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ" "ಐಕಾನ್ ಆಕಾರವನ್ನು ಬದಲಿಸಿ" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index cc15f04479..85ba8be3c3 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -35,9 +35,9 @@ "Туурасы: %1$d, бийиктиги: %2$d" "Кол менен жайгаштыруу үчүн басып туруп, таштаңыз" "Автоматтык түрдө кошуу" - "Колдонмолорду издөө" - "Колдонмолор жүктөлүүдө…" - "\"%1$s\" дал келген колдонмолор табылган жок" + "Колдонмолорду издөө" + "Колдонмолор жүктөлүүдө…" + "\"%1$s\" сурамына дал келген колдонмолор табылган жок" "Көбүрөөк колдонмолорду издөө" "Эскертмелер" "Бул Үй экранында бош орун жок." @@ -79,17 +79,18 @@ "Эскертме белгилери" "Күйүк" "Өчүк" + "Эскертмелерге уруксат берилиши керек" + "Эскертме белгилерин көрсөтүү максатында, %1$s үчүн колдонмонун эскертмелерин күйгүзүү керек" + "Жөндөөлөрдү өзгөртүү" "Башкы экранга сүрөтчө кошуу" "Жаңы колдонмолор үчүн" - - + "Сүрөтчөнүн формасын өзгөртүү" "Тутум сушунтаган демейкисин колдонуу" "Чарчы" "Бурчтары жумуру төрт бурчтук" "Тегерек" "Тамчы" - - + "Өзгөртүлгөн сүрөтчөнүн формасы колдонулууда" "Белгисиз" "Алып салуу" "Издөө" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index 0b294344e7..9a50c4b517 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -35,9 +35,9 @@ "ກວ້າງ %1$d ຄູນສູງ %2$d" "ແຕະຄ້າງໄວ້ເພື່ອວາງດ້ວຍຕົນເອງ" "ເພີ່ມໂດຍອັດຕະໂນມັດ" - "ຊອກຫາແອັບ" - "​ກຳ​ລັງ​ໂຫລດ​ແອັບ..." - "ບໍ່​ພົບ​ແອັບ​ໃດ​ທີ່​ກົງ​ກັນ \"%1$s\"" + "ຊອກຫາແອັບ" + "ກໍາລັງໂຫຼດແອັບ…" + "ບໍ່ພົບແອັບທີ່ກົງກັບ \"%1$s\"" "ຊອກຫາແອັບເພີ່ມເຕີມ" "ການແຈ້ງເຕືອນ" "ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກນີ້." @@ -79,17 +79,18 @@ "ຈຸດການແຈ້ງເຕືອນ" "ເປີດ" "ປິດ" + "ຕ້ອງໃຊ້ການເຂົ້າເຖິງການແຈ້ງເຕືອນ" + "ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ %1$s" + "ບັນທຶກການຕັ້ງຄ່າ" "ເພີ່ມໄອຄອນໃສ່ໜ້າຈໍຫຼັກ" "ສຳລັບແອັບໃໝ່" - - + "ປ່ຽນຮູບຮ່າງໄອຄອນ" "ໃຊ້ຄ່າເລີ່ມຕົ້ນລະບົບ" "ສີ່ຫຼ່ຽມຈັດຕຸລັດ" "ສີ່ຫຼ່ຽມຂອບມົນ" "ວົງມົນ" "ນ້ຳຢອດ" - - + "ນຳໃຊ້ການປ່ຽນແປງຮູບຮ່າງໄອຄອນ" "​ບໍ່​ຮູ້​ຈັກ" "ລຶບ​" "ຊອກຫາ" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index abd1d35dde..7d95a23a6c 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -35,9 +35,9 @@ "%1$d широк на %2$d висок" "Допрете и задржете за рачно поставување" "Додај автоматски" - "Пребарување апликации" - "Се вчитуваат апликации…" - "Не се најдени апликации што одговараат на „%1$s“" + "Пребарувајте апликации" + "Се вчитуваат апликации…" + "Не се најдени апликации што одговараат на „%1$s“" "Пребарај други апликации" "Известувања" "Нема повеќе простор на овој екран на почетната страница." @@ -79,17 +79,18 @@ "Точки за известување" "Вклучено" "Исклучено" + "Потребен е пристап до известувањата" + "За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата %1$s" + "Промени ги поставките" "Додајте икона на почетниот екран" "За нови апликации" - - + "Променете ја формата на иконата" "Користи ја стандардната поставка на системот" "Квадрат" "Заоблен квадрат" "Круг" "Солза" - - + "Се применуваат промените на формата на иконата" "Непознато" "Отстрани" "Барај" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index bad7e480a1..b6087546cd 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -35,9 +35,9 @@ "%1$d വീതിയും %2$d ഉയരവും" "സ്വമേധയാ സ്ഥാപിക്കുന്നതിന് സ്‌പർശിച്ചുപിടിക്കുക" "സ്വയമേവ ചേർക്കുക" - "ആപ്പുകളെ തിരയുക" - "ആപ്പുകൾ ലോഡുചെയ്യുന്നു..." - "\"%1$s\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പ്‌സൊന്നും കണ്ടെത്തിയില്ല" + "ആപ്പുകൾ തിരയുക" + "ആപ്പുകൾ ലോഡുചെയ്യുന്നു..." + "\"%1$s\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പുകളൊന്നും കണ്ടെത്തിയില്ല" "കൂടുതൽ ആപ്പുകൾക്ക് തിരയുക" "അറിയിപ്പുകൾ" "ഈ ഹോം സ്‌ക്രീനിൽ ഒഴിവൊന്നുമില്ല." @@ -79,6 +79,9 @@ "അറിയിപ്പ് ഡോട്ടുകൾ" "ഓൺ" "ഓഫ്" + "അറിയിപ്പിനായുള്ള ആക്‌സസ് ആവശ്യമാണ്" + "അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുന്നതിന്, %1$s എന്നയാളിനായുള്ള ആപ്പ് അറിയിപ്പുകൾ ഓണാക്കുക" + "ക്രമീകരണം മാറ്റുക" "ഹോം സ്ക്രീനിലേക്ക് ഐക്കൺ ചേർക്കുക" "പുതിയ ആപ്പുകൾക്ക്" "ഐക്കണിന്റെ ആകാരം മാറ്റുക" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 264e55a86e..22479cc3e4 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -35,9 +35,9 @@ "%1$d өргөн %2$d өндөр" "Гараар байршуулахын тулд дараад хүлээнэ үү" "Автоматаар нэмэх" - "Апп хайх" - "Аппликейшныг ачаалж байна..." - "\"%1$s\"-д нийцэх апп олдсонгүй" + "Апп хайх" + "Аппыг ачааллаж байна..." + "\"%1$s\"-д тохирох апп олдсонгүй" "Бусад апп-г хайх" "Мэдэгдэл" "Энэ Нүүр дэлгэц зайгүй." @@ -79,17 +79,18 @@ "Мэдэгдлийн цэг" "Асаалттай" "Унтраалттай" + "Мэдэгдлийн хандалт шаардлагатай" + "Мэдэгдлийн цэгийг харуулахын тулд %1$s-д аппын мэдэгдлийг асаана уу" + "Тохиргоог өөрчлөх" "Нүүр хуудаст дүрс тэмдэг нэмэх" "Шинэ аппад зориулсан" - - + "Дүрс тэмдгийн хэлбэрийг өөрчлөх" "Системийн өгөгдмөл тохиргоог ашиглах" "Дөрвөлжин" "Мохоо өнцөгтэй дөрвөлжин" "Дугуй" "Дусал" - - + "Дүрс тэмдгийн хэлбэрийг өөрчилж байна" "Тодорхойгүй" "Устгах" "Хайх" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index b23ea965d1..4fa8d49fe3 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -35,9 +35,9 @@ "%1$d रूंद बाय %2$d उंच" "स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा" "स्वयंचलितपणे जोडा" - "अॅप्स शोधा" - "अॅप्स लोड करीत आहे..." - "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत" + "अॅप्स शोधा" + "अॅप्स लोड करत आहे…" + "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत" "अधिक अॅप्स शोधा" "सूचना" "या मुख्य स्क्रीनवर आणखी जागा नाही." @@ -79,6 +79,9 @@ "सूचना बिंदू" "चालू" "बंद" + "सूचनांच्या अ‍ॅक्सेसची आवश्यकता आहे" + "सूचना बिंदू दाखवण्यासाठी, %1$s साठी अ‍ॅप सूचना चालू करा" + "सेटिंग्ज बदला" "मुख्य स्क्रीनवर चिन्ह जोडा" "नवीन अॅप्ससाठी" "चिन्हाचा आकार बदला" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 0928b7dc8b..f94b167a69 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -35,9 +35,9 @@ "Lebar %1$d kali tinggi %2$d" "Sentuh & tahan untuk meletakkan widget/ikon secara manual" "Tambahkan secara automatik" - "Cari Apl" - "Memuatkan Apl…" - "Tiada Apl yang ditemui sepadan dengan \"%1$s\"" + "Cari apl" + "Memuatkan apl…" + "Tiada apl yang ditemui sepadan dengan \"%1$s\"" "Cari lagi apl" "Pemberitahuan" "Tiada lagi ruang pada skrin Laman Utama ini." @@ -79,17 +79,18 @@ "Titik pemberitahuan" "Hidup" "Mati" + "Akses pemberitahuan diperlukan" + "Untuk menunjukkan Titik Pemberitahuan, hidupkan pemberitahuan apl untuk %1$s" + "Tukar tetapan" "Tambahkan ikon pada Skrin Utama" "Untuk apl baharu" - - + "Tukar bentuk ikon" "Gunakan lalai sistem" "Segi empat sama" "Segi empat berbucu bulat" "Bulatan" "Titisan air mata" - - + "Menggunakan perubahan bentuk ikon" "Tidak diketahui" "Alih keluar" "Carian" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index a4648b15a2..74574b9b23 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -35,9 +35,9 @@ "အလျား %1$d နှင့် အမြင့် %2$d" "ကိုယ်တိုင်ထည့်ရန် ထိထားပါ" "အလိုအလျောက် ထည့်ရန်" - "ရှာဖွေမှု အက်ပ်များ" - "အက်ပ်များ ရယူနေစဉ်..." - "\"%1$s\" နှင့်ကိုက်ညီသည့် အပ်ဖ်များမတွေ့ပါ" + "ရှာဖွေမှု အက်ပ်များ" + "အက်ပ်များကို ဖွင့်နေသည်…" + "\"%1$s\" နှင့်ကိုက်ညီသည့် အပ်ပ်များကို မတွေ့ပါ" "နောက်ထပ် အက်ပ်များကို ရှာပါ" "အကြောင်းကြားချက်များ" "ဤပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ" @@ -79,17 +79,18 @@ "အကြောင်းကြားချက်အမှတ်အသားများ" "ဖွင့်ထားသည်" "ပိတ်ထားသည်" + "အကြောင်းကြားချက် အသုံးပြုခွင့် လိုအပ်သည်" + "အကြောင်းကြားချက် အစက်များကို ပြသရန် %1$s အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ" + "ဆက်တင်များ ပြောင်းရန်" "ပင်မစာမျက်နှာသို့ သင်္ကေတပုံ ထည့်ရန်" "အက်ပ်အသစ်များအတွက်" - - + "သင်္ကေတပုံစံကို ပြောင်းရန်" "စနစ်၏ မူရင်းပုံကို အသုံးပြုရန်" "လေးထောင့်" "စတုရန်းမကျ စက်ဝိုင်းမကျပုံ" "စက်ဝိုင်း" "မျက်ရည်စက်ပုံ" - - + "သင်္ကေတပုံစံကို ပြောင်းလဲနေသည်" "မသိရ" "ဖယ်ရှားရန်" "ရှာဖွေရန်" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index bd348b0aab..65247c168d 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -84,13 +84,13 @@ "Endre innstillingene" "Legg til ikon på startsiden" "For nye apper" - "Endre ikonets form" + "Endre formen på ikonet" "Bruk systemstandard" "Kvadrat" "Superellipse" "Sirkel" "Dråpe" - "Aktiverer endringer av ikonets form" + "Aktiverer endringer av formen på ikonet" "Ukjent" "Fjern" "Søk" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 558b6cf8e5..904dad45e2 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -35,9 +35,9 @@ "%1$d चौडाइ गुणा %2$d उचाइ" "म्यानुअल तरिकाले थप्न छुनुहोस् र थिची राख्नुहोस्‌" "स्वतः थप्नुहोस्" - "अनुप्रयोगहरू खोज्नुहोस्" - "अनुप्रयोगहरू लोड गरिँदै..." - "\"%1$s\" सँग मिल्दो कुनै अनुप्रयोगहरू फेला परेनन्" + "खोजसम्बन्धी अनुप्रयोगहरू" + "अनुप्रयोगहरू लोड गर्दै…" + "\"%1$s\" सँग मिल्दो कुनै अनुप्रयोग भेटिएन" "थप अनुप्रयोगहरू खोज्नुहोस्" "सूचनाहरू" "यो गृह स्क्रिनमा कुनै थप ठाउँ छैन।" @@ -79,6 +79,9 @@ "सूचनाको प्रतीक जनाउने थोप्लोहरू" "सक्रिय छ" "निष्क्रिय छ" + "सूचनासम्बन्धी पहुँच आवश्यक हुन्छ" + "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन %1$s को अनुप्रयोगसम्बन्धी सूचनाहरूलाई सक्रिय गर्नुहोस्" + "सेटिङहरू बदल्नुहोस्" "गृह स्क्रिनमा आइकन थप्नुहोस्" "नयाँ अनुप्रयोगका लागि" "आइकनको आकार परिवर्तन गर्नुहोस्" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 05fe509a27..e4cff7b8c7 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -35,9 +35,9 @@ "%1$d ਚੌੜਾਈ ਅਤੇ %2$d ਲੰਬਾਈ" "ਹੱਥੀਂ ਰੱਖਣ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ" "ਸਵੈਚਲਿਤ ਤਰੀਕੇ ਨਾਲ ਸ਼ਾਮਲ ਕਰੋ" - "ਐਪਸ ਖੋਜੋ" - "ਐਪਾਂ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." - "\"%1$s\" ਨਾਲ ਮਿਲਦੀਆਂ ਕੋਈ ਵੀ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ" + "ਐਪਾਂ ਖੋਜੋ" + "ਐਪਾਂ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." + "\"%1$s\" ਨਾਲ ਮੇਲ ਖਾਂਦੀਆਂ ਕੋਈ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ" "ਹੋਰ ਐਪਾਂ ਖੋਜੋ" "ਸੂਚਨਾਵਾਂ" "ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ ਲਈ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ ਹੈ।" @@ -79,6 +79,9 @@ "ਸੂਚਨਾ ਬਿੰਦੂ" "ਚਾਲੂ" "ਬੰਦ" + "ਸੂਚਨਾ ਪਹੁੰਚ ਲੋੜੀਂਦੀ ਹੈ" + "ਸੂਚਨਾ ਬਿੰਦੀਆਂ ਦਿਖਾਉਣ ਲਈ, %1$s ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ" + "ਸੈਟਿੰਗਾਂ ਬਦਲੋ" "ਮੁੱਖ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰਤੀਕ ਸ਼ਾਮਲ ਕਰੋ" "ਨਵੀਆਂ ਐਪਾਂ ਲਈ" "ਆਈਕਨ ਦੀ ਆਕ੍ਰਿਤੀ ਬਦਲੋ" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index aed8f18e00..923f3573b3 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -28,9 +28,9 @@ "Виджеты отключены в безопасном режиме" "Ярлык недоступен" "Главный экран" - "Пользовательские действия" + "Специальные действия" "Чтобы выбрать виджет, нажмите на значок и удерживайте его." - "Чтобы выбрать виджет, нажмите на него дважды и не отпускайте или выполните предложенные действия." + "Чтобы выбрать виджет или использовать специальные действия, нажмите на него дважды и не отпускайте." "%1$d x %2$d" "Ширина %1$d, высота %2$d" "Нажмите и удерживайте, чтобы добавить вручную" @@ -90,7 +90,7 @@ "Квадрат с закругленными краями" "Круг" "Капля" - "Применение изменений..." + "Применение изменений…" "Неизвестно" "Удалить" "Найти" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 3b0425e33b..f6c42b2d9a 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -35,9 +35,9 @@ "පළල %1$d උස %2$d" "අතින් ස්ථානගත කිරීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න" "ස්වයංක්‍රියව එක් කරන්න" - "යෙදුම් සෙවීම" - "යෙදුම් පූරණය වෙමින්…" - "\"%1$s\" සමග ගැළපෙන යෙදුම් හමු නොවිණි" + "යෙදුම් සොයන්න" + "යෙදුම් පූරණය වෙමින්…" + "\"%1$s\" සමග ගැළපෙන යෙදුම් හමු නොවිණි" "තව යෙදුම් සඳහා සොයන්න" "දැනුම්දීම්" "මෙම මුල් පිටු තිරය මත තවත් අවසර නැත." @@ -79,17 +79,18 @@ "දැනුම්දීම් තිත්" "ක්‍රියාත්මකයි" "ක්‍රියාවිරහිතයි" + "දැනුම්දීම් ප්‍රවේශය අවශ්‍යයි" + "දැනුම්දීම් තිත් පෙන්වීමට, %1$s සඳහා යෙදුම් දැනුම්දීම් සබල කරන්න" + "සැකසීම් වෙනස් කරන්න" "මුල් පිටු තිරය වෙත අයිකනය එක් කරන්න" "නව යෙදුම් සඳහා" - - + "නිරූපක හැඩය වෙනස් කරන්න" "පද්ධති පෙරනිමි භාවිත කරන්න" "සමචතුරස්‍රය" "හතරැස් කවය" "කවය" "කඳුළු බිංදුව" - - + "නිරූපක හැඩය වෙනස් කිරීම් යොදමින්" "නොදනී" "ඉවත් කරන්න" "සොයන්න" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index 1400557c0c..3e6afee609 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -35,9 +35,9 @@ "%1$d i gjerë me %2$d i lartë" "Prek dhe mbaj të shtypur për të vendosur në mënyrë manuale" "Shto automatikisht" - "Kërko për aplikacione" - "Po ngarkon aplikacionet..." - "Nuk u gjet asnjë aplikacion që përputhet me \"%1$s\"" + "Kërko për aplikacione" + "Po ngarkon aplikacionet..." + "Nuk u gjet asnjë aplikacion që përputhet me \"%1$s\"" "Kërko për më shumë aplikacione" "Njoftimet" "Nuk ka më hapësirë në këtë ekran bazë." @@ -79,17 +79,18 @@ "Pikat e njoftimeve" "Aktiv" "Joaktiv" + "Nevojitet qasja në njoftime" + "Për të shfaqur \"Pikat e njoftimeve\", aktivizo njoftimet e aplikacionit për %1$s" + "Ndrysho cilësimet" "Shto ikonë në ekranin bazë" "Për aplikacionet e reja" - - + "Ndrysho formën e ikonës" "Përdor parazgjedhjen e sisteit" "Katror" "Katror me kënde të rrumbullakëta" "Rreth" "Pikë loti" - - + "Po zbatohen ndryshimet e formës së ikonës" "I panjohur" "Hiq" "Kërko" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index be8e82df6c..1d92581a05 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -35,9 +35,9 @@ "%1$d அகலத்திற்கு %2$d உயரம்" "நீங்களே சேர்க்க, தொட்டுப் பிடித்திருக்கவும்" "தானாகவே சேர்" - "பயன்பாடுகளில் தேடுக" - "பயன்பாடுகளை ஏற்றுகிறது..." - "\"%1$s\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை" + "பயன்பாடுகளில் தேடுக" + "பயன்பாடுகளை ஏற்றுகிறது…" + "\"%1$s\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை" "கூடுதல் பயன்பாடுகளைத் தேடு" "அறிவிப்புகள்" "முகப்புத் திரையில் இடமில்லை." @@ -79,17 +79,18 @@ "அறிவிப்புப் புள்ளிகள்" "இயக்கப்பட்டுள்ளது" "முடக்கப்பட்டுள்ளது" + "அறிவிப்பிற்கான அணுகல் தேவை" + "அறிவிப்புப் புள்ளிகளைக் காட்ட, %1$s இன் பயன்பாட்டு அறிவிப்புகளை இயக்கவும்" + "அமைப்புகளை மாற்று" "முகப்புத் திரையில் ஐகானைச் சேர்" "புதிய பயன்பாடுகளுக்கு" - - + "ஐகான் வடிவத்தை மாற்று" "அமைப்பின் இயல்புநிலையைப் பயன்படுத்து" "சதுரம்" "சதுரவட்டம்" "வட்டம்" "கண்ணீர்துளி" - - + "ஐகான் வடிவத்தை மாற்றுகிறது" "தெரியாதது" "அகற்று" "தேடு" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 15f3de7dab..7fa666c677 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -35,9 +35,9 @@ "%1$d వెడల్పు X %2$d ఎత్తు" "మాన్యువల్‌గా ఉంచడానికి నొక్కి &amp పట్టుకోండి" "స్వయంచాలకంగా జోడించు" - "అనువర్తనాలను శోధించండి" - "అనువర్తనాలను లోడ్ చేస్తోంది…" - "\"%1$s\"కి సరిపోలే అనువర్తనాలేవీ కనుగొనబడలేదు" + "అప్లికేషన్‌లను శోధించండి" + "అప్లికేషన్‌లను లోడ్ చేస్తోంది…" + "\"%1$s\"కి సరిపోలే అప్లికేషన్‌లేవీ కనుగొనబడలేదు" "మరిన్ని అనువర్తనాల కోసం శోధించు" "నోటిఫికేషన్‌లు" "ఈ హోమ్ స్క్రీన్‌లో ఖాళీ లేదు." @@ -79,6 +79,9 @@ "నోటిఫికేషన్ డాట్‌లు" "ఆన్" "ఆఫ్" + "నోటిఫికేషన్ యాక్సెస్ అవసరం" + "నోటిఫికేషన్ డాట్‌లను చూపించడానికి %1$sకు యాప్ నోటిఫికేషన్‌లను ఆన్ చేయండి" + "సెట్టింగ్‌లను మార్చు" "హోమ్ స్క్రీన్‌కి చిహ్నాన్ని జోడించు" "కొత్త అనువర్తనాల కోసం" "చిహ్న ఆకారాన్ని మార్చు" diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 84966b2888..a704fab4ca 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -35,9 +35,9 @@ "‏%1$d چوڑا اور ‎%2$d اونچا" "‏دستی طور پر رکھنے کیلئے ‎& ٹچ کرکے ہولڈ کریں" "خود کار طور پر شامل کریں" - "ایپس تلاش کریں" - "ایپس لوڈ ہو رہی ہیں…" - "\"%1$s\" سے مماثل کوئی ایپس نہیں ملیں" + "ایپس تلاش کریں" + "ایپس لوڈ کی جا رہی ہیں…" + "\"%1$s\" سے مماثل کوئی ایپس نہیں ملیں" "مزید ایپس تلاش کریں" "اطلاعات" "اس ہوم اسکرین پر مزید کوئی گنجائش نہیں ہے۔" @@ -79,6 +79,9 @@ "اطلاعاتی ڈاٹس" "آن" "آف" + "اطلاعاتی رسائی درکار ہے" + "اطلاعاتی ڈاٹس دکھانے کی خاطر %1$s کیلئے ایپ کی اطلاعات آن کریں" + "ترتیبات تبدیل کریں" "آئیکن کو ہوم اسکرین میں شامل کریں" "نئی ایپس کیلئے" "آئیکن کی شکل تبدیل کریں" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index a4725db53c..7e31889138 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -35,9 +35,9 @@ "Eni %1$d, bo‘yi %2$d" "Qo‘lda joylashtirish uchun bosib turing" "Avtomatik chiqarish" - "Ilovalar ichidan qidirish" - "Ilovalar yuklanmoqda…" - "“%1$s” so‘rovi bo‘yicha hech narsa topilmadi" + "Ilovalarni qidirish" + "Ilovalar yuklanmoqda…" + "“%1$s” bilan mos hech qanday ilova topilmadi" "Boshqa ilovalarni qidirish" "Bildirishnomalar" "Uy ekranida bitta ham xona yo‘q." @@ -79,17 +79,18 @@ "Bildirishnoma nuqtalari" "Yoniq" "O‘chiq" + "Bildirishnomalarga ruxsat berilmagan" + "Bildirishnoma nuqtalarini ko‘rsatish uchun %1$s ilovasida bildirishnomalarni yoqing" + "Sozlamalarni o‘zgartirish" "Bosh ekranga ikonka qo‘shish" "Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish" - - + "Ikonka shaklini o‘zgartirish" "Standart tizim parametrlaridan foydalanish" "Kvadrat" "Qirralari aylana kvadrat" "Aylana" "Tomchi" - - + "Ikonka shakli o‘zgartirilmoqda" "Noma’lum" "O‘chirish" "Qidirish" From 18751b649d02fd1e613c294e52193623b42f69e7 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 31 Jul 2017 17:25:27 -0700 Subject: [PATCH 11/38] Landscape launcher grid/all apps to spec. * Moves FastScroller to the right. Bug: 64160529 Change-Id: Ie0dfc0a2f0f2d6f6366e4f299769148d76017782 --- res/layout-land/all_apps_fast_scroller.xml | 9 +- res/values-land/dimens.xml | 16 ++- res/values/dimens.xml | 10 +- src/com/android/launcher3/DeviceProfile.java | 112 +++++++++++-------- 4 files changed, 93 insertions(+), 54 deletions(-) diff --git a/res/layout-land/all_apps_fast_scroller.xml b/res/layout-land/all_apps_fast_scroller.xml index 957c331741..6a68f84e98 100644 --- a/res/layout-land/all_apps_fast_scroller.xml +++ b/res/layout-land/all_apps_fast_scroller.xml @@ -22,7 +22,8 @@ style="@style/FastScrollerPopup" android:layout_alignParentEnd="true" android:layout_alignTop="@+id/apps_list_view" - android:layout_marginEnd="-5dp" /> + android:layout_marginTop="-5dp" + android:layout_marginEnd="-45dp" /> \ No newline at end of file diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml index 1b58e17754..92420a2f12 100644 --- a/res/values-land/dimens.xml +++ b/res/values-land/dimens.xml @@ -30,12 +30,24 @@ 4dp 0dp + 5.5dp + 2dp + + 50dp + 74dp + + + 0dp + + 50dp + 44dp 18dp + + 56dp + 32dp 6dp - 24dp - 32dp diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 28af705967..3f6efd794d 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -19,7 +19,8 @@ 8dp 32dp 1dp - 50dp + 0dp + 0dp 8dp 80dp 120dp @@ -31,16 +32,21 @@ 8dp 5.5dp + 0dp 8dp 8dp 2dp - 80dp + 80dp + 0dp 0dp 0dp 0dp + 0dp + 0dp + 48dp diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 6dfb1901e4..60c19bc5d0 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -75,6 +75,7 @@ public class DeviceProfile { // Workspace private final int desiredWorkspaceLeftRightMarginPx; public final int cellLayoutPaddingLeftRightPx; + public final int cellLayoutBottomPaddingPx; public final int edgeMarginPx; public final Rect defaultWidgetPadding; private final int defaultPageSpacingPx; @@ -84,7 +85,8 @@ public class DeviceProfile { // Page indicator private int pageIndicatorSizePx; - private final int pageIndicatorLandGutterPx; + private final int pageIndicatorLandLeftNavBarGutterPx; + private final int pageIndicatorLandRightNavBarGutterPx; private final int pageIndicatorLandWorkspaceOffsetPx; // Workspace icons @@ -113,13 +115,16 @@ public class DeviceProfile { // Hotseat public int hotseatCellHeightPx; - public int hotseatBarHeightPx; + // In portrait: size = height, in landscape: size = width + public int hotseatBarSizePx; public int hotseatBarTopPaddingPx; - public int hotseatBarLeftNavBarRightPaddingPx; - public int hotseatBarRightNavBarRightPaddingPx; public int hotseatBarBottomPaddingPx; - public int hotseatLandLeftNavBarGutterPx; - public int hotseatLandRightNavBarGutterPx; + + public int hotseatBarLeftNavBarLeftPaddingPx; + public int hotseatBarLeftNavBarRightPaddingPx; + + public int hotseatBarRightNavBarLeftPaddingPx; + public int hotseatBarRightNavBarRightPaddingPx; // All apps public int allAppsCellHeightPx; @@ -177,10 +182,14 @@ public class DeviceProfile { desiredWorkspaceLeftRightMarginPx = isVerticalBarLayout() ? 0 : edgeMarginPx; cellLayoutPaddingLeftRightPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding); + cellLayoutBottomPaddingPx = + res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_bottom_padding); pageIndicatorSizePx = res.getDimensionPixelSize( R.dimen.dynamic_grid_min_page_indicator_size); - pageIndicatorLandGutterPx = res.getDimensionPixelSize( - R.dimen.dynamic_grid_page_indicator_gutter_width); + pageIndicatorLandLeftNavBarGutterPx = res.getDimensionPixelSize( + R.dimen.dynamic_grid_page_indicator_land_left_nav_bar_gutter_width); + pageIndicatorLandRightNavBarGutterPx = res.getDimensionPixelSize( + R.dimen.dynamic_grid_page_indicator_land_right_nav_bar_gutter_width); pageIndicatorLandWorkspaceOffsetPx = res.getDimensionPixelSize(R.dimen.all_apps_caret_workspace_offset); defaultPageSpacingPx = @@ -213,16 +222,15 @@ public class DeviceProfile { R.dimen.dynamic_grid_hotseat_land_left_nav_bar_right_padding); hotseatBarRightNavBarRightPaddingPx = res.getDimensionPixelSize( R.dimen.dynamic_grid_hotseat_land_right_nav_bar_right_padding); - hotseatBarHeightPx = isVerticalBarLayout() - ? res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_height) - : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_height) + hotseatBarLeftNavBarLeftPaddingPx = res.getDimensionPixelSize( + R.dimen.dynamic_grid_hotseat_land_left_nav_bar_left_padding); + hotseatBarRightNavBarLeftPaddingPx = res.getDimensionPixelSize( + R.dimen.dynamic_grid_hotseat_land_right_nav_bar_left_padding); + hotseatBarSizePx = isVerticalBarLayout() + ? Utilities.pxFromDp(inv.iconSize, dm) + : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_size) + hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx; - hotseatLandLeftNavBarGutterPx = res.getDimensionPixelSize( - R.dimen.dynamic_grid_hotseat_land_left_nav_bar_gutter_width); - hotseatLandRightNavBarGutterPx = res.getDimensionPixelSize( - R.dimen.dynamic_grid_hotseat_land_right_nav_bar_gutter_width); - // Determine sizes. widthPx = width; heightPx = height; @@ -246,7 +254,7 @@ public class DeviceProfile { // in portrait mode closer together by adding more height to the hotseat. // Note: This calculation was created after noticing a pattern in the design spec. int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx; - hotseatBarHeightPx += extraSpace - pageIndicatorSizePx; + hotseatBarSizePx += extraSpace - pageIndicatorSizePx; // Recalculate the available dimensions using the new hotseat size. updateAvailableDimensions(dm, res); @@ -332,11 +340,16 @@ public class DeviceProfile { } private void updateIconSize(float scale, Resources res, DisplayMetrics dm) { + // Workspace float invIconSizePx = isVerticalBarLayout() ? inv.landscapeIconSize : inv.iconSize; iconSizePx = (int) (Utilities.pxFromDp(invIconSizePx, dm) * scale); iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale); iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale); + cellWidthPx = iconSizePx + iconDrawablePaddingPx; + cellHeightPx = iconSizePx + iconDrawablePaddingPx + + Utilities.calculateTextHeight(iconTextSizePx); + // All apps allAppsIconTextSizePx = iconTextSizePx; allAppsIconSizePx = iconSizePx; @@ -348,15 +361,14 @@ public class DeviceProfile { adjustToHideWorkspaceLabels(); } - cellWidthPx = iconSizePx + iconDrawablePaddingPx; - cellHeightPx = iconSizePx + iconDrawablePaddingPx - + Utilities.calculateTextHeight(iconTextSizePx); - // Hotseat + if (isVerticalBarLayout()) { + hotseatBarSizePx = iconSizePx; + } hotseatCellHeightPx = iconSizePx + iconDrawablePaddingPx; if (!isVerticalBarLayout()) { - int expectedWorkspaceHeight = availableHeightPx - hotseatBarHeightPx + int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx - pageIndicatorSizePx - topWorkspacePadding; float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace; workspaceSpringLoadShrinkFactor = Math.min( @@ -449,9 +461,10 @@ public class DeviceProfile { // Since we are only concerned with the overall padding, layout direction does // not matter. Point padding = getTotalWorkspacePadding(); - int cellPadding = cellLayoutPaddingLeftRightPx * 2; - result.x = calculateCellWidth(availableWidthPx - padding.x - cellPadding, inv.numColumns); - result.y = calculateCellHeight(availableHeightPx - padding.y, inv.numRows); + result.x = calculateCellWidth(availableWidthPx - padding.x + - cellLayoutPaddingLeftRightPx * 2, inv.numColumns); + result.y = calculateCellHeight(availableHeightPx - padding.y + - cellLayoutBottomPaddingPx, inv.numRows); return result; } @@ -467,20 +480,21 @@ public class DeviceProfile { Rect padding = recycle == null ? new Rect() : recycle; if (isVerticalBarLayout()) { if (mInsets.left > 0) { - padding.set(mInsets.left + pageIndicatorLandGutterPx, + padding.set(mInsets.left + pageIndicatorLandLeftNavBarGutterPx, 0, - hotseatBarHeightPx + hotseatLandLeftNavBarGutterPx - + hotseatBarLeftNavBarRightPaddingPx - mInsets.left, + hotseatBarSizePx + hotseatBarLeftNavBarRightPaddingPx + + hotseatBarLeftNavBarLeftPaddingPx + - mInsets.left, edgeMarginPx); } else { - padding.set(pageIndicatorLandGutterPx, + padding.set(pageIndicatorLandRightNavBarGutterPx, 0, - hotseatBarHeightPx + hotseatLandRightNavBarGutterPx - + hotseatBarRightNavBarRightPaddingPx, + hotseatBarSizePx + hotseatBarRightNavBarRightPaddingPx + + hotseatBarRightNavBarLeftPaddingPx, edgeMarginPx); } } else { - int paddingBottom = hotseatBarHeightPx + pageIndicatorSizePx; + int paddingBottom = hotseatBarSizePx + pageIndicatorSizePx; if (isTablet) { // Pad the left and right of the workspace to ensure consistent spacing // between all icons @@ -515,14 +529,14 @@ public class DeviceProfile { // Folders should only appear right of the drop target bar and left of the hotseat return new Rect(mInsets.left + dropTargetBarSizePx + edgeMarginPx, mInsets.top, - mInsets.left + availableWidthPx - hotseatBarHeightPx - edgeMarginPx, + mInsets.left + availableWidthPx - hotseatBarSizePx - edgeMarginPx, mInsets.top + availableHeightPx); } else { // Folders should only appear below the drop target bar and above the hotseat return new Rect(mInsets.left, mInsets.top + dropTargetBarSizePx + edgeMarginPx, mInsets.left + availableWidthPx, - mInsets.top + availableHeightPx - hotseatBarHeightPx + mInsets.top + availableHeightPx - hotseatBarSizePx - pageIndicatorSizePx - edgeMarginPx); } } @@ -609,38 +623,44 @@ public class DeviceProfile { if (hasVerticalBarLayout) { // Vertical hotseat -- The hotseat is fixed in the layout to be on the right of the // screen regardless of RTL - lp.gravity = Gravity.RIGHT; - lp.width = hotseatBarHeightPx + mInsets.left + mInsets.right; - lp.height = LayoutParams.MATCH_PARENT; - int paddingRight = mInsets.left > 0 ? hotseatBarLeftNavBarRightPaddingPx : hotseatBarRightNavBarRightPaddingPx; + int paddingLeft = mInsets.left > 0 + ? hotseatBarLeftNavBarLeftPaddingPx + : hotseatBarRightNavBarLeftPaddingPx; - hotseat.getLayout().setPadding(mInsets.left + cellLayoutPaddingLeftRightPx, - mInsets.top, mInsets.right + paddingRight + cellLayoutPaddingLeftRightPx, - workspacePadding.bottom); + lp.gravity = Gravity.RIGHT; + lp.width = hotseatBarSizePx + mInsets.left + mInsets.right + + paddingLeft + paddingRight; + lp.height = LayoutParams.MATCH_PARENT; + + hotseat.getLayout().setPadding(mInsets.left + cellLayoutPaddingLeftRightPx + + paddingLeft, + mInsets.top, + mInsets.right + cellLayoutPaddingLeftRightPx + paddingRight, + workspacePadding.bottom + cellLayoutBottomPaddingPx); } else if (isTablet) { // Pad the hotseat with the workspace padding calculated above lp.gravity = Gravity.BOTTOM; lp.width = LayoutParams.MATCH_PARENT; - lp.height = hotseatBarHeightPx + mInsets.bottom; + lp.height = hotseatBarSizePx + mInsets.bottom; hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx, hotseatBarTopPaddingPx, hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx, - hotseatBarBottomPaddingPx + mInsets.bottom); + hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx); } else { // For phones, layout the hotseat without any bottom margin // to ensure that we have space for the folders lp.gravity = Gravity.BOTTOM; lp.width = LayoutParams.MATCH_PARENT; - lp.height = hotseatBarHeightPx + mInsets.bottom; + lp.height = hotseatBarSizePx + mInsets.bottom; hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx, hotseatBarTopPaddingPx, hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx, - hotseatBarBottomPaddingPx + mInsets.bottom); + hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx); } hotseat.setLayoutParams(lp); @@ -659,7 +679,7 @@ public class DeviceProfile { // Put the page indicators above the hotseat lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; lp.height = pageIndicatorSizePx; - lp.bottomMargin = hotseatBarHeightPx + mInsets.bottom; + lp.bottomMargin = hotseatBarSizePx + mInsets.bottom; } pageIndicator.setLayoutParams(lp); } From 7f522a25c39ceb35aa009f029abe74497f03c403 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Fri, 28 Jul 2017 11:56:47 -0700 Subject: [PATCH 12/38] Optimizations to reduce all apps jank. * Since adding springs to the apps in All Apps, it is no longer efficient to build a hardware layer for it. * Pre-uploads bitmaps to RenderThread. * Only add overview animations if we are transitioning to/from it. Bug: 63711551 Change-Id: I948267598e95ec59dc156acb9abe6b5b789110c0 --- src/com/android/launcher3/BubbleTextView.java | 3 ++ .../LauncherStateTransitionAnimation.java | 6 ++-- .../WorkspaceStateTransitionAnimation.java | 36 +++++++++++-------- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index aeb82b376a..a63767c5d3 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -592,6 +592,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { mIconLoadRequest = null; mDisableRelayout = true; + // Optimization: Starting in N, pre-uploads the bitmap to RenderThread. + info.iconBitmap.prepareToDraw(); + if (info instanceof AppInfo) { applyFromApplicationInfo((AppInfo) info); } else if (info instanceof ShortcutInfo) { diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java index 44b9704f28..9ff61ec98b 100644 --- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java +++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java @@ -338,8 +338,10 @@ public class LauncherStateTransitionAnimation { toView.post(new StartAnimRunnable(animation, toView)); mCurrentAnimation = animation; } else if (animType == PULLUP) { - // We are animating the content view alpha, so ensure we have a layer for it - layerViews.addView(contentView); + if (!FeatureFlags.LAUNCHER3_PHYSICS) { + // We are animating the content view alpha, so ensure we have a layer for it. + layerViews.addView(contentView); + } animation.addListener(new AnimatorListenerAdapter() { @Override diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index 32deaf2862..76772dce44 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -274,7 +274,6 @@ public class WorkspaceStateTransitionAnimation { 1.0f : 0f; float finalHotseatAlpha = (states.stateIsNormal || states.stateIsSpringLoaded || (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && states.stateIsNormalHidden)) ? 1f : 0f; - float finalOverviewPanelAlpha = states.stateIsOverview ? 1f : 0f; float finalQsbAlpha = (states.stateIsNormal || (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && states.stateIsNormalHidden)) ? 1f : 0f; @@ -359,38 +358,47 @@ public class WorkspaceStateTransitionAnimation { final ViewGroup overviewPanel = mLauncher.getOverviewPanel(); + float finalOverviewPanelAlpha = states.stateIsOverview ? 1f : 0f; if (animated) { + // This is true when transitioning between: + // - Overview <-> Workspace + // - Overview <-> Widget Tray + if (finalOverviewPanelAlpha != overviewPanel.getAlpha()) { + Animator overviewPanelAlpha = ObjectAnimator.ofFloat( + overviewPanel, View.ALPHA, finalOverviewPanelAlpha); + overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel, + accessibilityEnabled)); + layerViews.addView(overviewPanel); + + if (states.overviewToWorkspace) { + overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2)); + } else if (states.workspaceToOverview) { + overviewPanelAlpha.setInterpolator(null); + } + + overviewPanelAlpha.setDuration(duration); + mStateAnimator.play(overviewPanelAlpha); + } + Animator scale = LauncherAnimUtils.ofPropertyValuesHolder(mWorkspace, new PropertyListBuilder().scale(mNewScale) .translationY(finalWorkspaceTranslationY).build()) .setDuration(duration); scale.setInterpolator(mZoomInInterpolator); mStateAnimator.play(scale); - Animator hotseatAlpha = mWorkspace.createHotseatAlphaAnimator(finalHotseatAlpha); - - Animator overviewPanelAlpha = ObjectAnimator.ofFloat( - overviewPanel, View.ALPHA, finalOverviewPanelAlpha); - overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel, - accessibilityEnabled)); // For animation optimization, we may need to provide the Launcher transition // with a set of views on which to force build and manage layers in certain scenarios. - layerViews.addView(overviewPanel); layerViews.addView(mLauncher.getHotseat()); layerViews.addView(mWorkspace.getPageIndicator()); + Animator hotseatAlpha = mWorkspace.createHotseatAlphaAnimator(finalHotseatAlpha); if (states.workspaceToOverview) { hotseatAlpha.setInterpolator(new DecelerateInterpolator(2)); - overviewPanelAlpha.setInterpolator(null); } else if (states.overviewToWorkspace) { hotseatAlpha.setInterpolator(null); - overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2)); } - - overviewPanelAlpha.setDuration(duration); hotseatAlpha.setDuration(duration); - - mStateAnimator.play(overviewPanelAlpha); mStateAnimator.play(hotseatAlpha); mStateAnimator.addListener(new AnimatorListenerAdapter() { boolean canceled = false; From eda690738702a85cfd03674e697178eba69f39e6 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 2 Aug 2017 23:28:53 -0700 Subject: [PATCH 13/38] Updating the shortcut icon for Launcher3Go Bug: 64273481 Change-Id: I46cfc21f1faa7032f1f220a3d4eff42be54e4deb --- go/res/drawable/ic_widget.xml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 go/res/drawable/ic_widget.xml diff --git a/go/res/drawable/ic_widget.xml b/go/res/drawable/ic_widget.xml new file mode 100644 index 0000000000..53368760ee --- /dev/null +++ b/go/res/drawable/ic_widget.xml @@ -0,0 +1,25 @@ + + + + From 902e235348d64e14ce103364987c2abd2a100f98 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 2 Aug 2017 16:17:31 -0700 Subject: [PATCH 14/38] Create new device profile for Android Go. Bug: 64109388 Change-Id: I8660f4e206eacd4eaccaebe794d255063eeb7e37 --- go/res/xml/device_profiles.xml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 go/res/xml/device_profiles.xml diff --git a/go/res/xml/device_profiles.xml b/go/res/xml/device_profiles.xml new file mode 100644 index 0000000000..094fc745c4 --- /dev/null +++ b/go/res/xml/device_profiles.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file From 27ad267a8154f1d4f8cab5f28f16fdd11ffd6e5c Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Thu, 3 Aug 2017 07:45:40 -0700 Subject: [PATCH 15/38] Fix bug where user gets stuck in overscroll. By not intercepting touch when in overscroll, the user can immediately exit by swiping the opposite direction. Bug: 64094565 Change-Id: I0b4e3e7a38d90d4e6a336985d939d177a8f04c9b --- .../allapps/AllAppsRecyclerView.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index 701402b028..657af15cbb 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -109,12 +109,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine } } - @Override - public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent ev) { - mPullDetector.onTouchEvent(ev); - return super.onInterceptTouchEvent(rv, ev) || mOverScrollHelper.isInOverScroll(); - } - @Override public boolean onTouchEvent(MotionEvent e) { mPullDetector.onTouchEvent(e); @@ -281,7 +275,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine @Override public boolean onInterceptTouchEvent(MotionEvent e) { - boolean result = super.onInterceptTouchEvent(e); + mPullDetector.onTouchEvent(e); + boolean result = super.onInterceptTouchEvent(e) || mOverScrollHelper.isInOverScroll(); if (!result && e.getAction() == MotionEvent.ACTION_DOWN && mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) { mEmptySearchBackground.setHotspot(e.getX(), e.getY()); @@ -540,11 +535,16 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine // and if one of the following criteria are met: // - User scrolls down when they're already at the bottom. // - User starts scrolling up, hits the top, and continues scrolling up. + boolean wasInOverScroll = mIsInOverScroll; mIsInOverScroll = !mScrollbar.isDraggingThumb() && ((!canScrollVertically(1) && displacement < 0) || (!canScrollVertically(-1) && isScrollingUp && mFirstScrollYOnScrollUp != 0)); - if (mIsInOverScroll) { + if (wasInOverScroll && !mIsInOverScroll) { + // Exit overscroll. This can happen when the user is in overscroll and then + // scrolls the opposite way. + reset(false /* shouldSpring */); + } else if (mIsInOverScroll) { if (Float.compare(mFirstDisplacement, 0) == 0) { // Because users can scroll before entering overscroll, we need to // subtract the amount where the user was not in overscroll. @@ -559,11 +559,15 @@ public class AllAppsRecyclerView extends BaseRecyclerView implements LogContaine @Override public void onDragEnd(float velocity, boolean fling) { + reset(mIsInOverScroll /* shouldSpring */); + } + + private void reset(boolean shouldSpring) { float y = getContentTranslationY(); if (Float.compare(y, 0) != 0) { - if (FeatureFlags.LAUNCHER3_PHYSICS) { + if (FeatureFlags.LAUNCHER3_PHYSICS && shouldSpring) { // We calculate our own velocity to give the springs the desired effect. - velocity = y / getDampedOverScroll(getHeight()) * MAX_RELEASE_VELOCITY; + float velocity = y / getDampedOverScroll(getHeight()) * MAX_RELEASE_VELOCITY; // We want to negate the velocity because we are moving to 0 from -1 due to the // downward motion. (y-axis -1 is above 0). mSpringAnimationHandler.animateToPositionWithVelocity(0, -1, -velocity); From 2bc5c995f6d75faab7e4fd1b40cbe25e61209b1f Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Thu, 3 Aug 2017 13:59:12 -0700 Subject: [PATCH 16/38] Add new GradientView just for WidgetsBottomSheet Reusing the one behind all apps caused problems when opening widgets sheets from all apps. Bug: 64344341 Change-Id: Ia964d8456645c78614f94693f9538dbac4f566a0 --- res/layout-land/launcher.xml | 7 +----- res/layout-port/launcher.xml | 7 +----- res/layout-sw720dp/launcher.xml | 7 +----- res/layout/gradient_bg.xml | 24 +++++++++++++++++++ .../launcher3/widget/WidgetsBottomSheet.java | 22 ++++++++++------- 5 files changed, 41 insertions(+), 26 deletions(-) create mode 100644 res/layout/gradient_bg.xml diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index dab074391d..ac440fc01e 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -42,12 +42,7 @@ android:layout_gravity="center" launcher:pageIndicator="@id/page_indicator" /> - + - + - + + + + \ No newline at end of file diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java index b2fb09157a..717a61c1cb 100644 --- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java +++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java @@ -89,7 +89,8 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab mInsets = new Rect(); mVerticalPullDetector = new VerticalPullDetector(context); mVerticalPullDetector.setListener(this); - mGradientBackground = (GradientView) mLauncher.findViewById(R.id.gradient_bg); + mGradientBackground = (GradientView) mLauncher.getLayoutInflater().inflate( + R.layout.gradient_bg, mLauncher.getDragLayer(), false); } @Override @@ -107,6 +108,8 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab onWidgetsBound(); + mLauncher.getDragLayer().addView(mGradientBackground); + mGradientBackground.setVisibility(VISIBLE); mLauncher.getDragLayer().addView(this); measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); setTranslationY(mTranslationYClosed); @@ -213,11 +216,8 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mIsOpen = false; mVerticalPullDetector.finishedScrolling(); - ((ViewGroup) getParent()).removeView(WidgetsBottomSheet.this); - mLauncher.getSystemUiController().updateUiState( - SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); + onCloseComplete(); } }); mOpenCloseAnimator.setInterpolator(mVerticalPullDetector.isIdleState() @@ -225,12 +225,18 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab mOpenCloseAnimator.start(); } else { setTranslationY(mTranslationYClosed); - mLauncher.getSystemUiController().updateUiState( - SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); - mIsOpen = false; + onCloseComplete(); } } + private void onCloseComplete() { + mIsOpen = false; + mLauncher.getDragLayer().removeView(mGradientBackground); + mLauncher.getDragLayer().removeView(WidgetsBottomSheet.this); + mLauncher.getSystemUiController().updateUiState( + SystemUiController.UI_STATE_WIDGET_BOTTOM_SHEET, 0); + } + @Override protected boolean isOfType(@FloatingViewType int type) { return (type & TYPE_WIDGETS_BOTTOM_SHEET) != 0; From d48710c2835d891b216914ef1fdd3740e6cfc101 Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 27 Jul 2017 23:23:58 -0700 Subject: [PATCH 17/38] Unbind notification listener when badging is disabled - Added SettingsObserver as wrapper around ContentObserver to observe Secure or System setting changes. - NotificationListener and LauncherAppState observe changes to the notification dots setting and unbind and rebind the NotificationListener service, respectively. Bug: 36815147 Change-Id: I2cc04ac816a8974969ad0ec759c5402e181fde24 --- .../android/launcher3/LauncherAppState.java | 27 ++++- .../android/launcher3/SettingsActivity.java | 42 +++----- .../notification/NotificationListener.java | 40 ++++++- .../launcher3/util/SettingsObserver.java | 100 ++++++++++++++++++ 4 files changed, 176 insertions(+), 33 deletions(-) create mode 100644 src/com/android/launcher3/util/SettingsObserver.java diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index cf20febd5b..1ffe41bc6c 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import android.content.ComponentName; import android.content.ContentProviderClient; import android.content.Context; import android.content.Intent; @@ -28,13 +29,17 @@ import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dynamicui.ExtractionUtils; +import com.android.launcher3.notification.NotificationListener; import com.android.launcher3.util.ConfigMonitor; import com.android.launcher3.util.Preconditions; +import com.android.launcher3.util.SettingsObserver; import com.android.launcher3.util.TestingUtils; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING; + public class LauncherAppState { public static final boolean PROFILE_STARTUP = FeatureFlags.IS_DOGFOOD_BUILD; @@ -47,7 +52,7 @@ public class LauncherAppState { private final IconCache mIconCache; private final WidgetPreviewLoader mWidgetCache; private final InvariantDeviceProfile mInvariantDeviceProfile; - + private final SettingsObserver mNotificationBadgingObserver; public static LauncherAppState getInstance(final Context context) { if (INSTANCE == null) { @@ -117,6 +122,23 @@ public class LauncherAppState { new ConfigMonitor(mContext).register(); ExtractionUtils.startColorExtractionServiceIfNecessary(mContext); + + if (!mContext.getResources().getBoolean(R.bool.notification_badging_enabled)) { + mNotificationBadgingObserver = null; + } else { + // Register an observer to rebind the notification listener when badging is re-enabled. + mNotificationBadgingObserver = new SettingsObserver.Secure( + mContext.getContentResolver()) { + @Override + public void onSettingChanged(boolean isNotificationBadgingEnabled) { + if (isNotificationBadgingEnabled) { + NotificationListener.requestRebind(new ComponentName( + mContext, NotificationListener.class)); + } + } + }; + mNotificationBadgingObserver.register(NOTIFICATION_BADGING); + } } /** @@ -127,6 +149,9 @@ public class LauncherAppState { final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext); launcherApps.removeOnAppsChangedCallback(mModel); PackageInstallerCompat.getInstance(mContext).onStop(); + if (mNotificationBadgingObserver != null) { + mNotificationBadgingObserver.unregister(); + } } LauncherModel setLauncher(Launcher launcher) { diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java index fa7769e3f6..90463725ff 100644 --- a/src/com/android/launcher3/SettingsActivity.java +++ b/src/com/android/launcher3/SettingsActivity.java @@ -26,17 +26,15 @@ import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.database.ContentObserver; import android.os.Bundle; -import android.os.Handler; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceFragment; import android.provider.Settings; -import android.provider.Settings.System; import com.android.launcher3.graphics.IconShapeOverride; import com.android.launcher3.notification.NotificationListener; +import com.android.launcher3.util.SettingsObserver; import com.android.launcher3.views.ButtonPreference; /** @@ -45,8 +43,8 @@ import com.android.launcher3.views.ButtonPreference; public class SettingsActivity extends Activity { private static final String ICON_BADGING_PREFERENCE_KEY = "pref_icon_badging"; - // TODO: use Settings.Secure.NOTIFICATION_BADGING - private static final String NOTIFICATION_BADGING = "notification_badging"; + /** Hidden field Settings.Secure.NOTIFICATION_BADGING */ + public static final String NOTIFICATION_BADGING = "notification_badging"; /** Hidden field Settings.Secure.ENABLED_NOTIFICATION_LISTENERS */ private static final String NOTIFICATION_ENABLED_LISTENERS = "enabled_notification_listeners"; @@ -88,12 +86,9 @@ public class SettingsActivity extends Activity { // Register a content observer to listen for system setting changes while // this UI is active. - resolver.registerContentObserver( - Settings.System.getUriFor(System.ACCELEROMETER_ROTATION), - false, mRotationLockObserver); + mRotationLockObserver.register(Settings.System.ACCELEROMETER_ROTATION); // Initialize the UI once - mRotationLockObserver.onChange(true); rotationPref.setDefaultValue(Utilities.getAllowRotationDefaultValue(getActivity())); } @@ -107,13 +102,7 @@ public class SettingsActivity extends Activity { // Listen to system notification badge settings while this UI is active. mIconBadgingObserver = new IconBadgingObserver( iconBadgingPref, resolver, getFragmentManager()); - resolver.registerContentObserver( - Settings.Secure.getUriFor(NOTIFICATION_BADGING), - false, mIconBadgingObserver); - resolver.registerContentObserver( - Settings.Secure.getUriFor(NOTIFICATION_ENABLED_LISTENERS), - false, mIconBadgingObserver); - mIconBadgingObserver.onChange(true); + mIconBadgingObserver.register(NOTIFICATION_BADGING, NOTIFICATION_ENABLED_LISTENERS); } Preference iconShapeOverride = findPreference(IconShapeOverride.KEY_PREFERENCE); @@ -129,11 +118,11 @@ public class SettingsActivity extends Activity { @Override public void onDestroy() { if (mRotationLockObserver != null) { - getActivity().getContentResolver().unregisterContentObserver(mRotationLockObserver); + mRotationLockObserver.unregister(); mRotationLockObserver = null; } if (mIconBadgingObserver != null) { - getActivity().getContentResolver().unregisterContentObserver(mIconBadgingObserver); + mIconBadgingObserver.unregister(); mIconBadgingObserver = null; } super.onDestroy(); @@ -144,22 +133,18 @@ public class SettingsActivity extends Activity { * Content observer which listens for system auto-rotate setting changes, and enables/disables * the launcher rotation setting accordingly. */ - private static class SystemDisplayRotationLockObserver extends ContentObserver { + private static class SystemDisplayRotationLockObserver extends SettingsObserver.System { private final Preference mRotationPref; - private final ContentResolver mResolver; public SystemDisplayRotationLockObserver( Preference rotationPref, ContentResolver resolver) { - super(new Handler()); + super(resolver); mRotationPref = rotationPref; - mResolver = resolver; } @Override - public void onChange(boolean selfChange) { - boolean enabled = Settings.System.getInt(mResolver, - Settings.System.ACCELEROMETER_ROTATION, 1) == 1; + public void onSettingChanged(boolean enabled) { mRotationPref.setEnabled(enabled); mRotationPref.setSummary(enabled ? R.string.allow_rotation_desc : R.string.allow_rotation_blocked_desc); @@ -170,7 +155,7 @@ public class SettingsActivity extends Activity { * Content observer which listens for system badging setting changes, * and updates the launcher badging setting subtext accordingly. */ - private static class IconBadgingObserver extends ContentObserver + private static class IconBadgingObserver extends SettingsObserver.Secure implements Preference.OnPreferenceClickListener { private final ButtonPreference mBadgingPref; @@ -179,15 +164,14 @@ public class SettingsActivity extends Activity { public IconBadgingObserver(ButtonPreference badgingPref, ContentResolver resolver, FragmentManager fragmentManager) { - super(new Handler()); + super(resolver); mBadgingPref = badgingPref; mResolver = resolver; mFragmentManager = fragmentManager; } @Override - public void onChange(boolean selfChange) { - boolean enabled = Settings.Secure.getInt(mResolver, NOTIFICATION_BADGING, 1) == 1; + public void onSettingChanged(boolean enabled) { int summary = enabled ? R.string.icon_badging_desc_on : R.string.icon_badging_desc_off; boolean serviceEnabled = true; diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java index 73d89aa189..6a7098915a 100644 --- a/src/com/android/launcher3/notification/NotificationListener.java +++ b/src/com/android/launcher3/notification/NotificationListener.java @@ -30,15 +30,20 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Pair; + import com.android.launcher3.LauncherModel; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.PackageUserKey; +import com.android.launcher3.util.SettingsObserver; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; +import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING; + /** * A {@link NotificationListenerService} that sends updates to its * {@link NotificationsChangedListener} when notifications are posted or canceled, @@ -57,12 +62,14 @@ public class NotificationListener extends NotificationListenerService { private static NotificationListener sNotificationListenerInstance = null; private static NotificationsChangedListener sNotificationsChangedListener; private static boolean sIsConnected; + private static boolean sIsCreated; private final Handler mWorkerHandler; private final Handler mUiHandler; - private final Ranking mTempRanking = new Ranking(); + private SettingsObserver mNotificationBadgingObserver; + private final Handler.Callback mWorkerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message message) { @@ -77,7 +84,7 @@ public class NotificationListener extends NotificationListenerService { List activeNotifications; if (sIsConnected) { try { - activeNotifications = filterNotifications(getActiveNotifications()); + activeNotifications = filterNotifications(getActiveNotifications()); } catch (SecurityException ex) { Log.e(TAG, "SecurityException: failed to fetch notifications"); activeNotifications = new ArrayList(); @@ -130,6 +137,28 @@ public class NotificationListener extends NotificationListenerService { sNotificationListenerInstance = this; } + @Override + public void onCreate() { + super.onCreate(); + sIsCreated = true; + mNotificationBadgingObserver = new SettingsObserver.Secure(getContentResolver()) { + @Override + public void onSettingChanged(boolean isNotificationBadgingEnabled) { + if (!isNotificationBadgingEnabled) { + requestUnbind(); + } + } + }; + mNotificationBadgingObserver.register(NOTIFICATION_BADGING); + } + + @Override + public void onDestroy() { + super.onDestroy(); + sIsCreated = false; + mNotificationBadgingObserver.unregister(); + } + public static @Nullable NotificationListener getInstanceIfConnected() { return sIsConnected ? sNotificationListenerInstance : null; } @@ -143,6 +172,11 @@ public class NotificationListener extends NotificationListenerService { NotificationListener notificationListener = getInstanceIfConnected(); if (notificationListener != null) { notificationListener.onNotificationFullRefresh(); + } else if (!sIsCreated && sNotificationsChangedListener != null) { + // User turned off badging globally, so we unbound this service; + // tell the listener that there are no notifications to remove dots. + sNotificationsChangedListener.onNotificationFullRefresh( + Collections.emptyList()); } } @@ -205,7 +239,7 @@ public class NotificationListener extends NotificationListenerService { .getActiveNotifications(NotificationKeyData.extractKeysOnly(keys) .toArray(new String[keys.size()])); return notifications == null - ? Collections.emptyList() : Arrays.asList(notifications); + ? Collections.emptyList() : Arrays.asList(notifications); } /** diff --git a/src/com/android/launcher3/util/SettingsObserver.java b/src/com/android/launcher3/util/SettingsObserver.java new file mode 100644 index 0000000000..6baa24293e --- /dev/null +++ b/src/com/android/launcher3/util/SettingsObserver.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.util; + +import android.content.ContentResolver; +import android.database.ContentObserver; +import android.os.Handler; +import android.provider.Settings; + +public interface SettingsObserver { + + /** + * Registers the content observer to call {@link #onSettingChanged(boolean)} when any of the + * passed settings change. The value passed to onSettingChanged() is based on the key setting. + */ + void register(String keySetting, String ... dependentSettings); + void unregister(); + void onSettingChanged(boolean keySettingEnabled); + + + abstract class Secure extends ContentObserver implements SettingsObserver { + private ContentResolver mResolver; + private String mKeySetting; + + public Secure(ContentResolver resolver) { + super(new Handler()); + mResolver = resolver; + } + + @Override + public void register(String keySetting, String ... dependentSettings) { + mKeySetting = keySetting; + mResolver.registerContentObserver( + Settings.Secure.getUriFor(mKeySetting), false, this); + for (String setting : dependentSettings) { + mResolver.registerContentObserver( + Settings.Secure.getUriFor(setting), false, this); + } + onChange(true); + } + + @Override + public void unregister() { + mResolver.unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + onSettingChanged(Settings.Secure.getInt(mResolver, mKeySetting, 1) == 1); + } + } + + abstract class System extends ContentObserver implements SettingsObserver { + private ContentResolver mResolver; + private String mKeySetting; + + public System(ContentResolver resolver) { + super(new Handler()); + mResolver = resolver; + } + + @Override + public void register(String keySetting, String ... dependentSettings) { + mKeySetting = keySetting; + mResolver.registerContentObserver( + Settings.System.getUriFor(mKeySetting), false, this); + for (String setting : dependentSettings) { + mResolver.registerContentObserver( + Settings.System.getUriFor(setting), false, this); + } + onChange(true); + } + + @Override + public void unregister() { + mResolver.unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + onSettingChanged(Settings.System.getInt(mResolver, mKeySetting, 1) == 1); + } + } +} From 3051dbabe7d32026339fa7afbd02f0d354a221a8 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Fri, 4 Aug 2017 09:26:14 -0700 Subject: [PATCH 18/38] Switch the status bar color earlier in the all apps transition -> When LAUNCHER3_GRADIENT_ALL_APPS is true, switch the status / nav bar to be dark when the transition is 75% of the way through, since at this point the gradient is already substantially under the status bar. issue 64385775 Change-Id: Ie27b8f2afa404c0b3081a4f17daa92ef4e0472bc --- .../launcher3/allapps/AllAppsTransitionController.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 44e0a0474b..b85321e638 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -283,7 +283,9 @@ public class AllAppsTransitionController implements TouchController, VerticalPul } // Use a light system UI (dark icons) if all apps is behind at least half of the status bar. - boolean forceChange = shift <= mStatusBarHeight / 2; + boolean forceChange = FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS ? + shift <= mShiftRange / 4 : + shift <= mStatusBarHeight / 2; if (forceChange) { mLauncher.getSystemUiController().updateUiState( SystemUiController.UI_STATE_ALL_APPS, !mIsDarkTheme); From 2917a8bf2b83c0d17400b1475f01a9a8d9137f62 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 31 Jul 2017 23:29:42 -0700 Subject: [PATCH 19/38] Defer some work until after workspace fade-in Defer: - Setting all apps - Setting widgets Also set the launcher-loader thread to THREAD_PRIORITY_BACKGROUND for the duration of the animation. Bug: 37965432 Change-Id: I8364940805b84aecb8353a473ab4d575c27bfec4 --- src/com/android/launcher3/Launcher.java | 24 +++++++++++++++++++ src/com/android/launcher3/LauncherModel.java | 4 ++++ .../launcher3/util/ViewOnDrawExecutor.java | 14 +++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7c258616f7..615ec47168 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -144,6 +144,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.Executor; /** * Default launcher application. @@ -1855,6 +1856,8 @@ public class Launcher extends BaseActivity LauncherAnimUtils.onDestroyActivity(); + clearPendingBinds(); + if (mLauncherCallbacks != null) { mLauncherCallbacks.onDestroy(); } @@ -3705,6 +3708,13 @@ public class Launcher extends BaseActivity } if (mAppsView != null) { + Executor pendingExecutor = getPendingExecutor(); + if (pendingExecutor != null && mState != State.APPS) { + // Wait until the fade in animation has finished before setting all apps list. + mTmpAppsList = apps; + pendingExecutor.execute(mBindAllApplicationsRunnable); + return; + } mAppsView.setApps(apps); } if (mLauncherCallbacks != null) { @@ -3712,6 +3722,14 @@ public class Launcher extends BaseActivity } } + /** + * Returns an Executor that will run after the launcher is first drawn (including after the + * initial fade in animation). Returns null if the first draw has already occurred. + */ + public @Nullable Executor getPendingExecutor() { + return mPendingExecutor != null && mPendingExecutor.canQueue() ? mPendingExecutor : null; + } + /** * Copies LauncherModel's map of activities to shortcut ids to Launcher's. This is necessary * because LauncherModel's map is updated in the background, while Launcher runs on the UI. @@ -3904,6 +3922,12 @@ public class Launcher extends BaseActivity } if (mWidgetsView != null && allWidgets != null) { + Executor pendingExecutor = getPendingExecutor(); + if (pendingExecutor != null && mState != State.WIDGETS) { + mAllWidgets = allWidgets; + pendingExecutor.execute(mBindAllWidgetsRunnable); + return; + } mWidgetsView.setWidgets(allWidgets); mAllWidgets = null; } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index f1638fda25..1007748661 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -689,4 +689,8 @@ public class LauncherModel extends BroadcastReceiver public static Looper getWorkerLooper() { return sWorkerThread.getLooper(); } + + public static void setWorkerPriority(final int priority) { + Process.setThreadPriority(sWorkerThread.getThreadId(), priority); + } } diff --git a/src/com/android/launcher3/util/ViewOnDrawExecutor.java b/src/com/android/launcher3/util/ViewOnDrawExecutor.java index 4cb6ca8314..e5c1dd1b43 100644 --- a/src/com/android/launcher3/util/ViewOnDrawExecutor.java +++ b/src/com/android/launcher3/util/ViewOnDrawExecutor.java @@ -16,11 +16,13 @@ package com.android.launcher3.util; +import android.os.Process; import android.view.View; import android.view.View.OnAttachStateChangeListener; import android.view.ViewTreeObserver.OnDrawListener; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherModel; import java.util.ArrayList; import java.util.concurrent.Executor; @@ -37,6 +39,7 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, private Launcher mLauncher; private View mAttachedView; private boolean mCompleted; + private boolean mIsExecuting; private boolean mLoadAnimationCompleted; private boolean mFirstDrawCompleted; @@ -62,6 +65,7 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, @Override public void execute(Runnable command) { mTasks.add(command); + LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_BACKGROUND); } @Override @@ -78,6 +82,13 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, mAttachedView.post(this); } + /** + * Returns whether the executor is still queuing tasks and hasn't yet executed them. + */ + public boolean canQueue() { + return !mIsExecuting && !mCompleted; + } + public void onLoadAnimationCompleted() { mLoadAnimationCompleted = true; if (mAttachedView != null) { @@ -89,6 +100,7 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, public void run() { // Post the pending tasks after both onDraw and onLoadAnimationCompleted have been called. if (mLoadAnimationCompleted && mFirstDrawCompleted && !mCompleted) { + mIsExecuting = true; for (final Runnable r : mTasks) { mExecutor.execute(r); } @@ -99,6 +111,7 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, public void markCompleted() { mTasks.clear(); mCompleted = true; + mIsExecuting = false; if (mAttachedView != null) { mAttachedView.getViewTreeObserver().removeOnDrawListener(this); mAttachedView.removeOnAttachStateChangeListener(this); @@ -106,5 +119,6 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable, if (mLauncher != null) { mLauncher.clearPendingExecutor(this); } + LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_DEFAULT); } } From 76bf7f3835915f33cf0af41bcb6fc6e465e33652 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Mon, 7 Aug 2017 01:38:03 -0700 Subject: [PATCH 20/38] Disable adaptive icon drawable parallax effect during drag and drop Bug: 34828147 Change-Id: I5abb0997ce42db1ea73ebe469686585282f43594 --- go/src_flags/com/android/launcher3/config/FeatureFlags.java | 1 + 1 file changed, 1 insertion(+) diff --git a/go/src_flags/com/android/launcher3/config/FeatureFlags.java b/go/src_flags/com/android/launcher3/config/FeatureFlags.java index 5bb2ac9a2e..b11bb7c6aa 100644 --- a/go/src_flags/com/android/launcher3/config/FeatureFlags.java +++ b/go/src_flags/com/android/launcher3/config/FeatureFlags.java @@ -25,4 +25,5 @@ public final class FeatureFlags extends BaseFlags { // Features to control Launcher3Go behavior public static final boolean GO_DISABLE_WIDGETS = true; + public static final boolean LAUNCHER3_SPRING_ICONS = false; } From 0b754e564b6a5fef535815467464a6abaa84d434 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 7 Aug 2017 07:42:45 -0700 Subject: [PATCH 21/38] Making some methods accessible Bug: 63996463 Change-Id: I3cd2e21b8aa6744fc8003a131178ce1671e024dd --- src/com/android/launcher3/CellLayout.java | 2 +- src/com/android/launcher3/ShortcutAndWidgetContainer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index aac80052e4..3ebccda9e7 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -780,7 +780,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { return mCellWidth; } - int getCellHeight() { + public int getCellHeight() { return mCellHeight; } diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java index fd708c0fd5..a7e68ff148 100644 --- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java +++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java @@ -101,7 +101,7 @@ public class ShortcutAndWidgetContainer extends ViewGroup { mInvertIfRtl = invert; } - int getCellContentHeight() { + public int getCellContentHeight() { return Math.min(getMeasuredHeight(), mLauncher.getDeviceProfile().getCellHeight(mContainerType)); } From 5be75795986da5229ec07ad8eec6a8cf0f7a19a3 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 7 Aug 2017 00:00:37 -0700 Subject: [PATCH 22/38] Fixing badge bounds incorrectly set when dragging icon Bug: 64427027 Change-Id: If57bdcab703b2cc30e8ca0c0fba0dd599792bd00 --- src/com/android/launcher3/dragndrop/DragView.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java index b6e38bb15e..e81e2a3863 100644 --- a/src/com/android/launcher3/dragndrop/DragView.java +++ b/src/com/android/launcher3/dragndrop/DragView.java @@ -218,6 +218,12 @@ public class DragView extends View { Rect bounds = new Rect(0, 0, w, h); bounds.inset(blurMargin, blurMargin); + // Badge is applied after icon normalization so the bounds for badge should not + // be scaled down due to icon normalization. + Rect badgeBounds = new Rect(bounds); + mBadge = getBadge(info, appState, outObj[0]); + mBadge.setBounds(badgeBounds); + Utilities.scaleRectAboutCenter(bounds, IconNormalizer.getInstance(mLauncher).getScale(dr, null, null, null)); AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) dr; @@ -234,9 +240,6 @@ public class DragView extends View { mTranslateY = new SpringFloatValue(DragView.this, h * AdaptiveIconDrawable.getExtraInsetFraction()); - mBadge = getBadge(info, appState, outObj[0]); - mBadge.setBounds(bounds); - bounds.inset( (int) (-bounds.width() * AdaptiveIconDrawable.getExtraInsetFraction()), (int) (-bounds.height() * AdaptiveIconDrawable.getExtraInsetFraction()) From f4085ff7cc56228825894e417b1165a235361a39 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Wed, 9 Aug 2017 04:24:16 -0700 Subject: [PATCH 23/38] Import translations. DO NOT MERGE Change-Id: Ia1a6c690e285583fe62a9743d8e283c26d020ba2 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- go/res/values-pa/strings.xml | 2 +- go/res/values-vi/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go/res/values-pa/strings.xml b/go/res/values-pa/strings.xml index fdb3c74152..f3982ab71b 100644 --- a/go/res/values-pa/strings.xml +++ b/go/res/values-pa/strings.xml @@ -20,7 +20,7 @@ "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" - "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਜਾਂ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਡਬਲ-ਟੈਪ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਡਬਲ-ਟੈਪ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ ਜਾਂ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਾਰਵਾਈਆਂ ਵਰਤੋ।" "ਸ਼ਾਰਟਕੱਟ" "%1$s ਸ਼ਾਰਟਕੱਟ" diff --git a/go/res/values-vi/strings.xml b/go/res/values-vi/strings.xml index 84ed627964..1197619c57 100644 --- a/go/res/values-vi/strings.xml +++ b/go/res/values-vi/strings.xml @@ -20,7 +20,7 @@ "Chạm và giữ để chọn lối tắt." - "Nhấn đúp và giữ để chọn lối tắt hoặc sử dụng tác vụ tùy chỉnh." + "Nhấn đúp và giữ để chọn lối tắt hoặc sử dụng hành động tùy chỉnh." "Lối tắt" "Lối tắt %1$s" From 5044c35b07f07f9bd0b26f44bc71b7bc8057b37f Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 9 Aug 2017 11:37:59 -0700 Subject: [PATCH 24/38] Update hotseat cell height calculation. The hotseat never has text, so we remove the icon drawable padding from the height calculation. This allows the items in the hotseat to be centered vertically properly. Bug: 63996463 Change-Id: Ie0c5706ae6edeafae321ca024c066439d40ca237 --- src/com/android/launcher3/DeviceProfile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 60c19bc5d0..150bc5309d 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -365,7 +365,7 @@ public class DeviceProfile { if (isVerticalBarLayout()) { hotseatBarSizePx = iconSizePx; } - hotseatCellHeightPx = iconSizePx + iconDrawablePaddingPx; + hotseatCellHeightPx = iconSizePx; if (!isVerticalBarLayout()) { int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx From 9593f9ed0cd0215dc3544f5524c40b9025709895 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Wed, 9 Aug 2017 14:57:30 -0700 Subject: [PATCH 25/38] Fix bug where workspace is not aligned with hotseat in landscape. The padding was added to the hotseat, but not to the workspace screens. Only affects landscape where bottomPadding != 0. Bug: 63996463 Change-Id: I8be0e36128963a1856d2effa76fdb2a6cfd966a8 --- src/com/android/launcher3/Workspace.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index a2270d6c57..f8d64984e9 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -671,7 +671,8 @@ public class Workspace extends PagedView newScreen.setSoundEffectsEnabled(false); int paddingLeftRight = mLauncher.getDeviceProfile().cellLayoutPaddingLeftRightPx; - newScreen.setPadding(paddingLeftRight, 0, paddingLeftRight, 0); + int paddingBottom = mLauncher.getDeviceProfile().cellLayoutBottomPaddingPx; + newScreen.setPadding(paddingLeftRight, 0, paddingLeftRight, paddingBottom); mWorkspaceScreens.put(screenId, newScreen); mScreenOrder.add(insertIndex, screenId); From 2d01eb610ce65b6fd4336a78d2a7c950beddce38 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Fri, 11 Aug 2017 14:00:59 -0700 Subject: [PATCH 26/38] Import translations. DO NOT MERGE Change-Id: I0c577cf7de02928f02d9fde76ea5b6ec35d18c70 Auto-generated-cl: translation import Exempt-From-Owner-Approval: translation import --- res/values-bn/strings.xml | 4 ++-- res/values-cs/strings.xml | 4 ++-- res/values-gu/strings.xml | 4 ++-- res/values-hi/strings.xml | 2 +- res/values-ml/strings.xml | 2 +- res/values-mr/strings.xml | 16 ++++++++-------- res/values-pa/strings.xml | 6 +++--- res/values-sk/strings.xml | 2 +- res/values-te/strings.xml | 12 ++++++------ 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 92f1affb69..471602f47d 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -27,7 +27,7 @@ "ডাউনলোড করা অ্যাপ্লিকেশান নিরাপদ মোডে অক্ষম রয়েছে" "সুরক্ষিত মোডে উইজেট নিষ্ক্রিয় থাকে" "শর্টকাটগুলি অনুপলব্ধ" - "হোম স্ক্রীন" + "হোম স্ক্রিন" "কাস্টম অ্যাকশন" "একটি উইজেট তুলতে তা স্পর্শ করে ধরে রাখুন৷" "কোনো উইজেট বেছে নিতে দুবার-আলতো চেপে ধরে থাকুন অথবা কাস্টম ক্রিয়াগুলি ব্যবহার করুন৷" @@ -60,7 +60,7 @@ "নামবিহীন ফোল্ডার" "%1$s অক্ষম করা হয়েছে" "%2$dটির মধ্যে %1$dটি পৃষ্ঠা" - "%2$dটির %1$d নম্বর হোম স্ক্রীন" + "%2$dটির %1$d নম্বর হোম স্ক্রিন" "নতুন হোম স্ক্রীনের পৃষ্ঠা" "ফোল্ডার খোলা হয়েছে, %1$d বাই %2$d" "ফোল্ডার বন্ধ করতে আলতো চাপ দিন" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index abc44c7142..e6dee3c3b3 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -76,11 +76,11 @@ "Povolit otáčení plochy" "Při otočení telefonu" "Aktuální nastavení displeje neumožňuje otáčení" - "Puntíky s oznámeními" + "Puntíky s oznámením" "Zapnuto" "Vypnuto" "Je třeba udělit přístup k oznámením" - "Chcete-li zobrazovat puntíky s oznámeními, zapněte oznámení z aplikace %1$s" + "Chcete-li zobrazovat puntíky s oznámením, zapněte oznámení z aplikace %1$s" "Změnit nastavení" "Přidat ikonu na plochu" "Pro nové aplikace" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 808c04756f..7096a3ee0a 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -29,7 +29,7 @@ "શૉર્ટકટ ઉપલબ્ધ નથી" "હોમ સ્ક્રીન" "કસ્ટમ ક્રિયાઓ" - "વિજેટ ચૂંટવા માટે ટચ કરો અને પકડી રાખો." + "વિજેટ ચૂંટવા માટે સ્પર્શ કરો અને પકડી રાખો." "વિજેટ ચૂંટવા અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટેપ કરો અને પકડી રાખો." "%1$d × %2$d" "%1$d પહોળાઈ X %2$d ઊંચાઈ" @@ -72,7 +72,7 @@ "વૉલપેપર્સ" "હોમ સેટિંગ્સ" "તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ" - "વિહંગાવલોકન" + "ઝલક" "હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો" "જ્યારે ફોન ફેરવવામાં આવે ત્યારે" "વર્તમાન પ્રદર્શન સેટિંગ ફેરવવાની પરવાનગી આપતી નથી" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 02c470ba07..f1ee0f2366 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -72,7 +72,7 @@ "वॉलपेपर" "होम सेटिंग" "आपके व्यवस्थापक द्वारा अक्षम" - "अवलोकन" + "खास जानकारी" "होमस्क्रीन घुमाने की अनुमति दें" "फ़ोन घुुमाए जाने पर" "वर्तमान प्रदर्शन सेटिंग घुमाने की अनुमति नहीं देती" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index b6087546cd..0cc7aa023c 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -72,7 +72,7 @@ "വാൾപേപ്പർ" "ഹോം ക്രമീകരണം" "അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു" - "കാഴ്ച" + "അവലോകനം" "ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക" "ഫോൺ തിരിച്ച നിലയിലായിരിക്കുമ്പോൾ" "നിലവിലെ ഡിസ്പ്ലേ ക്രമീകരണം തിരിക്കൽ അനുവദിക്കുന്നില്ല" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 4fa8d49fe3..751ad227ab 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -27,14 +27,14 @@ "डाउनलोड केलेला अ‍ॅप सुरक्षित मोड मध्‍ये अक्षम केला" "विजेट सुरक्षित मोडमध्ये अक्षम झाले" "शॉर्टकट उपलब्ध नाही" - "मुख्यपृष्ठ" + "होम स्क्रीन" "सानुकूल क्रिया" "विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." "एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा सानुकूल क्रिया वापरा." "%1$d × %2$d" "%1$d रूंद बाय %2$d उंच" "स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा" - "स्वयंचलितपणे जोडा" + "अापोआप जोडा" "अॅप्स शोधा" "अॅप्स लोड करत आहे…" "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत" @@ -43,15 +43,15 @@ "या मुख्य स्क्रीनवर आणखी जागा नाही." "आवडीच्या ट्रे मध्ये आणखी जागा नाही" "अॅप्स सूची" - "मुख्‍यपृष्‍ठ" + "होम" "काढा" "विस्थापित करा" "अॅप माहिती" "शॉर्टकट स्‍थापित करा" "वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते." - "मुख्यपृष्ठ सेटिंग्ज आणि शॉर्टकट वाचा" + "होम सेटिग्ज आणि शॉर्टकट वाचा" "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते." - "मुख्यपृष्ठ सेटिंग्ज आणि शॉर्टकट लिहा" + "होम स्क्रीन सेटिंग्ज आणि शॉर्टकट लिहा" "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते." "%1$s ला फोन कॉल करण्याची अनुमती नाही" "विजेट लोड करण्यात समस्या" @@ -72,7 +72,7 @@ "वॉलपेपर" "होम सेटिंग्‍ज" "आपल्या प्रशासकाने अक्षम केले" - "विहंगावलोकन" + "अवलोकन" "मुख्यस्क्रीन फिरविण्‍यास अनुमती द्या" "फोन फिरविला जातो तेव्हा" "वर्तमान प्रदर्शन सेटिंग फिरविण्यास परवानगी देत नाही" @@ -82,7 +82,7 @@ "सूचनांच्या अ‍ॅक्सेसची आवश्यकता आहे" "सूचना बिंदू दाखवण्यासाठी, %1$s साठी अ‍ॅप सूचना चालू करा" "सेटिंग्ज बदला" - "मुख्य स्क्रीनवर चिन्ह जोडा" + "होम स्क्रीनवर आयकन जोडा" "नवीन अॅप्ससाठी" "चिन्हाचा आकार बदला" "सिस्‍टमचे डीफॉल्‍ट वापरा" @@ -99,7 +99,7 @@ "%1$s डाउनलोड होत आहे , %2$s पूर्ण झाले" "%1$s स्थापित करण्याची प्रतिक्षा करीत आहे" "%1$s विजेट" - "मुख्य स्क्रीनवर जोडा" + "होम स्क्रीनवर जोडा" "आयटम येथे हलवा" "आयटम मुख्य स्क्रीनवर जोडला" "आयटम काढला" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index e4cff7b8c7..cf5351c7a7 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -25,7 +25,7 @@ "ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।" "ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" "ਡਾਊਨਲੋਡ ਕੀਤਾ ਐਪ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ" - "ਵਿਜਿਟ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ" + "ਵਿਜੇਟ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ" "ਸ਼ਾਰਟਕੱਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" "ਮੁੱਖ ਸਕ੍ਰੀਨ" "ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਾਰਵਾਈਆਂ" @@ -68,7 +68,7 @@ "ਫੋਲਡਰ ਬੰਦ ਕੀਤਾ" "ਫੋਲਡਰ ਨੂੰ %1$s ਮੁੜ ਨਾਮ ਦਿੱਤਾ ਗਿਆ" "ਫੋਲਡਰ: %1$s" - "ਵਿਜਿਟ" + "ਵਿਜੇਟ" "ਵਾਲਪੇਪਰ" "ਹੋਮ ਸੈਟਿੰਗਾਂ" "ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ" @@ -98,7 +98,7 @@ "ਇਸ ਆਈਕਨ ਲਈ ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਤੁਸੀਂ ਇਸਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ ਜਾਂ ਐਪ ਖੋਜ ਸਕਦੇ ਹੋ ਅਤੇ ਇਸਨੂੰ ਮੈਨੂਅਲੀ ਇੰਸਟੌਲ ਕਰ ਸਕਦੇ ਹੋ।" "%1$s ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, %2$s ਸੰਪੂਰਣ" "%1$s ਸਥਾਪਿਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ" - "%1$s ਵਿਜਿਟ" + "%1$s ਵਿਜੇਟ" "ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਜੋੜੋ" "ਆਈਟਮ ਨੂੰ ਇੱਥੇ ਮੂਵ ਕਰੋ" "ਆਈਟਮ ਨੂੰ ਮੁੱਖ ਸਕ੍ਰੀਨ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 490f823fe2..4dbc407b9c 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -58,7 +58,7 @@ "Nastavenie" "Toto je systémová aplikácia a nedá sa odinštalovať." "Nepomenovaný priečinok" - "Aplikácia %1$s je zakázaná" + "Aplikácia %1$s je deaktivovaná" "Stránka %1$d z %2$d" "Plocha %1$d z %2$d" "Nová stránka plochy" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 7fa666c677..6c6669938b 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -22,9 +22,9 @@ "Launcher3" "కార్యాలయం" - "అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు." - "అనువర్తనం అందుబాటులో లేదు" - "డౌన్‌లోడ్ చేసిన అనువర్తనం సురక్షిత మోడ్‌లో నిలిపివేయబడింది" + "యాప్ ఇన్‌స్టాల్ చేయబడలేదు." + "యాప్ అందుబాటులో లేదు" + "డౌన్‌లోడ్ చేసిన యాప్ సురక్షిత మోడ్‌లో నిలిపివేయబడింది" "సురక్షిత మోడ్‌లో విడ్జెట్‌లు నిలిపివేయబడ్డాయి" "సత్వరమార్గం అందుబాటులో లేదు" "హోమ్ స్క్రీన్" @@ -56,7 +56,7 @@ "ఫోన్ కాల్‌లను చేసేందుకు %1$sకి అనుమతి లేదు" "విడ్జెట్‌ను లోడ్ చేయడంలో సమస్య" "సెటప్ చేయి" - "ఇది సిస్టమ్ అనువర్తనం మరియు దీన్ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడదు." + "ఇది సిస్టమ్ యాప్ మరియు దీన్ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడదు." "పేరు లేని ఫోల్డర్" "%1$s నిలిపివేయబడింది" "%2$dలో %1$dవ పేజీ" @@ -94,8 +94,8 @@ "తెలియదు" "తీసివేయి" "శోధించు" - "ఈ అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు" - "ఈ చిహ్నం యొక్క అనువర్తనం ఇన్‌స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ అనువర్తనం కోసం శోధించి దాన్ని మాన్యువల్‌గా ఇన్‌స్టాల్ చేయవచ్చు." + "ఈ యాప్ ఇన్‌స్టాల్ చేయబడలేదు" + "ఈ చిహ్నం యొక్క యాప్ ఇన్‌స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ యాప్ కోసం శోధించి దాన్ని మాన్యువల్‌గా ఇన్‌స్టాల్ చేయవచ్చు." "%1$s డౌన్‌లోడ్ అవుతోంది, %2$s పూర్తయింది" "%1$s ఇన్‌స్టాల్ కావడానికి వేచి ఉంది" "%1$s విడ్జెట్‌లు" From bb10fa8fc2f125245163a50bf6cd04ff03bdfac4 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 14 Aug 2017 12:35:53 -0700 Subject: [PATCH 27/38] Fix bug where all apps scrollbar jumps. The problem is that rowAppIndex is not being set when we swap in the new predictions. So when we call AllAppsRecyclerView#getCurrentScrollY, the "item.rowAppIndex == 0" clause returns true for every predicted app, which results in a larger than expected value. Bug: 64628968 Change-Id: I37ca660522b5a99666de2ea0b9c0aa8cd3732aca --- src/com/android/launcher3/allapps/AlphabeticalAppsList.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index ee2756f2cb..43b56a4bb8 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -362,6 +362,7 @@ public class AlphabeticalAppsList { for (int i = 0; i < size; ++i) { AppInfo info = apps.get(i); AdapterItem appItem = AdapterItem.asPredictedApp(i, "", info, i); + appItem.rowAppIndex = i; mAdapterItems.set(i, appItem); mFilteredApps.set(i, info); mAdapter.notifyItemChanged(i); From bf17e50156fe783bc504601782686c92aba0a4d0 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Mon, 14 Aug 2017 16:10:13 -0700 Subject: [PATCH 28/38] Get rid of unnecessary int array allocation. Bug: 64656232 Change-Id: Ifc811c3930b8052d57fa33d35b9d50f11b541c94 Test: Tested manually --- .../launcher3/graphics/IconNormalizer.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/com/android/launcher3/graphics/IconNormalizer.java b/src/com/android/launcher3/graphics/IconNormalizer.java index 34d0b727c1..8ed62bcdcc 100644 --- a/src/com/android/launcher3/graphics/IconNormalizer.java +++ b/src/com/android/launcher3/graphics/IconNormalizer.java @@ -32,10 +32,8 @@ import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; - import com.android.launcher3.LauncherAppState; import com.android.launcher3.Utilities; - import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; @@ -84,12 +82,12 @@ public class IconNormalizer { private final Rect mBounds; private final Matrix mMatrix; - private Paint mPaintIcon; - private Canvas mCanvasARGB; + private final Paint mPaintIcon; + private final Canvas mCanvasARGB; - private File mDir; + private final File mDir; private int mFileId; - private Random mRandom; + private final Random mRandom; private IconNormalizer(Context context) { // Use twice the icon size as maximum size to avoid scaling down twice. @@ -122,7 +120,6 @@ public class IconNormalizer { mPaintMaskShapeOutline.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); mMatrix = new Matrix(); - int[] mPixels = new int[mMaxSize * mMaxSize]; mAdaptiveIconScale = SCALE_NOT_INITIALIZED; mDir = context.getExternalFilesDir(null); @@ -174,7 +171,8 @@ public class IconNormalizer { boolean isTrans = isTransparentBitmap(mBitmapARGB); if (DEBUG) { - final File afterFile = new File(mDir, "isShape" + mFileId + "_after_" + isTrans + ".png"); + final File afterFile = new File(mDir, + "isShape" + mFileId + "_after_" + isTrans + ".png"); try { mBitmapARGB.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(afterFile)); @@ -210,7 +208,9 @@ public class IconNormalizer { float percentageDiffPixels = ((float) sum) / (mBounds.width() * mBounds.height()); boolean transparentImage = percentageDiffPixels < PIXEL_DIFF_PERCENTAGE_THRESHOLD; if (DEBUG) { - Log.d(TAG, "Total # pixel that is different (id="+ mFileId + "):" + percentageDiffPixels + "="+ sum + "/" + mBounds.width() * mBounds.height()); + Log.d(TAG, + "Total # pixel that is different (id=" + mFileId + "):" + percentageDiffPixels + + "=" + sum + "/" + mBounds.width() * mBounds.height()); } return transparentImage; } From 7dfabaa02bdcf7d9307e11fa490c097bdc990025 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 15 Aug 2017 10:31:17 -0700 Subject: [PATCH 29/38] Fix bug where all apps items fade in. Removes all Add/Change/Move/Remove animations by clearing the AllAppsRecyclerView ItemAnimator. Bug: 64675794 Change-Id: I41f975ab6be4bf48c483828ea6f109382a8a9320 --- src/com/android/launcher3/allapps/AllAppsContainerView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index ede3bea725..828a347df2 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -224,8 +224,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc mAppsRecyclerView.setLayoutManager(mLayoutManager); mAppsRecyclerView.setAdapter(mAdapter); mAppsRecyclerView.setHasFixedSize(true); - // Removes the animation that can occur when updating the predicted apps in place. - mAppsRecyclerView.getItemAnimator().setChangeDuration(0); + // No animations will occur when changes occur to the items in this RecyclerView. + mAppsRecyclerView.setItemAnimator(null); if (FeatureFlags.LAUNCHER3_PHYSICS) { mAppsRecyclerView.setSpringAnimationHandler(mSpringAnimationHandler); } From 1fe0c2ca085a284936ac04fdb32b0cd9b82e9c4d Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 15 Aug 2017 12:54:42 -0700 Subject: [PATCH 30/38] Simpifying uninstall drop target to check item type instead of class instance Bug: 64719848 Change-Id: I34c13b461e204fbdc2c5b4ed6fa92564ebd5439a --- .../launcher3/UninstallDropTarget.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java index 45c14d6bba..e15cf9f50a 100644 --- a/src/com/android/launcher3/UninstallDropTarget.java +++ b/src/com/android/launcher3/UninstallDropTarget.java @@ -42,7 +42,7 @@ public class UninstallDropTarget extends ButtonDropTarget { return supportsDrop(getContext(), info); } - public static boolean supportsDrop(Context context, Object info) { + public static boolean supportsDrop(Context context, ItemInfo info) { UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); Bundle restrictions = userManager.getUserRestrictions(); if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false) @@ -56,21 +56,13 @@ public class UninstallDropTarget extends ButtonDropTarget { /** * @return the component name that should be uninstalled or null. */ - private static ComponentName getUninstallTarget(Context context, Object item) { + private static ComponentName getUninstallTarget(Context context, ItemInfo item) { Intent intent = null; UserHandle user = null; - if (item instanceof AppInfo) { - AppInfo info = (AppInfo) item; - intent = info.intent; - user = info.user; - } else if (item instanceof ShortcutInfo) { - ShortcutInfo info = (ShortcutInfo) item; - if (info.itemType == LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION) { - // Do not use restore/target intent here as we cannot uninstall an app which is - // being installed/restored. - intent = info.intent; - user = info.user; - } + if (item != null && + item.itemType == LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION) { + intent = item.getIntent(); + user = item.user; } if (intent != null) { LauncherActivityInfo info = LauncherAppsCompat.getInstance(context) From 48a4e91c73309342da224c218bbfb780ea30efed Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 15 Aug 2017 10:31:17 -0700 Subject: [PATCH 31/38] Fix bug where all apps items fade in. Removes all Add/Change/Move/Remove animations by clearing the AllAppsRecyclerView ItemAnimator. Bug: 64675794 Change-Id: I41f975ab6be4bf48c483828ea6f109382a8a9320 (cherry picked from commit 7dfabaa02bdcf7d9307e11fa490c097bdc990025) --- src/com/android/launcher3/allapps/AllAppsContainerView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index ede3bea725..828a347df2 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -224,8 +224,8 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc mAppsRecyclerView.setLayoutManager(mLayoutManager); mAppsRecyclerView.setAdapter(mAdapter); mAppsRecyclerView.setHasFixedSize(true); - // Removes the animation that can occur when updating the predicted apps in place. - mAppsRecyclerView.getItemAnimator().setChangeDuration(0); + // No animations will occur when changes occur to the items in this RecyclerView. + mAppsRecyclerView.setItemAnimator(null); if (FeatureFlags.LAUNCHER3_PHYSICS) { mAppsRecyclerView.setSpringAnimationHandler(mSpringAnimationHandler); } From b23980cc0e56b5d3f5ac0ca7714eca6479e502ae Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 17 Aug 2017 07:45:25 -0700 Subject: [PATCH 32/38] Fixing duplicate/inconsistent definitions for model and callbacks > 2 implementations for filtering workspace items > 2 implementations for binding widgets > duplicate logic for add and update appInfo Change-Id: Id68a49926af398478deca8ac85ab1f22341a9449 --- src/com/android/launcher3/Launcher.java | 65 ++++++------------- src/com/android/launcher3/LauncherModel.java | 11 ++-- .../LauncherAccessibilityDelegate.java | 4 +- .../ShortcutMenuAccessibilityDelegate.java | 2 +- .../allapps/AllAppsContainerView.java | 14 +--- .../allapps/AlphabeticalAppsList.java | 13 +--- .../model/AddWorkspaceItemsTask.java | 2 +- .../launcher3/model/CacheDataUpdatedTask.java | 2 +- .../launcher3/model/LoaderResults.java | 39 ++++------- .../launcher3/model/PackageUpdatedTask.java | 43 +++--------- .../model/AddWorkspaceItemsTaskTest.java | 2 +- 11 files changed, 57 insertions(+), 140 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 615ec47168..0841f4fa84 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3249,13 +3249,13 @@ public class Launcher extends BaseActivity } } + @Override public void bindAppsAdded(final ArrayList newScreens, final ArrayList addNotAnimated, - final ArrayList addAnimated, - final ArrayList addedApps) { + final ArrayList addAnimated) { Runnable r = new Runnable() { public void run() { - bindAppsAdded(newScreens, addNotAnimated, addAnimated, addedApps); + bindAppsAdded(newScreens, addNotAnimated, addAnimated); } }; if (waitUntilResume(r)) { @@ -3270,20 +3270,14 @@ public class Launcher extends BaseActivity // We add the items without animation on non-visible pages, and with // animations on the new page (which we will try and snap to). if (addNotAnimated != null && !addNotAnimated.isEmpty()) { - bindItems(addNotAnimated, 0, - addNotAnimated.size(), false); + bindItems(addNotAnimated, false); } if (addAnimated != null && !addAnimated.isEmpty()) { - bindItems(addAnimated, 0, - addAnimated.size(), true); + bindItems(addAnimated, true); } // Remove the extra empty screen mWorkspace.removeExtraEmptyScreen(false, false); - - if (addedApps != null && mAppsView != null) { - mAppsView.addApps(addedApps); - } } /** @@ -3292,11 +3286,10 @@ public class Launcher extends BaseActivity * Implementation of the method from LauncherModel.Callbacks. */ @Override - public void bindItems(final ArrayList items, final int start, final int end, - final boolean forceAnimateIcons) { + public void bindItems(final List items, final boolean forceAnimateIcons) { Runnable r = new Runnable() { public void run() { - bindItems(items, start, end, forceAnimateIcons); + bindItems(items, forceAnimateIcons); } }; if (waitUntilResume(r)) { @@ -3309,7 +3302,8 @@ public class Launcher extends BaseActivity final boolean animateIcons = forceAnimateIcons && canRunNewAppsAnimation(); Workspace workspace = mWorkspace; long newItemsScreenId = -1; - for (int i = start; i < end; i++) { + int end = items.size(); + for (int i = 0; i < end; i++) { final ItemInfo item = items.get(i); // Short circuit if we are loading dock items for a configuration which has no dock @@ -3334,19 +3328,10 @@ public class Launcher extends BaseActivity break; } case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: { - LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) item; - if (mIsSafeModeEnabled) { - view = new PendingAppWidgetHostView(this, info, mIconCache, true); - } else { - LauncherAppWidgetProviderInfo providerInfo = - mAppWidgetManager.getLauncherAppWidgetInfo(info.appWidgetId); - if (providerInfo == null) { - deleteWidgetInfo(info); - continue; - } - view = mAppWidgetHost.createView(this, info.appWidgetId, providerInfo); + view = bindAppWidget((LauncherAppWidgetInfo) item); + if (view == null) { + continue; } - prepareAppWidget((AppWidgetHostView) view, info); break; } default: @@ -3416,26 +3401,15 @@ public class Launcher extends BaseActivity /** * Add the views for a widget to the workspace. - * - * Implementation of the method from LauncherModel.Callbacks. */ - public void bindAppWidget(final LauncherAppWidgetInfo item) { - Runnable r = new Runnable() { - public void run() { - bindAppWidget(item); - } - }; - if (waitUntilResume(r)) { - return; - } - + public View bindAppWidget(LauncherAppWidgetInfo item) { if (mIsSafeModeEnabled) { PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item, mIconCache, true); prepareAppWidget(view, item); mWorkspace.addInScreen(view, item); mWorkspace.requestLayout(); - return; + return view; } final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0; @@ -3465,7 +3439,7 @@ public class Launcher extends BaseActivity + ", as the provider is null"); } getModelWriter().deleteItemFromDatabase(item); - return; + return null; } // If we do not have a valid id, try to bind an id. @@ -3533,7 +3507,7 @@ public class Launcher extends BaseActivity if (appWidgetInfo == null) { FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId); deleteWidgetInfo(item); - return; + return null; } item.minSpanX = appWidgetInfo.minSpanX; @@ -3550,6 +3524,7 @@ public class Launcher extends BaseActivity Log.d(TAG, "bound widget id="+item.appWidgetId+" in " + (SystemClock.uptimeMillis()-start) + "ms"); } + return view; } /** @@ -3744,10 +3719,10 @@ public class Launcher extends BaseActivity * * Implementation of the method from LauncherModel.Callbacks. */ - public void bindAppsUpdated(final ArrayList apps) { + public void bindAppsAddedOrUpdated(final ArrayList apps) { Runnable r = new Runnable() { public void run() { - bindAppsUpdated(apps); + bindAppsAddedOrUpdated(apps); } }; if (waitUntilResume(r)) { @@ -3755,7 +3730,7 @@ public class Launcher extends BaseActivity } if (mAppsView != null) { - mAppsView.updateApps(apps); + mAppsView.addOrUpdateApps(apps); } } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 1007748661..22d62ec5c6 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -138,18 +138,15 @@ public class LauncherModel extends BroadcastReceiver public int getCurrentWorkspaceScreen(); public void clearPendingBinds(); public void startBinding(); - public void bindItems(ArrayList shortcuts, int start, int end, - boolean forceAnimateIcons); + public void bindItems(List shortcuts, boolean forceAnimateIcons); public void bindScreens(ArrayList orderedScreenIds); public void finishFirstPageBind(ViewOnDrawExecutor executor); public void finishBindingItems(); - public void bindAppWidget(LauncherAppWidgetInfo info); public void bindAllApplications(ArrayList apps); + public void bindAppsAddedOrUpdated(ArrayList apps); public void bindAppsAdded(ArrayList newScreens, ArrayList addNotAnimated, - ArrayList addAnimated, - ArrayList addedApps); - public void bindAppsUpdated(ArrayList apps); + ArrayList addAnimated); public void bindPromiseAppProgressUpdated(PromiseAppInfo app); public void bindShortcutsChanged(ArrayList updated, ArrayList removed, UserHandle user); @@ -537,7 +534,7 @@ public class LauncherModel extends BroadcastReceiver scheduleCallbackTask(new CallbackTask() { @Override public void execute(Callbacks callbacks) { - callbacks.bindAppsAdded(null, null, null, arrayList); + callbacks.bindAppsAddedOrUpdated(arrayList); } }); } diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java index 34335330be..a0ad07aeb1 100644 --- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java @@ -173,7 +173,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme ArrayList itemList = new ArrayList<>(); itemList.add(info); - mLauncher.bindItems(itemList, 0, itemList.size(), true); + mLauncher.bindItems(itemList, true); } else if (item instanceof PendingAddItemInfo) { PendingAddItemInfo info = (PendingAddItemInfo) item; Workspace workspace = mLauncher.getWorkspace(); @@ -205,7 +205,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme public void run() { ArrayList itemList = new ArrayList<>(); itemList.add(item); - mLauncher.bindItems(itemList, 0, itemList.size(), true); + mLauncher.bindItems(itemList, true); announceConfirmation(R.string.item_moved); } }); diff --git a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java index b7c500fa6e..5b7353aa18 100644 --- a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java @@ -73,7 +73,7 @@ public class ShortcutMenuAccessibilityDelegate extends LauncherAccessibilityDele screenId, coordinates[0], coordinates[1]); ArrayList itemList = new ArrayList<>(); itemList.add(info); - mLauncher.bindItems(itemList, 0, itemList.size(), true); + mLauncher.bindItems(itemList, true); AbstractFloatingView.closeAllOpenViews(mLauncher); announceConfirmation(R.string.item_added_to_workspace); } diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 828a347df2..0d512ab420 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -132,18 +132,10 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc } /** - * Adds new apps to the list. + * Adds or updates existing apps in the list */ - public void addApps(List apps) { - mApps.addApps(apps); - mSearchUiManager.refreshSearchResult(); - } - - /** - * Updates existing apps in the list - */ - public void updateApps(List apps) { - mApps.updateApps(apps); + public void addOrUpdateApps(List apps) { + mApps.addOrUpdateApps(apps); mSearchUiManager.refreshSearchResult(); } diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 43b56a4bb8..5e7a5cac56 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -374,20 +374,13 @@ public class AlphabeticalAppsList { */ public void setApps(List apps) { mComponentToAppMap.clear(); - addApps(apps); + addOrUpdateApps(apps); } /** - * Adds new apps to the list. + * Adds or updates existing apps in the list */ - public void addApps(List apps) { - updateApps(apps); - } - - /** - * Updates existing apps in the list - */ - public void updateApps(List apps) { + public void addOrUpdateApps(List apps) { for (AppInfo app : apps) { mComponentToAppMap.put(app.toComponentKey(), app); } diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index 68012c4ba1..42926fa3ea 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -158,7 +158,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { } } callbacks.bindAppsAdded(addedWorkspaceScreensFinal, - addNotAnimated, addAnimated, null); + addNotAnimated, addAnimated); } }); } diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java index 8597e10486..7a27741c33 100644 --- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java +++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java @@ -77,7 +77,7 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask { scheduleCallbackTask(new CallbackTask() { @Override public void execute(Callbacks callbacks) { - callbacks.bindAppsUpdated(updatedApps); + callbacks.bindAppsAddedOrUpdated(updatedApps); } }); } diff --git a/src/com/android/launcher3/model/LoaderResults.java b/src/com/android/launcher3/model/LoaderResults.java index 0df8b6fee2..b7a6b68e83 100644 --- a/src/com/android/launcher3/model/LoaderResults.java +++ b/src/com/android/launcher3/model/LoaderResults.java @@ -122,7 +122,7 @@ public class LoaderResults { filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems, otherWorkspaceItems); - filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets, + filterCurrentWorkspaceItems(currentScreenId, appWidgets, currentAppWidgets, otherAppWidgets); sortWorkspaceItemsSpatially(currentWorkspaceItems); sortWorkspaceItemsSpatially(otherWorkspaceItems); @@ -208,12 +208,12 @@ public class LoaderResults { /** Filters the set of items who are directly or indirectly (via another container) on the * specified screen. */ - private void filterCurrentWorkspaceItems(long currentScreenId, - ArrayList allWorkspaceItems, - ArrayList currentScreenItems, - ArrayList otherScreenItems) { + private void filterCurrentWorkspaceItems(long currentScreenId, + ArrayList allWorkspaceItems, + ArrayList currentScreenItems, + ArrayList otherScreenItems) { // Purge any null ItemInfos - Iterator iter = allWorkspaceItems.iterator(); + Iterator iter = allWorkspaceItems.iterator(); while (iter.hasNext()) { ItemInfo i = iter.next(); if (i == null) { @@ -224,14 +224,14 @@ public class LoaderResults { // Order the set of items by their containers first, this allows use to walk through the // list sequentially, build up a list of containers that are in the specified screen, // as well as all items in those containers. - Set itemsOnScreen = new HashSet(); + Set itemsOnScreen = new HashSet<>(); Collections.sort(allWorkspaceItems, new Comparator() { @Override public int compare(ItemInfo lhs, ItemInfo rhs) { return Utilities.longCompare(lhs.container, rhs.container); } }); - for (ItemInfo info : allWorkspaceItems) { + for (T info : allWorkspaceItems) { if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { if (info.screenId == currentScreenId) { currentScreenItems.add(info); @@ -253,23 +253,6 @@ public class LoaderResults { } } - /** Filters the set of widgets which are on the specified screen. */ - private void filterCurrentAppWidgets(long currentScreenId, - ArrayList appWidgets, - ArrayList currentScreenWidgets, - ArrayList otherScreenWidgets) { - - for (LauncherAppWidgetInfo widget : appWidgets) { - if (widget == null) continue; - if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && - widget.screenId == currentScreenId) { - currentScreenWidgets.add(widget); - } else { - otherScreenWidgets.add(widget); - } - } - } - /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to * right) */ private void sortWorkspaceItemsSpatially(ArrayList workspaceItems) { @@ -322,7 +305,7 @@ public class LoaderResults { public void run() { Callbacks callbacks = mCallbacks.get(); if (callbacks != null) { - callbacks.bindItems(workspaceItems, start, start+chunkSize, false); + callbacks.bindItems(workspaceItems.subList(start, start+chunkSize), false); } } }; @@ -332,12 +315,12 @@ public class LoaderResults { // Bind the widgets, one at a time N = appWidgets.size(); for (int i = 0; i < N; i++) { - final LauncherAppWidgetInfo widget = appWidgets.get(i); + final ItemInfo widget = appWidgets.get(i); final Runnable r = new Runnable() { public void run() { Callbacks callbacks = mCallbacks.get(); if (callbacks != null) { - callbacks.bindAppWidget(widget); + callbacks.bindItems(Collections.singletonList(widget), false); } } }; diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index 1b2f8d63fa..c6e878cf11 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -147,51 +147,28 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { break; } - ArrayList added = null; - ArrayList modified = null; - final ArrayList removedApps = new ArrayList<>(); + final ArrayList addedOrModified = new ArrayList<>(); + addedOrModified.addAll(appsList.added); + appsList.added.clear(); + addedOrModified.addAll(appsList.modified); + appsList.modified.clear(); - if (appsList.added.size() > 0) { - added = new ArrayList<>(appsList.added); - appsList.added.clear(); - } - if (appsList.modified.size() > 0) { - modified = new ArrayList<>(appsList.modified); - appsList.modified.clear(); - } - if (appsList.removed.size() > 0) { - removedApps.addAll(appsList.removed); - appsList.removed.clear(); - } + final ArrayList removedApps = new ArrayList<>(appsList.removed); + appsList.removed.clear(); final ArrayMap addedOrUpdatedApps = new ArrayMap<>(); - - if (added != null) { - final ArrayList addedApps = added; + if (!addedOrModified.isEmpty()) { scheduleCallbackTask(new CallbackTask() { @Override public void execute(Callbacks callbacks) { - callbacks.bindAppsAdded(null, null, null, addedApps); + callbacks.bindAppsAddedOrUpdated(addedOrModified); } }); - for (AppInfo ai : added) { + for (AppInfo ai : addedOrModified) { addedOrUpdatedApps.put(ai.componentName, ai); } } - if (modified != null) { - final ArrayList modifiedFinal = modified; - for (AppInfo ai : modified) { - addedOrUpdatedApps.put(ai.componentName, ai); - } - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindAppsUpdated(modifiedFinal); - } - }); - } - // Update shortcut infos if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) { final ArrayList updatedShortcuts = new ArrayList<>(); diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java index ae15f086f3..82f34e43de 100644 --- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java +++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java @@ -131,7 +131,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { // only info2 should be added because info was already added to the workspace // in setupWorkspaceWithHoles() verify(callbacks).bindAppsAdded(any(ArrayList.class), notAnimated.capture(), - animated.capture(), isNull(ArrayList.class)); + animated.capture()); assertTrue(notAnimated.getValue().isEmpty()); assertEquals(1, animated.getValue().size()); From 6e13dd3aa867d01f3f1d196ac82eca184328577c Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 17 Aug 2017 03:01:19 -0700 Subject: [PATCH 33/38] Simplifying some package matching code by using common itemInfo mathcher Change-Id: Ib98d528391e19c0de3fe11304330dfa37710548c --- src/com/android/launcher3/Launcher.java | 52 +++---------------- src/com/android/launcher3/LauncherModel.java | 8 ++- .../launcher3/model/BaseModelUpdateTask.java | 26 ++++++---- .../launcher3/model/PackageUpdatedTask.java | 25 +++------ .../launcher3/model/ShortcutsChangedTask.java | 37 +++++++------ .../model/UserLockStateChangedTask.java | 16 +++--- .../launcher3/util/ItemInfoMatcher.java | 37 +++++++++++++ 7 files changed, 100 insertions(+), 101 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 0841f4fa84..8814eb8f7f 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3768,16 +3768,12 @@ public class Launcher extends BaseActivity * Implementation of the method from LauncherModel.Callbacks. * * @param updated list of shortcuts which have changed. - * @param removed list of shortcuts which were deleted in the background. This can happen when - * an app gets removed from the system or some of its components are no longer - * available. */ @Override - public void bindShortcutsChanged(final ArrayList updated, - final ArrayList removed, final UserHandle user) { + public void bindShortcutsChanged(final ArrayList updated, final UserHandle user) { Runnable r = new Runnable() { public void run() { - bindShortcutsChanged(updated, removed, user); + bindShortcutsChanged(updated, user); } }; if (waitUntilResume(r)) { @@ -3787,31 +3783,6 @@ public class Launcher extends BaseActivity if (!updated.isEmpty()) { mWorkspace.updateShortcuts(updated); } - - if (!removed.isEmpty()) { - HashSet removedComponents = new HashSet<>(); - HashSet removedDeepShortcuts = new HashSet<>(); - - for (ShortcutInfo si : removed) { - if (si.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) { - removedDeepShortcuts.add(ShortcutKey.fromItemInfo(si)); - } else { - removedComponents.add(si.getTargetComponent()); - } - } - - if (!removedComponents.isEmpty()) { - ItemInfoMatcher matcher = ItemInfoMatcher.ofComponents(removedComponents, user); - mWorkspace.removeItemsByMatcher(matcher); - mDragController.onAppsRemoved(matcher); - } - - if (!removedDeepShortcuts.isEmpty()) { - ItemInfoMatcher matcher = ItemInfoMatcher.ofShortcutKeys(removedDeepShortcuts); - mWorkspace.removeItemsByMatcher(matcher); - mDragController.onAppsRemoved(matcher); - } - } } /** @@ -3841,28 +3812,17 @@ public class Launcher extends BaseActivity * package-removal should clear all items by package name. */ @Override - public void bindWorkspaceComponentsRemoved( - final HashSet packageNames, final HashSet components, - final UserHandle user) { + public void bindWorkspaceComponentsRemoved(final ItemInfoMatcher matcher) { Runnable r = new Runnable() { public void run() { - bindWorkspaceComponentsRemoved(packageNames, components, user); + bindWorkspaceComponentsRemoved(matcher); } }; if (waitUntilResume(r)) { return; } - if (!packageNames.isEmpty()) { - ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(packageNames, user); - mWorkspace.removeItemsByMatcher(matcher); - mDragController.onAppsRemoved(matcher); - - } - if (!components.isEmpty()) { - ItemInfoMatcher matcher = ItemInfoMatcher.ofComponents(components, user); - mWorkspace.removeItemsByMatcher(matcher); - mDragController.onAppsRemoved(matcher); - } + mWorkspace.removeItemsByMatcher(matcher); + mDragController.onAppsRemoved(matcher); } @Override diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 22d62ec5c6..a906b00f1f 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -56,6 +56,7 @@ import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; @@ -148,13 +149,10 @@ public class LauncherModel extends BroadcastReceiver ArrayList addNotAnimated, ArrayList addAnimated); public void bindPromiseAppProgressUpdated(PromiseAppInfo app); - public void bindShortcutsChanged(ArrayList updated, - ArrayList removed, UserHandle user); + public void bindShortcutsChanged(ArrayList updated, UserHandle user); public void bindWidgetsRestored(ArrayList widgets); public void bindRestoreItemsChange(HashSet updates); - public void bindWorkspaceComponentsRemoved( - HashSet packageNames, HashSet components, - UserHandle user); + public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher); public void bindAppInfosRemoved(ArrayList appInfos); public void bindAllWidgets(MultiHashMap widgets); public void onPageBoundSynchronously(int page); diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java index 9b4510fcae..d5b5aa7cf3 100644 --- a/src/com/android/launcher3/model/BaseModelUpdateTask.java +++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java @@ -26,6 +26,7 @@ import com.android.launcher3.LauncherModel.CallbackTask; import com.android.launcher3.LauncherModel.Callbacks; import com.android.launcher3.ShortcutInfo; import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.MultiHashMap; import java.util.ArrayList; @@ -94,19 +95,12 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask { public void bindUpdatedShortcuts( - ArrayList updatedShortcuts, UserHandle user) { - bindUpdatedShortcuts(updatedShortcuts, new ArrayList(), user); - } - - public void bindUpdatedShortcuts( - final ArrayList updatedShortcuts, - final ArrayList removedShortcuts, - final UserHandle user) { - if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) { + final ArrayList updatedShortcuts, final UserHandle user) { + if (!updatedShortcuts.isEmpty()) { scheduleCallbackTask(new CallbackTask() { @Override public void execute(Callbacks callbacks) { - callbacks.bindShortcutsChanged(updatedShortcuts, removedShortcuts, user); + callbacks.bindShortcutsChanged(updatedShortcuts, user); } }); } @@ -132,4 +126,16 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask { } }); } + + public void deleteAndBindComponentsRemoved(final ItemInfoMatcher matcher) { + getModelWriter().deleteItemsFromDatabase(matcher); + + // Call the components-removed callback + scheduleCallbackTask(new CallbackTask() { + @Override + public void execute(Callbacks callbacks) { + callbacks.bindWorkspaceComponentsRemoved(matcher); + } + }); + } } diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index c6e878cf11..6c78d5bfca 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -43,6 +43,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.LauncherIcons; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; @@ -172,7 +173,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { // Update shortcut infos if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) { final ArrayList updatedShortcuts = new ArrayList<>(); - final ArrayList removedShortcuts = new ArrayList<>(); + final LongArrayMap removedShortcuts = new LongArrayMap<>(); final ArrayList widgets = new ArrayList<>(); synchronized (dataModel) { @@ -213,7 +214,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } if ((intent == null) || (appInfo == null)) { - removedShortcuts.add(si); + removedShortcuts.put(si.id, true); continue; } si.intent = intent; @@ -267,9 +268,9 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } } - bindUpdatedShortcuts(updatedShortcuts, removedShortcuts, mUser); + bindUpdatedShortcuts(updatedShortcuts, mUser); if (!removedShortcuts.isEmpty()) { - getModelWriter().deleteItemsFromDatabase(removedShortcuts); + deleteAndBindComponentsRemoved(ItemInfoMatcher.ofItemIds(removedShortcuts, false)); } if (!widgets.isEmpty()) { @@ -306,22 +307,12 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) { - getModelWriter().deleteItemsFromDatabase( - ItemInfoMatcher.ofPackages(removedPackages, mUser)); - getModelWriter().deleteItemsFromDatabase( - ItemInfoMatcher.ofComponents(removedComponents, mUser)); + ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser) + .or(ItemInfoMatcher.ofComponents(removedComponents, mUser)); + deleteAndBindComponentsRemoved(removeMatch); // Remove any queued items from the install queue InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser); - - // Call the components-removed callback - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindWorkspaceComponentsRemoved( - removedPackages, removedComponents, mUser); - } - }); } if (!removedApps.isEmpty()) { diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java index 17cc238d42..c1f33a6b2c 100644 --- a/src/com/android/launcher3/model/ShortcutsChangedTask.java +++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java @@ -26,9 +26,12 @@ import com.android.launcher3.ShortcutInfo; import com.android.launcher3.graphics.LauncherIcons; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutInfoCompat; +import com.android.launcher3.shortcuts.ShortcutKey; +import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.MultiHashMap; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; /** @@ -56,33 +59,35 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask { deepShortcutManager.onShortcutsChanged(mShortcuts); // Find ShortcutInfo's that have changed on the workspace. - final ArrayList removedShortcutInfos = new ArrayList<>(); - MultiHashMap idsToWorkspaceShortcutInfos = new MultiHashMap<>(); + HashSet removedKeys = new HashSet<>(); + MultiHashMap keyToShortcutInfo = new MultiHashMap<>(); + HashSet allIds = new HashSet<>(); + for (ItemInfo itemInfo : dataModel.itemsIdMap) { if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) { ShortcutInfo si = (ShortcutInfo) itemInfo; - if (si.getIntent().getPackage().equals(mPackageName) - && si.user.equals(mUser)) { - idsToWorkspaceShortcutInfos.addToList(si.getDeepShortcutId(), si); + if (si.getIntent().getPackage().equals(mPackageName) && si.user.equals(mUser)) { + keyToShortcutInfo.addToList(ShortcutKey.fromItemInfo(si), si); + allIds.add(si.getDeepShortcutId()); } } } final ArrayList updatedShortcutInfos = new ArrayList<>(); - if (!idsToWorkspaceShortcutInfos.isEmpty()) { + if (!keyToShortcutInfo.isEmpty()) { // Update the workspace to reflect the changes to updated shortcuts residing on it. List shortcuts = deepShortcutManager.queryForFullDetails( - mPackageName, new ArrayList<>(idsToWorkspaceShortcutInfos.keySet()), mUser); + mPackageName, new ArrayList<>(allIds), mUser); for (ShortcutInfoCompat fullDetails : shortcuts) { - List shortcutInfos = idsToWorkspaceShortcutInfos - .remove(fullDetails.getId()); + ShortcutKey key = ShortcutKey.fromInfo(fullDetails); + List shortcutInfos = keyToShortcutInfo.remove(key); if (!fullDetails.isPinned()) { // The shortcut was previously pinned but is no longer, so remove it from // the workspace and our pinned shortcut counts. // Note that we put this check here, after querying for full details, // because there's a possible race condition between pinning and // receiving this callback. - removedShortcutInfos.addAll(shortcutInfos); + removedKeys.add(key); continue; } for (final ShortcutInfo shortcutInfo : shortcutInfos) { @@ -94,16 +99,14 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask { } } - // If there are still entries in idsToWorkspaceShortcutInfos, that means that + // If there are still entries in keyToShortcutInfo, that means that // the corresponding shortcuts weren't passed in onShortcutsChanged(). This // means they were cleared, so we remove and unpin them now. - for (String id : idsToWorkspaceShortcutInfos.keySet()) { - removedShortcutInfos.addAll(idsToWorkspaceShortcutInfos.get(id)); - } + removedKeys.addAll(keyToShortcutInfo.keySet()); - bindUpdatedShortcuts(updatedShortcutInfos, removedShortcutInfos, mUser); - if (!removedShortcutInfos.isEmpty()) { - getModelWriter().deleteItemsFromDatabase(removedShortcutInfos); + bindUpdatedShortcuts(updatedShortcutInfos, mUser); + if (!keyToShortcutInfo.isEmpty()) { + deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys)); } if (mUpdateIdMap) { diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java index 802771f048..8170f9a67f 100644 --- a/src/com/android/launcher3/model/UserLockStateChangedTask.java +++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java @@ -29,9 +29,11 @@ import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.ItemInfoMatcher; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -70,17 +72,19 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask { // Update the workspace to reflect the changes to updated shortcuts residing on it. ArrayList updatedShortcutInfos = new ArrayList<>(); - ArrayList deletedShortcutInfos = new ArrayList<>(); + HashSet removedKeys = new HashSet<>(); + for (ItemInfo itemInfo : dataModel.itemsIdMap) { if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT && mUser.equals(itemInfo.user)) { ShortcutInfo si = (ShortcutInfo) itemInfo; if (isUserUnlocked) { - ShortcutInfoCompat shortcut = pinnedShortcuts.get(ShortcutKey.fromItemInfo(si)); + ShortcutKey key = ShortcutKey.fromItemInfo(si); + ShortcutInfoCompat shortcut = pinnedShortcuts.get(key); // We couldn't verify the shortcut during loader. If its no longer available // (probably due to clear data), delete the workspace item as well if (shortcut == null) { - deletedShortcutInfos.add(si); + removedKeys.add(key); continue; } si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_LOCKED_USER; @@ -93,9 +97,9 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask { updatedShortcutInfos.add(si); } } - bindUpdatedShortcuts(updatedShortcutInfos, deletedShortcutInfos, mUser); - if (!deletedShortcutInfos.isEmpty()) { - getModelWriter().deleteItemsFromDatabase(deletedShortcutInfos); + bindUpdatedShortcuts(updatedShortcutInfos, mUser); + if (!removedKeys.isEmpty()) { + deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys)); } // Remove shortcut id map for that user diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java index 42de284665..18787b6a2a 100644 --- a/src/com/android/launcher3/util/ItemInfoMatcher.java +++ b/src/com/android/launcher3/util/ItemInfoMatcher.java @@ -18,6 +18,7 @@ package com.android.launcher3.util; import android.content.ComponentName; import android.os.UserHandle; +import android.util.SparseLongArray; import com.android.launcher3.FolderInfo; import com.android.launcher3.ItemInfo; @@ -66,6 +67,32 @@ public abstract class ItemInfoMatcher { return filtered; } + /** + * Returns a new matcher with returns true if either this or {@param matcher} returns true. + */ + public ItemInfoMatcher or(final ItemInfoMatcher matcher) { + final ItemInfoMatcher that = this; + return new ItemInfoMatcher() { + @Override + public boolean matches(ItemInfo info, ComponentName cn) { + return that.matches(info, cn) || matcher.matches(info, cn); + } + }; + } + + /** + * Returns a new matcher with returns true if both this and {@param matcher} returns true. + */ + public ItemInfoMatcher and(final ItemInfoMatcher matcher) { + final ItemInfoMatcher that = this; + return new ItemInfoMatcher() { + @Override + public boolean matches(ItemInfo info, ComponentName cn) { + return that.matches(info, cn) && matcher.matches(info, cn); + } + }; + } + public static ItemInfoMatcher ofUser(final UserHandle user) { return new ItemInfoMatcher() { @Override @@ -104,4 +131,14 @@ public abstract class ItemInfoMatcher { } }; } + + public static ItemInfoMatcher ofItemIds( + final LongArrayMap ids, final Boolean matchDefault) { + return new ItemInfoMatcher() { + @Override + public boolean matches(ItemInfo info, ComponentName cn) { + return ids.get(info.id, matchDefault); + } + }; + } } From a9a1a210d3b8fac736555b133a815f463641b50e Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 18 Aug 2017 01:03:21 -0700 Subject: [PATCH 34/38] Fixing crashloop due to ag/2750101 Change-Id: Idebf6bfad4e56a52780b848fbb09b3a0134ffdc2 --- src/com/android/launcher3/Launcher.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 0841f4fa84..28b44825db 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3328,7 +3328,7 @@ public class Launcher extends BaseActivity break; } case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: { - view = bindAppWidget((LauncherAppWidgetInfo) item); + view = inflateAppWidget((LauncherAppWidgetInfo) item); if (view == null) { continue; } @@ -3402,13 +3402,19 @@ public class Launcher extends BaseActivity /** * Add the views for a widget to the workspace. */ - public View bindAppWidget(LauncherAppWidgetInfo item) { + public void bindAppWidget(LauncherAppWidgetInfo item) { + View view = inflateAppWidget(item); + if (view != null) { + mWorkspace.addInScreen(view, item); + mWorkspace.requestLayout(); + } + } + + private View inflateAppWidget(LauncherAppWidgetInfo item) { if (mIsSafeModeEnabled) { PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item, mIconCache, true); prepareAppWidget(view, item); - mWorkspace.addInScreen(view, item); - mWorkspace.requestLayout(); return view; } @@ -3517,8 +3523,6 @@ public class Launcher extends BaseActivity view = new PendingAppWidgetHostView(this, item, mIconCache, false); } prepareAppWidget(view, item); - mWorkspace.addInScreen(view, item); - mWorkspace.requestLayout(); if (DEBUG_WIDGETS) { Log.d(TAG, "bound widget id="+item.appWidgetId+" in " From 906c6b2f6c6eab68c46a8c32fec6eb82bd057cb2 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 18 Aug 2017 00:35:52 -0700 Subject: [PATCH 35/38] Fixing wrong intests being sent to DeviceProfile in case of lowRam device Also fixing the navbar to dark theme when a black bar is drawn behind nav bar Fixing left/right margins not getting updated on lowRam device when they change from non-zero value to 0 Bug: 64363693 Bug: 62547502 Change-Id: I4952ad2f564b71b39318350445f116a0f601a10f --- .../android/launcher3/LauncherRootView.java | 29 +++++++++++++------ .../launcher3/util/SystemUiController.java | 3 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java index 643d48adfc..a814323633 100644 --- a/src/com/android/launcher3/LauncherRootView.java +++ b/src/com/android/launcher3/LauncherRootView.java @@ -11,6 +11,9 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewDebug; +import static com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV; +import static com.android.launcher3.util.SystemUiController.UI_STATE_ROOT_VIEW; + public class LauncherRootView extends InsettableFrameLayout { private final Paint mOpaquePaint; @@ -44,20 +47,28 @@ public class LauncherRootView extends InsettableFrameLayout { @TargetApi(23) @Override protected boolean fitSystemWindows(Rect insets) { - boolean rawInsetsChanged = !mInsets.equals(insets); mDrawSideInsetBar = (insets.right > 0 || insets.left > 0) && (!Utilities.ATLEAST_MARSHMALLOW || - getContext().getSystemService(ActivityManager.class).isLowRamDevice()); - mRightInsetBarWidth = insets.right; - mLeftInsetBarWidth = insets.left; - setInsets(mDrawSideInsetBar ? new Rect(0, insets.top, 0, insets.bottom) : insets); + getContext().getSystemService(ActivityManager.class).isLowRamDevice()); + if (mDrawSideInsetBar) { + mLeftInsetBarWidth = insets.left; + mRightInsetBarWidth = insets.right; + insets = new Rect(0, insets.top, 0, insets.bottom); + } else { + mLeftInsetBarWidth = mRightInsetBarWidth = 0; + } + Launcher.getLauncher(getContext()).getSystemUiController().updateUiState( + UI_STATE_ROOT_VIEW, mDrawSideInsetBar ? FLAG_DARK_NAV : 0); - if (mAlignedView != null && mDrawSideInsetBar) { + boolean rawInsetsChanged = !mInsets.equals(insets); + setInsets(insets); + + if (mAlignedView != null) { // Apply margins on aligned view to handle left/right insets. MarginLayoutParams lp = (MarginLayoutParams) mAlignedView.getLayoutParams(); - if (lp.leftMargin != insets.left || lp.rightMargin != insets.right) { - lp.leftMargin = insets.left; - lp.rightMargin = insets.right; + if (lp.leftMargin != mLeftInsetBarWidth || lp.rightMargin != mRightInsetBarWidth) { + lp.leftMargin = mLeftInsetBarWidth; + lp.rightMargin = mRightInsetBarWidth; mAlignedView.setLayoutParams(lp); } } diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java index 6b5b095c78..d7a2625e94 100644 --- a/src/com/android/launcher3/util/SystemUiController.java +++ b/src/com/android/launcher3/util/SystemUiController.java @@ -30,6 +30,7 @@ public class SystemUiController { public static final int UI_STATE_BASE_WINDOW = 0; public static final int UI_STATE_ALL_APPS = 1; public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2; + public static final int UI_STATE_ROOT_VIEW = 3; public static final int FLAG_LIGHT_NAV = 1 << 0; public static final int FLAG_DARK_NAV = 1 << 1; @@ -37,7 +38,7 @@ public class SystemUiController { public static final int FLAG_DARK_STATUS = 1 << 3; private final Window mWindow; - private final int[] mStates = new int[3]; + private final int[] mStates = new int[4]; public SystemUiController(Window window) { mWindow = window; From 49fc3f7aa8b0da180f6cbc61da4df942ba398c2c Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 18 Aug 2017 10:17:06 -0700 Subject: [PATCH 36/38] Fixing bindAllApplications scheduled with null list. When deferring bindAllApplications, the same global state was being used to store the pending state. This global state was being cleared in one deferred execution after a second execution was scheduled, causing the second execution to get null/wrong values. Instead using independent local/anonymous class to maintian states, so that it does not get cleared by other methods. Bug: 64789383 Change-Id: I78477a110fe663603b4bdeb7d1fac7c4ce0831a2 --- src/com/android/launcher3/Launcher.java | 58 ++++++++----------- .../launcher3/util/RunnableWithId.java | 36 ++++++++++++ 2 files changed, 59 insertions(+), 35 deletions(-) create mode 100644 src/com/android/launcher3/util/RunnableWithId.java diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 28b44825db..e229d6c65a 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -119,6 +119,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; import com.android.launcher3.util.ActivityResultInfo; +import com.android.launcher3.util.RunnableWithId; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.MultiHashMap; @@ -146,6 +147,9 @@ import java.util.List; import java.util.Set; import java.util.concurrent.Executor; +import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_APPS; +import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_WIDGETS; + /** * Default launcher application. */ @@ -246,7 +250,6 @@ public class Launcher extends BaseActivity // Main container view and the model for the widget tray screen. @Thunk WidgetsContainerView mWidgetsView; - @Thunk MultiHashMap mAllWidgets; // We set the state in both onCreate and then onNewIntent in some cases, which causes both // scroll issues (because the workspace may not have been measured yet) and extra work. @@ -3113,12 +3116,12 @@ public class Launcher extends BaseActivity * * @return {@code true} if we are currently paused. The caller might be able to skip some work */ - @Thunk boolean waitUntilResume(Runnable run, boolean deletePreviousRunnables) { + @Thunk boolean waitUntilResume(Runnable run) { if (mPaused) { if (LOGD) Log.d(TAG, "Deferring update until onResume"); - if (deletePreviousRunnables) { - while (mBindOnResumeCallbacks.remove(run)) { - } + if (run instanceof RunnableWithId) { + // Remove any runnables which have the same id + while (mBindOnResumeCallbacks.remove(run)) { } } mBindOnResumeCallbacks.add(run); return true; @@ -3127,10 +3130,6 @@ public class Launcher extends BaseActivity } } - private boolean waitUntilResume(Runnable run) { - return waitUntilResume(run, false); - } - public void addOnResumeCallback(Runnable run) { mOnResumeCallbacks.add(run); } @@ -3663,26 +3662,18 @@ public class Launcher extends BaseActivity return LauncherCallbacks.SEARCH_BAR_HEIGHT_NORMAL; } - /** - * A runnable that we can dequeue and re-enqueue when all applications are bound (to prevent - * multiple calls to bind the same list.) - */ - @Thunk ArrayList mTmpAppsList; - private final Runnable mBindAllApplicationsRunnable = new Runnable() { - public void run() { - bindAllApplications(mTmpAppsList); - mTmpAppsList = null; - } - }; - /** * Add the icons for all apps. * * Implementation of the method from LauncherModel.Callbacks. */ public void bindAllApplications(final ArrayList apps) { - if (waitUntilResume(mBindAllApplicationsRunnable, true)) { - mTmpAppsList = apps; + Runnable r = new RunnableWithId(RUNNABLE_ID_BIND_APPS) { + public void run() { + bindAllApplications(apps); + } + }; + if (waitUntilResume(r)) { return; } @@ -3690,10 +3681,10 @@ public class Launcher extends BaseActivity Executor pendingExecutor = getPendingExecutor(); if (pendingExecutor != null && mState != State.APPS) { // Wait until the fade in animation has finished before setting all apps list. - mTmpAppsList = apps; - pendingExecutor.execute(mBindAllApplicationsRunnable); + pendingExecutor.execute(r); return; } + mAppsView.setApps(apps); } if (mLauncherCallbacks != null) { @@ -3887,28 +3878,25 @@ public class Launcher extends BaseActivity } } - private final Runnable mBindAllWidgetsRunnable = new Runnable() { + @Override + public void bindAllWidgets(final MultiHashMap allWidgets) { + Runnable r = new RunnableWithId(RUNNABLE_ID_BIND_WIDGETS) { + @Override public void run() { - bindAllWidgets(mAllWidgets); + bindAllWidgets(allWidgets); } }; - - @Override - public void bindAllWidgets(MultiHashMap allWidgets) { - if (waitUntilResume(mBindAllWidgetsRunnable, true)) { - mAllWidgets = allWidgets; + if (waitUntilResume(r)) { return; } if (mWidgetsView != null && allWidgets != null) { Executor pendingExecutor = getPendingExecutor(); if (pendingExecutor != null && mState != State.WIDGETS) { - mAllWidgets = allWidgets; - pendingExecutor.execute(mBindAllWidgetsRunnable); + pendingExecutor.execute(r); return; } mWidgetsView.setWidgets(allWidgets); - mAllWidgets = null; } AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this); diff --git a/src/com/android/launcher3/util/RunnableWithId.java b/src/com/android/launcher3/util/RunnableWithId.java new file mode 100644 index 0000000000..030eb09ff3 --- /dev/null +++ b/src/com/android/launcher3/util/RunnableWithId.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.util; + +/** + * A runnable with an id associated which is used for equality check. + */ +public abstract class RunnableWithId implements Runnable { + + public static final int RUNNABLE_ID_BIND_APPS = 1; + public static final int RUNNABLE_ID_BIND_WIDGETS = 2; + + public final int id; + + public RunnableWithId(int id) { + this.id = id; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof RunnableWithId && ((RunnableWithId) obj).id == id; + } +} From d725f644b70239332a4440173e6411e9ffb169a0 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Thu, 17 Aug 2017 22:26:35 -0700 Subject: [PATCH 37/38] Remove LAUNCHER3_ALL_APPS_PULL_UP Bug: 63712253 Verified: all apps transition fully functional Verified: NO_ALL_APPS_ICON = false case also works. Change-Id: I779fb7bd4927c5923da3f85590d912dbbbcdef4d --- .../android/launcher3/BaseContainerView.java | 2 +- src/com/android/launcher3/Launcher.java | 6 +-- .../LauncherStateTransitionAnimation.java | 24 +++------ .../WorkspaceStateTransitionAnimation.java | 10 ++-- .../allapps/AllAppsContainerView.java | 51 +++++-------------- .../search/AppsSearchContainerLayout.java | 3 +- .../android/launcher3/config/BaseFlags.java | 1 - .../launcher3/dragndrop/DragLayer.java | 2 +- .../launcher3/ui/AbstractLauncherUiTest.java | 2 +- 9 files changed, 30 insertions(+), 71 deletions(-) diff --git a/src/com/android/launcher3/BaseContainerView.java b/src/com/android/launcher3/BaseContainerView.java index c55a5860ef..82175b721d 100644 --- a/src/com/android/launcher3/BaseContainerView.java +++ b/src/com/android/launcher3/BaseContainerView.java @@ -62,7 +62,7 @@ public abstract class BaseContainerView extends FrameLayout public BaseContainerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && this instanceof AllAppsContainerView) { + if (this instanceof AllAppsContainerView) { mBaseDrawable = new ColorDrawable(); } else { TypedArray a = context.obtainStyledAttributes(attrs, diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 615ec47168..106a11b738 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1307,9 +1307,7 @@ public class Launcher extends BaseActivity mDragController.addDropTarget(mWorkspace); mDropTargetBar.setup(mDragController); - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { - mAllAppsController.setupViews(mAppsView, mHotseat, mWorkspace); - } + mAllAppsController.setupViews(mAppsView, mHotseat, mWorkspace); if (TestingUtils.MEMORY_DUMP_ENABLED) { TestingUtils.addWeightWatcher(this); @@ -2277,7 +2275,7 @@ public class Launcher extends BaseActivity if (v instanceof FolderIcon) { onClickFolderIcon(v); } - } else if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator) || + } else if ((v instanceof PageIndicator) || (v == mAllAppsButton && mAllAppsButton != null)) { onClickAllAppsButton(v); } else if (tag instanceof AppInfo) { diff --git a/src/com/android/launcher3/LauncherStateTransitionAnimation.java b/src/com/android/launcher3/LauncherStateTransitionAnimation.java index 9ff61ec98b..e2474900da 100644 --- a/src/com/android/launcher3/LauncherStateTransitionAnimation.java +++ b/src/com/android/launcher3/LauncherStateTransitionAnimation.java @@ -80,13 +80,11 @@ import com.android.launcher3.widget.WidgetsContainerView; public class LauncherStateTransitionAnimation { /** - * animation used for all apps and widget tray when - *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code false} + * animation used for the widget tray */ public static final int CIRCULAR_REVEAL = 0; /** - * animation used for all apps and not widget tray when - *{@link FeatureFlags#LAUNCHER3_ALL_APPS_PULL_UP} is {@code true} + * animation used for all apps tray */ public static final int PULLUP = 1; @@ -154,13 +152,9 @@ public class LauncherStateTransitionAnimation { mLauncher.getUserEventDispatcher().resetElapsedContainerMillis(); } }; - int animType = CIRCULAR_REVEAL; - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { - animType = PULLUP; - } // Only animate the search bar if animating from spring loaded mode back to all apps startAnimationToOverlay( - Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, animType, cb); + Workspace.State.NORMAL_HIDDEN, buttonView, toView, animated, PULLUP, cb); } /** @@ -193,12 +187,8 @@ public class LauncherStateTransitionAnimation { if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED || mAllAppsController.isTransitioning()) { - int animType = CIRCULAR_REVEAL; - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { - animType = PULLUP; - } startAnimationToWorkspaceFromAllApps(fromWorkspaceState, toWorkspaceState, - animated, animType, onCompleteRunnable); + animated, PULLUP, onCompleteRunnable); } else if (fromState == Launcher.State.WIDGETS || fromState == Launcher.State.WIDGETS_SPRING_LOADED) { startAnimationToWorkspaceFromWidgets(fromWorkspaceState, toWorkspaceState, @@ -235,8 +225,7 @@ public class LauncherStateTransitionAnimation { playCommonTransitionAnimations(toWorkspaceState, animated, initialized, animation, layerViews); if (!animated || !initialized) { - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && - toWorkspaceState == Workspace.State.NORMAL_HIDDEN) { + if (toWorkspaceState == Workspace.State.NORMAL_HIDDEN) { mAllAppsController.finishPullUp(); } toView.setTranslationX(0.0f); @@ -527,8 +516,7 @@ public class LauncherStateTransitionAnimation { playCommonTransitionAnimations(toWorkspaceState, animated, initialized, animation, layerViews); if (!animated || !initialized) { - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && - fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) { + if (fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) { mAllAppsController.finishPullDown(); } fromView.setVisibility(View.GONE); diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index 76772dce44..a105a73034 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -273,9 +273,8 @@ public class WorkspaceStateTransitionAnimation { float finalBackgroundAlpha = (states.stateIsSpringLoaded || states.stateIsOverview) ? 1.0f : 0f; float finalHotseatAlpha = (states.stateIsNormal || states.stateIsSpringLoaded || - (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && states.stateIsNormalHidden)) ? 1f : 0f; - float finalQsbAlpha = (states.stateIsNormal || - (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && states.stateIsNormalHidden)) ? 1f : 0f; + states.stateIsNormalHidden) ? 1f : 0f; + float finalQsbAlpha = (states.stateIsNormal || states.stateIsNormalHidden) ? 1f : 0f; float finalWorkspaceTranslationY = 0; if (states.stateIsOverview || states.stateIsOverviewHidden) { @@ -312,8 +311,7 @@ public class WorkspaceStateTransitionAnimation { if (states.stateIsOverviewHidden) { finalAlpha = 0f; } else if(states.stateIsNormalHidden) { - finalAlpha = (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && - i == mWorkspace.getNextPage()) ? 1 : 0; + finalAlpha = (i == mWorkspace.getNextPage()) ? 1 : 0; } else if (states.stateIsNormal && mWorkspaceFadeInAdjacentScreens) { finalAlpha = (i == toPage || i < customPageCount) ? 1f : 0f; } else { @@ -322,7 +320,7 @@ public class WorkspaceStateTransitionAnimation { // If we are animating to/from the small state, then hide the side pages and fade the // current page in - if (!FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && !mWorkspace.isSwitchingState()) { + if (!FeatureFlags.NO_ALL_APPS_ICON && !mWorkspace.isSwitchingState()) { if (states.workspaceToAllApps || states.allAppsToWorkspace) { boolean isCurrentPage = (i == toPage); if (states.allAppsToWorkspace && isCurrentPage) { diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 828a347df2..93f04e93b8 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -102,18 +102,14 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc @Override protected void updateBackground( int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { - if (mLauncher.getDeviceProfile().isVerticalBarLayout()) { - getRevealView().setBackground(new InsetDrawable(mBaseDrawable, - paddingLeft, paddingTop, paddingRight, paddingBottom)); - getContentView().setBackground( - new InsetDrawable(new ColorDrawable(Color.TRANSPARENT), - paddingLeft, paddingTop, paddingRight, paddingBottom)); - } else { - getRevealView().setBackground(mBaseDrawable); - } + if (mLauncher.getDeviceProfile().isVerticalBarLayout()) { + getRevealView().setBackground(new InsetDrawable(mBaseDrawable, + paddingLeft, paddingTop, paddingRight, paddingBottom)); + getContentView().setBackground( + new InsetDrawable(new ColorDrawable(Color.TRANSPARENT), + paddingLeft, paddingTop, paddingRight, paddingBottom)); } else { - super.updateBackground(paddingLeft, paddingTop, paddingRight, paddingBottom); + getRevealView().setBackground(mBaseDrawable); } } @@ -240,11 +236,9 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc mAppsRecyclerView.preMeasureViews(mAdapter); mAdapter.setIconFocusListener(focusedItemDecorator.getFocusListener()); - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { - getRevealView().setVisibility(View.VISIBLE); - getContentView().setVisibility(View.VISIBLE); - getContentView().setBackground(null); - } + getRevealView().setVisibility(View.VISIBLE); + getContentView().setVisibility(View.VISIBLE); + getContentView().setBackground(null); } public SearchUiManager getSearchUiManager() { @@ -262,32 +256,15 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc // Update the number of items in the grid before we measure the view grid.updateAppsViewNumCols(); - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { - if (mNumAppsPerRow != grid.inv.numColumns || - mNumPredictedAppsPerRow != grid.inv.numColumns) { - mNumAppsPerRow = grid.inv.numColumns; - mNumPredictedAppsPerRow = grid.inv.numColumns; - - mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow); - mAdapter.setNumAppsPerRow(mNumAppsPerRow); - mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - return; - } - - // --- remove START when {@code FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP} is enabled. --- - if (mNumAppsPerRow != grid.allAppsNumCols || - mNumPredictedAppsPerRow != grid.allAppsNumPredictiveCols) { - mNumAppsPerRow = grid.allAppsNumCols; - mNumPredictedAppsPerRow = grid.allAppsNumPredictiveCols; + if (mNumAppsPerRow != grid.inv.numColumns || + mNumPredictedAppsPerRow != grid.inv.numColumns) { + mNumAppsPerRow = grid.inv.numColumns; + mNumPredictedAppsPerRow = grid.inv.numColumns; mAppsRecyclerView.setNumAppsPerRow(grid, mNumAppsPerRow); mAdapter.setNumAppsPerRow(mNumAppsPerRow); mApps.setNumAppsPerRow(mNumAppsPerRow, mNumPredictedAppsPerRow); } - - // --- remove END when {@code FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP} is enabled. --- super.onMeasure(widthMeasureSpec, heightMeasureSpec); } diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java index 39e2088746..d504551712 100644 --- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java +++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java @@ -108,8 +108,7 @@ public class AppsSearchContainerLayout extends FrameLayout @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && - !mLauncher.getDeviceProfile().isVerticalBarLayout()) { + if (!mLauncher.getDeviceProfile().isVerticalBarLayout()) { getLayoutParams().height = mLauncher.getDragLayer().getInsets().top + mMinHeight; } super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 7964dd15d3..456562e2b5 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -34,7 +34,6 @@ abstract class BaseFlags { public static boolean LAUNCHER3_DISABLE_ICON_NORMALIZATION = false; public static boolean LAUNCHER3_LEGACY_FOLDER_ICON = false; public static boolean LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW = false; - public static boolean LAUNCHER3_ALL_APPS_PULL_UP = true; public static boolean LAUNCHER3_NEW_FOLDER_ANIMATION = true; // When enabled allows to use any point on the fast scrollbar to start dragging. public static final boolean LAUNCHER3_DIRECT_SCROLL = true; diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java index be5f01adbe..ee6a0e0b8c 100644 --- a/src/com/android/launcher3/dragndrop/DragLayer.java +++ b/src/com/android/launcher3/dragndrop/DragLayer.java @@ -243,7 +243,7 @@ public class DragLayer extends InsettableFrameLayout { return true; } - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && mAllAppsController.onControllerInterceptTouchEvent(ev)) { + if (mAllAppsController.onControllerInterceptTouchEvent(ev)) { mActiveController = mAllAppsController; return true; } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 7fb5d85212..1be33d2f86 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -103,7 +103,7 @@ public abstract class AbstractLauncherUiTest { */ protected UiObject2 openAllApps() { mDevice.waitForIdle(); - if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP) { + if (FeatureFlags.NO_ALL_APPS_ICON) { // clicking on the page indicator brings up all apps tray on non tablets. findViewById(R.id.page_indicator).click(); } else { From 78356a542e14ad6eefd5288506d1e53f601257f6 Mon Sep 17 00:00:00 2001 From: Mario Bertschler Date: Mon, 21 Aug 2017 15:12:57 -0700 Subject: [PATCH 38/38] Adjusting reflection api for color addOnColorsChangedListener that caused reflection to break. The new api method is available in both DR and MR1. Bug: 64908004 Bug: 64839046 Change-Id: I812c320e2c817aea8264de8764e33ad218b591c5 --- .../launcher3/compat/WallpaperManagerCompatVOMR1.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java index 6233fabb2b..fe5ff2a8c6 100644 --- a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java +++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java @@ -20,6 +20,7 @@ import android.app.WallpaperManager; import android.content.Context; import android.graphics.Color; import android.os.Build; +import android.os.Handler; import android.support.annotation.Nullable; import android.util.Log; @@ -48,8 +49,7 @@ public class WallpaperManagerCompatVOMR1 extends WallpaperManagerCompat { mOCLClass = Class.forName("android.app.WallpaperManager$OnColorsChangedListener"); mAddOCLMethod = WallpaperManager.class.getDeclaredMethod( - "addOnColorsChangedListener", mOCLClass); - + "addOnColorsChangedListener", mOCLClass, Handler.class); mWCGetMethod = WallpaperManager.class.getDeclaredMethod("getWallpaperColors", int.class); Class wallpaperColorsClass = mWCGetMethod.getReturnType(); mWCGetPrimaryColorMethod = wallpaperColorsClass.getDeclaredMethod("getPrimaryColor"); @@ -89,7 +89,7 @@ public class WallpaperManagerCompatVOMR1 extends WallpaperManagerCompat { } }); try { - mAddOCLMethod.invoke(mWm, onChangeListener); + mAddOCLMethod.invoke(mWm, onChangeListener, null); } catch (Exception e) { Log.e(TAG, "Error calling wallpaper API", e); }