From 1e58cd727013bcc294c22216fa70513c6263b37d Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 4 Dec 2018 14:03:32 -0800 Subject: [PATCH 01/15] Remove notification dot if app is disabled For instance, when turning off work profile, all work profile apps are disabled and notifications are removed. Previously, we weren't updating the dots in this case because we ignore unsupported ItemInfos (e.g. disabled items in this case). Note that this was only user-visible for Folders, because regular shortcuts were updated when the disabled state changes. Bug: 111791593 Change-Id: I3c49e6e3bf18753a868eb993b29c77abbefd3466 --- src/com/android/launcher3/Workspace.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 8a39b3b40f..c2f445b53a 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -3174,9 +3174,9 @@ public class Workspace extends PagedView mapOverItems(MAP_RECURSE, new ItemOperator() { @Override public boolean evaluate(ItemInfo info, View v) { - if (info instanceof ShortcutInfo && v instanceof BubbleTextView - && packageUserKey.updateFromItemInfo(info)) { - if (updatedDots.contains(packageUserKey)) { + if (info instanceof ShortcutInfo && v instanceof BubbleTextView) { + if (!packageUserKey.updateFromItemInfo(info) + || updatedDots.contains(packageUserKey)) { ((BubbleTextView) v).applyDotState(info, true /* animate */); folderIds.add(info.container); } From 415f17333123eb40e7677cf0766f59e7af3f7418 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 29 Nov 2018 10:33:47 -0800 Subject: [PATCH 02/15] Changing the format for device profile definition Device profiles are defined such that the grid size is fixed and only the icon and text sizes change. For every grid size option there are multiple display configurations. Bug: 118758696 Change-Id: I54aac9106c576324b02530913c447e849b4ae1da --- res/values-land/dimens.xml | 2 - res/values/attrs.xml | 18 +- res/values/dimens.xml | 2 +- res/xml/default_workspace_3x3.xml | 17 -- res/xml/default_workspace_4x4.xml | 44 ++- res/xml/default_workspace_5x5.xml | 53 +++- res/xml/default_workspace_5x6.xml | 37 --- res/xml/device_profiles.xml | 213 +++++-------- res/xml/dw_phone_hotseat.xml | 70 ----- res/xml/dw_tablet_hotseat.xml | 84 ------ src/com/android/launcher3/DeviceProfile.java | 9 +- .../launcher3/InvariantDeviceProfile.java | 283 +++++++++++------- src/com/android/launcher3/Utilities.java | 16 + .../model/GridSizeMigrationTask.java | 12 +- .../launcher3/provider/ImportDataTask.java | 16 +- 15 files changed, 397 insertions(+), 479 deletions(-) delete mode 100644 res/xml/default_workspace_5x6.xml delete mode 100644 res/xml/dw_phone_hotseat.xml delete mode 100644 res/xml/dw_tablet_hotseat.xml diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml index f0021956a1..b2f357565f 100644 --- a/res/values-land/dimens.xml +++ b/res/values-land/dimens.xml @@ -31,7 +31,5 @@ 5.5dp - - 0dp 16dp diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 29bd3c8879..8c4dd1efdc 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -93,10 +93,8 @@ - + - - @@ -106,13 +104,21 @@ + + + + + + + + + - - - + + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 8adae36187..078ce60a62 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -36,7 +36,7 @@ 2dp 0dp - 80dp + 34dp 0dp diff --git a/res/xml/default_workspace_3x3.xml b/res/xml/default_workspace_3x3.xml index 8d99404504..31376e1d5e 100644 --- a/res/xml/default_workspace_3x3.xml +++ b/res/xml/default_workspace_3x3.xml @@ -68,21 +68,4 @@ - - - - - - - - - - - diff --git a/res/xml/default_workspace_4x4.xml b/res/xml/default_workspace_4x4.xml index 979a1b4c84..bf3c62c77d 100644 --- a/res/xml/default_workspace_4x4.xml +++ b/res/xml/default_workspace_4x4.xml @@ -16,8 +16,48 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml index ef6e14506b..88b1bc95ae 100644 --- a/res/xml/device_profiles.xml +++ b/res/xml/device_profiles.xml @@ -17,158 +17,109 @@ - + launcher:defaultLayoutId="@xml/default_workspace_3x3" > - + - + + + + + launcher:numHotseatIcons="4" + launcher:defaultLayoutId="@xml/default_workspace_4x4" > - + - + - + - + - + + + + + launcher:defaultLayoutId="@xml/default_workspace_5x5" > - + - + - + \ No newline at end of file diff --git a/res/xml/dw_phone_hotseat.xml b/res/xml/dw_phone_hotseat.xml deleted file mode 100644 index c691ebc3da..0000000000 --- a/res/xml/dw_phone_hotseat.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/xml/dw_tablet_hotseat.xml b/res/xml/dw_tablet_hotseat.xml deleted file mode 100644 index 6fe7f93d82..0000000000 --- a/res/xml/dw_tablet_hotseat.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index c1c12046e8..812cf9f8e4 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -207,11 +207,10 @@ public class DeviceProfile { // Add a bit of space between nav bar and hotseat in multi-window vertical bar layout. hotseatBarSidePaddingStartPx = isMultiWindowMode && isVerticalBarLayout() ? edgeMarginPx : 0; - hotseatBarSizePx = isVerticalBarLayout() - ? Utilities.pxFromDp(inv.iconSize, dm) + hotseatBarSidePaddingStartPx - + hotseatBarSidePaddingEndPx - : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_size) - + hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx; + hotseatBarSizePx = Utilities.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout() + ? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx) + : (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size) + + hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx)); // Calculate all of the remaining variables. updateAvailableDimensions(dm, res); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 0b2f4d921e..257e46c2f4 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -24,6 +24,8 @@ import android.content.res.Configuration; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.Point; +import android.text.TextUtils; +import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.util.Xml; @@ -32,15 +34,12 @@ import android.view.WindowManager; import com.android.launcher3.util.ConfigMonitor; import com.android.launcher3.util.MainThreadInitializedObject; -import com.android.launcher3.util.Thunk; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import androidx.annotation.VisibleForTesting; @@ -50,6 +49,8 @@ public class InvariantDeviceProfile { public static final MainThreadInitializedObject INSTANCE = new MainThreadInitializedObject<>(InvariantDeviceProfile::new); + private static final String KEY_IDP_GRIP_NAME = "idp_grid_name"; + private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48; public static final int CHANGE_FLAG_GRID = 1 << 0; @@ -63,11 +64,6 @@ public class InvariantDeviceProfile { // used to offset float not being able to express extremely small weights in extreme cases. private static float WEIGHT_EFFICIENT = 100000f; - // Profile-defining invariant properties - private String name; - private float minWidthDps; - private float minHeightDps; - /** * Number of icons per row and column in the workspace. */ @@ -90,7 +86,7 @@ public class InvariantDeviceProfile { */ public int numHotseatIcons; - int defaultLayoutId; + public int defaultLayoutId; int demoModeLayoutId; public DeviceProfile landscapeProfile; @@ -105,37 +101,26 @@ public class InvariantDeviceProfile { public InvariantDeviceProfile() {} private InvariantDeviceProfile(InvariantDeviceProfile p) { - this(p.name, p.minWidthDps, p.minHeightDps, p.numRows, p.numColumns, - p.numFolderRows, p.numFolderColumns, - p.iconSize, p.landscapeIconSize, p.iconTextSize, p.numHotseatIcons, - p.defaultLayoutId, p.demoModeLayoutId); - } - - private InvariantDeviceProfile(String n, float w, float h, int r, int c, int fr, int fc, - float is, float lis, float its, int hs, int dlId, int dmlId) { - name = n; - minWidthDps = w; - minHeightDps = h; - numRows = r; - numColumns = c; - numFolderRows = fr; - numFolderColumns = fc; - iconSize = is; - landscapeIconSize = lis; - iconTextSize = its; - numHotseatIcons = hs; - defaultLayoutId = dlId; - demoModeLayoutId = dmlId; + numRows = p.numRows; + numColumns = p.numColumns; + numFolderRows = p.numFolderRows; + numFolderColumns = p.numFolderColumns; + iconSize = p.iconSize; + landscapeIconSize = p.landscapeIconSize; + iconTextSize = p.iconTextSize; + numHotseatIcons = p.numHotseatIcons; + defaultLayoutId = p.defaultLayoutId; + demoModeLayoutId = p.demoModeLayoutId; } @TargetApi(23) private InvariantDeviceProfile(Context context) { - initGrid(context); + initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRIP_NAME, null)); mConfigMonitor = new ConfigMonitor(context, APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess); } - private void initGrid(Context context) { + private void initGrid(Context context, String gridName) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); DisplayMetrics dm = new DisplayMetrics(); @@ -145,16 +130,18 @@ public class InvariantDeviceProfile { Point largestSize = new Point(); display.getCurrentSizeRange(smallestSize, largestSize); + ArrayList allOptions = getPredefinedDeviceProfiles(context, gridName); // This guarantees that width < height - minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm); - minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm); + float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), dm); + float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), dm); + // Sort the profiles based on the closeness to the device size + allOptions.sort((a, b) -> + Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps), + dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps))); + DisplayOption interpolatedDisplayOption = + invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions); - ArrayList closestProfiles = findClosestDeviceProfiles( - minWidthDps, minHeightDps, getPredefinedDeviceProfiles(context)); - InvariantDeviceProfile interpolatedDeviceProfileOut = - invDistWeightedInterpolate(minWidthDps, minHeightDps, closestProfiles); - - InvariantDeviceProfile closestProfile = closestProfiles.get(0); + GridOption closestProfile = allOptions.get(0).grid; numRows = closestProfile.numRows; numColumns = closestProfile.numColumns; numHotseatIcons = closestProfile.numHotseatIcons; @@ -162,11 +149,15 @@ public class InvariantDeviceProfile { demoModeLayoutId = closestProfile.demoModeLayoutId; numFolderRows = closestProfile.numFolderRows; numFolderColumns = closestProfile.numFolderColumns; + if (!closestProfile.name.equals(gridName)) { + Utilities.getPrefs(context).edit() + .putString(KEY_IDP_GRIP_NAME, closestProfile.name).apply(); + } - iconSize = interpolatedDeviceProfileOut.iconSize; - landscapeIconSize = interpolatedDeviceProfileOut.landscapeIconSize; + iconSize = interpolatedDisplayOption.iconSize; + landscapeIconSize = interpolatedDisplayOption.landscapeIconSize; iconBitmapSize = Utilities.pxFromDp(iconSize, dm); - iconTextSize = interpolatedDeviceProfileOut.iconTextSize; + iconTextSize = interpolatedDisplayOption.iconTextSize; fillResIconDpi = getLauncherIconDensity(iconBitmapSize); // If the partner customization apk contains any grid overrides, apply them @@ -210,7 +201,7 @@ public class InvariantDeviceProfile { InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this); // Re-init grid - initGrid(context); + initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRIP_NAME, null)); int changeFlags = 0; if (numRows != oldProfile.numRows || @@ -234,41 +225,53 @@ public class InvariantDeviceProfile { } } - ArrayList getPredefinedDeviceProfiles(Context context) { - ArrayList profiles = new ArrayList<>(); + static ArrayList getPredefinedDeviceProfiles(Context context, String gridName) { + ArrayList profiles = new ArrayList<>(); try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) { final int depth = parser.getDepth(); int type; while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { - if ((type == XmlPullParser.START_TAG) && "profile".equals(parser.getName())) { - TypedArray a = context.obtainStyledAttributes( - Xml.asAttributeSet(parser), R.styleable.InvariantDeviceProfile); - int numRows = a.getInt(R.styleable.InvariantDeviceProfile_numRows, 0); - int numColumns = a.getInt(R.styleable.InvariantDeviceProfile_numColumns, 0); - float iconSize = a.getFloat(R.styleable.InvariantDeviceProfile_iconSize, 0); - profiles.add(new InvariantDeviceProfile( - a.getString(R.styleable.InvariantDeviceProfile_name), - a.getFloat(R.styleable.InvariantDeviceProfile_minWidthDps, 0), - a.getFloat(R.styleable.InvariantDeviceProfile_minHeightDps, 0), - numRows, - numColumns, - a.getInt(R.styleable.InvariantDeviceProfile_numFolderRows, numRows), - a.getInt(R.styleable.InvariantDeviceProfile_numFolderColumns, numColumns), - iconSize, - a.getFloat(R.styleable.InvariantDeviceProfile_landscapeIconSize, iconSize), - a.getFloat(R.styleable.InvariantDeviceProfile_iconTextSize, 0), - a.getInt(R.styleable.InvariantDeviceProfile_numHotseatIcons, numColumns), - a.getResourceId(R.styleable.InvariantDeviceProfile_defaultLayoutId, 0), - a.getResourceId(R.styleable.InvariantDeviceProfile_demoModeLayoutId, 0))); - a.recycle(); + if ((type == XmlPullParser.START_TAG) && "grid-option".equals(parser.getName())) { + + GridOption gridOption = new GridOption(context, Xml.asAttributeSet(parser)); + final int displayDepth = parser.getDepth(); + while (((type = parser.next()) != XmlPullParser.END_TAG || + parser.getDepth() > displayDepth) + && type != XmlPullParser.END_DOCUMENT) { + if ((type == XmlPullParser.START_TAG) && "display-option".equals( + parser.getName())) { + profiles.add(new DisplayOption( + gridOption, context, Xml.asAttributeSet(parser))); + } + } } } } catch (IOException|XmlPullParserException e) { throw new RuntimeException(e); } - return profiles; + + ArrayList filteredProfiles = new ArrayList<>(); + if (!TextUtils.isEmpty(gridName)) { + for (DisplayOption option : profiles) { + if (gridName.equals(option.grid.name)) { + filteredProfiles.add(option); + } + } + } + if (filteredProfiles.isEmpty()) { + // No grid found, use the default options + for (DisplayOption option : profiles) { + if (option.canBeDefault) { + filteredProfiles.add(option); + } + } + } + if (filteredProfiles.isEmpty()) { + throw new RuntimeException("No display option with canBeDefault=true"); + } + return filteredProfiles; } private int getLauncherIconDensity(int requiredSize) { @@ -307,60 +310,40 @@ public class InvariantDeviceProfile { } } - @Thunk float dist(float x0, float y0, float x1, float y1) { + private static float dist(float x0, float y0, float x1, float y1) { return (float) Math.hypot(x1 - x0, y1 - y0); } /** * Returns the closest device profiles ordered by closeness to the specified width and height */ - // Package private visibility for testing. - ArrayList findClosestDeviceProfiles( - final float width, final float height, ArrayList points) { - - // Sort the profiles by their closeness to the dimensions - ArrayList pointsByNearness = points; - Collections.sort(pointsByNearness, new Comparator() { - public int compare(InvariantDeviceProfile a, InvariantDeviceProfile b) { - return Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps), - dist(width, height, b.minWidthDps, b.minHeightDps)); - } - }); - - return pointsByNearness; + @VisibleForTesting + static ArrayList sortByClosenessToSize( + float width, float height, ArrayList points) { + points.sort((a, b) -> + Float.compare(dist(width, height, a.minWidthDps, a.minHeightDps), + dist(width, height, b.minWidthDps, b.minHeightDps))); + return points; } - // Package private visibility for testing. - InvariantDeviceProfile invDistWeightedInterpolate(float width, float height, - ArrayList points) { + @VisibleForTesting + static DisplayOption invDistWeightedInterpolate(float width, float height, + ArrayList points) { float weights = 0; - InvariantDeviceProfile p = points.get(0); + DisplayOption p = points.get(0); if (dist(width, height, p.minWidthDps, p.minHeightDps) == 0) { return p; } - InvariantDeviceProfile out = new InvariantDeviceProfile(); + DisplayOption out = new DisplayOption(); for (int i = 0; i < points.size() && i < KNEARESTNEIGHBOR; ++i) { - p = new InvariantDeviceProfile(points.get(i)); + p = points.get(i); float w = weight(width, height, p.minWidthDps, p.minHeightDps, WEIGHT_POWER); weights += w; - out.add(p.multiply(w)); + out.add(new DisplayOption().add(p).multiply(w)); } - return out.multiply(1.0f/weights); - } - - private void add(InvariantDeviceProfile p) { - iconSize += p.iconSize; - landscapeIconSize += p.landscapeIconSize; - iconTextSize += p.iconTextSize; - } - - private InvariantDeviceProfile multiply(float w) { - iconSize *= w; - landscapeIconSize *= w; - iconTextSize *= w; - return this; + return out.multiply(1.0f / weights); } public DeviceProfile getDeviceProfile(Context context) { @@ -368,7 +351,7 @@ public class InvariantDeviceProfile { == Configuration.ORIENTATION_LANDSCAPE ? landscapeProfile : portraitProfile; } - private float weight(float x0, float y0, float x1, float y1, float pow) { + private static float weight(float x0, float y0, float x1, float y1, float pow) { float d = dist(x0, y0, x1, y1); if (Float.compare(d, 0f) == 0) { return Float.POSITIVE_INFINITY; @@ -409,4 +392,94 @@ public class InvariantDeviceProfile { void onIdpChanged(int changeFlags, InvariantDeviceProfile profile); } + + + private static final class GridOption { + + private final String name; + private final int numRows; + private final int numColumns; + + private final int numFolderRows; + private final int numFolderColumns; + + private final int numHotseatIcons; + + private final int defaultLayoutId; + private final int demoModeLayoutId; + + GridOption(Context context, AttributeSet attrs) { + TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.GridDisplayOption); + name = a.getString(R.styleable.GridDisplayOption_name); + numRows = a.getInt(R.styleable.GridDisplayOption_numRows, 0); + numColumns = a.getInt(R.styleable.GridDisplayOption_numColumns, 0); + + defaultLayoutId = a.getResourceId( + R.styleable.GridDisplayOption_defaultLayoutId, 0); + demoModeLayoutId = a.getResourceId( + R.styleable.GridDisplayOption_demoModeLayoutId, defaultLayoutId); + numHotseatIcons = a.getInt( + R.styleable.GridDisplayOption_numHotseatIcons, numColumns); + numFolderRows = a.getInt( + R.styleable.GridDisplayOption_numFolderRows, numRows); + numFolderColumns = a.getInt( + R.styleable.GridDisplayOption_numFolderColumns, numColumns); + a.recycle(); + } + } + + private static final class DisplayOption { + private final GridOption grid; + + private final String name; + private final float minWidthDps; + private final float minHeightDps; + private final boolean canBeDefault; + + private float iconSize; + private float landscapeIconSize; + private float iconTextSize; + + DisplayOption(GridOption grid, Context context, AttributeSet attrs) { + this.grid = grid; + + TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.ProfileDisplayOption); + + name = a.getString(R.styleable.ProfileDisplayOption_name); + minWidthDps = a.getFloat(R.styleable.ProfileDisplayOption_minWidthDps, 0); + minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0); + canBeDefault = a.getBoolean( + R.styleable.ProfileDisplayOption_canBeDefault, false); + + iconSize = a.getFloat(R.styleable.ProfileDisplayOption_iconSize, 0); + landscapeIconSize = a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize, + iconSize); + iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0); + a.recycle(); + } + + DisplayOption() { + grid = null; + name = null; + minWidthDps = 0; + minHeightDps = 0; + canBeDefault = false; + } + + private DisplayOption multiply(float w) { + iconSize *= w; + landscapeIconSize *= w; + iconTextSize *= w; + return this; + } + + private DisplayOption add(DisplayOption p) { + iconSize += p.iconSize; + landscapeIconSize += p.landscapeIconSize; + iconTextSize += p.iconTextSize; + return this; + } + } } \ No newline at end of file diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 65f0703278..a0f005c432 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -31,6 +31,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; @@ -587,6 +588,21 @@ public final class Utilities { handler.sendMessage(msg); } + /** + * Parses a string encoded using {@link #getPointString(int, int)} + */ + public static Point parsePoint(String point) { + String[] split = point.split(","); + return new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + } + + /** + * Encodes a point to string to that it can be persisted atomically. + */ + public static String getPointString(int x, int y) { + return String.format(Locale.ENGLISH, "%d,%d", x, y); + } + public interface Consumer { void accept(T var1); } diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java index 2c1aa745f0..289de1a4b1 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationTask.java +++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java @@ -1,5 +1,8 @@ package com.android.launcher3.model; +import static com.android.launcher3.Utilities.getPointString; +import static com.android.launcher3.Utilities.parsePoint; + import android.content.ComponentName; import android.content.ContentProviderOperation; import android.content.ContentValues; @@ -877,15 +880,6 @@ public class GridSizeMigrationTask { return dup; } - private static Point parsePoint(String point) { - String[] split = point.split(","); - return new Point(Integer.parseInt(split[0]), Integer.parseInt(split[1])); - } - - private static String getPointString(int x, int y) { - return String.format(Locale.ENGLISH, "%d,%d", x, y); - } - public static void markForMigration( Context context, int gridX, int gridY, int hotseatSize) { Utilities.getPrefs(context).edit() diff --git a/src/com/android/launcher3/provider/ImportDataTask.java b/src/com/android/launcher3/provider/ImportDataTask.java index e1b26980c1..b389b145d2 100644 --- a/src/com/android/launcher3/provider/ImportDataTask.java +++ b/src/com/android/launcher3/provider/ImportDataTask.java @@ -44,7 +44,6 @@ import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.Settings; import com.android.launcher3.LauncherSettings.WorkspaceScreens; -import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; import com.android.launcher3.compat.UserManagerCompat; @@ -378,18 +377,13 @@ public class ImportDataTask { return false; } - private static int getMyHotseatLayoutId(Context context) { - return LauncherAppState.getIDP(context).numHotseatIcons <= 5 - ? R.xml.dw_phone_hotseat - : R.xml.dw_tablet_hotseat; - } - /** * Extension of {@link DefaultLayoutParser} which only allows icons and shortcuts. */ private static class HotseatLayoutParser extends DefaultLayoutParser { public HotseatLayoutParser(Context context, LayoutParserCallback callback) { - super(context, null, callback, context.getResources(), getMyHotseatLayoutId(context)); + super(context, null, callback, context.getResources(), + LauncherAppState.getIDP(context).defaultLayoutId); } @Override @@ -434,6 +428,12 @@ public class ImportDataTask { // No need to add more items. return 0; } + if (!Integer.valueOf(Favorites.CONTAINER_HOTSEAT) + .equals(values.getAsInteger(Favorites.CONTAINER))) { + // Ignore items which are not for hotseat. + return 0; + } + Intent intent; try { intent = Intent.parseUri(values.getAsString(Favorites.INTENT), 0); From ed01e28408fd3b6080c35ace35a26d4046be7ec3 Mon Sep 17 00:00:00 2001 From: Vadim Tryshev Date: Thu, 6 Dec 2018 13:21:16 -0800 Subject: [PATCH 03/15] Moving TaplTests to AOSP And fixing TAPL for AOSP. Bug: 110103162 Test: TaplTests Change-Id: Ib9fef02b789a9c7444643550d56b9dda4e085b03 --- .../src/com/android/quickstep/TaplTests.java | 482 ++++++++++++++++++ .../com/android/launcher3/tapl/Workspace.java | 32 +- 2 files changed, 492 insertions(+), 22 deletions(-) create mode 100644 quickstep/tests/src/com/android/quickstep/TaplTests.java diff --git a/quickstep/tests/src/com/android/quickstep/TaplTests.java b/quickstep/tests/src/com/android/quickstep/TaplTests.java new file mode 100644 index 0000000000..701229c98c --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/TaplTests.java @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep; + +import static androidx.test.InstrumentationRegistry.getInstrumentation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.app.Instrumentation; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.RemoteException; +import android.util.Log; + +import androidx.test.filters.LargeTest; +import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.Until; + +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.tapl.AllApps; +import com.android.launcher3.tapl.AllAppsFromOverview; +import com.android.launcher3.tapl.AppIcon; +import com.android.launcher3.tapl.Background; +import com.android.launcher3.tapl.Overview; +import com.android.launcher3.tapl.OverviewTask; +import com.android.launcher3.tapl.TestHelpers; +import com.android.launcher3.tapl.Widgets; +import com.android.launcher3.tapl.Workspace; +import com.android.launcher3.views.OptionsPopupView; +import com.android.launcher3.widget.WidgetsFullSheet; +import com.android.launcher3.widget.WidgetsRecyclerView; +import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff; +import com.android.quickstep.views.RecentsView; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestWatcher; +import org.junit.runner.Description; +import org.junit.runner.RunWith; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class TaplTests extends AbstractQuickStepTest { + private static final int WAIT_TIME_MS = 60000; + private static final String TAG = "TaplTests"; + + private static int sScreenshotCount = 0; + + @Rule + public TestWatcher mFailureWatcher = new TestWatcher() { + private void dumpViewHierarchy() { + final ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try { + mDevice.dumpWindowHierarchy(stream); + stream.flush(); + stream.close(); + for (String line : stream.toString().split("\\r?\\n")) { + Log.e(TaplTests.TAG, line.trim()); + } + } catch (IOException e) { + Log.e(TaplTests.TAG, "error dumping XML to logcat", e); + } + } + + @Override + protected void failed(Throwable e, Description description) { + if (mDevice == null) return; + final String pathname = getInstrumentation().getTargetContext(). + getFilesDir().getPath() + "/TaplTestScreenshot" + sScreenshotCount++ + ".png"; + Log.e(TaplTests.TAG, "Failed test " + description.getMethodName() + + ", screenshot will be saved to " + pathname + + ", track trace is below, UI object dump is further below:\n" + + Log.getStackTraceString(e)); + dumpViewHierarchy(); + mDevice.takeScreenshot(new File(pathname)); + } + }; + + @Before + public void setUp() throws Exception { + super.setUp(); + + clearLauncherData(); + + mDevice.pressHome(); + waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL); + waitForResumed("Launcher internal state is still Background"); + } + + private String resolveSystemApp(String category) { + return getInstrumentation().getContext().getPackageManager().resolveActivity( + new Intent(Intent.ACTION_MAIN).addCategory(category), + PackageManager.MATCH_SYSTEM_ONLY). + activityInfo.packageName; + } + + private boolean isInState(LauncherState state) { + if (!TestHelpers.isInLauncherProcess()) return true; + return getFromLauncher(launcher -> launcher.getStateManager().getState() == state); + } + + // Please don't add negative test cases for methods that fail only after a long wait. + private void expectFail(String message, Runnable action) { + boolean failed = false; + try { + action.run(); + } catch (AssertionError e) { + failed = true; + } + assertTrue(message, failed); + } + + private boolean isWorkspaceScrollable(Launcher launcher) { + return launcher.getWorkspace().getPageCount() > 1; + } + + private boolean isInBackground(Launcher launcher) { + return !launcher.hasBeenResumed(); + } + + private void startAppFast(String packageName) { + final Instrumentation instrumentation = getInstrumentation(); + final Intent intent = instrumentation.getContext().getPackageManager(). + getLaunchIntentForPackage(packageName); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + instrumentation.getTargetContext().startActivity(intent); + assertTrue(packageName + " didn't start", + mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), WAIT_TIME_MS)); + } + + private void startTestApps() throws Exception { + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_MESSAGING)); + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CONTACTS)); + + executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + isInBackground(launcher))); + } + + private int getCurrentWorkspacePage(Launcher launcher) { + return launcher.getWorkspace().getCurrentPage(); + } + + private WidgetsRecyclerView getWidgetsView(Launcher launcher) { + return WidgetsFullSheet.getWidgetsView(launcher); + } + + @Test + public void testDevicePressMenu() throws Exception { + mDevice.pressMenu(); + mDevice.waitForIdle(); + executeOnLauncher( + launcher -> assertTrue("Launcher internal state didn't switch to Showing Menu", + OptionsPopupView.getOptionsPopup(launcher) != null)); + } + + @Test + @PortraitLandscape + public void testPressRecentAppsLauncherAndGetOverview() throws RemoteException { + mDevice.pressRecentApps(); + waitForState("Launcher internal state didn't switch to Overview", LauncherState.OVERVIEW); + + assertNotNull("getOverview() returned null", mLauncher.getOverview()); + } + + private void runAllAppsTest(AllApps allApps) throws Exception { + assertNotNull("allApps parameter is null", allApps); + + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + + // Test flinging forward and backward. + executeOnLauncher(launcher -> assertEquals("All Apps started in already scrolled state", 0, + getAllAppsScroll(launcher))); + + allApps.flingForward(); + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + final Integer flingForwardY = getFromLauncher(launcher -> getAllAppsScroll(launcher)); + executeOnLauncher( + launcher -> assertTrue("flingForward() didn't scroll App Apps", flingForwardY > 0)); + + allApps.flingBackward(); + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + final Integer flingBackwardY = getFromLauncher(launcher -> getAllAppsScroll(launcher)); + executeOnLauncher(launcher -> assertTrue("flingBackward() didn't scroll App Apps", + flingBackwardY < flingForwardY)); + + // Test scrolling down to YouTube. + assertNotNull("All apps: can't fine YouTube", allApps.getAppIcon("YouTube")); + // Test scrolling up to Camera. + assertNotNull("All apps: can't fine Camera", allApps.getAppIcon("Camera")); + // Test failing to find a non-existing app. + final AllApps allAppsFinal = allApps; + expectFail("All apps: could find a non-existing app", + () -> allAppsFinal.getAppIcon("NO APP")); + + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + } + + private int getAllAppsScroll(Launcher launcher) { + return launcher.getAppsView().getActiveRecyclerView().getCurrentScrollY(); + } + + @Test + @PortraitLandscape + public void testAllAppsFromHome() throws Exception { + // Test opening all apps + assertNotNull("switchToAllApps() returned null", + mLauncher.getWorkspace().switchToAllApps()); + + runAllAppsTest(mLauncher.getAllApps()); + + // Testing pressHome. + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + assertNotNull("pressHome returned null", mLauncher.pressHome()); + assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); + assertNotNull("getHome returned null", mLauncher.getWorkspace()); + } + + @Test + @QuickstepOnOff + @PortraitLandscape + public void testWorkspaceSwitchToAllApps() { + assertNotNull("switchToAllApps() returned null", + mLauncher.getWorkspace().switchToAllApps()); + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + } + + @Test + public void testAllAppsFromOverview() throws Exception { + // Test opening all apps from Overview. + assertNotNull("switchToAllApps() returned null", + mLauncher.getWorkspace().switchToOverview().switchToAllApps()); + + runAllAppsTest(mLauncher.getAllAppsFromOverview()); + } + + @Test + public void testWorkspace() throws Exception { + final Workspace workspace = mLauncher.getWorkspace(); + + // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there. + executeOnLauncher(launcher -> assertFalse("Initial workspace state is scrollable", + isWorkspaceScrollable(launcher))); + assertNull("Messages app was found on empty workspace", + workspace.tryGetWorkspaceAppIcon("Messages")); + + workspace.ensureWorkspaceIsScrollable(); + + executeOnLauncher( + launcher -> assertEquals("Ensuring workspace scrollable didn't switch to page #1", + 1, getCurrentWorkspacePage(launcher))); + executeOnLauncher( + launcher -> assertTrue("ensureScrollable didn't make workspace scrollable", + isWorkspaceScrollable(launcher))); + assertNotNull("ensureScrollable didn't add Messages app", + workspace.tryGetWorkspaceAppIcon("Messages")); + + // Test flinging workspace. + workspace.flingBackward(); + assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); + executeOnLauncher( + launcher -> assertEquals("Flinging back didn't switch workspace to page #0", + 0, getCurrentWorkspacePage(launcher))); + + workspace.flingForward(); + executeOnLauncher( + launcher -> assertEquals("Flinging forward didn't switch workspace to page #1", + 1, getCurrentWorkspacePage(launcher))); + assertTrue("Launcher internal state is not Home", isInState(LauncherState.NORMAL)); + + // Test starting a workspace app. + final AppIcon app = workspace.tryGetWorkspaceAppIcon("Messages"); + assertNotNull("No Messages app in workspace", app); + assertNotNull("AppIcon.launch returned null", + app.launch(resolveSystemApp(Intent.CATEGORY_APP_MESSAGING))); + executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + isInBackground(launcher))); + } + + @Test + @PortraitLandscape + public void testOverview() throws Exception { + startTestApps(); + Overview overview = mLauncher.pressHome().switchToOverview(); + assertTrue("Launcher internal state didn't switch to Overview", + isInState(LauncherState.OVERVIEW)); + executeOnLauncher( + launcher -> assertTrue("Don't have at least 3 tasks", getTaskCount(launcher) >= 3)); + + // Test flinging forward and backward. + executeOnLauncher(launcher -> assertEquals("Current task in Overview is not 0", + 0, getCurrentOverviewPage(launcher))); + + overview.flingForward(); + assertTrue("Launcher internal state is not Overview", isInState(LauncherState.OVERVIEW)); + final Integer currentTaskAfterFlingForward = getFromLauncher( + launcher -> getCurrentOverviewPage(launcher)); + executeOnLauncher(launcher -> assertTrue("Current task in Overview is still 0", + currentTaskAfterFlingForward > 0)); + + overview.flingBackward(); + assertTrue("Launcher internal state is not Overview", isInState(LauncherState.OVERVIEW)); + executeOnLauncher(launcher -> assertTrue("Flinging back in Overview did nothing", + getCurrentOverviewPage(launcher) < currentTaskAfterFlingForward)); + + // Test opening a task. + OverviewTask task = mLauncher.pressHome().switchToOverview().getCurrentTask(); + assertNotNull("overview.getCurrentTask() returned null (1)", task); + assertNotNull("OverviewTask.open returned null", task.open()); + assertTrue("Contacts app didn't open from Overview", mDevice.wait(Until.hasObject( + By.pkg(resolveSystemApp(Intent.CATEGORY_APP_CONTACTS)).depth(0)), WAIT_TIME_MS)); + executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + isInBackground(launcher))); + + // Test dismissing a task. + overview = mLauncher.pressHome().switchToOverview(); + assertTrue("Launcher internal state didn't switch to Overview", + isInState(LauncherState.OVERVIEW)); + final Integer numTasks = getFromLauncher(launcher -> getTaskCount(launcher)); + task = overview.getCurrentTask(); + assertNotNull("overview.getCurrentTask() returned null (2)", task); + task.dismiss(); + executeOnLauncher( + launcher -> assertEquals("Dismissing a task didn't remove 1 task from Overview", + numTasks - 1, getTaskCount(launcher))); + + if (!TestHelpers.isInLauncherProcess() || + getFromLauncher(launcher -> !launcher.getDeviceProfile().isLandscape)) { + // Test switching to all apps and back. + final AllAppsFromOverview allApps = overview.switchToAllApps(); + assertNotNull("overview.switchToAllApps() returned null (1)", allApps); + assertTrue("Launcher internal state is not All Apps (1)", + isInState(LauncherState.ALL_APPS)); + + overview = allApps.switchBackToOverview(); + assertNotNull("allApps.switchBackToOverview() returned null", overview); + assertTrue("Launcher internal state didn't switch to Overview", + isInState(LauncherState.OVERVIEW)); + + // Test UIDevice.pressBack() + overview.switchToAllApps(); + assertNotNull("overview.switchToAllApps() returned null (2)", allApps); + assertTrue("Launcher internal state is not All Apps (2)", + isInState(LauncherState.ALL_APPS)); + mDevice.pressBack(); + mLauncher.getOverview(); + } + + // Test UIDevice.pressHome, once we are in AllApps. + mDevice.pressHome(); + waitForState("Launcher internal state didn't switch to Home", LauncherState.NORMAL); + } + + private int getCurrentOverviewPage(Launcher launcher) { + return launcher.getOverviewPanel().getCurrentPage(); + } + + private int getTaskCount(Launcher launcher) { + return launcher.getOverviewPanel().getTaskViewCount(); + } + + private void runIconLaunchFromAllAppsTest(AllApps allApps) throws Exception { + final AppIcon app = allApps.getAppIcon("Calculator"); + assertNotNull("AppIcon.launch returned null", app.launch( + resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR))); + executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + isInBackground(launcher))); + } + + @Test + @PortraitLandscape + public void testAppIconLaunchFromAllAppsFromHome() throws Exception { + final AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + + runIconLaunchFromAllAppsTest(allApps); + } + + @Test + public void testAppIconLaunchFromAllAppsFromOverview() throws Exception { + final AllApps allApps = + mLauncher.getWorkspace().switchToOverview().switchToAllApps(); + assertTrue("Launcher internal state is not All Apps", isInState(LauncherState.ALL_APPS)); + + runIconLaunchFromAllAppsTest(allApps); + } + + @Test + @PortraitLandscape + public void testWidgets() throws Exception { + // Test opening widgets. + executeOnLauncher(launcher -> + assertTrue("Widgets is initially opened", getWidgetsView(launcher) == null)); + Widgets widgets = mLauncher.getWorkspace().openAllWidgets(); + assertNotNull("openAllWidgets() returned null", widgets); + widgets = mLauncher.getAllWidgets(); + assertNotNull("getAllWidgets() returned null", widgets); + executeOnLauncher(launcher -> + assertTrue("Widgets is not shown", getWidgetsView(launcher).isShown())); + executeOnLauncher(launcher -> assertEquals("Widgets is scrolled upon opening", + 0, getWidgetsScroll(launcher))); + + // Test flinging widgets. + widgets.flingForward(); + Integer flingForwardY = getFromLauncher(launcher -> getWidgetsScroll(launcher)); + executeOnLauncher(launcher -> assertTrue("Flinging forward didn't scroll widgets", + flingForwardY > 0)); + + widgets.flingBackward(); + executeOnLauncher(launcher -> assertTrue("Flinging backward didn't scroll widgets", + getWidgetsScroll(launcher) < flingForwardY)); + + mDevice.pressHome(); + waitForLauncherCondition("Widgets were not closed", + launcher -> getWidgetsView(launcher) == null); + } + + private int getWidgetsScroll(Launcher launcher) { + return getWidgetsView(launcher).getCurrentScrollY(); + } + + @Test + @QuickstepOnOff + @PortraitLandscape + public void testSwitchToOverview() throws Exception { + assertNotNull("Workspace.switchToOverview() returned null", + mLauncher.pressHome().switchToOverview()); + assertTrue("Launcher internal state didn't switch to Overview", + isInState(LauncherState.OVERVIEW)); + } + + @Test + @QuickstepOnOff + @PortraitLandscape + public void testBackground() throws Exception { + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); + final Background background = mLauncher.getBackground(); + assertNotNull("Launcher.getBackground() returned null", background); + executeOnLauncher(launcher -> assertTrue( + "Launcher activity is the top activity; expecting another activity to be the top " + + "one", + isInBackground(launcher))); + + assertNotNull("Background.switchToOverview() returned null", background.switchToOverview()); + assertTrue("Launcher internal state didn't switch to Overview", + isInState(LauncherState.OVERVIEW)); + } +} diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java index c63822e2ea..c45f0f0d81 100644 --- a/tests/tapl/com/android/launcher3/tapl/Workspace.java +++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java @@ -46,28 +46,16 @@ public final class Workspace extends Home { @NonNull public AllApps switchToAllApps() { verifyActiveContainer(); - if (mLauncher.isSwipeUpEnabled()) { - int midX = mLauncher.getDevice().getDisplayWidth() / 2; - int height = mLauncher.getDevice().getDisplayHeight(); - // Swipe from 6/7ths down the screen to 1/7th down the screen. - mLauncher.swipe( - midX, - height * 6 / 7, - midX, - height / 7 - ); - } else { - // Swipe from the hotseat to near the top, e.g. 10% of the screen. - final UiObject2 hotseat = mHotseat; - final Point start = hotseat.getVisibleCenter(); - final int endY = (int) (mLauncher.getDevice().getDisplayHeight() * 0.1f); - mLauncher.swipe( - start.x, - start.y, - start.x, - endY - ); - } + // Swipe from the hotseat to near the top, e.g. 10% of the screen. + final UiObject2 hotseat = mHotseat; + final Point start = hotseat.getVisibleCenter(); + final int endY = (int) (mLauncher.getDevice().getDisplayHeight() * 0.1f); + mLauncher.swipe( + start.x, + start.y, + start.x, + endY + ); return new AllApps(mLauncher); } From c5939393a92e3a07fbd6e17527b8b2a1d108f1d7 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 7 Dec 2018 11:43:47 -0800 Subject: [PATCH 04/15] Bye bye workspace screens table Removing a separate table for workspace screens. List of screens are automatically parsed using the items in the favorites DB. Order of the screen based on the screen id and rearranging screens is no longer supported. In case the screens need to be rearranged, all the items in the favorites db will need to be updated with new screen ids. This makes backing up the DB (in the same database) easier as only one table needs to be duplicates. Change-Id: I8ba947a898f637d780e2f49925e78604263126e8 --- res/raw/downgrade_schema.json | 6 +- .../resources}/db_schema_v10.json | 0 .../model/AddWorkspaceItemsTaskTest.java | 48 ++- .../model/DbDowngradeHelperTest.java | 45 ++- .../model/GridSizeMigrationTaskTest.java | 12 +- src/com/android/launcher3/Launcher.java | 1 - src/com/android/launcher3/LauncherModel.java | 67 +---- .../android/launcher3/LauncherProvider.java | 280 +++++------------- .../android/launcher3/LauncherSettings.java | 37 +-- .../launcher3/SecondaryDropTarget.java | 2 +- src/com/android/launcher3/ShortcutInfo.java | 17 +- src/com/android/launcher3/Workspace.java | 13 - .../model/AddWorkspaceItemsTask.java | 16 +- .../launcher3/model/DbDowngradeHelper.java | 6 +- .../model/GridSizeMigrationTask.java | 38 +-- .../android/launcher3/model/LoaderCursor.java | 11 +- .../android/launcher3/model/LoaderTask.java | 20 +- .../android/launcher3/model/ModelWriter.java | 2 +- .../launcher3/provider/ImportDataTask.java | 62 ++-- .../launcher3/provider/LauncherDbUtils.java | 63 ++-- src/com/android/launcher3/util/IntSet.java | 11 + .../launcher3/model/LoaderCursorTest.java | 52 +--- .../launcher3/ui/widget/BindWidgetTest.java | 4 - 23 files changed, 247 insertions(+), 566 deletions(-) rename {tests/res/raw => robolectric_tests/resources}/db_schema_v10.json (100%) rename {tests => robolectric_tests}/src/com/android/launcher3/model/DbDowngradeHelperTest.java (81%) diff --git a/res/raw/downgrade_schema.json b/res/raw/downgrade_schema.json index 3c1b64f92a..8f1780e5f7 100644 --- a/res/raw/downgrade_schema.json +++ b/res/raw/downgrade_schema.json @@ -2,8 +2,12 @@ // Note: Comments are not supported in JSON schema, but android parser is lenient. // Maximum DB version supported by this schema - "version" : 27, + "version" : 28, + "downgrade_to_27" : [ + "CREATE TABLE workspaceScreens (_id INTEGER PRIMARY KEY,screenRank INTEGER,modified INTEGER NOT NULL DEFAULT 0)", + "insert into workspaceScreens (_id, screenRank) select screen as _id, screen as screenRank from favorites where container = -100 group by screen order by screen" + ], // Downgrade from 27 to 26. Empty array indicates, the DB is compatible "downgrade_to_26" : [], "downgrade_to_25" : [], diff --git a/tests/res/raw/db_schema_v10.json b/robolectric_tests/resources/db_schema_v10.json similarity index 100% rename from tests/res/raw/db_schema_v10.json rename to robolectric_tests/resources/db_schema_v10.json diff --git a/robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java index fd31033db0..4f49817bf0 100644 --- a/robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java +++ b/robolectric_tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java @@ -18,7 +18,9 @@ import android.util.Pair; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherProvider; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.ShortcutInfo; +import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSparseArrayMap; @@ -31,6 +33,8 @@ import org.robolectric.RobolectricTestRunner; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Tests for {@link AddWorkspaceItemsTask} @@ -60,15 +64,11 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { for (ItemInfo item : items) { list.add(Pair.create(item, null)); } - return new AddWorkspaceItemsTask(list) { - - @Override - protected void updateScreens(Context context, IntArray workspaceScreens) { } - }; + return new AddWorkspaceItemsTask(list); } @Test - public void testFindSpaceForItem_prefers_second() { + public void testFindSpaceForItem_prefers_second() throws Exception { // First screen has only one hole of size 1 int nextId = setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3)); @@ -93,7 +93,6 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { public void testFindSpaceForItem_adds_new_screen() throws Exception { // First screen has 2 holes of sizes 3x2 and 2x3 setupWorkspaceWithHoles(1, 1, new Rect(2, 0, 5, 2), new Rect(0, 2, 2, 5)); - commitScreensToDb(); IntArray oldScreens = existingScreens.clone(); int[] spaceFound = newTask() @@ -109,7 +108,6 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { // Setup a screen with a hole setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3)); - commitScreensToDb(); // Nothing was added assertTrue(executeTaskForTest(newTask(info)).isEmpty()); @@ -125,7 +123,6 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { // Setup a screen with a hole setupWorkspaceWithHoles(1, 1, new Rect(2, 2, 3, 3)); - commitScreensToDb(); executeTaskForTest(newTask(info, info2)).get(0).run(); ArgumentCaptor notAnimated = ArgumentCaptor.forClass(ArrayList.class); @@ -141,7 +138,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { assertTrue(animated.getValue().contains(info2)); } - private int setupWorkspaceWithHoles(int startId, int screenId, Rect... holes) { + private int setupWorkspaceWithHoles(int startId, int screenId, Rect... holes) throws Exception { GridOccupancy occupancy = new GridOccupancy(idp.numColumns, idp.numRows); occupancy.markCells(0, 0, idp.numColumns, idp.numRows, true); for (Rect r : holes) { @@ -151,6 +148,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { existingScreens.add(screenId); screenOccupancy.append(screenId, occupancy); + ExecutorService executor = Executors.newSingleThreadExecutor(); for (int x = 0; x < idp.numColumns; x++) { for (int y = 0; y < idp.numRows; y++) { if (!occupancy.cells[x][y]) { @@ -165,27 +163,19 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase { info.cellY = y; info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP; bgDataModel.addItem(targetContext, info, false); + + executor.execute(() -> { + ContentWriter writer = new ContentWriter(targetContext); + info.writeToValues(writer); + writer.put(Favorites._ID, info.id); + targetContext.getContentResolver().insert(Favorites.CONTENT_URI, + writer.getValues(targetContext)); + }); } } + + executor.submit(() -> null).get(); + executor.shutdown(); return startId; } - - private void commitScreensToDb() throws Exception { - LauncherSettings.Settings.call(targetContext.getContentResolver(), - LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB); - - Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI; - ArrayList ops = new ArrayList<>(); - // Clear the table - ops.add(ContentProviderOperation.newDelete(uri).build()); - int count = existingScreens.size(); - for (int i = 0; i < count; i++) { - ContentValues v = new ContentValues(); - int screenId = existingScreens.get(i); - v.put(LauncherSettings.WorkspaceScreens._ID, screenId); - v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build()); - } - targetContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, ops); - } } diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java similarity index 81% rename from tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java rename to robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java index 0903ddc16d..a46617ec28 100644 --- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java +++ b/robolectric_tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java @@ -20,14 +20,17 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertTrue; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + import android.content.ContentValues; import android.content.Context; +import android.content.res.Resources; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import com.android.launcher3.LauncherProvider; import com.android.launcher3.LauncherProvider.DatabaseHelper; @@ -37,14 +40,15 @@ import com.android.launcher3.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; import java.io.File; /** * Tests for {@link DbDowngradeHelper} */ -@SmallTest -@RunWith(AndroidJUnit4.class) +@RunWith(RobolectricTestRunner.class) public class DbDowngradeHelperTest { private static final String SCHEMA_FILE = "test_schema.json"; @@ -56,35 +60,47 @@ public class DbDowngradeHelperTest { @Before public void setup() { - mContext = InstrumentationRegistry.getTargetContext(); + mContext = RuntimeEnvironment.application; mSchemaFile = mContext.getFileStreamPath(SCHEMA_FILE); mDbFile = mContext.getDatabasePath(DB_FILE); } + @Test + public void testDowngradeSchemaMatchesVersion() throws Exception { + mSchemaFile.delete(); + assertFalse(mSchemaFile.exists()); + DbDowngradeHelper.updateSchemaFile(mSchemaFile, 0, mContext); + assertEquals(LauncherProvider.SCHEMA_VERSION, DbDowngradeHelper.parse(mSchemaFile).version); + } + @Test public void testUpdateSchemaFile() throws Exception { - Context myContext = InstrumentationRegistry.getContext(); - int testResId = myContext.getResources().getIdentifier( - "db_schema_v10", "raw", myContext.getPackageName()); + // Setup mock resources + Resources res = spy(mContext.getResources()); + doAnswer(i ->this.getClass().getResourceAsStream("/db_schema_v10.json")) + .when(res).openRawResource(eq(R.raw.downgrade_schema)); + Context context = spy(mContext); + when(context.getResources()).thenReturn(res); + mSchemaFile.delete(); assertFalse(mSchemaFile.exists()); - DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, myContext, testResId); + DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, context); assertTrue(mSchemaFile.exists()); assertEquals(10, DbDowngradeHelper.parse(mSchemaFile).version); // Schema is updated on version upgrade assertTrue(mSchemaFile.setLastModified(0)); - DbDowngradeHelper.updateSchemaFile(mSchemaFile, 11, myContext, testResId); + DbDowngradeHelper.updateSchemaFile(mSchemaFile, 11, context); assertNotSame(0, mSchemaFile.lastModified()); // Schema is not updated when version is same assertTrue(mSchemaFile.setLastModified(0)); - DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, myContext, testResId); + DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, context); assertEquals(0, mSchemaFile.lastModified()); // Schema is not updated on version downgrade - DbDowngradeHelper.updateSchemaFile(mSchemaFile, 3, myContext, testResId); + DbDowngradeHelper.updateSchemaFile(mSchemaFile, 3, context); assertEquals(0, mSchemaFile.lastModified()); } @@ -143,8 +159,7 @@ public class DbDowngradeHelperTest { mSchemaFile.delete(); mDbFile.delete(); - DbDowngradeHelper.updateSchemaFile(mSchemaFile, LauncherProvider.SCHEMA_VERSION, mContext, - R.raw.downgrade_schema); + DbDowngradeHelper.updateSchemaFile(mSchemaFile, LauncherProvider.SCHEMA_VERSION, mContext); DatabaseHelper dbHelper = new DatabaseHelper(mContext, null, DB_FILE) { @Override diff --git a/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java index 67580ddd8d..d4188aa8e8 100644 --- a/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java +++ b/robolectric_tests/src/com/android/launcher3/model/GridSizeMigrationTaskTest.java @@ -1,5 +1,7 @@ package com.android.launcher3.model; +import static com.android.launcher3.model.GridSizeMigrationTask.getWorkspaceScreenIds; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -10,7 +12,6 @@ import android.database.Cursor; import android.graphics.Point; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherProvider; import com.android.launcher3.LauncherSettings; import com.android.launcher3.config.FlagOverrideRule; @@ -55,7 +56,6 @@ public class GridSizeMigrationTaskTest { @Before public void setUp() { - mValidPackages = new HashSet<>(); mValidPackages.add(TEST_PACKAGE); mIdp = new InvariantDeviceProfile(); @@ -307,11 +307,6 @@ public class GridSizeMigrationTaskTest { LauncherSettings.Settings.call(mContext.getContentResolver(), LauncherSettings.Settings.METHOD_NEW_SCREEN_ID); - ContentValues v = new ContentValues(); - v.put(LauncherSettings.WorkspaceScreens._ID, screenId); - v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - mContext.getContentResolver().insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v); - ids[i] = new int[typeArray[i].length][]; for (int y = 0; y < typeArray[i].length; y++) { ids[i][y] = new int[typeArray[i][y].length]; @@ -326,7 +321,6 @@ public class GridSizeMigrationTaskTest { } } - IntArray allScreens = LauncherModel.loadWorkspaceScreensDb(mContext); return ids; } @@ -336,7 +330,7 @@ public class GridSizeMigrationTaskTest { * represent the workspace grid. */ private void verifyWorkspace(int[][][] ids) { - IntArray allScreens = LauncherModel.loadWorkspaceScreensDb(mContext); + IntArray allScreens = getWorkspaceScreenIds(mContext); assertEquals(ids.length, allScreens.size()); int total = 0; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index b4cc1ceffc..f8b44d00c2 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1747,7 +1747,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, orderedScreenIds.indexOf(Workspace.FIRST_SCREEN_ID) != 0) { orderedScreenIds.removeValue(Workspace.FIRST_SCREEN_ID); orderedScreenIds.add(0, Workspace.FIRST_SCREEN_ID); - LauncherModel.updateWorkspaceScreenOrder(this, orderedScreenIds); } else if (!FeatureFlags.QSB_ON_FIRST_SCREEN.get() && orderedScreenIds.isEmpty()) { // If there are no screens, we need to have an empty screen diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index a5f97de7ab..9b4c5fd095 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -20,12 +20,8 @@ import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD; import static com.android.launcher3.config.FeatureFlags.IS_DOGFOOD_BUILD; import android.content.BroadcastReceiver; -import android.content.ContentProviderOperation; -import android.content.ContentResolver; -import android.content.ContentValues; import android.content.Context; import android.content.Intent; -import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -38,8 +34,8 @@ import android.util.Pair; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserManagerCompat; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.icons.IconCache; +import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.AddWorkspaceItemsTask; import com.android.launcher3.model.BaseModelUpdateTask; import com.android.launcher3.model.BgDataModel; @@ -51,7 +47,6 @@ import com.android.launcher3.model.PackageInstallStateChangedTask; import com.android.launcher3.model.PackageUpdatedTask; import com.android.launcher3.model.ShortcutsChangedTask; import com.android.launcher3.model.UserLockStateChangedTask; -import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.util.ComponentKey; @@ -70,7 +65,6 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.Executor; @@ -268,53 +262,6 @@ public class LauncherModel extends BroadcastReceiver runOnWorkerThread(r); } - /** - * Update the order of the workspace screens in the database. The array list contains - * a list of screen ids in the order that they should appear. - */ - public static void updateWorkspaceScreenOrder(Context context, IntArray screens) { - final ContentResolver cr = context.getContentResolver(); - final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI; - - // Create a copy with only non-negative values - final IntArray screensCopy = new IntArray(); - for (int i = 0; i < screens.size(); i++) { - int id = screens.get(i); - if (id >= 0) { - screensCopy.add(id); - } - } - - Runnable r = new Runnable() { - @Override - public void run() { - ArrayList ops = new ArrayList(); - // Clear the table - ops.add(ContentProviderOperation.newDelete(uri).build()); - int count = screensCopy.size(); - for (int i = 0; i < count; i++) { - ContentValues v = new ContentValues(); - int screenId = screensCopy.get(i); - v.put(LauncherSettings.WorkspaceScreens._ID, screenId); - v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build()); - } - - try { - cr.applyBatch(LauncherProvider.AUTHORITY, ops); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - - synchronized (sBgDataModel) { - sBgDataModel.workspaceScreens.clear(); - sBgDataModel.workspaceScreens.addAll(screensCopy); - } - } - }; - runOnWorkerThread(r); - } - /** * Set this as the current Launcher activity object for the loader. */ @@ -519,18 +466,6 @@ public class LauncherModel extends BroadcastReceiver } } - /** - * Loads the workspace screen ids in an ordered list. - */ - public static IntArray loadWorkspaceScreensDb(Context context) { - final ContentResolver contentResolver = context.getContentResolver(); - final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI; - - // Get screens ordered by rank. - return LauncherDbUtils.getScreenIdsFromCursor(contentResolver.query( - screensUri, null, null, null, LauncherSettings.WorkspaceScreens.SCREEN_RANK)); - } - public void onInstallSessionCreated(final PackageInstallInfo sessionInfo) { enqueueModelUpdateTask(new BaseModelUpdateTask() { @Override diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 7db3d5b9db..8ed3314efd 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -32,6 +32,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.database.Cursor; +import android.database.DatabaseUtils; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; @@ -45,12 +46,12 @@ import android.os.Message; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; +import android.provider.BaseColumns; import android.text.TextUtils; import android.util.Log; import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback; import com.android.launcher3.LauncherSettings.Favorites; -import com.android.launcher3.LauncherSettings.WorkspaceScreens; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.FileLog; @@ -70,6 +71,7 @@ import java.io.PrintWriter; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Locale; public class LauncherProvider extends ContentProvider { private static final String TAG = "LauncherProvider"; @@ -79,8 +81,9 @@ public class LauncherProvider extends ContentProvider { /** * Represents the schema of the database. Changes in scheme need not be backwards compatible. + * When increasing the scheme version, ensure that downgrade_schema.json is updated */ - public static final int SCHEMA_VERSION = 27; + public static final int SCHEMA_VERSION = 28; public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings"; @@ -175,10 +178,10 @@ public class LauncherProvider extends ContentProvider { if (values == null) { throw new RuntimeException("Error: attempting to insert null values"); } - if (!values.containsKey(LauncherSettings.ChangeLogColumns._ID)) { + if (!values.containsKey(LauncherSettings.Favorites._ID)) { throw new RuntimeException("Error: attempting to add item without specifying an id"); } - helper.checkId(table, values); + helper.checkId(values); return (int) db.insert(table, nullColumnHack, values); } @@ -262,24 +265,7 @@ public class LauncherProvider extends ContentProvider { } } - // Add screen id if not present - int screenId = values.getAsInteger(LauncherSettings.Favorites.SCREEN); - SQLiteStatement stmp = null; - try { - stmp = mOpenHelper.getWritableDatabase().compileStatement( - "INSERT OR IGNORE INTO workspaceScreens (_id, screenRank) " + - "select ?, (ifnull(MAX(screenRank), -1)+1) from workspaceScreens"); - stmp.bindLong(1, screenId); - - ContentValues valuesInserted = new ContentValues(); - valuesInserted.put(LauncherSettings.BaseLauncherColumns._ID, stmp.executeInsert()); - mOpenHelper.checkId(WorkspaceScreens.TABLE_NAME, valuesInserted); - return true; - } catch (Exception e) { - return false; - } finally { - Utilities.closeSilently(stmp); - } + return true; } @Override @@ -404,7 +390,6 @@ public class LauncherProvider extends ContentProvider { * @return Ids of deleted folders. */ private IntArray deleteEmptyFolders() { - IntArray folderIds = new IntArray(); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); try (SQLiteTransaction t = new SQLiteTransaction(db)) { // Select folders whose id do not match any container value. @@ -413,21 +398,19 @@ public class LauncherProvider extends ContentProvider { + LauncherSettings.Favorites._ID + " NOT IN (SELECT " + LauncherSettings.Favorites.CONTAINER + " FROM " + Favorites.TABLE_NAME + ")"; - try (Cursor c = db.query(Favorites.TABLE_NAME, - new String[] {LauncherSettings.Favorites._ID}, - selection, null, null, null, null)) { - LauncherDbUtils.iterateCursor(c, 0, folderIds); - } + + IntArray folderIds = LauncherDbUtils.queryIntArray(db, Favorites.TABLE_NAME, + Favorites._ID, selection, null, null); if (!folderIds.isEmpty()) { db.delete(Favorites.TABLE_NAME, Utilities.createDbSelectionQuery( LauncherSettings.Favorites._ID, folderIds), null); } t.commit(); + return folderIds; } catch (SQLException ex) { Log.e(TAG, ex.getMessage(), ex); - folderIds.clear(); + return new IntArray(); } - return folderIds; } /** @@ -438,7 +421,7 @@ public class LauncherProvider extends ContentProvider { } @Thunk static void addModifiedTime(ContentValues values) { - values.put(LauncherSettings.ChangeLogColumns.MODIFIED, System.currentTimeMillis()); + values.put(LauncherSettings.Favorites.MODIFIED, System.currentTimeMillis()); } private void clearFlagEmptyDbCreated() { @@ -551,11 +534,10 @@ public class LauncherProvider extends ContentProvider { // Table creation sometimes fails silently, which leads to a crash loop. // This way, we will try to create a table every time after crash, so the device // would eventually be able to recover. - if (!tableExists(Favorites.TABLE_NAME) || !tableExists(WorkspaceScreens.TABLE_NAME)) { + if (!tableExists(Favorites.TABLE_NAME)) { Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate"); // This operation is a no-op if the table already exists. addFavoritesTable(getWritableDatabase(), true); - addWorkspacesTable(getWritableDatabase(), true); } initIds(); @@ -602,7 +584,6 @@ public class LauncherProvider extends ContentProvider { mMaxScreenId = 0; addFavoritesTable(db, false); - addWorkspacesTable(db, false); // Fresh and clean launcher DB. mMaxItemId = initializeMaxItemId(db); @@ -633,46 +614,6 @@ public class LauncherProvider extends ContentProvider { Favorites.addTableToDb(db, getDefaultUserSerial(), optional); } - private void addWorkspacesTable(SQLiteDatabase db, boolean optional) { - String ifNotExists = optional ? " IF NOT EXISTS " : ""; - db.execSQL("CREATE TABLE " + ifNotExists + WorkspaceScreens.TABLE_NAME + " (" + - LauncherSettings.WorkspaceScreens._ID + " INTEGER PRIMARY KEY," + - LauncherSettings.WorkspaceScreens.SCREEN_RANK + " INTEGER," + - LauncherSettings.ChangeLogColumns.MODIFIED + " INTEGER NOT NULL DEFAULT 0" + - ");"); - } - - private void removeOrphanedItems(SQLiteDatabase db) { - // Delete items directly on the workspace who's screen id doesn't exist - // "DELETE FROM favorites WHERE screen NOT IN (SELECT _id FROM workspaceScreens) - // AND container = -100" - String removeOrphanedDesktopItems = "DELETE FROM " + Favorites.TABLE_NAME + - " WHERE " + - LauncherSettings.Favorites.SCREEN + " NOT IN (SELECT " + - LauncherSettings.WorkspaceScreens._ID + " FROM " + WorkspaceScreens.TABLE_NAME + ")" + - " AND " + - LauncherSettings.Favorites.CONTAINER + " = " + - LauncherSettings.Favorites.CONTAINER_DESKTOP; - db.execSQL(removeOrphanedDesktopItems); - - // Delete items contained in folders which no longer exist (after above statement) - // "DELETE FROM favorites WHERE container <> -100 AND container <> -101 AND container - // NOT IN (SELECT _id FROM favorites WHERE itemType = 2)" - String removeOrphanedFolderItems = "DELETE FROM " + Favorites.TABLE_NAME + - " WHERE " + - LauncherSettings.Favorites.CONTAINER + " <> " + - LauncherSettings.Favorites.CONTAINER_DESKTOP + - " AND " - + LauncherSettings.Favorites.CONTAINER + " <> " + - LauncherSettings.Favorites.CONTAINER_HOTSEAT + - " AND " - + LauncherSettings.Favorites.CONTAINER + " NOT IN (SELECT " + - LauncherSettings.Favorites._ID + " FROM " + Favorites.TABLE_NAME + - " WHERE " + LauncherSettings.Favorites.ITEM_TYPE + " = " + - LauncherSettings.Favorites.ITEM_TYPE_FOLDER + ")"; - db.execSQL(removeOrphanedFolderItems); - } - @Override public void onOpen(SQLiteDatabase db) { super.onOpen(db); @@ -681,8 +622,7 @@ public class LauncherProvider extends ContentProvider { if (!schemaFile.exists()) { handleOneTimeDataUpgrade(db); } - DbDowngradeHelper.updateSchemaFile(schemaFile, SCHEMA_VERSION, mContext, - R.raw.downgrade_schema); + DbDowngradeHelper.updateSchemaFile(schemaFile, SCHEMA_VERSION, mContext); } /** @@ -709,12 +649,8 @@ public class LauncherProvider extends ContentProvider { switch (oldVersion) { // The version cannot be lower that 12, as Launcher3 never supported a lower // version of the DB. - case 12: { - // With the new shrink-wrapped and re-orderable workspaces, it makes sense - // to persist workspace screens and their relative order. - mMaxScreenId = 0; - addWorkspacesTable(db, false); - } + case 12: + // No-op case 13: { try (SQLiteTransaction t = new SQLiteTransaction(db)) { // Insert new column for holding widget provider name @@ -728,15 +664,7 @@ public class LauncherProvider extends ContentProvider { } } case 14: { - try (SQLiteTransaction t = new SQLiteTransaction(db)) { - // Insert new column for holding update timestamp - db.execSQL("ALTER TABLE favorites " + - "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;"); - db.execSQL("ALTER TABLE workspaceScreens " + - "ADD COLUMN modified INTEGER NOT NULL DEFAULT 0;"); - t.commit(); - } catch (SQLException ex) { - Log.e(TAG, ex.getMessage(), ex); + if (!addIntegerColumn(db, Favorites.MODIFIED, 0)) { // Old version remains, which means we wipe old data break; } @@ -747,22 +675,15 @@ public class LauncherProvider extends ContentProvider { break; } } - case 16: { + case 16: // No-op - } - case 17: { + case 17: + // No-op + case 18: // No-op - } - case 18: { - // Due to a data loss bug, some users may have items associated with screen ids - // which no longer exist. Since this can cause other problems, and since the user - // will never see these items anyway, we use database upgrade as an opportunity to - // clean things up. - removeOrphanedItems(db); - } case 19: { // Add userId column - if (!addProfileColumn(db)) { + if (!addIntegerColumn(db, Favorites.PROFILE_ID, getDefaultUserSerial())) { // Old version remains, which means we wipe old data break; } @@ -772,10 +693,7 @@ public class LauncherProvider extends ContentProvider { break; } case 21: - // Recreate workspace table with screen id a primary key - if (!recreateWorkspaceTable(db)) { - break; - } + // No-op case 22: { if (!addIntegerColumn(db, Favorites.OPTIONS, 0)) { // Old version remains, which means we wipe old data @@ -794,7 +712,30 @@ public class LauncherProvider extends ContentProvider { !LauncherDbUtils.prepareScreenZeroToHostQsb(mContext, db)) { break; } - case 27: + case 27: { + // Update the favorites table so that the screen ids are ordered based on + // workspace page rank. + IntArray finalScreens = LauncherDbUtils.queryIntArray(db, "workspaceScreens", + BaseColumns._ID, null, null, "screenRank"); + int[] original = finalScreens.toArray(); + Arrays.sort(original); + String updatemap = ""; + for (int i = 0; i < original.length; i++) { + if (finalScreens.get(i) != original[i]) { + updatemap += String.format(Locale.ENGLISH, " WHEN %1$s=%2$d THEN %3$d", + Favorites.SCREEN, finalScreens.get(i), original[i]); + } + } + if (!TextUtils.isEmpty(updatemap)) { + String query = String.format(Locale.ENGLISH, + "UPDATE %1$s SET %2$s=CASE %3$s ELSE %2$s END WHERE %4$s = %5$d", + Favorites.TABLE_NAME, Favorites.SCREEN, updatemap, + Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP); + db.execSQL(query); + } + db.execSQL("DROP TABLE IF EXISTS workspaceScreens"); + } + case 28: // DB Upgraded successfully return; } @@ -822,7 +763,7 @@ public class LauncherProvider extends ContentProvider { public void createEmptyDB(SQLiteDatabase db) { try (SQLiteTransaction t = new SQLiteTransaction(db)) { db.execSQL("DROP TABLE IF EXISTS " + Favorites.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + WorkspaceScreens.TABLE_NAME); + db.execSQL("DROP TABLE IF EXISTS workspaceScreens"); onCreate(db); t.commit(); } @@ -845,17 +786,9 @@ public class LauncherProvider extends ContentProvider { Log.e(TAG, "getAppWidgetIds not supported", e); return; } - final IntSet validWidgets = new IntSet(); - try (Cursor c = db.query(Favorites.TABLE_NAME, - new String[] {Favorites.APPWIDGET_ID }, - "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null, null, null)) { - while (c.moveToNext()) { - validWidgets.add(c.getInt(0)); - } - } catch (SQLException ex) { - Log.w(TAG, "Error getting widgets list", ex); - return; - } + final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(db, + Favorites.TABLE_NAME, Favorites.APPWIDGET_ID, + "itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null)); for (int widgetId : allWidgets) { if (!validWidgets.contains(widgetId)) { try { @@ -910,46 +843,6 @@ public class LauncherProvider extends ContentProvider { } } - /** - * Recreates workspace table and migrates data to the new table. - */ - public boolean recreateWorkspaceTable(SQLiteDatabase db) { - try (SQLiteTransaction t = new SQLiteTransaction(db)) { - final IntArray sortedIDs; - - try (Cursor c = db.query(WorkspaceScreens.TABLE_NAME, - new String[] {LauncherSettings.WorkspaceScreens._ID}, - null, null, null, null, - LauncherSettings.WorkspaceScreens.SCREEN_RANK)) { - // Use LinkedHashSet so that ordering is preserved - sortedIDs = LauncherDbUtils.getScreenIdsFromCursor(c); - } - db.execSQL("DROP TABLE IF EXISTS " + WorkspaceScreens.TABLE_NAME); - addWorkspacesTable(db, false); - - // Add all screen ids back - int total = sortedIDs.size(); - for (int i = 0; i < total; i++) { - ContentValues values = new ContentValues(); - values.put(LauncherSettings.WorkspaceScreens._ID, sortedIDs.get(i)); - values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - addModifiedTime(values); - db.insertOrThrow(WorkspaceScreens.TABLE_NAME, null, values); - } - t.commit(); - - mMaxScreenId = 0; - for (int i = 0; i < sortedIDs.size(); i++) { - mMaxScreenId = Math.max(mMaxScreenId, sortedIDs.get(i)); - } - } catch (SQLException ex) { - // Old version remains, which means we wipe old data - Log.e(TAG, ex.getMessage(), ex); - return false; - } - return true; - } - @Thunk boolean updateFolderItemsRank(SQLiteDatabase db, boolean addRankColumn) { try (SQLiteTransaction t = new SQLiteTransaction(db)) { if (addRankColumn) { @@ -979,10 +872,6 @@ public class LauncherProvider extends ContentProvider { return true; } - private boolean addProfileColumn(SQLiteDatabase db) { - return addIntegerColumn(db, Favorites.PROFILE_ID, getDefaultUserSerial()); - } - private boolean addIntegerColumn(SQLiteDatabase db, String columnName, long defaultValue) { try (SQLiteTransaction t = new SQLiteTransaction(db)) { db.execSQL("ALTER TABLE favorites ADD COLUMN " @@ -1018,17 +907,20 @@ public class LauncherProvider extends ContentProvider { return dbInsertAndCheck(this, db, Favorites.TABLE_NAME, null, values); } - public void checkId(String table, ContentValues values) { - int id = values.getAsInteger(LauncherSettings.BaseLauncherColumns._ID); - if (WorkspaceScreens.TABLE_NAME.equals(table)) { - mMaxScreenId = Math.max(id, mMaxScreenId); - } else { - mMaxItemId = Math.max(id, mMaxItemId); + public void checkId(ContentValues values) { + int id = values.getAsInteger(Favorites._ID); + mMaxItemId = Math.max(id, mMaxItemId); + + Integer screen = values.getAsInteger(Favorites.SCREEN); + Integer container = values.getAsInteger(Favorites.CONTAINER); + if (screen != null && container != null + && container.intValue() == Favorites.CONTAINER_DESKTOP) { + mMaxScreenId = Math.max(screen, mMaxScreenId); } } private int initializeMaxItemId(SQLiteDatabase db) { - return getMaxId(db, Favorites.TABLE_NAME); + return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s", Favorites._ID, Favorites.TABLE_NAME); } // Generates a new ID to use for an workspace screen in your database. This method @@ -1045,34 +937,18 @@ public class LauncherProvider extends ContentProvider { } private int initializeMaxScreenId(SQLiteDatabase db) { - return getMaxId(db, WorkspaceScreens.TABLE_NAME); + return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s WHERE %3$s = %4$d", + Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER, + Favorites.CONTAINER_DESKTOP); } @Thunk int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) { - IntArray screenIds = new IntArray(); // TODO: Use multiple loaders with fall-back and transaction. - int count = loader.loadLayout(db, screenIds); - - // Add the screens specified by the items above - int[] sortedScreenIds = screenIds.toArray(); - Arrays.sort(sortedScreenIds); - int rank = 0; - ContentValues values = new ContentValues(); - for (int id : sortedScreenIds) { - values.clear(); - values.put(LauncherSettings.WorkspaceScreens._ID, id); - values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, rank); - if (dbInsertAndCheck(this, db, WorkspaceScreens.TABLE_NAME, null, values) < 0) { - throw new RuntimeException("Failed initialize screen table" - + "from default layout"); - } - rank++; - } + int count = loader.loadLayout(db, new IntArray()); // Ensure that the max ids are initialized mMaxItemId = initializeMaxItemId(db); mMaxScreenId = initializeMaxScreenId(db); - return count; } } @@ -1080,22 +956,14 @@ public class LauncherProvider extends ContentProvider { /** * @return the max _id in the provided table. */ - @Thunk static int getMaxId(SQLiteDatabase db, String table) { - Cursor c = db.rawQuery("SELECT MAX(_id) FROM " + table, null); - // get the result - int id = -1; - if (c != null && c.moveToNext()) { - id = c.getInt(0); + @Thunk static int getMaxId(SQLiteDatabase db, String query, Object... args) { + int max = (int) DatabaseUtils.longForQuery(db, + String.format(Locale.ENGLISH, query, args), + null); + if (max < 0) { + throw new RuntimeException("Error: could not query max id"); } - if (c != null) { - c.close(); - } - - if (id == -1) { - throw new RuntimeException("Error: could not query max id in " + table); - } - - return id; + return max; } static class SqlArguments { diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 0b12b15f9e..79c8208736 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -26,16 +26,17 @@ import android.provider.BaseColumns; * Settings related utilities. */ public class LauncherSettings { - /** Columns required on table staht will be subject to backup and restore. */ - static interface ChangeLogColumns extends BaseColumns { + + /** + * Favorites. + */ + public static final class Favorites implements BaseColumns { /** * The time of the last update to this row. *

Type: INTEGER

*/ public static final String MODIFIED = "modified"; - } - static public interface BaseLauncherColumns extends ChangeLogColumns { /** * Descriptive name of the gesture that can be displayed to the user. *

Type: TEXT

@@ -84,34 +85,6 @@ public class LauncherSettings { *

Type: BLOB

*/ public static final String ICON = "icon"; - } - - /** - * Workspace Screens. - * - * Tracks the order of workspace screens. - */ - public static final class WorkspaceScreens implements ChangeLogColumns { - - public static final String TABLE_NAME = "workspaceScreens"; - - /** - * The content:// style URL for this table - */ - public static final Uri CONTENT_URI = Uri.parse("content://" + - LauncherProvider.AUTHORITY + "/" + TABLE_NAME); - - /** - * The rank of this screen -- ie. how it is ordered relative to the other screens. - *

Type: INTEGER

- */ - public static final String SCREEN_RANK = "screenRank"; - } - - /** - * Favorites. - */ - public static final class Favorites implements BaseLauncherColumns { public static final String TABLE_NAME = "favorites"; diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java index 6083415d52..0cf6e44c63 100644 --- a/src/com/android/launcher3/SecondaryDropTarget.java +++ b/src/com/android/launcher3/SecondaryDropTarget.java @@ -150,7 +150,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList Intent intent = null; UserHandle user = null; if (item != null && - item.itemType == LauncherSettings.BaseLauncherColumns.ITEM_TYPE_APPLICATION) { + item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { intent = item.getIntent(); user = item.user; } diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java index 19c647fd74..c2c3287458 100644 --- a/src/com/android/launcher3/ShortcutInfo.java +++ b/src/com/android/launcher3/ShortcutInfo.java @@ -89,7 +89,7 @@ public class ShortcutInfo extends ItemInfoWithIcon { private int mInstallProgress; public ShortcutInfo() { - itemType = LauncherSettings.BaseLauncherColumns.ITEM_TYPE_SHORTCUT; + itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; } public ShortcutInfo(ShortcutInfo info) { @@ -114,24 +114,23 @@ public class ShortcutInfo extends ItemInfoWithIcon { @TargetApi(Build.VERSION_CODES.N) public ShortcutInfo(ShortcutInfoCompat shortcutInfo, Context context) { user = shortcutInfo.getUserHandle(); - itemType = LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; + itemType = Favorites.ITEM_TYPE_DEEP_SHORTCUT; updateFromDeepShortcutInfo(shortcutInfo, context); } @Override public void onAddToDatabase(ContentWriter writer) { super.onAddToDatabase(writer); - writer.put(LauncherSettings.BaseLauncherColumns.TITLE, title) - .put(LauncherSettings.BaseLauncherColumns.INTENT, getIntent()) - .put(LauncherSettings.Favorites.RESTORED, status); + writer.put(Favorites.TITLE, title) + .put(Favorites.INTENT, getIntent()) + .put(Favorites.RESTORED, status); if (!usingLowResIcon()) { writer.putIcon(iconBitmap, user); } if (iconResource != null) { - writer.put(LauncherSettings.BaseLauncherColumns.ICON_PACKAGE, iconResource.packageName) - .put(LauncherSettings.BaseLauncherColumns.ICON_RESOURCE, - iconResource.resourceName); + writer.put(Favorites.ICON_PACKAGE, iconResource.packageName) + .put(Favorites.ICON_RESOURCE, iconResource.resourceName); } } @@ -189,7 +188,7 @@ public class ShortcutInfo extends ItemInfoWithIcon { @Override public ComponentName getTargetComponent() { ComponentName cn = super.getTargetComponent(); - if (cn == null && (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT + if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT || hasStatusFlag(FLAG_SUPPORTS_WEB_UI))) { // Legacy shortcuts and promise icons with web UI may not have a componentName but just // a packageName. In that case create a dummy componentName instead of adding additional diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 47ebb17952..56aca02ed1 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -619,9 +619,6 @@ public class Workspace extends PagedView // if this is the last screen, convert it to the empty screen mWorkspaceScreens.put(EXTRA_EMPTY_SCREEN_ID, finalScreen); mScreenOrder.add(EXTRA_EMPTY_SCREEN_ID); - - // Update the model if we have changed any screens - LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder); } } @@ -728,9 +725,6 @@ public class Workspace extends PagedView mWorkspaceScreens.put(newId, cl); mScreenOrder.add(newId); - // Update the model for the new screen - LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder); - return newId; } @@ -828,13 +822,6 @@ public class Workspace extends PagedView } } - if (!removeScreens.isEmpty()) { - // Update the model if we have changed any screens - mLauncher.getModelWriter().enqueueDeleteRunnable( - () -> LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder)); - - } - if (pageShift >= 0) { setCurrentPage(currentPage - pageShift); } diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index 756d44e814..5fc555172f 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -15,11 +15,11 @@ */ package com.android.launcher3.model; -import android.content.Context; import android.content.Intent; import android.os.UserHandle; import android.util.LongSparseArray; import android.util.Pair; + import com.android.launcher3.AllAppsList; import com.android.launcher3.AppInfo; import com.android.launcher3.FolderInfo; @@ -27,7 +27,6 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetInfo; -import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.CallbackTask; import com.android.launcher3.LauncherModel.Callbacks; import com.android.launcher3.LauncherSettings; @@ -58,16 +57,12 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { if (mItemList.isEmpty()) { return; } - Context context = app.getContext(); final ArrayList addedItemsFinal = new ArrayList<>(); final IntArray addedWorkspaceScreensFinal = new IntArray(); - // Get the list of workspace screens. We need to append to this list and - // can not use sBgWorkspaceScreens because loadWorkspace() may not have been - // called. - IntArray workspaceScreens = LauncherModel.loadWorkspaceScreensDb(context); synchronized(dataModel) { + IntArray workspaceScreens = dataModel.workspaceScreens.clone(); List filteredItems = new ArrayList<>(); for (Pair entry : mItemList) { @@ -116,9 +111,6 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { } } - // Update the workspace screens - updateScreens(context, workspaceScreens); - if (!addedItemsFinal.isEmpty()) { scheduleCallbackTask(new CallbackTask() { @Override @@ -143,10 +135,6 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { } } - protected void updateScreens(Context context, IntArray workspaceScreens) { - LauncherModel.updateWorkspaceScreenOrder(context, workspaceScreens); - } - /** * Returns true if the shortcuts already exists on the workspace. This must be called after * the workspace has been loaded. We identify a shortcut by its intent. diff --git a/src/com/android/launcher3/model/DbDowngradeHelper.java b/src/com/android/launcher3/model/DbDowngradeHelper.java index cd86b728b1..e5c44d1aad 100644 --- a/src/com/android/launcher3/model/DbDowngradeHelper.java +++ b/src/com/android/launcher3/model/DbDowngradeHelper.java @@ -21,6 +21,7 @@ import android.database.sqlite.SQLiteException; import android.util.Log; import android.util.SparseArray; +import com.android.launcher3.R; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; import com.android.launcher3.util.IOUtils; @@ -87,8 +88,7 @@ public class DbDowngradeHelper { return helper; } - public static void updateSchemaFile(File schemaFile, int expectedVersion, - Context context, int schemaResId) { + public static void updateSchemaFile(File schemaFile, int expectedVersion, Context context) { try { if (DbDowngradeHelper.parse(schemaFile).version >= expectedVersion) { return; @@ -99,7 +99,7 @@ public class DbDowngradeHelper { // Write the updated schema try (FileOutputStream fos = new FileOutputStream(schemaFile); - InputStream in = context.getResources().openRawResource(schemaResId)) { + InputStream in = context.getResources().openRawResource(R.raw.downgrade_schema)) { IOUtils.copy(in, fos); } catch (IOException e) { Log.e(TAG, "Error writing schema file", e); diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java index 289de1a4b1..a9ddccb670 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationTask.java +++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java @@ -13,14 +13,12 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Point; -import android.net.Uri; import android.util.Log; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; -import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherProvider; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; @@ -31,12 +29,14 @@ import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSparseArrayMap; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.Locale; + +import androidx.annotation.VisibleForTesting; /** * This class takes care of shrinking the workspace (by maximum of one row and one column), as a @@ -180,11 +180,25 @@ public class GridSizeMigrationTask { return applyOperations(); } + @VisibleForTesting + static IntArray getWorkspaceScreenIds(Context context) { + IntSet set = new IntSet(); + try (Cursor c = context.getContentResolver().query(Favorites.CONTENT_URI, + new String[] {Favorites.SCREEN}, + Favorites.CONTAINER + " = " + Favorites.CONTAINER_DESKTOP, + null, Favorites.SCREEN)) { + while (c.moveToNext()) { + set.add(c.getInt(0)); + } + } + return set.getArray(); + } + /** * @return true if any DB change was made */ protected boolean migrateWorkspace() throws Exception { - IntArray allScreens = LauncherModel.loadWorkspaceScreensDb(mContext); + IntArray allScreens = getWorkspaceScreenIds(mContext); if (allScreens.isEmpty()) { throw new Exception("Unable to get workspace screens"); } @@ -216,9 +230,8 @@ public class GridSizeMigrationTask { int newScreenId = LauncherSettings.Settings.call( mContext.getContentResolver(), LauncherSettings.Settings.METHOD_NEW_SCREEN_ID) - .getInt(LauncherSettings.Settings.EXTRA_VALUE); + .getInt(LauncherSettings.Settings.EXTRA_VALUE); - allScreens.add(newScreenId); for (DbEntry item : placement.finalPlacedItems) { if (!mCarryOver.remove(itemMap.get(item.id))) { throw new Exception("Unable to find matching items"); @@ -231,19 +244,6 @@ public class GridSizeMigrationTask { } } while (!mCarryOver.isEmpty()); - - // Update screens - final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI; - mUpdateOperations.add(ContentProviderOperation.newDelete(uri).build()); - int count = allScreens.size(); - for (int i = 0; i < count; i++) { - ContentValues v = new ContentValues(); - int screenId = allScreens.get(i); - v.put(LauncherSettings.WorkspaceScreens._ID, screenId); - v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - mUpdateOperations.add(ContentProviderOperation.newInsert(uri).withValues( - v).build()); - } } return applyOperations(); } diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index 8efebf14b9..d104a8b22f 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -380,7 +380,7 @@ public class LoaderCursor extends CursorWrapper { * otherwise marks it for deletion. */ public void checkAndAddItem(ItemInfo info, BgDataModel dataModel) { - if (checkItemPlacement(info, dataModel.workspaceScreens)) { + if (checkItemPlacement(info)) { dataModel.addItem(mContext, info, false); } else { markDeleted("Item position overlap"); @@ -390,7 +390,7 @@ public class LoaderCursor extends CursorWrapper { /** * check & update map of what's occupied; used to discard overlapping/invalid items */ - protected boolean checkItemPlacement(ItemInfo item, IntArray workspaceScreens) { + protected boolean checkItemPlacement(ItemInfo item) { int containerIndex = item.screenId; if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { final GridOccupancy hotseatOccupancy = @@ -420,12 +420,7 @@ public class LoaderCursor extends CursorWrapper { occupied.put(LauncherSettings.Favorites.CONTAINER_HOTSEAT, occupancy); return true; } - } else if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { - if (!workspaceScreens.contains(item.screenId)) { - // The item has an invalid screen id. - return false; - } - } else { + } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { // Skip further checking if it is not the hotseat or workspace container return true; } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index f711787cfe..a4fe57086a 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -72,6 +72,7 @@ import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.IntSet; import com.android.launcher3.util.LooperIdleLock; import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageManagerHelper; @@ -293,7 +294,6 @@ public class LoaderTask implements Runnable { final HashMap installingPkgs = mPackageInstaller.updateAndGetActiveSessionCache(); mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs); - mBgDataModel.workspaceScreens.addAll(LauncherModel.loadWorkspaceScreensDb(context)); Map shortcutKeyToPinnedShortcuts = new HashMap<>(); final LoaderCursor c = new LoaderCursor(contentResolver.query( @@ -780,21 +780,15 @@ public class LoaderTask implements Runnable { new Handler(LauncherModel.getWorkerLooper())); } - // Remove any empty screens - IntArray unusedScreens = mBgDataModel.workspaceScreens.clone(); + // Initialize the screens array. Using an InstSet ensures that the screen ids + // are sorted. + IntSet screenSet = new IntSet(); for (ItemInfo item: mBgDataModel.itemsIdMap) { - int screenId = item.screenId; - if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && - unusedScreens.contains(screenId)) { - unusedScreens.removeValue(screenId); + if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { + screenSet.add(item.screenId); } } - - // If there are any empty screens remove them, and update. - if (unusedScreens.size() != 0) { - mBgDataModel.workspaceScreens.removeAllValues(unusedScreens); - LauncherModel.updateWorkspaceScreenOrder(context, mBgDataModel.workspaceScreens); - } + mBgDataModel.workspaceScreens.addAll(screenSet.getArray()); } } diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index f7961d5d87..ca5428d94d 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -333,7 +333,7 @@ public class ModelWriter { * {@link #commitDelete()} is called (or abandoned if {@link #abortDelete()} is called). * Otherwise, we run the Runnable immediately. */ - public void enqueueDeleteRunnable(Runnable r) { + private void enqueueDeleteRunnable(Runnable r) { if (mPreparingToUndo) { mDeleteRunnables.add(r); } else { diff --git a/src/com/android/launcher3/provider/ImportDataTask.java b/src/com/android/launcher3/provider/ImportDataTask.java index b389b145d2..86fcc06802 100644 --- a/src/com/android/launcher3/provider/ImportDataTask.java +++ b/src/com/android/launcher3/provider/ImportDataTask.java @@ -33,7 +33,6 @@ import android.os.Process; import android.text.TextUtils; import android.util.ArrayMap; import android.util.SparseBooleanArray; -import android.util.SparseIntArray; import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback; import com.android.launcher3.DefaultLayoutParser; @@ -43,7 +42,6 @@ import com.android.launcher3.LauncherProvider; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.Settings; -import com.android.launcher3.LauncherSettings.WorkspaceScreens; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; import com.android.launcher3.compat.UserManagerCompat; @@ -72,7 +70,6 @@ public class ImportDataTask { private final Context mContext; - private final Uri mOtherScreensUri; private final Uri mOtherFavoritesUri; private int mHotseatSize; @@ -81,41 +78,14 @@ public class ImportDataTask { private ImportDataTask(Context context, String sourceAuthority) { mContext = context; - mOtherScreensUri = Uri.parse("content://" + - sourceAuthority + "/" + WorkspaceScreens.TABLE_NAME); mOtherFavoritesUri = Uri.parse("content://" + sourceAuthority + "/" + Favorites.TABLE_NAME); } public boolean importWorkspace() throws Exception { - IntArray allScreens = LauncherDbUtils.getScreenIdsFromCursor( - mContext.getContentResolver().query(mOtherScreensUri, null, null, null, - LauncherSettings.WorkspaceScreens.SCREEN_RANK)); FileLog.d(TAG, "Importing DB from " + mOtherFavoritesUri); - // During import we reset the screen IDs to 0-indexed values. - if (allScreens.isEmpty()) { - // No thing to migrate - FileLog.e(TAG, "No data found to import"); - return false; - } - mHotseatSize = mMaxGridSizeX = mMaxGridSizeY = 0; - - // Build screen update - ArrayList screenOps = new ArrayList<>(); - int count = allScreens.size(); - SparseIntArray screenIdMap = new SparseIntArray(count); - for (int i = 0; i < count; i++) { - ContentValues v = new ContentValues(); - v.put(LauncherSettings.WorkspaceScreens._ID, i); - v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i); - screenIdMap.put(allScreens.get(i), i); - screenOps.add(ContentProviderOperation.newInsert( - LauncherSettings.WorkspaceScreens.CONTENT_URI).withValues(v).build()); - } - mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, screenOps); - importWorkspaceItems(allScreens.get(0), screenIdMap); - + importWorkspaceItems(); GridSizeMigrationTask.markForMigration(mContext, mMaxGridSizeX, mMaxGridSizeY, mHotseatSize); // Create empty DB flag. @@ -129,17 +99,17 @@ public class ImportDataTask { * 2) For home screen entries, maps the screen id based on {@param screenIdMap} * 3) In the end fills any holes in hotseat with items from default hotseat layout. */ - private void importWorkspaceItems( - int firstScreenId, SparseIntArray screenIdMap) throws Exception { + private void importWorkspaceItems() throws Exception { String profileId = Long.toString(UserManagerCompat.getInstance(mContext) .getSerialNumberForUser(Process.myUserHandle())); boolean createEmptyRowOnFirstScreen; if (FeatureFlags.QSB_ON_FIRST_SCREEN.get()) { try (Cursor c = mContext.getContentResolver().query(mOtherFavoritesUri, null, - // get items on the first row of the first screen - "profileId = ? AND container = -100 AND screen = ? AND cellY = 0", - new String[]{profileId, Integer.toString(firstScreenId)}, + // get items on the first row of the first screen (min screen id) + "profileId = ? AND container = -100 AND cellY = 0 AND screen = " + + "(SELECT MIN(screen) FROM favorites WHERE container = -100)", + new String[]{profileId}, null)) { // First row of first screen is not empty createEmptyRowOnFirstScreen = c.moveToNext(); @@ -163,7 +133,7 @@ public class ImportDataTask { Favorites.PROFILE_ID + " = ?", new String[]{profileId}, // Get the items sorted by container, so that the folders are loaded // before the corresponding items. - Favorites.CONTAINER)) { + Favorites.CONTAINER + " , " + Favorites.SCREEN)) { // various columns we expect to exist. final int idIndex = c.getColumnIndexOrThrow(Favorites._ID); @@ -185,6 +155,7 @@ public class ImportDataTask { SparseBooleanArray mValidFolders = new SparseBooleanArray(); ContentValues values = new ContentValues(); + Integer firstScreenId = null; while (c.moveToNext()) { values.clear(); int id = c.getInt(idIndex); @@ -201,16 +172,21 @@ public class ImportDataTask { switch (container) { case Favorites.CONTAINER_DESKTOP: { - Integer newScreenId = screenIdMap.get(screen); - if (newScreenId == null) { - FileLog.d(TAG, String.format("Skipping item %d, type %d not on a valid screen %d", id, type, screen)); + if (screen < Workspace.FIRST_SCREEN_ID) { + FileLog.d(TAG, String.format( + "Skipping item %d, type %d not on a valid screen %d", + id, type, screen)); continue; } + if (firstScreenId == null) { + firstScreenId = screen; + } // Reset the screen to 0-index value - screen = newScreenId; - if (createEmptyRowOnFirstScreen && screen == Workspace.FIRST_SCREEN_ID) { + if (createEmptyRowOnFirstScreen && firstScreenId.equals(screen)) { // Shift items by 1. cellY++; + // Change the screen id to first screen + screen = Workspace.FIRST_SCREEN_ID; } mMaxGridSizeX = Math.max(mMaxGridSizeX, cellX + spanX); @@ -218,7 +194,7 @@ public class ImportDataTask { break; } case Favorites.CONTAINER_HOTSEAT: { - mHotseatSize = Math.max(mHotseatSize, (int) screen + 1); + mHotseatSize = Math.max(mHotseatSize, screen + 1); break; } default: diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java index ab0703fed2..b79478ac6f 100644 --- a/src/com/android/launcher3/provider/LauncherDbUtils.java +++ b/src/com/android/launcher3/provider/LauncherDbUtils.java @@ -25,11 +25,9 @@ import android.util.Log; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings.Favorites; -import com.android.launcher3.LauncherSettings.WorkspaceScreens; import com.android.launcher3.util.IntArray; -import java.util.ArrayList; -import java.util.Collection; +import java.util.Locale; /** * A set of utility methods for Launcher DB used for DB updates and migration. @@ -47,26 +45,25 @@ public class LauncherDbUtils { */ public static boolean prepareScreenZeroToHostQsb(Context context, SQLiteDatabase db) { try (SQLiteTransaction t = new SQLiteTransaction(db)) { - // Get the existing screens - IntArray screenIds = getScreenIdsFromCursor(db.query(WorkspaceScreens.TABLE_NAME, - null, null, null, null, null, WorkspaceScreens.SCREEN_RANK)); + // Get the first screen + final int firstScreenId; + try (Cursor c = db.rawQuery(String.format(Locale.ENGLISH, + "SELECT MIN(%1$s) from %2$s where %3$s = %4$d", + Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER, + Favorites.CONTAINER_DESKTOP), null)) { - if (screenIds.isEmpty()) { - // No update needed - t.commit(); - return true; - } - if (screenIds.get(0) != 0) { - // First screen is not 0, we need to rename screens - if (screenIds.contains(0)) { - // There is already a screen 0. First rename it to a different screen. - int newScreenId = 1; - while (screenIds.contains(newScreenId)) newScreenId++; - renameScreen(db, 0, newScreenId); + if (!c.moveToNext()) { + // No update needed + t.commit(); + return true; } + firstScreenId = c.getInt(0); + } + + if (firstScreenId != 0) { // Rename the first screen to 0. - renameScreen(db, screenIds.get(0), 0); + renameScreen(db, firstScreenId, 0); } // Check if the first row is empty @@ -89,31 +86,19 @@ public class LauncherDbUtils { private static void renameScreen(SQLiteDatabase db, int oldScreen, int newScreen) { String[] whereParams = new String[] { Integer.toString(oldScreen) }; - ContentValues values = new ContentValues(); - values.put(WorkspaceScreens._ID, newScreen); - db.update(WorkspaceScreens.TABLE_NAME, values, "_id = ?", whereParams); - - values.clear(); values.put(Favorites.SCREEN, newScreen); db.update(Favorites.TABLE_NAME, values, "container = -100 and screen = ?", whereParams); } - /** - * Parses the cursor containing workspace screens table and returns the list of screen IDs - */ - public static IntArray getScreenIdsFromCursor(Cursor sc) { - try { - return iterateCursor(sc, - sc.getColumnIndexOrThrow(WorkspaceScreens._ID), new IntArray()); - } finally { - sc.close(); - } - } - - public static IntArray iterateCursor(Cursor c, int columnIndex, IntArray out) { - while (c.moveToNext()) { - out.add(c.getInt(columnIndex)); + public static IntArray queryIntArray(SQLiteDatabase db, String tableName, String columnName, + String selection, String groupBy, String orderBy) { + IntArray out = new IntArray(); + try (Cursor c = db.query(tableName, new String[] { columnName }, selection, null, + groupBy, null, orderBy)) { + while (c.moveToNext()) { + out.add(c.getInt(0)); + } } return out; } diff --git a/src/com/android/launcher3/util/IntSet.java b/src/com/android/launcher3/util/IntSet.java index 63499b06d6..2459fad327 100644 --- a/src/com/android/launcher3/util/IntSet.java +++ b/src/com/android/launcher3/util/IntSet.java @@ -48,4 +48,15 @@ public class IntSet { public int size() { return mArray.size(); } + + public IntArray getArray() { + return mArray; + } + + public static IntSet wrap(IntArray array) { + IntSet set = new IntSet(); + set.mArray.addAll(array); + Arrays.sort(set.mArray.mValues, 0, set.mArray.mSize); + return set; + } } diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java index ac1be1777a..df935b8dbe 100644 --- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java +++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java @@ -18,16 +18,12 @@ import com.android.launcher3.ShortcutInfo; import com.android.launcher3.Utilities; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.icons.BitmapInfo; -import com.android.launcher3.util.IntArray; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; -import java.util.Arrays; - -import static com.android.launcher3.LauncherSettings.BaseLauncherColumns.INTENT; +import static com.android.launcher3.LauncherSettings.Favorites.INTENT; import static com.android.launcher3.LauncherSettings.Favorites.CELLX; import static com.android.launcher3.LauncherSettings.Favorites.CELLY; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER; @@ -148,81 +144,57 @@ public class LoaderCursorTest { assertEquals(ITEM_TYPE_SHORTCUT, info.itemType); } - @Test - public void checkItemPlacement_wrongWorkspaceScreen() { - IntArray workspaceScreens = IntArray.wrap(1, 3); - mIDP.numRows = 4; - mIDP.numColumns = 4; - mIDP.numHotseatIcons = 3; - - // Item on unknown screen are not placed - assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 4), workspaceScreens)); - assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 5), workspaceScreens)); - assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2), workspaceScreens)); - - assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens)); - assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 3), workspaceScreens)); - - } @Test public void checkItemPlacement_outsideBounds() { - IntArray workspaceScreens = IntArray.wrap(1, 2); mIDP.numRows = 4; mIDP.numColumns = 4; mIDP.numHotseatIcons = 3; // Item outside screen bounds are not placed assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(4, 4, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens)); + newItemInfo(4, 4, 1, 1, CONTAINER_DESKTOP, 1))); } @Test public void checkItemPlacement_overlappingItems() { - IntArray workspaceScreens = IntArray.wrap(1, 2); mIDP.numRows = 4; mIDP.numColumns = 4; mIDP.numHotseatIcons = 3; // Overlapping items are not placed assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens)); + newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1))); assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens)); + newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 1))); assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2), workspaceScreens)); + newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2))); assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2), workspaceScreens)); + newItemInfo(0, 0, 1, 1, CONTAINER_DESKTOP, 2))); assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(1, 1, 1, 1, CONTAINER_DESKTOP, 1), workspaceScreens)); + newItemInfo(1, 1, 1, 1, CONTAINER_DESKTOP, 1))); assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(2, 2, 2, 2, CONTAINER_DESKTOP, 1), workspaceScreens)); + newItemInfo(2, 2, 2, 2, CONTAINER_DESKTOP, 1))); assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(3, 2, 1, 2, CONTAINER_DESKTOP, 1), workspaceScreens)); + newItemInfo(3, 2, 1, 2, CONTAINER_DESKTOP, 1))); } @Test public void checkItemPlacement_hotseat() { - IntArray workspaceScreens = new IntArray(); mIDP.numRows = 4; mIDP.numColumns = 4; mIDP.numHotseatIcons = 3; // Hotseat items are only placed based on screenId assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 1), workspaceScreens)); + newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 1))); assertTrue(mLoaderCursor.checkItemPlacement( - newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 2), workspaceScreens)); + newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 2))); assertFalse(mLoaderCursor.checkItemPlacement( - newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 3), workspaceScreens)); + newItemInfo(3, 3, 1, 1, CONTAINER_HOTSEAT, 3))); } private ItemInfo newItemInfo(int cellX, int cellY, int spanX, int spanY, diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java index 22bc05c942..8b8e43626c 100644 --- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java @@ -297,10 +297,6 @@ public class BindWidgetTest extends AbstractLauncherUiTest { if (screenId > Workspace.FIRST_SCREEN_ID) { screenId = Workspace.FIRST_SCREEN_ID; } - ContentValues v = new ContentValues(); - v.put(LauncherSettings.WorkspaceScreens._ID, screenId); - v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, 0); - mResolver.insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v); // Insert the item ContentWriter writer = new ContentWriter(mTargetContext); From b93e419e8b129d201b268d741053ed2d58ea6aad Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Mon, 10 Dec 2018 15:18:32 -0800 Subject: [PATCH 05/15] Speed up corner animation The size of the window changes during the animation progress, making the window look rounded for longer. What we want is to animate it from the shape of the icon to the shape of the display. Change-Id: Ib4889b697bf78cdc37c160130fde961650080fb7 Fixes: 120553563 Test: visual --- .../com/android/launcher3/LauncherAppTransitionManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 1049cca597..20a83b5cd0 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -618,7 +618,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag // Animate window corner radius from 100% to windowCornerRadius. float windowCornerRadius = RecentsModel.INSTANCE.get(mLauncher) .getWindowCornerRadius(); - float circleRadius = scaledWindowWidth / 2f; + float circleRadius = iconWidth / 2f; float windowRadius = Utilities.mapRange(easePercent, circleRadius, windowCornerRadius); From 282ad21f71e4fe87623c9bc1ed47596663f642ef Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 10 Dec 2018 19:08:44 -0800 Subject: [PATCH 06/15] Fix issue with swipe up animation stalling after swiping up - When the launcher activity is killed, the next init will attempt to create a sync applier, which uses the ViewRootImpl of the target view. But when onActivityInit() is called, the recents view has not been attached to the hierarchy so the view root is not accessible. The SyncRtSurfaceTransactionApplier also ignores scheduling all updates when it has a non-existant view root, which leads to the app surface getting stuck midway during a swipe up (only affects the duration of the animation) Bug: 119661847 Test: adb shell am force-stop com.google.android.apps.nexuslauncher then try and swipe up slowly Change-Id: I8eef9fe38c55c0cb438d63b41c335f78679278a3 --- .../quickstep/WindowTransformSwipeHandler.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 78a2055bb5..878af1b92a 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -403,7 +403,20 @@ public class WindowTransformSwipeHandler { } mRecentsView = activity.getOverviewPanel(); - mSyncTransactionApplier = new SyncRtSurfaceTransactionApplier(mRecentsView); + mRecentsView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + // We can only initialize the SyncRtSurfaceTransactionApplier when the view has been + // attached + mSyncTransactionApplier = new SyncRtSurfaceTransactionApplier(mRecentsView); + mRecentsView.removeOnAttachStateChangeListener(this); + } + + @Override + public void onViewDetachedFromWindow(View v) { + // Do nothing + } + }); mQuickScrubController = mRecentsView.getQuickScrubController(); mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity); From 80f5c19fd277bbaf0cd5aad6f42b2bd5994fb205 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 11 Dec 2018 10:47:07 -0800 Subject: [PATCH 07/15] Import translations. DO NOT MERGE Change-Id: I1539df9cc5f5633585a5714fc8069163d7edb951 Auto-generated-cl: translation import --- quickstep/res/values-mr/strings.xml | 2 +- res/values-af/strings.xml | 20 +++++++-------- res/values-am/strings.xml | 20 +++++++-------- res/values-ar/strings.xml | 24 +++++++++--------- res/values-as/strings.xml | 20 +++++++-------- res/values-az/strings.xml | 20 +++++++-------- res/values-b+sr+Latn/strings.xml | 21 ++++++++-------- res/values-be/strings.xml | 22 ++++++++--------- res/values-bg/strings.xml | 20 +++++++-------- res/values-bn/strings.xml | 20 +++++++-------- res/values-bs/strings.xml | 21 ++++++++-------- res/values-ca/strings.xml | 20 +++++++-------- res/values-cs/strings.xml | 22 ++++++++--------- res/values-da/strings.xml | 20 +++++++-------- res/values-de/strings.xml | 20 +++++++-------- res/values-el/strings.xml | 20 +++++++-------- res/values-en-rAU/strings.xml | 20 +++++++-------- res/values-en-rGB/strings.xml | 20 +++++++-------- res/values-en-rIN/strings.xml | 20 +++++++-------- res/values-es-rUS/strings.xml | 20 +++++++-------- res/values-es/strings.xml | 20 +++++++-------- res/values-et/strings.xml | 20 +++++++-------- res/values-fa/strings.xml | 20 +++++++-------- res/values-fi/strings.xml | 20 +++++++-------- res/values-fr-rCA/strings.xml | 20 +++++++-------- res/values-fr/strings.xml | 20 +++++++-------- res/values-gl/strings.xml | 20 +++++++-------- res/values-gu/strings.xml | 20 +++++++-------- res/values-hi/strings.xml | 22 ++++++++--------- res/values-hr/strings.xml | 21 ++++++++-------- res/values-hu/strings.xml | 20 +++++++-------- res/values-hy/strings.xml | 20 +++++++-------- res/values-in/strings.xml | 20 +++++++-------- res/values-is/strings.xml | 20 +++++++-------- res/values-it/strings.xml | 20 +++++++-------- res/values-iw/strings.xml | 22 ++++++++--------- res/values-ja/strings.xml | 20 +++++++-------- res/values-ka/strings.xml | 20 +++++++-------- res/values-kk/strings.xml | 20 +++++++-------- res/values-km/strings.xml | 20 +++++++-------- res/values-kn/strings.xml | 20 +++++++-------- res/values-ko/strings.xml | 20 +++++++-------- res/values-ky/strings.xml | 20 +++++++-------- res/values-lo/strings.xml | 20 +++++++-------- res/values-lt/strings.xml | 22 ++++++++--------- res/values-lv/strings.xml | 21 ++++++++-------- res/values-mk/strings.xml | 20 +++++++-------- res/values-ml/strings.xml | 20 +++++++-------- res/values-mn/strings.xml | 20 +++++++-------- res/values-mr/strings.xml | 38 ++++++++++++++--------------- res/values-ms/strings.xml | 20 +++++++-------- res/values-my/strings.xml | 20 +++++++-------- res/values-nb/strings.xml | 20 +++++++-------- res/values-ne/strings.xml | 20 +++++++-------- res/values-nl/strings.xml | 20 +++++++-------- res/values-or/strings.xml | 20 +++++++-------- res/values-pa/strings.xml | 20 +++++++-------- res/values-pl/strings.xml | 22 ++++++++--------- res/values-pt/strings.xml | 20 +++++++-------- res/values-ro/strings.xml | 21 ++++++++-------- res/values-ru/strings.xml | 22 ++++++++--------- res/values-si/strings.xml | 20 +++++++-------- res/values-sk/strings.xml | 22 ++++++++--------- res/values-sl/strings.xml | 22 ++++++++--------- res/values-sq/strings.xml | 20 +++++++-------- res/values-sr/strings.xml | 21 ++++++++-------- res/values-sv/strings.xml | 20 +++++++-------- res/values-sw/strings.xml | 20 +++++++-------- res/values-ta/strings.xml | 20 +++++++-------- res/values-te/strings.xml | 20 +++++++-------- res/values-th/strings.xml | 20 +++++++-------- res/values-tl/strings.xml | 20 +++++++-------- res/values-tr/strings.xml | 20 +++++++-------- res/values-uk/strings.xml | 24 +++++++++--------- res/values-ur/strings.xml | 20 +++++++-------- res/values-uz/strings.xml | 20 +++++++-------- res/values-vi/strings.xml | 20 +++++++-------- res/values-zh-rCN/strings.xml | 20 +++++++-------- res/values-zh-rHK/strings.xml | 20 +++++++-------- res/values-zh-rTW/strings.xml | 20 +++++++-------- res/values-zu/strings.xml | 20 +++++++-------- 81 files changed, 760 insertions(+), 892 deletions(-) diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index f88bb77f4b..fa8574a3cf 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -25,7 +25,7 @@ "अवलोकन" "कोणतेही अलीकडील आयटम नाहीत" "बंद" - "अॅप वापर सेटिंग्ज" + "अ‍ॅप वापर सेटिंग्ज" "सर्व साफ करा" "अलीकडील अॅप्स" diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index b93c3701eb..3f505462ee 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -39,8 +39,7 @@ "Laai tans programme …" "Kon geen programme kry wat by \"%1$s\" pas nie" "Soek meer programme" - - + "Program" "Kennisgewings" "Raak en hou om \'n kortpad op te tel." "Dubbeltik en hou om \'n kortpad op te tel of gebruik gepasmaakte handelinge." @@ -66,7 +65,10 @@ "Dit is \'n stelselprogram en kan nie gedeïnstalleer word nie." "Naamlose vouer" "Het %1$s gedeaktiveer" - + + %1$s, het %2$d kennisgewings + %1$s, het %2$d kennisgewing + "Bladsy %1$d van %2$d" "Tuisskerm %1$d van %2$d" "Nuwe tuisskermbladsy" @@ -82,17 +84,13 @@ "Gedeaktiveer deur jou administrateur" "Laat toe dat tuisskerm gedraai word" "Wanneer foon gedraai word" - - - - - - + "Kennisgewingkolle" + "Aan" + "Af" "Kennisgewingtoegang word benodig" "Skakel programkennisgewings vir %1$s aan om kennisgewingkolle te sien" "Verander instellings" - - + "Wys kennisgewingkolle" "Voeg ikoon by tuisskerm" "Vir nuwe programme" "Verander ikoon se vorm" diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index d65fa673d7..9f8ee87ca5 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -39,8 +39,7 @@ "መተግበሪያዎችን በመጫን ላይ…" "ከ«%1$s» ጋር የሚዛመዱ ምንም መተግበሪያዎች አልተገኙም" "ተጨማሪ መተግበሪያዎች ይፈልጉ" - - + "መተግበሪያ" "ማሳወቂያዎች" "አንድ አቋራጭ ለመውሰድ ነክተው ይያዙ።" "አንድ አቋራጭ ለመውሰድ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ አድርገው ይያዙ።" @@ -66,7 +65,10 @@ "ይህ የስርዓት መተግበሪያ ነው እና ማራገፍ አይቻልም።" "ስም-አልባ አቃፊ" "%1$s ተሰናክሏል" - + + %1$s%2$d ማሳወቂያ አለው + %1$s%2$d ማሳወቂያ አለው + "ገጽ %1$d ከ%2$d" "መነሻ ማያ ገጽ %1$d ከ%2$d" "አዲስ የመነሻ ማያ ገጽ" @@ -82,17 +84,13 @@ "በእርስዎ አስተዳዳሪ የተሰናከለ" "የመነሻ ማያ ገጽ ማሽከርከርን ይፍቀዱ" "ስልኩ ሲዞር" - - - - - - + "የማሳወቂያ ነጥቦች" + "አብራ" + "ጠፍቷል" "የማሳወቂያ መዳረሻ ያስፈልጋል" "የማሳወቂያ ነጥቦችን ለማሳየት የመተግብሪያ ማሳወቂያዎችን ለ%1$s ያብሩ" "ቅንብሮችን ቀይር" - - + "የማሳወቂያ ነጥቦችን አሳይ" "አዶ ወደ የመነሻ ማያ ገጽ አክል" "ለአዲስ መተግበሪያዎች" "የአዶ ቅርፅ ለውጥ" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 988f9b9e29..97e9784d2f 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -39,8 +39,7 @@ "جارٍ تحميل التطبيقات…" "لم يتم العثور على أي تطبيقات تتطابق مع \"%1$s\"" "البحث عن مزيد من التطبيقات" - - + "تطبيق" "الإشعارات" "انقر مع الاستمرار لاختيار اختصار." "يمكنك النقر مرّتين مع الاستمرار لاختيار اختصار أو استخدام الإجراءات المخصصة." @@ -66,7 +65,14 @@ "هذا تطبيق نظام وتتعذر إزالته." "مجلد بدون اسم" "تم إيقاف %1$s" - + + يتضمن تطبيق %1$s %2$d إشعار.​ + يتضمن تطبيق %1$s إشعارين (%2$d). + يتضمن تطبيق %1$s %2$d إشعارات.​ + يتضمن تطبيق %1$s %2$d إشعارًا. + يتضمن تطبيق %1$s %2$d إشعار. + يتضمن تطبيق %1$s إشعارًا واحدًا (%2$d). + "‏الصفحة %1$d من %2$d" "‏الشاشة الرئيسية %1$d من %2$d" "صفحة الشاشة الرئيسية الجديدة" @@ -82,17 +88,13 @@ "أوقف المشرف هذه الميزة" "السماح بتدوير الشاشة الرئيسية" "عند تدوير الهاتف" - - - - - - + "نقاط الإشعارات" + "مفعّل" + "غير مفعّل" "يلزم تفعيل الوصول إلى الإشعارات" "لعرض نقاط الإشعارات، يجب تشغيل إشعارات التطبيق في %1$s" "تغيير الإعدادات" - - + "عرض نقاط الإشعارات" "إضافة رمز إلى الشاشة الرئيسية" "للتطبيقات الجديدة" "تغيير شكل الرمز" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index 149a19d639..e4293cfe42 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -39,8 +39,7 @@ "এপসমূহ ল’ড কৰি থকা হৈছে…" "\"%1$s\"ৰ সৈতে মিলা কোনো এপ্ বিচাৰি পোৱা নগ\'ল" "আৰু অধিক এপবোৰ সন্ধান কৰক" - - + "এপ্" "জাননীসমূহ" "কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ স্পৰ্শ কৰি হেঁচি ধৰক।" "কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ দুবাৰ টিপি হেঁচি ধৰক, বা নিজৰ উপযোগিতা অনুসৰি সৃষ্টি কৰা কাৰ্যসমূহ ব্যৱহাৰ কৰক।" @@ -66,7 +65,10 @@ "এইটো এটা ছিষ্টেম এপ আৰু ইয়াক আনইনষ্টল কৰিব নোৱৰি" "নামবিহীন ফ\'ল্ডাৰ" "%1$s অক্ষম কৰা হ\'ল" - + + %1$s%2$dটা জাননী আছে + %1$s%2$dটা জাননী আছে + "%2$dৰ %1$d পৃষ্ঠা" "গৃহ স্ক্ৰীণ %2$dৰ %1$d" "গৃহ স্ক্ৰীণৰ নতুন পৃষ্ঠা" @@ -82,17 +84,13 @@ "আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে" "গৃহ স্ক্ৰীণ ঘূৰোৱাৰ অনুমতি দিয়ক" "ফ\'নটো যেতিয়া ঘূৰোৱা হয়" - - - - - - + "জাননী বিন্দু" + "অন আছে" + "অফ আছে" "জাননী চাবলৈ অনুমতিৰ প্ৰয়োজন" "জাননী সম্পৰ্কীয় বিন্দুবোৰ দেখুৱাবলৈ %1$sৰ বাবে এপৰ জাননীসমূহ অন কৰক" "ছেটিংসমূহ সলনি কৰক" - - + "জাননী বিন্দু দেখুৱাওক" "গৃহ স্ক্ৰীণত আইকনটো যোগ কৰক" "নতুন এপসমূহৰ বাবে" "আইকনৰ আকৃতি সলনি কৰক" diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 2a8f046953..5381114d6c 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -39,8 +39,7 @@ "Tətbiqlər yüklənir…" "%1$s sorğusuna uyğun tətbiq tapılmadı" "Daha çox tətbiq üçün axtarış edin" - - + "Tətbiq" "Bildirişlər" "Qısayolu seçmək üçün basıb saxlayın." "Qısayolu seçmək üçün iki dəfə basıb saxlayın və ya fərdi əməliyyatlardan istifadə edin." @@ -66,7 +65,10 @@ "Bu sistem tətbiqi olduğu üçün sistemdən silinə bilməz." "Adsız Qovluq" "%1$s deaktiv edildi" - + + %1$s tətbiqində %2$d bildiriş var + %1$s tətbiqində %2$d bildiriş var + "Səhifə %1$d of %2$d" "Əsas Səhifə ekranı %1$d of %2$d" "Yeni əsas ekran səhifəsi" @@ -82,17 +84,13 @@ "Admininiz tərəfindən deaktiv edilib" "Əsas ekranın firlanmağına icazə verin" "Telefon çevrilən zaman" - - - - - - + "Bildiriş nöqtələri" + "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" - - + "Bildiriş nöqtələrini göstərin" "Əsas ekrana ikona əlavə edin" "Yeni tətbiqlər üçün" "İkona formasını dəyişin" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index c89330e773..568a0fbc20 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -39,8 +39,7 @@ "Aplikacije se učitavaju…" "Nije pronađena nijedna aplikacija za „%1$s“" "Pretraži još aplikacija" - - + "Aplikacija" "Obaveštenja" "Dodirnite i zadržite da biste izabrali prečicu." "Dvaput dodirnite i zadržite da biste izabrali prečicu ili koristite prilagođene radnje." @@ -66,7 +65,11 @@ "Ovo je sistemska aplikacija i ne može da se deinstalira." "Neimenovani direktorijum" "Aplikacija %1$s je onemogućena" - + + %1$s, ima %2$d obaveštenje + %1$s, ima %2$d obaveštenja + %1$s, ima %2$d obaveštenja + "%1$d. stranica od %2$d" "%1$d. početni ekran od %2$d" "Nova stranica početnog ekrana" @@ -82,17 +85,13 @@ "Administrator je onemogućio" "Dozvoli rotaciju početnog ekrana" "Kada se telefon rotira" - - - - - - + "Tačke za obaveštenja" + "Uključeno" + "Isključeno" "Potreban je pristup za obaveštenja" "Da biste prikazali tačke za obaveštenja, uključite obaveštenja za aplikaciju %1$s" "Promenite podešavanja" - - + "Prikazuj tačke za obaveštenja" "Dodaj ikonu na početni ekran" "Za nove aplikacije" "Promenite oblik ikona" diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 39db29ad37..2f5fd30054 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -39,8 +39,7 @@ "Праграмы загружаюцца…" "Праграм, якія адпавядаюць запыту \"%1$s\", не знойдзена" "Шукаць іншыя праграмы" - - + "Праграма" "Апавяшчэнні" "Дакраніцеся і ўтрымлiвайце ярлык, каб дадаць яго." "Дакраніцеся двойчы і ўтрымлівайце, каб выбраць ярлык або выкарыстоўваць спецыяльныя дзеянні." @@ -66,7 +65,12 @@ "Гэта сістэмная праграма, яе нельга выдаліць." "Папка без назвы" "%1$s адключана" - + + %1$s, мае %2$d апавяшчэнне + %1$s, мае %2$d апавяшчэнні + %1$s, мае %2$d апавяшчэнняў + %1$s, мае %2$d апавяшчэння + "Старонка %1$d з %2$d" "Галоўны экран %1$d з %2$d" "Новая старонка галоўнага экрана" @@ -82,17 +86,13 @@ "Адключаная адміністратарам" "Дазволіць паварот галоўнага экрана" "Пры павароце тэлефона" - - - - - - + "Значкі апавяшчэнняў" + "Укл." + "Выкл." "Патрабуецца доступ да апавяшчэнняў" "Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для %1$s" "Змяніць налады" - - + "Паказваць значкі апавяшчэнняў" "Дадаць значок на Галоўны экран" "Для новых праграм" "Змяніць форму значка" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 9083f4ce0d..286a6e886a 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -39,8 +39,7 @@ "Приложенията се зареждат…" "Няма намерени приложения, съответстващи на „%1$s“" "Търсене на още приложения" - - + "Приложение" "Известия" "Докоснете и задръжте за избор на пряк път." "Докоснете двукратно и задръжте за избор на пряк път или използвайте персонализирани действия." @@ -66,7 +65,10 @@ "Това е системно приложение и не може да се деинсталира." "Папка без име" "Деактивирахте %1$s" - + + %1$s – има %2$d известия + %1$s – има %2$d известие + "Страница %1$d от %2$d" "Начален екран %1$d от %2$d" "Нова страница на началния екран" @@ -82,17 +84,13 @@ "Деактивирано от администратора ви" "Разрешаване на завъртането на началния екран" "При завъртане на телефона" - - - - - - + "Точки за известия" + "Вкл." + "Изкл." "Необходим е достъп до известията" "За да се показват точки за известия, включете известията за приложението %1$s" "Промяна на настройките" - - + "Показване на точките за известия" "Добавяне на икона към началния екран" "За нови приложения" "Промяна на формата на иконите" diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index c5adb7b1c2..6356f149d7 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -39,8 +39,7 @@ "অ্যাপ লোড হচ্ছে…" "\"%1$s\" এর সাথে মেলে এমন কোনো অ্যাপ পাওয়া যায়নি" "আরও অ্যাপ্লিকেশানের জন্য খুঁজুন" - - + "অ্যাপ" "বিজ্ঞপ্তি" "কোনও শর্টকাট বেছে নিতে টাচ করে ধরে থাকুন।" "কোনও শর্টকাট বেছে নিতে ডবল ট্যাপ করে ধরে থাকুন অথবা কাস্টম অ্যাকশন ব্যবহার করুন।" @@ -66,7 +65,10 @@ "এটি একটি সিস্টেম অ্যাপ্লিকেশান এবং আনইনস্টল করা যাবে না৷" "নামবিহীন ফোল্ডার" "%1$s অক্ষম করা হয়েছে" - + + %1$s, %2$dটি বিজ্ঞপ্তি আছে + %1$s, %2$dটি বিজ্ঞপ্তি আছে + "%2$dটির মধ্যে %1$dটি পৃষ্ঠা" "%2$dটির %1$d নম্বর হোম স্ক্রিন" "নতুন হোম স্ক্রীনের পৃষ্ঠা" @@ -82,17 +84,13 @@ "আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে" "হোমস্ক্রীন ঘোরানোর অনুমতি দিন" "যখন ফোনটি ঘোরানো হয়" - - - - - - + "বিজ্ঞপ্তি ডট" + "চালু" + "বন্ধ" "বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন" "বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, %1$s এর অ্যাপ বিজ্ঞপ্তি চালু করুন" "সেটিংস পরিবর্তন করুন" - - + "বিজ্ঞপ্তির ডট দেখুন" "হোম স্ক্রিনে আইকন যোগ করুন" "নতুন অ্যাপ্লিকেশানগুলির জন্যে" "আইকনের আকৃতি পরিবর্তন করুন" diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 74624cad7f..e98e1cde3a 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -39,8 +39,7 @@ "Aplikacije se učitavaju…" "Nije pronađena nijedna aplikacija za upit \"%1$s\"" "Pretraži više aplikacija" - - + "Aplikacija" "Obavještenja" "Dodirnite i držite da uzmete prečicu." "Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije." @@ -66,7 +65,11 @@ "Ovo je sistemska aplikacija i ne može se deinstalirati." "Neimenovani folder" "Aplikacija %1$s je onemogućena" - + + Aplikacija %1$s ima%2$d obavještenje​ + Aplikacija %1$s ima%2$d obavještenja​ + Aplikacija %1$s ima%2$d obavještenja​ + "Strana %1$d od %2$d" "Početni ekran %1$d od %2$d" "Nova stranica početnog ekrana" @@ -82,17 +85,13 @@ "Onemogućio vaš administrator" "Dozvoli rotiranje početnog ekrana" "Kada se telefon zarotira" - - - - - - + "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" - - + "Prikaži tačke za obavještenja" "Dodaj ikonu na početni ekran" "Za nove aplikacije" "Promjena oblika ikona" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index b34dcb67c2..52cd6a3bbb 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -39,8 +39,7 @@ "S\'estan carregant les aplicacions…" "No s\'ha trobat cap aplicació que coincideixi amb \"%1$s\"" "Cerca més aplicacions" - - + "Aplicació" "Notificacions" "Mantén premuda una drecera per seleccionar-la." "Fes doble toc i mantén premut per seleccionar una drecera o per utilitzar accions personalitzades." @@ -66,7 +65,10 @@ "Aquesta aplicació és una aplicació del sistema i no es pot desinstal·lar." "Carpeta sense nom" "S\'ha desactivat %1$s" - + + %1$s​ té %2$d notificacions + %1$s%2$d notificació + "Pàgina %1$d de %2$d" "Pantalla d\'inici %1$d de %2$d" "Pàgina de la pantalla d\'inici nova" @@ -82,17 +84,13 @@ "Desactivada per l\'administrador" "Permet la rotació de la pantalla d\'inici" "En girar el telèfon" - - - - - - + "Punts de notificació" + "Activats" + "Desactivats" "Cal que tingui accés a les notificacions" "Per veure els punts de notificació, activa les notificacions de l\'aplicació %1$s" "Canvia la configuració" - - + "Mostra els punts de notificació" "Afegeix la icona a la pantalla d\'inici" "Per a les aplicacions noves" "Canvia la forma de les icones" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 187b60b7f6..59dabbc403 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -39,8 +39,7 @@ "Načítání aplikací…" "Dotazu „%1$s“ neodpovídají žádné aplikace" "Vyhledat další aplikace" - - + "Aplikace" "Oznámení" "Zkratku vyberete podržením." "Dvojitým klepnutím a podržením vyberte zkratku, případně použijte vlastní akce." @@ -66,7 +65,12 @@ "Toto je systémová aplikace a nelze ji odinstalovat." "Složka bez názvu" "Aplikace %1$s je zakázána" - + + Aplikace %1$s%2$d oznámení + Aplikace %1$s%2$d oznámení + Aplikace %1$s%2$d oznámení + Aplikace %1$s%2$d oznámení + "Strana %1$d z %2$d" "Plocha %1$d z %2$d" "Nová stránka plochy" @@ -82,17 +86,13 @@ "Zakázáno administrátorem" "Povolit otáčení plochy" "Při otočení telefonu" - - - - - - + "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ím, zapněte oznámení z aplikace %1$s" "Změnit nastavení" - - + "Zobrazovat puntíky s oznámením" "Přidat ikonu na plochu" "Pro nové aplikace" "Změnit tvar ikony" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 745b534736..19ffe36673 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -39,8 +39,7 @@ "Indlæser apps…" "Der blev ikke fundet nogen apps, som matcher \"%1$s\"" "Søg efter flere apps" - - + "App" "Underretninger" "Hold en genvej nede for at samle den op." "Tryk to gange, og hold en genvej nede for at samle den op eller bruge tilpassede handlinger." @@ -66,7 +65,10 @@ "Dette er en systemapp, som ikke kan afinstalleres." "Unavngiven mappe" "%1$s er deaktiveret" - + + %1$s, har %2$d underretning + %1$s, har %2$d underretninger + "Side %1$d ud af %2$d" "Startskærm %1$d ud af %2$d" "Ny startskærm" @@ -82,17 +84,13 @@ "Deaktiveret af din administrator" "Tillad rotation af startskærmen" "Når telefonen roteres" - - - - - - + "Underretningscirkler" + "Til" + "Fra" "Kræver adgang til underretninger" "Hvis du vil se underretningscirkler, skal du aktivere appunderretninger for %1$s" "Skift indstillinger" - - + "Vis underretningscirkler" "Føj ikon til startskærmen" "For nye apps" "Skift ikonform" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 33016318fb..4d4c1daf23 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -39,8 +39,7 @@ "Apps werden geladen…" "Keine Apps für \"%1$s\" gefunden" "Weitere Apps suchen" - - + "App" "Benachrichtigungen" "Tippen und halten, um eine Verknüpfung auszuwählen." "Doppeltippen und halten, um eine Verknüpfung auszuwählen oder benutzerdefinierte Aktionen zu nutzen." @@ -66,7 +65,10 @@ "Dies ist eine Systemanwendung, die nicht deinstalliert werden kann." "Unbenannter Ordner" "%1$s deaktiviert" - + + %1$s, hat %2$d Benachrichtigungen + %1$s, hat %2$d Benachrichtigung + "Seite %1$d von %2$d" "Startbildschirm %1$d von %2$d" "Neue Startbildschirmseite" @@ -82,17 +84,13 @@ "Von deinem Administrator deaktiviert" "Drehung des Startbildschirms zulassen" "Bei Drehung des Smartphones" - - - - - - + "App-Benachrichtigungspunkte" + "An" + "Aus" "Benachrichtigungszugriff erforderlich" "Um dir Benachrichtigungspunkte anzeigen zu lassen, aktiviere die Benachrichtigungen für die App \"%1$s\"" "Einstellungen ändern" - - + "App-Benachrichtigungspunkte anzeigen" "Symbol zu Startbildschirm hinzufügen" "Für neue Apps" "Form des Symbols ändern" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 690da09e1d..35aba42a37 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -39,8 +39,7 @@ "Φόρτωση εφαρμογών…" "Δεν βρέθηκαν εφαρμογές αντιστοίχισης για \"%1$s\"" "Αναζήτηση περισσότερων εφαρμογών" - - + "Εφαρμογή" "Ειδοποιήσεις" "Αγγίξτε παρατεταμένα για επιλογή συντόμευσης." "Πατήσετε δύο φορές παρατεταμένα για επιλογή συντόμευσης ή χρήση προσαρμοσμένων ενεργειών." @@ -66,7 +65,10 @@ "Αυτή είναι μια εφαρμογή συστήματος και δεν είναι δυνατή η κατάργηση της εγκατάστασής της." "Φάκελος χωρίς όνομα" "Η εφαρμογή %1$s είναι απενεργοποιημένη" - + + Η εφαρμογή %1$s, έχει %2$d ειδοποιήσεις + Η εφαρμογή %1$s, έχει %2$d ειδοποίηση + "Σελίδα %1$d από %2$d" "Αρχική οθόνη %1$d από %2$d" "Νέα σελίδα αρχικής οθόνης" @@ -82,17 +84,13 @@ "Απενεργοποιήθηκε από τον διαχειριστή σας" "Να επιτρέπεται η περιστροφή της αρχικής οθόνης" "Όταν το τηλέφωνο περιστρέφεται" - - - - - - + "Κουκκίδες ειδοποίησης" + "Ενεργοποίηση" + "Απενεργοποίηση" "Απαιτείται πρόσβαση στις ειδοποιήσεις" "Για να εμφανιστούν οι Κουκκίδες ειδοποίησης, ενεργοποιήστε τις κουκκίδες εφαρμογής για την εφαρμογή %1$s" "Αλλαγή ρυθμίσεων" - - + "Εμφάνιση κουκκίδων ειδοποιήσεων" "Προσθήκη εικονιδίου στην Αρχική οθόνη" "Για νέες εφαρμογές" "Αλλαγή σχήματος εικονιδίου" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 7360892f9c..a56fbefa46 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -39,8 +39,7 @@ "Loading apps…" "No apps found matching \'%1$s\'" "Search for more apps" - - + "App" "Notifications" "Touch & hold to pick up a shortcut." "Double-tap & hold to pick up a shortcut or use custom actions." @@ -66,7 +65,10 @@ "This is a system app and can\'t be uninstalled." "Unnamed Folder" "Disabled %1$s" - + + %1$s, has %2$d notifications + %1$s, has %2$d notification + "Page %1$d of %2$d" "Home screen %1$d of %2$d" "New home screen page" @@ -82,17 +84,13 @@ "Disabled by your admin" "Allow Homescreen rotation" "When phone is rotated" - - - - - - + "Notification dots" + "On" + "Off" "Notification access needed" "To show Notification Dots, turn on app notifications for %1$s" "Change settings" - - + "Show notification dots" "Add icon to Home screen" "For new apps" "Change icon shape" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index 7360892f9c..a56fbefa46 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -39,8 +39,7 @@ "Loading apps…" "No apps found matching \'%1$s\'" "Search for more apps" - - + "App" "Notifications" "Touch & hold to pick up a shortcut." "Double-tap & hold to pick up a shortcut or use custom actions." @@ -66,7 +65,10 @@ "This is a system app and can\'t be uninstalled." "Unnamed Folder" "Disabled %1$s" - + + %1$s, has %2$d notifications + %1$s, has %2$d notification + "Page %1$d of %2$d" "Home screen %1$d of %2$d" "New home screen page" @@ -82,17 +84,13 @@ "Disabled by your admin" "Allow Homescreen rotation" "When phone is rotated" - - - - - - + "Notification dots" + "On" + "Off" "Notification access needed" "To show Notification Dots, turn on app notifications for %1$s" "Change settings" - - + "Show notification dots" "Add icon to Home screen" "For new apps" "Change icon shape" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index 7360892f9c..a56fbefa46 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -39,8 +39,7 @@ "Loading apps…" "No apps found matching \'%1$s\'" "Search for more apps" - - + "App" "Notifications" "Touch & hold to pick up a shortcut." "Double-tap & hold to pick up a shortcut or use custom actions." @@ -66,7 +65,10 @@ "This is a system app and can\'t be uninstalled." "Unnamed Folder" "Disabled %1$s" - + + %1$s, has %2$d notifications + %1$s, has %2$d notification + "Page %1$d of %2$d" "Home screen %1$d of %2$d" "New home screen page" @@ -82,17 +84,13 @@ "Disabled by your admin" "Allow Homescreen rotation" "When phone is rotated" - - - - - - + "Notification dots" + "On" + "Off" "Notification access needed" "To show Notification Dots, turn on app notifications for %1$s" "Change settings" - - + "Show notification dots" "Add icon to Home screen" "For new apps" "Change icon shape" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index b1fd75be7f..f88f8fca73 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -39,8 +39,7 @@ "Cargando apps…" "No hay apps que coincidan con \"%1$s\"" "Buscar más apps" - - + "App" "Notificaciones" "Mantén presionado para elegir un acceso directo." "Presiona dos veces y mantén presionado para elegir un acceso directo o usar acciones personalizadas." @@ -66,7 +65,10 @@ "Esta es una aplicación del sistema y no se puede desinstalar." "Carpeta sin nombre" "Se inhabilitó %1$s" - + + %1$s tiene %2$d notificaciones + %1$s tiene %2$d notificación + "Página %1$d de %2$d" "Pantalla principal %1$d de %2$d" "Nueva página en la pantalla principal" @@ -82,17 +84,13 @@ "El administrador inhabilitó esta función" "Permitir la rotación de la pantalla principal" "Al girar el teléfono" - - - - - - + "Puntos de notificación" + "Activado" + "Desactivado" "Se necesita acceso a las notificaciones" "Para mostrar los puntos de notificación, activa las notificaciones de la app para %1$s" "Cambiar la configuración" - - + "Mostrar puntos de notificación" "Agregar ícono a la pantalla principal" "Para nuevas apps" "Cambiar forma de los íconos" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 3021c71b31..3f3322c400 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -39,8 +39,7 @@ "Cargando aplicaciones…" "No se han encontrado aplicaciones que contengan \"%1$s\"" "Buscar más aplicaciones" - - + "Aplicación" "Notificaciones" "Mantén pulsado para elegir un acceso directo." "Toca dos veces y mantén pulsado para elegir un acceso directo o utilizar acciones personalizadas." @@ -66,7 +65,10 @@ "Esta aplicación es del sistema y no se puede desinstalar." "Carpeta sin nombre" "Se ha inhabilitado %1$s" - + + %1$s tiene %2$d notificaciones + %1$s tiene %2$d notificación + "Página %1$d de %2$d" "Pantalla de inicio %1$d de %2$d" "Nueva página de pantalla de inicio" @@ -82,17 +84,13 @@ "Inhabilitado por el administrador" "Permitir rotación de la pantalla de inicio" "Al girar el teléfono" - - - - - - + "Burbujas de notificación" + "Activadas" + "Desactivadas" "Se necesita acceso a las notificaciones" "Para mostrar burbujas de notificación, activa las notificaciones de %1$s" "Cambiar ajustes" - - + "Mostrar burbujas de notificación" "Añadir icono a la pantalla de inicio" "Para aplicaciones nuevas" "Cambiar forma de los iconos" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index f3c14a36c5..ea04cdda7b 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -39,8 +39,7 @@ "Rakenduste laadimine …" "Päringule „%1$s” ei vastanud ükski rakendus" "Otsi rohkem rakendusi" - - + "Rakendus" "Märguanded" "Otsetee valimiseks puudutage seda pikalt." "Topeltpuudutage ja hoidke otsetee valimiseks või kohandatud toimingute kasutamiseks." @@ -66,7 +65,10 @@ "See on süsteemirakendus ja seda ei saa desinstallida." "Nimetu kaust" "Rakendus %1$s on keelatud" - + + %1$s, %2$d märguannet + %1$s, %2$d märguanne + "Leht %1$d/%2$d" "Avaekraan %1$d/%2$d" "Uus avaekraan" @@ -82,17 +84,13 @@ "Keelas administraator" "Luba avaekraani pööramine" "Kui telefoni pööratakse" - - - - - - + "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" - - + "Kuva märguandetäpid" "Lisa ikoon avaekraanile" "Uute rakenduste puhul" "Ikooni kuju muutmine" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index c24ebec249..539c7599c7 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -39,8 +39,7 @@ "درحال بارگیری برنامه‌‌ها…" "هیچ برنامه‌ای در مطابقت با «%1$s» پیدا نشد" "جستجوی برنامه‌های بیشتر" - - + "برنامه" "اعلان‌ها" "برای انتخاب میان‌بر، لمس کنید و نگه‌دارید." "برای انتخاب میان‌بر، دو ضربه سریع بزنید و نگه‌دارید یا از کنش‌های سفارشی استفاده کنید." @@ -66,7 +65,10 @@ "این برنامه سیستمی است و حذف نصب نمی‌شود." "پوشه بی‌نام" "%1$s غیرفعال شد" - + + %1$s، %2$d اعلان دارد + %1$s، %2$d اعلان دارد + "‏صفحه %1$d از %2$d" "‏صفحه اصلی %1$d از %2$d" "صفحه اصلی جدید" @@ -82,17 +84,13 @@ "توسط سرپرست سیستم غیرفعال شده است" "امکان دادن به چرخش صفحه اصلی" "وقتی تلفن چرخانده می‌شود" - - - - - - + "نقطه‌های اعلان" + "روشن" + "خاموش" "دسترسی به اعلان نیاز است" "برای نمایش «نقطه‌های اعلان»، اعلان‌های برنامه را برای %1$s روشن کنید" "تغییر تنظیمات" - - + "نمایش نقطه‌های اعلان" "افزودن نماد به صفحه اصلی" "برای برنامه‌های جدید" "تغییر شکل نماد" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 5cc6a5a477..70853bd235 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -39,8 +39,7 @@ "Ladataan sovelluksia…" "%1$s ei palauttanut sovelluksia." "Hae lisää sovelluksia" - - + "Sovellus" "Ilmoitukset" "Valitse pikakuvake painamalla sitä pitkään." "Valitse pikakuvake tai käytä muokattuja toimintoja kaksoisnapauttamalla ja painamalla pitkään." @@ -66,7 +65,10 @@ "Tämä on järjestelmäsovellus, eikä sitä voi poistaa." "Nimetön kansio" "%1$s poistettiin käytöstä" - + + %1$s: %2$d ilmoitusta + %1$s: %2$d ilmoitus + "Sivu %1$d / %2$d" "Aloitusruutu %1$d/%2$d" "Uusi aloitusnäytön sivu" @@ -82,17 +84,13 @@ "Järjestelmänvalvoja on poistanut toiminnon käytöstä." "Salli aloitusnäytön kiertäminen" "Kun puhelinta kierretään" - - - - - - + "Pistemerkit" + "Käytössä" + "Ei käytössä" "Ilmoituksien käyttöoikeus tarvitaan" "%1$s tarvitsee ilmoitusten käyttöoikeuden, jotta pistemerkkejä voidaan näyttää." "Muuta asetuksia" - - + "Näytä ilmoituksista kertovat pistemerkit" "Lisää kuvake aloitusruutuun" "Uusille sovelluksille" "Muuta kuvakkeen muotoa" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index f82ea47462..2a70d3d153 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -39,8 +39,7 @@ "Chargement des applications en cours…" "Aucune application trouvée correspondant à « %1$s »" "Rechercher plus d\'applications" - - + "Application" "Notifications" "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." @@ -66,7 +65,10 @@ "Impossible de désinstaller cette application, car il s\'agit d\'une application système." "Dossier sans nom" "L\'application %1$s est désactivée" - + + %1$s a %2$d notification + %1$s a %2$d notificatio​ns + "Page %1$d sur %2$d" "Écran d\'accueil %1$d sur %2$d" "Nouvelle page d\'écran d\'accueil" @@ -82,17 +84,13 @@ "Cette fonction est désactivée par votre administrateur" "Autoriser la rotation de l\'écran d\'accueil" "Lorsque vous faites pivoter le téléphone" - - - - - - + "Points de notification" + "Activé" + "Désactivé" "L\'accès aux notifications est requis" "Pour afficher les points de notification, activez les notifications d\'application pour %1$s" "Modifier les paramètres" - - + "Afficher les points de notification" "Ajouter l\'icône à l\'écran d\'accueil" "Pour les nouvelles applications" "Modifier la forme de l\'icône" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 1d2e743d9d..35b8ca655f 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -39,8 +39,7 @@ "Chargement des applications…" "Aucune application ne correspond à la requête \"%1$s\"" "Rechercher plus d\'applications" - - + "Application" "Notifications" "Appui prolongé pour sélectionner un raccourci." "Appuyez 2X et maintenez la pression pour choisir un raccourci ou utilisez les actions personnalisées" @@ -66,7 +65,10 @@ "Impossible de désinstaller cette application, car il s\'agit d\'une application système." "Dossier sans nom" "%1$s est désactivé." - + + %1$s comporte %2$d notification + %1$s comporte %2$d notifications + "Page %1$d sur %2$d" "Écran d\'accueil %1$d sur %2$d" "Nouvelle page d\'écran d\'accueil" @@ -82,17 +84,13 @@ "Désactivé par votre administrateur" "Autoriser la rotation de l\'écran d\'accueil" "Lorsque vous faites pivoter le téléphone" - - - - - - + "Pastilles de notification" + "Activées" + "Désactivées" "Accès aux notifications requis" "Pour afficher les pastilles de notification, activez les notifications de l\'application %1$s" "Modifier les paramètres" - - + "Afficher les pastilles de notification" "Ajouter l\'icône à l\'écran d\'accueil" "Pour les nouvelles applications" "Modifier la forme des icônes" diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 7e1788ad03..4a9f8dc6d7 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -39,8 +39,7 @@ "Cargando aplicacións…" "Non se atoparon aplicacións que coincidan con \"%1$s\"" "Buscar máis aplicacións" - - + "Aplicación" "Notificacións" "Mantén premido un atallo para seleccionalo." "Toca dúas veces e mantén premido para seleccionar un atallo ou utiliza accións personalizadas." @@ -66,7 +65,10 @@ "Esta aplicación é do sistema e non se pode desinstalar." "Cartafol sen nome" "Desactivouse %1$s" - + + A aplicación %1$s ten %2$d notificacións + A aplicación %1$s ten %2$d notificación + "Páxina %1$d de %2$d" "Pantalla de inicio %1$d de %2$d" "Nova páxina da pantalla de inicio" @@ -82,17 +84,13 @@ "Función desactivada polo administrador" "Permitir xirar a pantalla de inicio" "Ao xirar o teléfono" - - - - - - + "Puntos de notificacións" + "Opción activada" + "Opción desactivada" "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" - - + "Mostrar puntos de notificacións" "Engadir icona á pantalla de inicio" "Para novas aplicacións" "Cambiar forma das iconas" diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index 0db294f402..d0f7cc3f24 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -39,8 +39,7 @@ "ઍપ્લિકેશનો લોડ કરી રહ્યું છે…" "\"%1$s\"થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી" "વધુ ઍપ્લિકેશનો શોધો" - - + "ઍપ" "નોટિફિકેશનો" "એક શૉર્ટકટ ચૂંટવા માટે સ્પર્શ કરી રાખો." "એક શૉર્ટકટ ચૂંટવા અથવા કોઈ કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટૅપ કરીને દબાવી રાખો." @@ -66,7 +65,10 @@ "આ એક સિસ્ટમ ઍપ્લિકેશન છે અને અનઇન્સ્ટોલ કરી શકાતી નથી." "અનામી ફોલ્ડર" "%1$s અક્ષમ કરી" - + + %1$sના %2$d નોટિફિકેશન છે + %1$sના %2$d નોટિફિકેશન છે + "%2$d માંથી %1$d પૃષ્ઠ" "%2$d માંથી %1$d હોમ સ્ક્રીન" "નવું હોમ સ્ક્રીન પૃષ્ઠ" @@ -82,17 +84,13 @@ "તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ" "હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો" "જ્યારે ફોન ફેરવવામાં આવે ત્યારે" - - - - - - + "નોટિફિકેશન માટેના ચિહ્નો" + "ચાલુ છે" + "બંધ છે" "નોટિફિકેશનનો ઍક્સેસની જરૂરી છે" "નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, %1$s માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો" "સેટિંગ્સ બદલો" - - + "નોટિફિકેશન માટેના ચિહ્ન બતાવો" "હોમ સ્ક્રીન પર આઇકન ઉમેરો" "નવી ઍપ્લિકેશનો માટે" "આઇકનનો આકાર બદલો" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 992122625d..b37b17c8d2 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -39,8 +39,7 @@ "ऐप्लिकेशन लोड हो रहे हैं…" "\"%1$s\" से मिलता-जुलता कोई ऐप्लिकेशन नहीं मिला" "और ऐप सर्च करें" - - + "ऐप्लिकेशन" "सूचनाएं" "शॉर्टकट चुनने के लिए दबाकर रखें." "शॉर्टकट चुनने या पसंद के मुताबिक कार्रवाई करने के लिए दो बार टैप करें और कुछ देर दबाए रखें." @@ -52,7 +51,7 @@ "होम पेज" "निकालें" "अनइंस्टॉल करें" - "ऐप की जानकारी" + "ऐप्लिकेशन की जानकारी" "इंस्‍टॉल करें" "शॉर्टकट इंस्‍टॉल करें" "ऐप को उपयोगकर्ता के हस्‍तक्षेप के बिना शॉर्टकट जोड़ने देती है." @@ -66,7 +65,10 @@ "यह एक सिस्टम ऐप्लिकेशन है और इसे अनइंस्टॉल नहीं किया जा सकता." "अनामित फ़ोल्डर" "%1$s अक्षम है" - + + %1$s की %2$d सूचना है + %1$s की %2$d सूचनाएं हैं + "पेज %2$d में से %1$d" "होम स्क्रीन %2$d में से %1$d" "नया होम स्‍क्रीन पेज" @@ -82,17 +84,13 @@ "आपके एडमिन ने बंद किया हुआ है" "होमस्क्रीन घुमाने की अनुमति दें" "फ़ोन घुुमाए जाने पर" - - - - - - + "नई सूचनाएं बताने वाला गोल निशान" + "चालू" + "चालू" "सूचना के एक्सेस की ज़रूरत है" "सूचना बिंदु दिखाने के लिए, %1$s के ऐप्लिकेशन सूचना चालू करें" "सेटिंग बदलें" - - + "नई सूचनाएं बताने वाला गोल निशान दिखाएं" "होम स्क्रीन में आइकॉन जोड़ें" "नए ऐप्लिकेशन के लिए" "आइकॉन का आकार बदलें" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 26dc811be2..1d1919b30a 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -39,8 +39,7 @@ "Učitavanje aplikacija…" "Nema aplikacija podudarnih s upitom \"%1$s\"" "Traži više aplikacija" - - + "Aplikacija" "Obavijesti" "Dodirnite i zadržite kako biste podigli prečac." "Dvaput dodirnite i zadržite pritisak kako biste podigli prečac ili pokušajte prilagođenim radnjama." @@ -66,7 +65,11 @@ "Ovo je aplikacija sustava i ne može se ukloniti." "Neimenovana mapa" "Aplikacija %1$s onemogućena" - + + %1$s, ima %2$d obavijest + %1$s, ima %2$d obavijesti + %1$s, ima %2$d obavijesti + "Stranica %1$d od %2$d" "Početni zaslon %1$d od %2$d" "Nova stranica početnog zaslona" @@ -82,17 +85,13 @@ "Onemogućio administrator" "Dopusti zakretanje početnog zaslona" "Kada se telefon zakrene" - - - - - - + "Točke obavijesti" + "Uključeno" + "Isključeno" "Potreban je pristup obavijestima" "Za prikaz točaka obavijesti uključite obavijesti aplikacije %1$s" "Promjena postavki" - - + "Prikaži točke obavijesti" "Dodaj ikonu na početni zaslon" "Za nove aplikacije" "Promijeni oblik ikona" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index b005f3ee8a..9f965bc4a2 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -39,8 +39,7 @@ "Alkalmazások betöltése…" "Nem található alkalmazás a(z) „%1$s” lekérdezésre" "További alkalmazások keresése" - - + "Alkalmazás" "Értesítések" "Felvételhez tartsa nyomva a parancsikont." "Parancsikon felvételéhez koppintson rá duplán és tartsa nyomva, vagy használjon egyéni műveleteket." @@ -66,7 +65,10 @@ "Ez egy rendszeralkalmazás, és nem lehet eltávolítani." "Névtelen mappa" "A(z) %1$s letiltva" - + + A(z) %1$s %2$d értesítéssel rendelkezik + A(z) %1$s %2$d értesítéssel rendelkezik + "%2$d/%1$d. oldal" "%2$d/%1$d. kezdőképernyő" "Új kezdőképernyő oldal" @@ -82,17 +84,13 @@ "A rendszergazda letiltotta" "A kezdőképernyő elforgatásának engedélyezése" "A telefon elforgatásakor" - - - - - - + "Értesítési pöttyök" + "Be" + "Ki" "Értesítésekhez való hozzáférésre van szükség" "Az értesítési pöttyök megjelenítéséhez kapcsolja be a(z) %1$s alkalmazás értesítéseit" "Beállítások módosítása" - - + "Értesítési pöttyök megjelenítése" "Ikon hozzáadása a kezdőképernyőhöz" "Új alkalmazásoknál" "Ikon formájának módosítása" diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 6239ecdbd0..ca56102723 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -39,8 +39,7 @@ "Հավելվածների բեռնում…" %1$s» հարցմանը համապատասխանող հավելվածներ չեն գտնվել" "Որոնել այլ հավելվածներ" - - + "Հավելված" "Ծանուցումներ" "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար։" "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար կամ օգտվեք հարմարեցրած գործողություններից:" @@ -66,7 +65,10 @@ "Սա համակարգային ծրագիր է և չի կարող ապատեղադրվել:" "Անանուն պանակ" "%1$s հավելվածն անջատված է" - + + %1$s, ունի %2$d ծանուցում + %1$s, ունի %2$d ծանուցում + "Էջ %1$d՝ %2$d-ից" "Հիմնական էկրան %1$d` %2$d-ից" "Հիմնական էկրանի նոր էջ" @@ -82,17 +84,13 @@ "Անջատվել է ձեր ադմինիստրատորի կողմից" "Թույլ տալ հիմնական էկրանի պտտումը" "Հեռախոսը պտտելու դեպքում" - - - - - - + "Ծանուցումների կետիկներ" + "Միացված է" + "Անջատած է" "Անհրաժեշտ է ծանուցման թույլտվություն" "Ծանուցումների կետիկները ցուցադրելու համար միացրեք ծանուցումները %1$s-ի համար" "Փոխել կարգավորումները" - - + "Ցուցադրել ծանուցումների կետիկները" "Ավելացնել պատկերակը Հիմնական էկրանին" "Նոր հավելվածների համար" "Փոխել պատկերակների տեսքը" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 9f58265e6d..396c5b164b 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -39,8 +39,7 @@ "Memuat aplikasi…" "Tidak ditemukan aplikasi yang cocok dengan \"%1$s\"" "Telusuri aplikasi lainnya" - - + "Aplikasi" "Notifikasi" "Tap lama untuk memilih pintasan." "Tap dua kali & tahan untuk memilih pintasan atau menggunakan tindakan khusus." @@ -66,7 +65,10 @@ "Ini adalah aplikasi sistem dan tidak dapat dicopot pemasangannya." "Folder Tanpa Nama" "%1$s dinonaktifkan" - + + %1$s, memiliki %2$d notifikasi + %1$s, memiliki %2$d notifikasi + "Halaman %1$d dari %2$d" "Layar utama %1$d dari %2$d" "Halaman layar utama baru" @@ -82,17 +84,13 @@ "Dinonaktifkan oleh admin" "Izinkan layar Utama diputar" "Saat ponsel diputar" - - - - - - + "Titik notifikasi" + "Aktif" + "Nonaktif" "Perlu akses notifikasi" "Guna menampilkan Titik Notifikasi, aktifkan notifikasi aplikasi untuk %1$s" "Ubah setelan" - - + "Tampilkan titik notifikasi" "Tambahkan ikon ke Layar utama" "Untuk aplikasi baru" "Ubah bentuk ikon" diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 2826861ffd..99bd888ade 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -39,8 +39,7 @@ "Hleður forrit…" "Ekki fundust forrit sem samsvara „%1$s“" "Leita að fleiri forritum" - - + "Forrit" "Tilkynningar" "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." @@ -66,7 +65,10 @@ "Þetta er kerfisforrit sem ekki er hægt að fjarlægja." "Ónefnd mappa" "Óvirkt %1$s" - + + %1$s, er með %2$d tilkynningu + %1$s, er með %2$d tilkynningar + "Síða %1$d af %2$d" "Heimaskjár %1$d af %2$d" "Ný síða á heimaskjá" @@ -82,17 +84,13 @@ "Gert óvirkt af kerfisstjóra" "Leyfa snúning fyrir heimaskjá" "Þegar símanum er snúið" - - - - - - + "Tilkynningapunktar" + "Kveikt" + "Slökkt" "Aðgangs að tilkynningum er krafist" "Til að sýna tilkynningarpunkta skaltu kveikja á forritstilkynningum fyrir %1$s" "Breyta stillingum" - - + "Sýna tilkynningapunkta" "Bæta tákni á heimaskjáinn" "Fyrir ný forrit" "Breyta formi tákns" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 825f914fe5..0bdc5afc97 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -39,8 +39,7 @@ "Caricamento delle app…" "Nessuna app trovata corrispondente a \"%1$s\"" "Cerca altre app" - - + "App" "Notifiche" "Tocca e tieni premuto per scegliere la scorciatoia" "Tocca due volte e tieni premuto per scegliere una scorciatoia o per usare azioni personalizzate." @@ -66,7 +65,10 @@ "Questa è un\'app di sistema e non può essere disinstallata." "Cartella senza nome" "App %1$s disattivata" - + + %1$s, ha %2$d notifiche + %1$s, ha %2$d notifica + "Pagina %1$d di %2$d" "Schermata Home %1$d di %2$d" "Nuova pagina Schermata Home" @@ -82,17 +84,13 @@ "Disattivata dall\'amministratore" "Consenti rotazione della schermata Home" "Con il telefono ruotato" - - - - - - + "Indicatori di notifica" + "On" + "Off" "Accesso alle notifiche necessario" "Per mostrare gli indicatori di notifica, attiva le notifiche per l\'app %1$s" "Modifica impostazioni" - - + "Mostra indicatori di notifica" "Aggiungi icone alla schermata Home" "Per le nuove app" "Cambia la forma delle icone" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index 6104bc0d19..9525468f68 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -39,8 +39,7 @@ "טוען אפליקציות…" "לא נמצאו אפליקציות התואמות ל-\"%1$s\"" "חפש אפליקציות נוספות" - - + "אפליקציה" "התראות" "כדי להוסיף קיצור דרך, יש לגעת בו ולהחזיק אותו." "כדי להוסיף קיצור דרך או להשתמש בפעולות מותאמות אישית, יש להקיש על קיצור הדרך פעמיים ולהחזיק אותו." @@ -66,7 +65,12 @@ "זוהי אפליקציית מערכת ולא ניתן להסיר את התקנתה." "תיקיה ללא שם" "%1$s מושבתת" - + + לאפליקציה %1$s יש %2$d התראות + לאפליקציה %1$s יש %2$d התראות + לאפליקציה %1$s יש %2$d התראות + לאפליקציה %1$s יש התראה אחת (%2$d) + "‏דף %1$d מתוך %2$d" "‏מסך דף הבית %1$d מתוך %2$d" "מסך דף הבית חדש" @@ -82,17 +86,13 @@ "הושבת על ידי מנהל המערכת שלך" "אפשרות סיבוב של מסך דף הבית" "כאשר הטלפון מסובב" - - - - - - + "סימני ההתראות" + "מופעל" + "כבוי" "נדרשת גישה להתראות" "כדי להציג את סימני ההתראות,יש להפעיל התראות מהאפליקציה %1$s" "שנה את ההגדרות" - - + "הצגת סימני ההתראות" "הוספת סמל במסך דף הבית" "לאפליקציות חדשות" "שינוי הצורה של הסמלים" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 089b938d51..2c5da02c38 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -39,8 +39,7 @@ "アプリを読み込んでいます…" "「%1$s」に一致するアプリは見つかりませんでした" "他のアプリを検索" - - + "アプリ" "通知" "ショートカットを追加するには押し続けます。" "ダブルタップ後に押し続けてショートカットを選択するか、カスタム操作を使用してください。" @@ -66,7 +65,10 @@ "このシステムアプリはアンインストールできません。" "名前のないフォルダ" "「%1$s」は無効です" - + + %1$s の通知が %2$d 件あります + %1$s の通知が %2$d 件あります + "%1$d/%2$dページ" "ホーム画面: %1$d/%2$d" "新しいホーム画面ページ" @@ -82,17 +84,13 @@ "管理者により無効にされています" "ホーム画面の回転を許可" "スマートフォンが回転したとき" - - - - - - + "通知ドット" + "ON" + "OFF" "通知へのアクセス権限が必要" "通知ドットを表示するには、「%1$s」のアプリ通知を ON にしてください" "設定を変更" - - + "通知ドットの表示" "ホーム画面にアイコンを追加" "新しいアプリをダウンロードしたとき" "アイコンの形の変更" diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index fef1a48689..af603c86e0 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -39,8 +39,7 @@ "აპები იტვირთება…" "„%1$s“-ის თანხვედრი აპები არ მოიძებნა" "მეტი აპის პოვნა" - - + "აპი" "შეტყობინებები" "შეეხეთ და დააყოვნეთ მალსახმობის ასარჩევად." "ორმაგად შეეხეთ და გეჭიროთ მალსახმობის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად." @@ -66,7 +65,10 @@ "ეს სისტემური აპია და მისი წაშლა შეუძლებელია." "უსახელო საქაღალდე" "%1$s გაითიშა" - + + %1$s-ში არის %2$d შეტყობინება + %1$s-ში არის %2$d შეტყობინება + "გვერდი %1$d %2$d-დან" "მთავარი ეკრანი %1$d, %2$d-დან" "მთავარი ეკრანის ახალი გვერდი" @@ -82,17 +84,13 @@ "გათიშულია თქვენი ადმინისტრატორის მიერ" "მთავარი ეკრანის შეტრიალების დაშვება" "ტელეფონის შეტრიალებისას" - - - - - - + "შეტყობინების ნიშნულები" + "ჩართულია" + "გამორთულია" "საჭიროა შეტყობინებებზე წვდომა" "შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები %1$s-ისთვის" "პარამეტრების შეცვლა" - - + "შეტყობინების ნიშნულების ჩვენება" "ხატულას მთავარ ეკრანზე დამატება" "ახალი აპებისთვის" "ხატულას ფორმის შეცვლა" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index dd26eab103..135360e722 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -39,8 +39,7 @@ "Қолданбалар жүктелуде…" "\"%1$s\" сұрауына сәйкес келетін қолданбалар жоқ" "Қосымша қолданбалар іздеу" - - + "Қолданба" "Хабарландырулар" "Таңбашаны таңдау үшін оны басып, ұстап тұрыңыз." "Екі рет басып, ұстап тұрып, таңбашаны таңдаңыз немесе арнаулы әрекеттерді пайдаланыңыз." @@ -66,7 +65,10 @@ "Бұл жүйе қолданбасы, сондықтан оны алу мүмкін емес." "Атауы жоқ қалта" "%1$s өшірілді" - + + %1$s қолданбасында %2$d хабарландыру бар + %1$s қолданбасында %2$d хабарландыру бар + "%1$d бет, барлығы %2$d" "%1$d негізгі экран, барлығы %2$d" "Жаңа негізгі экран беті" @@ -82,17 +84,13 @@ "Әкімші өшірді" "Негізгі экранның бұрылуына рұқсат ету" "Телефон бұрылғанда" - - - - - - + "Хабарландыру белгілері" + "Қосулы" + "Өшірулі" "Хабарландыруға кіру рұқсаты қажет" "Хабарландыру белгілерін көрсету үшін %1$s қолданбасының қолданба хабарландыруларын қосыңыз" "Параметрлерді өзгерту" - - + "Хабарландыру белгілерін көрсету" "Негізгі экранға белгіше енгізу" "Жаңа қолданбаларға арналған" "Белгіше пішінін өзгерту" diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index c6e0ba4831..d7c8c8895b 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -39,8 +39,7 @@ "កំពុងផ្ទុកកម្មវិធី…" "រកមិនឃើញកម្មវិធី​ដែលត្រូវគ្នាជាមួយ \"%1$s\" ទេ" "ស្វែងរកកម្មវិធីច្រើនទៀត" - - + "កម្មវិធី" "ការ​ជូនដំណឹង" "ចុច​ឱ្យ​ជាប់​ដើម្បី​ជ្រើស​រើស​ផ្លូវកាត់​មួយ។" "ចុច​ពីរ​ដង ហើយ​ចុច​ឱ្យ​ជាប់​ដើម្បី​ជ្រើសរើស​ផ្លូវកាត់​មួយ ឬ​ប្រើ​សកម្មភាព​ផ្ទាល់ខ្លួន។" @@ -66,7 +65,10 @@ "នេះ​​​ជា​កម្មវិធី​ប្រព័ន្ធ មិន​អាច​លុប​បាន​ទេ។" "ថត​គ្មាន​ឈ្មោះ" "បានបិទដំណើរការ %1$s" - + + %1$s, មាន​ការជូនដំណឹង %2$d + %1$s, មាន​ការជូនដំណឺង %2$d + "ទំព័រ %1$d នៃ %2$d" "អេក្រង់​ដើម %1$d នៃ %2$d" "ទំព័រអេក្រង់ដើមថ្មី" @@ -82,17 +84,13 @@ "បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក" "អនុញ្ញាតការបងិ្វលអេក្រង់ដើម" "នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក" - - - - - - + "ស្លាកជូនដំណឹង" + "បើក" + "បិទ" "តម្រូវ​ឲ្យមាន​សិទ្ធិចូល​ប្រើប្រាស់​ការជូនដំណឹង" "ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ %1$s" "ប្ដូរ​ការកំណត់" - - + "បង្ហាញ​ស្លាក​ជូនដំណឹង" "បញ្ចូល​រូបតំណាង​ទៅ​អេក្រង់​ដើម" "សម្រាប់កម្មវិធីថ្មី" "ប្តូររូបរាងរូបតំណាង" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 965700e6a1..de9ee52cd3 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -39,8 +39,7 @@ "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..." "\"%1$s\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ" "ಮತ್ತಷ್ಟು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹುಡುಕಿ" - - + "ಆ್ಯಪ್" "ಅಧಿಸೂಚನೆಗಳು" "ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ." "ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ." @@ -66,7 +65,10 @@ "ಇದೊಂದು ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." "ಹೆಸರಿಲ್ಲದ ಫೋಲ್ಡರ್" "%1$s ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" - + + %1$s, %2$d ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ + %1$s, %2$d ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ + "%2$d ರಲ್ಲಿ %1$d ಪುಟ" "%2$d ರಲ್ಲಿ %1$d ಮುಖಪುಟದ ಪರದೆ" "ಹೊಸ ಮುಖಪುಟ ಪರದೆ" @@ -82,17 +84,13 @@ "ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ" "ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ" "ಫೋನ್‌ ತಿರುಗಿಸಿದಾಗ" - - - - - - + "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳು" + "ಆನ್ ಆಗಿದೆ" + "ಆಫ್ ಆಗಿದೆ" "ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ" "ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, %1$s ಗೆ ಅಪ್ಲಿಕೇಶನ್‌ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್‌ ಮಾಡಿ" "ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ" - - + "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳನ್ನು ತೋರಿಸಿ" "ಮುಖಪುಟದ ಪರದೆಗೆ ಐಕಾನ್ ಸೇರಿಸಿ" "ಹೊಸ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ" "ಐಕಾನ್ ಆಕಾರವನ್ನು ಬದಲಿಸಿ" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 3ed09e5ef9..121f141112 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -39,8 +39,7 @@ "앱 로드 중…" "\'%1$s\'과(와) 일치하는 앱이 없습니다." "더 많은 앱 검색" - - + "앱" "알림" "바로가기를 선택하려면 길게 터치하세요." "바로가기를 선택하려면 두 번 탭한 다음 길게 터치하거나 맞춤 동작을 사용하세요." @@ -66,7 +65,10 @@ "시스템 앱은 제거할 수 없습니다." "이름이 없는 폴더" "%1$s 사용 안함" - + + %1$s%2$d개의 알림이 있음 + %1$s%2$d개의 알림이 있음 + "페이지 %1$d/%2$d" "홈 화면 %1$d/%2$d" "새로운 홈 화면 페이지" @@ -82,17 +84,13 @@ "관리자가 사용 중지함" "홈 화면 회전 허용" "휴대전화 회전 시" - - - - - - + "알림 표시 점" + "사용" + "사용 안함" "알림 액세스 권한 필요" "알림 표시점을 표시하려면 %1$s의 앱 알림을 사용 설정하세요." "설정 변경" - - + "알림 표시 점 보기" "홈 화면에 아이콘 추가" "새로 설치한 앱에 적용" "아이콘 모양 변경" diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 4db7c8d01c..301840c11f 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -39,8 +39,7 @@ "Колдонмолор жүктөлүүдө…" "\"%1$s\" сурамына дал келген колдонмолор табылган жок" "Көбүрөөк колдонмолорду издөө" - - + "Колдонмо" "Билдирмелер" "Кыска жолду тандоо үчүн басып туруңуз." "Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." @@ -66,7 +65,10 @@ "Бул системдик колдонмо жана аны чечкенге болбойт." "Аты жок фолдер" "%1$s өчүрүлгөн" - + + %1$s, %2$d билдирмеси бар + %1$s, %2$d билдирмеси бар + "%2$d ичинен %1$d барак" "Үй экраны %2$d ичинен %1$d" "Жаңы башкы экран барагы" @@ -82,17 +84,13 @@ "Администраторуңуз өчүрүп койгон" "Башкы экранды айлантууга уруксат берүү" "Телефон айланганда" - - - - - - + "Билдирмелер белгилери" + "Күйүк" + "Өчүк" "Эскертмелерге уруксат берилиши керек" "Эскертме белгилерин көрсөтүү максатында, %1$s үчүн колдонмонун эскертмелерин күйгүзүү керек" "Жөндөөлөрдү өзгөртүү" - - + "Билдирмелер белгилерин көрсөтүү" "Башкы экранга сүрөтчө кошуу" "Жаңы колдонмолор үчүн" "Сүрөтчөнүн формасын өзгөртүү" diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index 3c55a8712f..692e5afe97 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -39,8 +39,7 @@ "ກໍາລັງໂຫຼດແອັບ…" "ບໍ່ພົບແອັບທີ່ກົງກັບ \"%1$s\"" "ຊອກຫາແອັບເພີ່ມເຕີມ" - - + "ແອັບ" "ການແຈ້ງເຕືອນ" "ແຕະຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ." "ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ ຫຼື ໃຊ້ຄຳສັ່ງແບບກຳນົດເອງ." @@ -66,7 +65,10 @@ "ນີ້ແມ່ນແອັບຯຂອງລະບົບ ແລະບໍ່ສາມາດຖອນການຕິດຕັ້ງອອກໄດ້." "ໂຟນເດີຍັງບໍ່ຖືກຕັ້ງຊື່" "ປິດການນຳໃຊ້ %1$s ແລ້ວ" - + + %1$s, ມີ %2$d ການແຈ້ງເຕືອນ + %1$s, ມີ %2$d ການແຈ້ງເຕືອນ + "ໜ້າ %1$d ຈາກ %2$d" "ໜ້າຈໍຫຼັກ %1$d ໃນ %2$d" "ໜ້າ​ຂອງ​ໜ້າ​ຈໍ​ຫຼັກ​ໃໝ່" @@ -82,17 +84,13 @@ "ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ" "ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້" "ເມື່ອໝຸນໂທລະສັບ" - - - - - - + "ຈຸດການແຈ້ງເຕືອນ" + "ເປີດ" + "ປິດ" "ຕ້ອງໃຊ້ການເຂົ້າເຖິງການແຈ້ງເຕືອນ" "ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ %1$s" "ບັນທຶກການຕັ້ງຄ່າ" - - + "ສະແດງຈຸດການແຈ້ງເຕືອນ" "ເພີ່ມໄອຄອນໃສ່ໜ້າຈໍຫຼັກ" "ສຳລັບແອັບໃໝ່" "ປ່ຽນຮູບຮ່າງໄອຄອນ" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index 592eb9d821..22d0c7be73 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -39,8 +39,7 @@ "Įkeliamos programos…" "Nerasta jokių užklausą „%1$s“ atitinkančių programų" "Ieškoti daugiau programų" - - + "Programa" "Pranešimai" "Paliesk. ir palaikyk., kad pasirinkt. spart. klav." "Dukart palieskite ir palaikykite, kad pasirinkt. spartųjį klavišą ar naudotumėte tinkintus veiksmus." @@ -66,7 +65,12 @@ "Tai sistemos programa ir jos negalima pašalinti." "Aplankas be pavadinimo" "„%1$s“ išjungta" - + + Programoje „%1$s“ yra %2$d pranešimas + Programoje „%1$s“ yra %2$d pranešimai + Programoje „%1$s“ yra %2$d pranešimo + Programoje „%1$s“ yra %2$d pranešimų + "%1$d psl. iš %2$d" "%1$d pagrindinis ekranas iš %2$d" "Naujas pagrindinio ekrano puslapis" @@ -82,17 +86,13 @@ "Išjungė administratorius" "Leisti pasukti pagrindinį ekraną" "Kai telefonas pasukamas" - - - - - - + "Pranešimų taškai" + "Įjungta" + "Išjungta" "Reikalinga prieiga prie pranešimų" "Kad būtų rodomi pranešimų taškai, įjunkite programos „%1$s“ pranešimus." "Keisti nustatymus" - - + "Rodyti pranešimų taškus" "Pridėti piktogr. prie pagrindinio ekrano" "Skirta naujoms programoms" "Pakeisti piktogramos formą" diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 174cda2a63..f9240bd4da 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -39,8 +39,7 @@ "Notiek lietotņu ielāde…" "Vaicājumam “%1$s” neatbilda neviena lietotne" "Meklēt citas lietotnes" - - + "Lietotne" "Paziņojumi" "Lai atlasītu saīsni, pieskarieties un turiet to." "Lai atlasītu saīsni, veiciet dubultskārienu uz tās un turiet to. Varat arī veikt pielāgotas darbības." @@ -66,7 +65,11 @@ "Šī ir sistēmas lietotne, un to nevar atinstalēt." "Mape bez nosaukuma" "Lietotne %1$s ir atspējota" - + + Lietotnē %1$s ir %2$d paziņojumi + Lietotnē %1$s ir %2$d paziņojums + Lietotnē %1$s ir %2$d paziņojumi + "%1$d. lapa no %2$d" "Sākuma ekrāns: %1$d no %2$d" "Jauna sākuma ekrāna lapa" @@ -82,17 +85,13 @@ "Atspējojis administrators" "Atļaut sākuma ekrāna pagriešanu" "Pagriežot tālruni" - - - - - - + "Paziņojumu punkti" + "Ieslēgts" + "Izslēgts" "Nepieciešama piekļuve paziņojumiem" "Lai tiktu rādīti paziņojumu punkti, ieslēdziet paziņojumus lietotnei %1$s." "Mainīt iestatījumus" - - + "Rādīt paziņojumu punktus" "Pievienot ikonu sākuma ekrānā" "Jaunām lietotnēm" "Mainīt ikonu formu" diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 4252a78e76..d40b925ebf 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -39,8 +39,7 @@ "Се вчитуваат апликации…" "Не се најдени апликации што одговараат на „%1$s“" "Пребарај други апликации" - - + "Апликација" "Известувања" "Допрете двапати и задржете за избор на кратенка." "Допрете двапати и задржете за избор на кратенка или користете приспособени дејства." @@ -66,7 +65,10 @@ "Ова е системска апликација и не може да се деинсталира." "Неименувана папка" "%1$s е оневозможена" - + + %1$s има %2$d известување + %1$s има %2$d известувања + "Страница %1$d од %2$d" "Екран на почетна страница %1$d од %2$d" "Нова страница на почетен екран" @@ -82,17 +84,13 @@ "Оневозможено од администраторот" "Дозволете ротација на Почетниот екран" "Кога телефонот се ротира" - - - - - - + "Точки за известување" + "Вклучено" + "Исклучено" "Потребен е пристап до известувањата" "За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата %1$s" "Промени ги поставките" - - + "Прикажувај точки за известување" "Додај икона на почетниот екран" "За нови апликации" "Променете ја формата на иконата" diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index f34d58c904..93426ad1e0 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -39,8 +39,7 @@ "ആപ്പുകൾ ലോഡുചെയ്യുന്നു..." "\"%1$s\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പുകളൊന്നും കണ്ടെത്തിയില്ല" "കൂടുതൽ ആപ്പുകൾക്ക് തിരയുക" - - + "ആപ്പ്" "അറിയിപ്പുകൾ" "തിരഞ്ഞെടുക്കുന്നതിന് കുറുക്കുവഴി സ്‌പർശിച്ച് പിടിക്കുക." "കുറുക്കുവഴി തിരഞ്ഞെടുക്കാനോ ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ 2 തവണ ടാപ്പ് ചെയ്‌ത് പിടിക്കുക." @@ -66,7 +65,10 @@ "ഇതൊരു സിസ്‌റ്റം അപ്ലിക്കേഷനായതിനാൽ അൺഇൻസ്‌റ്റാളുചെയ്യാനാവില്ല." "പേരുനൽകാത്ത ഫോൾഡർ" "%1$s പ്രവർത്തനരഹിതമാക്കി" - + + %1$s എന്ന ആപ്പിന്, %2$d അറിയിപ്പുകൾ ഉണ്ട് + %1$s എന്ന ആപ്പിന്, %2$d അറിയിപ്പുണ്ട് + "പേജ് %1$d / %2$d" "ഹോം സ്‌ക്രീൻ %1$d / %2$d" "പുതിയ ഹോം സ്ക്രീൻ പേജ്" @@ -82,17 +84,13 @@ "അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു" "ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക" "ഫോൺ തിരിച്ച നിലയിലായിരിക്കുമ്പോൾ" - - - - - - + "അറിയിപ്പ് ഡോട്ടുകൾ" + "ഓണാണ്" + "ഓഫാണ്" "അറിയിപ്പിനായുള്ള ആക്‌സസ് ആവശ്യമാണ്" "അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുന്നതിന്, %1$s എന്നയാളിനായുള്ള ആപ്പ് അറിയിപ്പുകൾ ഓണാക്കുക" "ക്രമീകരണം മാറ്റുക" - - + "അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുക" "ഹോം സ്ക്രീനിലേക്ക് ഐക്കൺ ചേർക്കുക" "പുതിയ ആപ്പുകൾക്ക്" "ഐക്കണിന്റെ ആകാരം മാറ്റുക" diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index e6c9af827f..1b8b3efd8a 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -39,8 +39,7 @@ "Аппыг ачааллаж байна..." "\"%1$s\"-д тохирох апп олдсонгүй" "Бусад апп-г хайх" - - + "Апп" "Мэдэгдэл" "Товчлол авах бол удаан дарна уу." "Товчлол авах эсвэл тохируулсан үйлдлийг ашиглахын тулд давхар товшоод хүлээнэ үү." @@ -66,7 +65,10 @@ "Энэ апп нь системийн апп ба устгах боломжгүй." "Нэргүй фолдер" "%1$s-г идэвхгүй болгосон" - + + %1$s, %2$d мэдэгдэлтэй байна + %1$s, %2$d мэдэгдэлтэй байна + "%2$d-н %1$d хуудас" "%2$d-н Нүүр дэлгэц %1$d" "Шинэ үндсэн нүүр хуудас" @@ -82,17 +84,13 @@ "Таны админ идэвхгүй болгосон" "Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх" "Утсыг эргүүлсэн үед" - - - - - - + "Мэдэгдлийн цэг" + "Асаалттай" + "Унтраалттай" "Мэдэгдлийн хандалт шаардлагатай" "Мэдэгдлийн цэгийг харуулахын тулд %1$s-д аппын мэдэгдлийг асаана уу" "Тохиргоог өөрчлөх" - - + "Мэдэгдлийн цэгийг харуулах" "Нүүр хуудаст дүрс тэмдэг нэмэх" "Шинэ аппад зориулсан" "Дүрс тэмдгийн хэлбэрийг өөрчлөх" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 022cb7b51c..4f0de654d6 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -22,8 +22,8 @@ "Launcher3" "कार्य" - "अॅप इंस्टॉल केलेला नाही." - "अॅप उपलब्ध नाही" + "अ‍ॅप इंस्टॉल केलेला नाही." + "अ‍ॅप उपलब्ध नाही" "डाउनलोड केलेला अ‍ॅप सुरक्षित मोड मध्‍ये अक्षम केला" "विजेट सुरक्षित मोडमध्ये अक्षम झाले" "शॉर्टकट उपलब्ध नाही" @@ -39,8 +39,7 @@ "अॅप्स लोड करत आहे…" "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत" "अधिक अॅप्स शोधा" - - + "अॅप" "सूचना" "शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." "शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा." @@ -52,21 +51,24 @@ "होम" "काढा" "अनइंस्टॉल करा" - "अॅप माहिती" + "अ‍ॅप माहिती" "इंस्टॉल करा" "शॉर्टकट स्‍थापित करा" - "वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते." + "वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अ‍ॅप ला अनुमती देते." "होम सेटिंग्ज आणि शॉर्टकट वाचा" - "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते." + "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अ‍ॅप ला अनुमती देते." "होम सेटिंग्ज आणि शॉर्टकट लिहा" - "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते." + "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अ‍ॅप ला अनुमती देते." "%1$s ला फोन कॉल करण्याची अनुमती नाही" "विजेट लोड करण्यात समस्या" "सेटअप" - "हा सिस्टम अॅप आहे आणि अनइंस्टॉल केला जाऊ शकत नाही." + "हा सिस्टम अ‍ॅप आहे आणि अनइंस्टॉल केला जाऊ शकत नाही." "अनामित फोल्डर" "%1$s अक्षम केला आहे" - + + %1$sसाठी%2$dसूचना आहेत + %1$sसाठी %2$d सूचना आहेत + "%2$d पैकी %1$d पृष्ठ" "%2$d पैकी %1$d मुख्य स्क्रीन" "नवीन मुख्य स्क्रीन पृष्ठ" @@ -82,17 +84,13 @@ "आपल्या प्रशासकाने अक्षम केले" "मुख्यस्क्रीन फिरविण्‍यास अनुमती द्या" "फोन फिरविला जातो तेव्हा" - - - - - - + "सूचना बिंदू" + "सुरू" + "बंद" "सूचनांच्या अ‍ॅक्सेसची आवश्यकता आहे" "सूचना बिंदू दाखवण्यासाठी, %1$s साठी अ‍ॅप सूचना चालू करा" "सेटिंग्ज बदला" - - + "सूचना बिंदू दाखवा" "होम स्क्रीनवर आयकन जोडा" "नवीन अॅप्ससाठी" "चिन्हाचा आकार बदला" @@ -106,8 +104,8 @@ "अज्ञात" "काढा" "शोधा" - "हा अॅप इंस्टॉल केलेला नाही" - "या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता." + "हा अ‍ॅप इंस्टॉल केलेला नाही" + "या चिन्हासाठी अ‍ॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अ‍ॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता." "%1$s डाउनलोड होत आहे , %2$s पूर्ण झाले" "%1$s इंस्टॉल करण्याची प्रतिक्षा करत आहे" "%1$s विजेट" diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index e30d632687..4654209c1a 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -39,8 +39,7 @@ "Memuatkan apl…" "Tiada apl yang ditemui sepadan dengan \"%1$s\"" "Cari lagi apl" - - + "Apl" "Pemberitahuan" "Sentuh & tahan untuk mengambil pintasan." "Ketik dua kali & tahan untuk mengambil pintasan atau menggunakan tindakan tersuai." @@ -66,7 +65,10 @@ "Ini ialah apl sistem dan tidak boleh dinyahpasang." "Folder Tanpa Nama" "%1$s dilumpuhkan" - + + %1$s, mempunyai %2$d pemberitahuan + %1$s, mempunyai %2$d pemberitahuan + "Halaman %1$d daripada %2$d" "Skrin Laman Utama %1$d daripada %2$d" "Halaman skrin utama baharu" @@ -82,17 +84,13 @@ "Dilumpuhkan oleh pentadbir anda" "Benarkan putaran Skrin Utama" "Apabila telefon diputar" - - - - - - + "Titik pemberitahuan" + "Hidup" + "Mati" "Akses pemberitahuan diperlukan" "Untuk menunjukkan Titik Pemberitahuan, hidupkan pemberitahuan apl untuk %1$s" "Tukar tetapan" - - + "Tunjukkan titik pemberitahuan" "Tambahkan ikon pada Skrin Utama" "Untuk apl baharu" "Tukar bentuk ikon" diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 06598e06fb..f25de749f2 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -39,8 +39,7 @@ "အက်ပ်များကို ဖွင့်နေသည်…" "\"%1$s\" နှင့်ကိုက်ညီသည့် အပ်ပ်များကို မတွေ့ပါ" "နောက်ထပ် အက်ပ်များကို ရှာပါ" - - + "အက်ပ်" "အကြောင်းကြားချက်များ" "ဖြတ်လမ်းလင့်ခ်တစ်ခုကို ရွေးရန် ထိပြီး ဖိထားပါ။" "ဖြတ်လမ်းလင့်ခ်ကို ရွေးရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။" @@ -66,7 +65,10 @@ "ဤအပ်ပလီကေးရှင်းမှာ စစ်စတန်ပိုင်းဆိုင်ရာ အပ်ပလီကေးရှင်းဖြစ်ပါသည်။ ထုတ်ပစ်၍ မရပါ" "အမည်မရှိအကန့်" "%1$s ကို ပိတ်ထားသည်" - + + %1$s တွင် သတိပေးချက် %2$d ခု ရှိသည် + %1$s တွင် သတိပေးချက် %2$d ခု ရှိသည် + "စာမျက်နှာ %1$d မှ %2$d" "ပင်မစာမျက်နှာ %1$d မှ %2$d" "ပင်မမျက်နှာပြင် စာမျက်နှာသစ်" @@ -82,17 +84,13 @@ "သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်" "ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ" "ဖုန်းကိုလှည့်ထားစဉ်" - - - - - - + "သတိပေးချက် အစက်များ" + "ဖွင့်ထားသည်" + "ပိတ်ထားသည်" "အကြောင်းကြားချက် အသုံးပြုခွင့် လိုအပ်သည်" "အကြောင်းကြားချက် အစက်များကို ပြသရန် %1$s အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ" "ဆက်တင်များ ပြောင်းရန်" - - + "သတိပေးချက် အစက်များ ပြရန်" "ပင်မစာမျက်နှာသို့ သင်္ကေတပုံ ထည့်ရန်" "အက်ပ်အသစ်များအတွက်" "သင်္ကေတပုံစံကို ပြောင်းရန်" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 6534f85fbc..7400beb62d 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -39,8 +39,7 @@ "Laster inn appene …" "Fant ingen apper som samsvarer med «%1$s»" "Søk etter flere apper" - - + "App" "Varsler" "Trykk og hold for å velge en snarvei." "Dobbelttrykk og hold for å velge en snarvei eller bruke tilpassede handlinger." @@ -66,7 +65,10 @@ "Dette er en systemapp som ikke kan avinstalleres." "Mappe uten navn" "Slo av %1$s" - + + %1$s har %2$d varsler + %1$s har %2$d varsel + "Side %1$d av %2$d" "Startside %1$d av %2$d" "Ny side på startskjermen" @@ -82,17 +84,13 @@ "Administratoren har slått av funksjonen" "Tillat rotasjon av startskjermen" "Når telefonen roteres" - - - - - - + "Varselsprikker" + "På" + "Av" "Tilgang til varsler er nødvendig" "Slå på appvarsler for %1$s for å vise varselsprikker" "Endre innstillingene" - - + "Vis varselsprikker" "Legg til ikon på startsiden" "For nye apper" "Endre formen på ikonet" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index d205109d7b..be40ec162d 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -39,8 +39,7 @@ "अनुप्रयोगहरू लोड गर्दै…" "\"%1$s\" सँग मिल्दो कुनै अनुप्रयोग भेटिएन" "थप अनुप्रयोगहरू खोज्नुहोस्" - - + "अनुप्रयोग" "सूचनाहरू" "कुनै सर्टकट छनौट गर्न छोइराख्नुहोस्।" "कुनै सर्टकट छनौट गर्न वा रोजेका कारबाहीहरू प्रयोग गर्न डबल ट्याप गरेर छोइराख्नुहोस्।" @@ -66,7 +65,10 @@ "यो प्रणाली अनुप्रयोग हो र यसलाई स्थापना रद्द गर्न सकिँदैन।" "बेनाम फोल्डर" "असक्षम पारिएको %1$s" - + + %1$s, का %2$d सूचनाहरू छन् + %1$s, को %2$d सूचना छ + "पृष्ठ %2$d को %1$d" "गृह स्क्रिन %1$d को %2$d" "नयाँ गृह स्क्रिन पृष्ठ" @@ -82,17 +84,13 @@ "तपाईँको प्रशासकद्वारा असक्षम गरिएको" "गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्" "फोनलाई घुमाइँदा" - - - - - - + "सूचनाको प्रतीक जनाउने थोप्लाहरू" + "सक्रिय" + "निष्क्रिय" "सूचनासम्बन्धी पहुँच आवश्यक हुन्छ" "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन %1$s को अनुप्रयोगसम्बन्धी सूचनाहरूलाई सक्रिय गर्नुहोस्" "सेटिङहरू बदल्नुहोस्" - - + "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउनुहोस्" "गृह स्क्रिनमा आइकन थप्नुहोस्" "नयाँ अनुप्रयोगका लागि" "आइकनको आकार परिवर्तन गर्नुहोस्" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index e4b22332a5..b0e0cb23ce 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -39,8 +39,7 @@ "Apps laden…" "Er zijn geen apps gevonden die overeenkomen met \'%1$s\'" "Zoeken naar meer apps" - - + "App" "Meldingen" "Tik en houd vast om snelkoppeling toe te voegen." "Dubbeltik en houd vast om een snelkoppeling toe te voegen of aangepaste acties te gebruiken." @@ -66,7 +65,10 @@ "Dit is een systeemapp die niet kan worden verwijderd." "Naamloze map" "%1$s is uitgeschakeld" - + + %1$s, heeft %2$d meldingen + %1$s, heeft %2$d melding + "Pagina %1$d van %2$d" "Startscherm %1$d van %2$d" "Nieuwe startschermpagina" @@ -82,17 +84,13 @@ "Uitgeschakeld door je beheerder" "Draaien van startscherm toestaan" "Wanneer de telefoon gedraaid is" - - - - - - + "Meldingsstipjes" + "Aan" + "Uit" "Toegang tot meldingen vereist" "Als je meldingsstipjes wilt weergeven, schakel je app-meldingen in voor %1$s" "Instellingen wijzigen" - - + "Meldingsstipjes weergeven" "Pictogram toevoegen aan startscherm" "Voor nieuwe apps" "Vorm van pictogram wijzigen" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index e4351c18c7..8c2632529c 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -39,8 +39,7 @@ "ଆପ୍‌ ଲୋଡ୍‌ ହେଉଛି..." "\"%1$s\" ସହିତ ମେଳ ହେଉଥିବା କୌଣସି ଆପ୍‌ ମିଳିଲା ନାହିଁ" "ଅଧିକ ଆପ୍‌ ଖୋଜନ୍ତୁ" - - + "ଆପ୍" "ବିଜ୍ଞପ୍ତି" "ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।" "ଡବଲ୍‌-ଟାପ୍‌ କରନ୍ତୁ ଏବଂ ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ଧରି ରଖନ୍ତୁ କିମ୍ୱା କଷ୍ଟମ୍ ପ୍ରକ୍ରିୟା ବ୍ୟବହାର କରନ୍ତୁ।" @@ -66,7 +65,10 @@ "ଏହା ଏକ ସିଷ୍ଟମ୍‌ ଆପ୍‌ ଅଟେ ଏବଂ ଏହା ଅନଇନଷ୍ଟଲ୍‌ କରାଯାଇ ପାରିବ ନାହିଁ।" "ବେନାମୀ ଫୋଲ୍ଡର୍‌" "%1$s ଅକ୍ଷମ କରାଗଲା" - + + %1$s, %2$dଟି ବିଜ୍ଞପ୍ତି ରହିଛି + %1$s, %2$dଟି ବିଜ୍ଞପ୍ତି ରହିଛି + "ମୋଟ %2$dରୁ %1$d ନମ୍ବର ପୃଷ୍ଠା" "%2$dରୁ %1$d ହୋମ୍‌ ସ୍କ୍ରୀନ୍" "ନୂଆ ହୋମ୍‌ ସ୍କ୍ରୀନ୍‌ ପୃଷ୍ଠା" @@ -82,17 +84,13 @@ "ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି" "ହୋମ୍‌ ସ୍କ୍ରୀନ୍ ବୁଲାଇବା ଅନୁମତି ଦିଅନ୍ତୁ" "ଯେତେବେଳେ ଫୋନକୁ ବୁଲାଯାଇଥାଏ" - - - - - - + "ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁଗୁଡ଼ିକ" + "ଚାଲୁ କରନ୍ତୁ" + "ବନ୍ଦ କରନ୍ତୁ" "ବିଜ୍ଞପ୍ତି ଆକ୍ସେସ୍‌ ଆବଶ୍ୟକ ଅଟେ" "ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁ ଦେଖାଇବାକୁ, %1$s ପାଇଁ ଆପ୍‌ ବିଜ୍ଞପ୍ତି ଅନ୍‌ କରନ୍ତୁ" "ସେଟିଙ୍ଗ ପରିବର୍ତ୍ତନ କରନ୍ତୁ" - - + "ବିଜ୍ଞପ୍ତି ଡଟ୍‌ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ" "ହୋମ୍‌ ସ୍କ୍ରୀନରେ ଆଇକନ୍‌କୁ ଯୋଡ଼ନ୍ତୁ" "ନୂଆ ଆପ୍‌ ପାଇଁ" "ଆଇକନ୍‌ର ଆକାର ପରିବର୍ତ୍ତନ କରନ୍ତୁ" diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index ba75e1e205..f21fc0df16 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -39,8 +39,7 @@ "ਐਪਾਂ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." "\"%1$s\" ਨਾਲ ਮੇਲ ਖਾਂਦੀਆਂ ਕੋਈ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ" "ਹੋਰ ਐਪਾਂ ਖੋਜੋ" - - + "ਐਪ" "ਸੂਚਨਾਵਾਂ" "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਸਪੱਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।" "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਡਬਲ ਟੈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ ਜਾਂ ਵਿਉਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤੋ।" @@ -66,7 +65,10 @@ "ਇਹ ਇੱਕ ਸਿਸਟਮ ਐਪ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।" "ਬਿਨਾਂ ਨਾਮ ਦਿੱਤਾ ਫੋਲਡਰ" "%1$s ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ" - + + %1$s ਦੀ %2$d ਸੂਚਨਾ + %1$s ਦੀਆਂ %2$d ਸੂਚਨਾਵਾਂ + "ਸਫ਼ਾ %2$d ਦਾ %1$d" "ਹੋਮ ਸਕ੍ਰੀਨ %2$d ਦੀ %1$d" "ਨਵਾਂ ਹੋਮ ਸਕ੍ਰੀਨ ਸਫ਼ਾ" @@ -82,17 +84,13 @@ "ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ" "ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁੰਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ" "ਜਦੋਂ ਫ਼ੋਨ ਘੁੰਮਾਇਆ ਜਾਂਦਾ ਹੈ" - - - - - - + "ਸੂਚਨਾ ਬਿੰਦੂ" + "ਚਾਲੂ" + "ਬੰਦ" "ਸੂਚਨਾ ਪਹੁੰਚ ਲੋੜੀਂਦੀ ਹੈ" "ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, %1$s ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ" "ਸੈਟਿੰਗਾਂ ਬਦਲੋ" - - + "ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ" "ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰਤੀਕ ਸ਼ਾਮਲ ਕਰੋ" "ਨਵੀਆਂ ਐਪਾਂ ਲਈ" "ਪ੍ਰਤੀਕ ਦੀ ਆਕ੍ਰਿਤੀ ਬਦਲੋ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index a4a6e98379..242d00dd39 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -39,8 +39,7 @@ "Ładuję aplikacje…" "Nie znaleziono aplikacji pasujących do zapytania „%1$s”" "Wyszukaj więcej aplikacji" - - + "Aplikacja" "Powiadomienia" "Kliknij i przytrzymaj, by wybrać skrót." "Kliknij dwukrotnie i przytrzymaj, by wybrać skrót lub użyć działań niestandardowych." @@ -66,7 +65,12 @@ "To aplikacja systemowa i nie można jej odinstalować." "Folder bez nazwy" "Aplikacja %1$s jest wyłączona" - + + %1$s%2$d powiadomienia + %1$s%2$d powiadomień + %1$s%2$d powiadomienia + %1$s%2$d powiadomienie + "Strona %1$d z %2$d" "Ekran główny %1$d z %2$d" "Nowa strona ekranu głównego" @@ -82,17 +86,13 @@ "Funkcja wyłączona przez administratora" "Zezwalaj na obrót ekranu głównego" "Po obróceniu telefonu" - - - - - - + "Plakietki z powiadomieniami" + "Włączono" + "Wyłączono" "Wymagany jest dostęp do powiadomień" "Aby pokazać plakietki z powiadomieniami, włącz powiadomienia aplikacji %1$s" "Zmień ustawienia" - - + "Pokaż plakietki z powiadomieniami" "Dodaj ikonę do ekranu głównego" "W przypadku nowych aplikacji" "Zmień kształt ikon" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 39bd520fcc..1e89abe4b7 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -39,8 +39,7 @@ "Carregando apps…" "Nenhum app encontrado que corresponda a \"%1$s\"" "Pesquisar mais apps" - - + "App" "Notificações" "Toque e segure para selecionar um atalho." "Toque duas vezes na tela e segure para selecionar um atalho ou usar ações personalizadas." @@ -66,7 +65,10 @@ "Este é um app do sistema e não pode ser desinstalado." "Pasta sem nome" "%1$s desativado" - + + O app %1$stem %2$d notificação + O app %1$stem %2$d notificações + "Página %1$d de %2$d" "Tela inicial %1$d de %2$d" "Nova página na tela inicial" @@ -82,17 +84,13 @@ "Desativado pelo administrador" "Permitir rotação da tela inicial" "Quando o smartphone for girado" - - - - - - + "Pontos de notificação" + "Ativado" + "Desativado" "Acesso a notificações necessário" "Para mostrar pontos de notificação, ative as notificações de app para %1$s" "Alterar configurações" - - + "Mostrar pontos de notificação" "Adicionar ícone à tela inicial" "Para novos apps" "Alterar forma de ícones" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index c66016af4b..7135f62cca 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -39,8 +39,7 @@ "Se încarcă aplicații…" "Nu s-a găsit nicio aplicație pentru „%1$s\"" "Căutați mai multe aplicații" - - + "Aplicație" "Notificări" "Atingeți lung pentru a selecta o comandă rapidă." "Atingeți lung pentru a selecta o comandă rapidă sau folosiți acțiuni personalizate." @@ -66,7 +65,11 @@ "Aceasta este o aplicație de sistem și nu poate fi dezinstalată." "Dosar fără nume" "S-a dezactivat %1$s" - + + %1$s are %2$d notificări + %1$s​ are %2$d de notificări + %1$s are %2$d notificare + "Pagina %1$d din %2$d" "Ecranul de pornire %1$d din %2$d" "Pagină nouă pe ecranul de pornire" @@ -82,17 +85,13 @@ "Dezactivată de administrator" "Permiteți rotirea ecranului de pornire" "Când telefonul este rotit" - - - - - - + "Puncte de notificare" + "Activate" + "Dezactivate" "Este necesar accesul la notificări" "Pentru a afișa punctele de notificare, activați notificările din aplicație pentru %1$s" "Modificați setările" - - + "Afișați punctele de notificare" "Adaugă pictograme în ecranul de pornire" "Pentru aplicații noi" "Schimbați forma pictogramei" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 7e73dd6e16..b4d1664f9d 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -39,8 +39,7 @@ "Загрузка приложений…" "По запросу \"%1$s\" ничего не найдено" "Искать другие приложения" - - + "Приложение" "Уведомления" "Нажмите и удерживайте, чтобы выбрать ярлык." "Нажмите дважды и удерживайте, чтобы выбрать ярлык или использовать специальные действия." @@ -66,7 +65,12 @@ "Это системное приложение, его нельзя удалить." "Папка без названия" "Приложение %1$s отключено" - + + В приложении \"%1$s\" %2$d уведомление + В приложении \"%1$s\" %2$d уведомления + В приложении \"%1$s\" %2$d уведомлений + В приложении \"%1$s\" %2$d уведомления + "Стр. %1$d из %2$d" "Главный экран %1$d из %2$d" "Новый экран" @@ -82,17 +86,13 @@ "Функция отключена администратором" "Разрешить поворачивать главный экран" "Когда телефон повернут" - - - - - - + "Значки уведомлений" + "Включены" + "Отключены" "Нет доступа к уведомлениям" "Чтобы показывать значки уведомлений, включите уведомления в приложении \"%1$s\"" "Изменить настройки" - - + "Показывать значки уведомлений" "Добавлять значки" "Добавлять значки установленных приложений на главный экран" "Изменить форму значков" diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index b175f890bb..af428a9ed7 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -39,8 +39,7 @@ "යෙදුම් පූරණය වෙමින්…" "\"%1$s\" සමග ගැළපෙන යෙදුම් හමු නොවිණි" "තව යෙදුම් සඳහා සොයන්න" - - + "යෙදුම" "දැනුම්දීම්" "කෙටි මගක් තෝරා ගැනීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න." "විජට් එකක් තෝරා ගැනීමට හෝ අභිරුචි භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න." @@ -66,7 +65,10 @@ "මෙය පද්ධති යෙදුමක් වන අතර අස්ථාපනය කළ නොහැක." "නම් නොකළ ෆෝල්ඩරය" "%1$s අබල කෙරිණි" - + + %1$s, දැනුම්දීම් %2$dක් ඇත + %1$s, දැනුම්දීම් %2$dක් ඇත + "%2$d හි %1$d පිටුව" "මුල් පිටු තිරය %2$d හි %1$d" "නව මුල් පිටුව" @@ -82,17 +84,13 @@ "ඔබගේ පරිපාලක විසින් අබල කරන ලදී" "මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න" "දුරකථනය කරකවන විට" - - - - - - + "දැනුම්දීම් තිත්" + "ක්‍රියාත්මකයි" + "ක්‍රියාවිරහිතයි" "දැනුම්දීම් ප්‍රවේශය අවශ්‍යයි" "දැනුම්දීම් තිත් පෙන්වීමට, %1$s සඳහා යෙදුම් දැනුම්දීම් සබල කරන්න" "සැකසීම් වෙනස් කරන්න" - - + "දැනුම්දීම් තිත් පෙන්වන්න" "මුල් පිටු තිරය වෙත අයිකනය එක් කරන්න" "නව යෙදුම් සඳහා" "නිරූපක හැඩය වෙනස් කරන්න" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index af66bf731f..b7014b2212 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -39,8 +39,7 @@ "Načítavajú sa aplikácie…" "Nenašli sa žiadne aplikácie zodpovedajúce dopytu %1$s" "Hľadať ďalšie aplikácie" - - + "Aplikácia" "Upozornenia" "Skratku pridáte pridržaním." "Skratku pridáte dvojitým klepnutím a pridržaním alebo pomocou vlastných akcií." @@ -66,7 +65,12 @@ "Toto je systémová aplikácia a nedá sa odinštalovať." "Nepomenovaný priečinok" "Aplikácia %1$s je deaktivovaná" - + + %1$s, má %2$d upozornenia + %1$s, has %2$d notifications + %1$s, má %2$d upozornení + %1$s, má %2$d upozornenie + "Stránka %1$d z %2$d" "Plocha %1$d z %2$d" "Nová stránka plochy" @@ -82,17 +86,13 @@ "Zakázané vaším správcom" "Povoliť otáčanie plochy" "Pri otočení telefónu" - - - - - - + "Bodky upozornení" + "Zapnuté" + "Vypnuté" "Vyžaduje sa prístup k upozorneniam" "Ak chcete, aby sa zobrazovali bodky upozornení, zapnite upozornenia aplikácie %1$s" "Zmeniť nastavenia" - - + "Zobrazovať bodky upozornení" "Pridať ikonu na plochu" "Pri inštalácii novej aplikácie" "Zmeniť tvar ikony" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 4f5fc1214d..891fd1f906 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -39,8 +39,7 @@ "Nalaganje aplikacij …" "Ni aplikacij, ki bi ustrezale poizvedbi »%1$s«" "Iskanje več aplikacij" - - + "Aplikacija" "Obvestila" "Pridržite bližnjico, da jo izberete." "Dvakrat se dotaknite bližnjice in jo pridržite, da jo izberete, ali pa uporabite dejanja po meri." @@ -66,7 +65,12 @@ "To je sistemska aplikacija in je ni mogoče odstraniti." "Neimenovana mapa" "Aplikacija %1$s je onemogočena" - + + %1$s ima %2$d obvestilo + %1$s ima %2$d obvestili + %1$s ima %2$d obvestila + %1$s ima %2$d obvestil + "Stran %1$d od %2$d" "Začetni zaslon %1$d od %2$d" "Nova stran na začetnem zaslonu" @@ -82,17 +86,13 @@ "Onemogočil skrbnik." "Omogočanje sukanja začetnega zaslona" "Ko se telefon zasuka" - - - - - - + "Obvestilne pike" + "Vklopljeno" + "Izklopljeno" "Potreben je dostop do obvestil" "Za prikaz obvestilnih pik vklopite obvestila aplikacije %1$s" "Spremeni nastavitve" - - + "Pokaži obvestilne pike" "Dodaj ikono na začetni zaslon" "Za nove aplikacije" "Spremeni obliko ikon" diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index ad53e119c0..dd657d7f26 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -39,8 +39,7 @@ "Po ngarkon aplikacionet..." "Nuk u gjet asnjë aplikacion që përputhet me \"%1$s\"" "Kërko për më shumë aplikacione" - - + "Aplikacioni" "Njoftimet" "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." @@ -66,7 +65,10 @@ "Ky është aplikacion sistemi dhe nuk mund të çinstalohet." "Dosje e paemërtuar" "%1$s u çaktivizua" - + + %1$s, ka %2$d njoftime + %1$s, ka %2$d njoftim + "Faqja: %1$d nga gjithsej %2$d" "Ekrani bazë: %1$d nga gjithsej %2$d" "Faqja e ekranit të ri kryesor" @@ -82,17 +84,13 @@ "Çaktivizuar nga administratori" "Lejo rrotullimin e ekranit kryesor" "Kur telefoni rrotullohet" - - - - - - + "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" - - + "Shfaq pikat e njoftimeve" "Shto ikonë në ekranin bazë" "Për aplikacionet e reja" "Ndrysho formën e ikonës" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index d68696a941..c16d32f26f 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -39,8 +39,7 @@ "Апликације се учитавају…" "Није пронађена ниједна апликација за „%1$s“" "Претражи још апликација" - - + "Апликација" "Обавештења" "Додирните и задржите да бисте изабрали пречицу." "Двапут додирните и задржите да бисте изабрали пречицу или користите прилагођене радње." @@ -66,7 +65,11 @@ "Ово је системска апликација и не може да се деинсталира." "Неименовани директоријум" "Апликација %1$s је онемогућена" - + + %1$s, има %2$d обавештење + %1$s, има %2$d обавештења + %1$s, има %2$d обавештења + "%1$d. страница од %2$d" "%1$d. почетни екран од %2$d" "Нова страница почетног екрана" @@ -82,17 +85,13 @@ "Администратор је онемогућио" "Дозволи ротацију почетног екрана" "Када се телефон ротира" - - - - - - + "Тачке за обавештења" + "Укључено" + "Искључено" "Потребан је приступ за обавештења" "Да бисте приказали тачке за обавештења, укључите обавештења за апликацију %1$s" "Промените подешавања" - - + "Приказуј тачке за обавештења" "Додај икону на почетни екран" "За нове апликације" "Промените облик икона" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 7c4f41f035..feb087c91a 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -39,8 +39,7 @@ "Läser in appar …" "Inga appar som matchar %1$s hittades" "Sök efter fler appar" - - + "App" "Aviseringar" "Tryck länge om du vill ta upp en genväg." "Tryck snabbt två gånger och håll kvar om du vill ta upp en genväg eller använda anpassade åtgärder." @@ -66,7 +65,10 @@ "Det här är en systemapp som inte kan avinstalleras." "Namnlös mapp" "%1$s har inaktiverats" - + + %1$s har %2$d aviseringar + %1$s har %2$d avisering + "Sidan %1$d av %2$d" "Startskärmen %1$d av %2$d" "Ny sida på startskärmen" @@ -82,17 +84,13 @@ "Inaktiverat av administratören" "Tillåt rotering av startskärmen" "När mobilen vrids" - - - - - - + "Aviseringsprickar" + "På" + "Av" "Åtkomst till aviseringar krävs" "Aktivera appaviseringar för %1$s om du vill att aviseringsprickar ska visas" "Ändra inställningar" - - + "Visa aviseringsprickar" "Lägg till ikonen på startskärmen" "För nya appar" "Ändra form på ikoner" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index b6bdbd3fb7..99d3008914 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -39,8 +39,7 @@ "Inapakia programu..." "Haikupata programu zozote zinazolingana na \"%1$s\"" "Tafuta programu zaidi" - - + "Programu" "Arifa" "Gusa na ushikilie ili uchague njia ya mkato." "Gusa mara mbili na ushikilie ili uchague njia ya mkato au utumie vitendo maalum." @@ -66,7 +65,10 @@ "Hii ni programu ya mfumo na haiwezi kuondolewa." "Folda isiyo na jina" "%1$s imezimwa" - + + %1$s, ina arifa %2$d + %1$s, ina arifa %2$d + "Ukurasa%1$d wa %2$d" @@ -84,17 +86,13 @@ "Imezimwa na msimamizi wako" "Ruhusu kuzungusha skrini ya Kwanza" "Simu inapozungushwa" - - - - - - + "Vitone vya arifa" + "Imewashwa" + "Imezimwa" "Inahitaji idhini ya kufikia arifa" "Ili kuonyesha Vitone vya Arifa, washa kipengele cha arifa za programu katika %1$s" "Badilisha mipangilio" - - + "Onyesha vitone vya arifa" "Ongeza aikoni kwenye Skrini ya kwanza" "Kwa ajili ya programu mpya" "Badilisha umbo la aikoni" diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index b25d1d21a3..43ff0977cd 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -39,8 +39,7 @@ "பயன்பாடுகளை ஏற்றுகிறது…" "\"%1$s\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை" "கூடுதல் பயன்பாடுகளைத் தேடு" - - + "ஆப்ஸ்" "அறிவிப்புகள்" "ஷார்ட்கட்டைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்." "ஷார்ட்கட்டைச் சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் (அ) தனிப்பயன் செயல்களைப் பயன்படுத்தவும்." @@ -66,7 +65,10 @@ "இது அமைப்பு பயன்பாடு என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது." "பெயரிடப்படாத கோப்புறை" "%1$s முடக்கப்பட்டது" - + + %1$s ஆப்ஸில் %2$d அறிவிப்புகள் வந்துள்ளன + %1$s ஆப்ஸில் %2$d அறிவிப்பு வந்துள்ளது + "பக்கம் %1$d / %2$d" "முகப்புத் திரை %1$d of %2$d" "புதிய முகப்புத் திரை பக்கம்" @@ -82,17 +84,13 @@ "உங்கள் நிர்வாகி முடக்கியுள்ளார்" "முகப்புத் திரை சுழற்சியை அனுமதி" "மொபைலைச் சுழற்றும் போது" - - - - - - + "அறிவிப்புப் புள்ளிகள்" + "ஆன்" + "ஆஃப்" "அறிவிப்பிற்கான அணுகல் தேவை" "அறிவிப்புப் புள்ளிகளைக் காட்ட, %1$s இன் பயன்பாட்டு அறிவிப்புகளை இயக்கவும்" "அமைப்புகளை மாற்று" - - + "அறிவிப்புப் புள்ளிகளைக் காட்டு" "முகப்புத் திரையில் ஐகானைச் சேர்" "புதிய பயன்பாடுகளுக்கு" "ஐகான் வடிவத்தை மாற்று" diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 4ec35a9e77..04f253936f 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -39,8 +39,7 @@ "అప్లికేషన్‌లను లోడ్ చేస్తోంది…" "\"%1$s\"కి సరిపోలే అప్లికేషన్‌లేవీ కనుగొనబడలేదు" "మరిన్ని యాప్‌ల కోసం వెతుకు" - - + "యాప్" "నోటిఫికేషన్‌లు" "షార్ట్‌కట్‌ని ఎంచుకోవడం కోసం నొక్కి, పట్టుకోండి." "రెండుసార్లు నొక్కి, పట్టుకోవడం ద్వారా షార్ట్‌కట్‌ని ఎంచుకోండి లేదా అనుకూల చర్యలను ఉపయోగించండి." @@ -66,7 +65,10 @@ "ఇది సిస్టమ్ యాప్ మరియు దీన్ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడదు." "పేరు లేని ఫోల్డర్" "%1$s నిలిపివేయబడింది" - + + %1$s, నుంచి %2$d నోటిఫికేషన్‌లు ఉన్నాయి + %1$s, నుంచి %2$d నోటిఫికేషన్ ఉంది + "%2$dలో %1$dవ పేజీ" "%2$dలో %1$dవ హోమ్ స్క్రీన్" "కొత్త హోమ్ స్క్రీన్ పేజీ" @@ -82,17 +84,13 @@ "మీ నిర్వాహకులు నిలిపివేసారు" "హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి" "ఫోన్‌‌ను తిప్పినప్పుడు" - - - - - - + "నోటిఫికేషన్ డాట్‌లు" + "ఆన్" + "ఆఫ్" "నోటిఫికేషన్ యాక్సెస్ అవసరం" "నోటిఫికేషన్ డాట్‌లను చూపించడానికి %1$sకు యాప్ నోటిఫికేషన్‌లను ఆన్ చేయండి" "సెట్టింగ్‌లను మార్చు" - - + "నోటిఫికేషన్ డాట్‌లను చూపు" "హోమ్ స్క్రీన్‌కి చిహ్నాన్ని జోడించు" "కొత్త యాప్‌ల కోసం" "చిహ్న ఆకారాన్ని మార్చు" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index 4895c376f9..8473ec0b36 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -39,8 +39,7 @@ "กำลังโหลดแอป…" "ไม่พบแอปที่ตรงกับ \"%1$s\"" "ค้นหาแอปเพิ่มเติม" - - + "แอป" "การแจ้งเตือน" "แตะค้างไว้เพื่อเลือกทางลัด" "แตะสองครั้งค้างไว้เพื่อเลือกทางลัดหรือใช้การกระทำที่กำหนดเอง" @@ -66,7 +65,10 @@ "นี่เป็นแอประบบและไม่สามารถถอนการติดตั้งได้" "โฟลเดอร์ที่ไม่มีชื่อ" "ปิดใช้ %1$s" - + + %1$s มีการแจ้งเตือน %2$d รายการ + %1$s มีการแจ้งเตือน %2$d รายการ + "หน้า %1$d จาก %2$d" "หน้าจอหลัก %1$d จาก %2$d" "หน้าใหม่ในหน้าจอหลัก" @@ -82,17 +84,13 @@ "ปิดใช้โดยผู้ดูแลระบบ" "อนุญาตให้หมุนหน้าจอหลัก" "เมื่อหมุนโทรศัพท์" - - - - - - + "เครื่องหมายจุดแสดงการแจ้งเตือน" + "เปิด" + "ปิด" "ต้องได้รับสิทธิ์เข้าถึงการแจ้งเตือน" "เปิดการแจ้งเตือนแอปของ %1$s เพื่อแสดงจุดแจ้งเตือน" "เปลี่ยนการตั้งค่า" - - + "แสดงเครื่องหมายจุดแสดงการแจ้งเตือน" "เพิ่มไอคอนในหน้าจอหลัก" "สำหรับแอปใหม่" "เปลี่ยนรูปร่างไอคอน" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 90f1bf4999..90b0a182d5 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -39,8 +39,7 @@ "Naglo-load ng mga app…" "Walang nahanap na app na tumutugma sa \"%1$s\"" "Maghanap ng higit pang mga app" - - + "App" "Mga Notification" "Pindutin nang matagal para kumuha ng shortcut." "I-double tap nang matagal para kumuha ng shortcut o gumamit ng mga custom na pagkilos." @@ -66,7 +65,10 @@ "Isa itong app ng system at hindi maaaring i-uninstall." "Walang Pangalang Folder" "Naka-disable ang %1$s" - + + May %2$d (na) notification ang %1$s + May %2$d (na) notification ang %1$s + "Pahina %1$d ng %2$d" "Home screen %1$d ng %2$d" "Bagong page ng home screen" @@ -82,17 +84,13 @@ "Na-disable ng iyong admin" "Payagan ang pag-rotate ng Home screen" "Kailan maro-rotate ang telepono" - - - - - - + "Mga notification dot" + "Naka-on" + "Naka-off" "Kinakailangan ng access sa notification" "Upang ipakita ang Mga Notification Dot, i-on ang mga notification ng app para sa %1$s" "Baguhin ang mga setting" - - + "Ipakita ang mga notification dot" "Idagdag ang icon sa Home screen" "Para sa mga bagong app" "Baguhin ang hugis ng icon" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 34171fc00a..88b85f7fc3 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -39,8 +39,7 @@ "Uygulamalar yükleniyor…" "\"%1$s\" ile eşleşen uygulama bulunamadı" "Başka uygulamalar ara" - - + "Uygulama" "Bildirimler" "Kısayol seçmek için dokunun ve basılı tutun." "Bir kısayolu seçmek veya özel işlemleri kullanmak için iki kez dokunun ve basılı tutun." @@ -66,7 +65,10 @@ "Bu bir sistem uygulamasıdır ve yüklemesi kaldırılamaz." "Adsız Klasör" "%1$s devre dışı" - + + %1$s uygulamasının %2$d bildirimi var + %1$s uygulamasının %2$d bildirimi var + "Sayfa %1$d / %2$d" "Ana ekran %1$d / %2$d" "Yeni ana ekran sayfası" @@ -82,17 +84,13 @@ "Yöneticiniz tarafından devre dışı bırakıldı" "Ana ekranı döndürmeye izin ver" "Telefon döndürüldüğünde" - - - - - - + "Bildirim noktaları" + "Açık" + "Kapalı" "Bildirim erişimi gerekli" "Bildirim Noktaları\'nı göstermek için %1$s uygulamasının bildirimlerini açın" "Ayarları değiştir" - - + "Bildirim noktalarını göster" "Ana ekrana simge ekle" "Yeni uygulamalar için" "Simge şeklini değiştir" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 17dac15971..e62cb52c23 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -39,8 +39,7 @@ "Завантаження додатків…" "Немає додатків для запиту \"%1$s\"" "Шукати ще додатки" - - + "Додаток" "Сповіщення" "Натисніть і втримуйте, щоб вибрати ярлик." "Двічі натисніть і втримуйте, щоб вибрати ярлик, або виконайте іншу дію." @@ -66,7 +65,12 @@ "Це системна програма, її неможливо видалити." "Папка без назви" "%1$s вимкнено" - + + Додаток %1$s має %2$d сповіщення + Додаток %1$s має %2$d сповіщення + Додаток %1$s має %2$d сповіщень + Додаток %1$s має %2$d сповіщення + "Сторінка %1$d з %2$d" "Головний екран %1$d з %2$d" "Нова сторінка головного екрана" @@ -82,17 +86,13 @@ "Вимкнув адміністратор" "Дозволити обертання головного екрана" "Коли телефон обертається" - - - - - - + "Значки сповіщень" + "Увімкнено" + "Вимкнено" "Потрібен доступ до сповіщень" "Щоб показувати значки сповіщень, увімкніть сповіщення в додатку %1$s" "Змінити налаштування" - - + "Показувати значки сповіщень" "Додати значок на головний екран" "Для нових додатків" "Змінити форму значка" @@ -104,7 +104,7 @@ "Сльоза" "Змінюється форма значка" "Невідомо" - "Вилучити значок" + "Прибрати" "Шукати" "Цей додаток не встановлено" "Додаток для цього значка не встановлено. Можна видалити значок або знайти додаток і встановити його вручну." diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index e8b6b6b7ff..fde98c90f5 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -39,8 +39,7 @@ "ایپس لوڈ کی جا رہی ہیں…" "\"%1$s\" سے مماثل کوئی ایپس نہیں ملیں" "مزید ایپس تلاش کریں" - - + "ایپ" "اطلاعات" "ایک شارٹ کٹ منتخب کرنے کیلئے ٹچ کر کے دبائے رکھیں۔" "ایک شارٹ کٹ منتخب کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور دبائے رکھیں۔" @@ -66,7 +65,10 @@ "یہ ایک سسٹم ایپ ہے اور اسے اَن انسٹال نہیں کیا جا سکتا ہے۔" "بلا نام فولڈر" "%1$s غیر فعال ہے" - + + %1$s میں%2$d اطلاعات ہیں + %1$s میں%2$d اطلاع ہے + "‏صفحہ ‎%1$d از ‎%2$d" "‏ہوم اسکرین ‎%1$d از ‎%2$d" "نیا ہوم اسکرین صفحہ" @@ -82,17 +84,13 @@ "آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا" "ہوم اسکرین گھمانے کی اجازت دیں" "جب فون گھمایا جاتا ہے" - - - - - - + "اطلاعاتی ڈاٹس" + "آن ہے" + "آف ہے" "اطلاعاتی رسائی درکار ہے" "اطلاعاتی ڈاٹس دکھانے کی خاطر %1$s کیلئے ایپ کی اطلاعات آن کریں" "ترتیبات تبدیل کریں" - - + "اطلاعاتی ڈاٹس دکھائیں" "آئیکن کو ہوم اسکرین میں شامل کریں" "نئی ایپس کیلئے" "آئیکن کی شکل تبدیل کریں" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 3165726977..015dcda745 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -39,8 +39,7 @@ "Ilovalar yuklanmoqda…" "“%1$s” bilan mos hech qanday ilova topilmadi" "Boshqa ilovalarni qidirish" - - + "Ilova" "Bildirishnomalar" "Yorliqni tanlab olish uchun bosib turing." "Ikki marta bosib va bosib turgan holatda yorliqni tanlang yoki maxsus amaldan foydalaning." @@ -66,7 +65,10 @@ "Bu tizim ilovasi, shuning uchun o‘chirib bo‘lmaydi." "Nomsiz jild" "%1$s ilovasi o‘chirib qo‘yildi" - + + %1$s ilovasida %2$d ta bildirishnoma bor + %1$s ilovasida %2$d ta bildirishnoma bor + "%2$ddan %1$d ta sahifa" "Uy ekrani %2$ddan %1$d" "Yangi bosh ekran sahifasi" @@ -82,17 +84,13 @@ "Administrator tomonidan o‘chirilgan" "Asosiy ekranni aylantirishga ruxsat berish" "Telefon burilganda" - - - - - - + "Bildirishnoma belgilari" + "Yoniq" + "Yoqilmagan" "Bildirishnomalarga ruxsat berilmagan" "Bildirishnoma belgilarini ko‘rsatish uchun %1$s ilovasida bildirishnomalarni yoqing" "Sozlamalarni o‘zgartirish" - - + "Bildirishnoma belgilarini chiqarish" "Bosh ekranga ikonka chiqarish" "Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish" "Ikonka shaklini o‘zgartirish" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 254420d13d..69b17c6836 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -39,8 +39,7 @@ "Đang tải ứng dụng…" "Không tìm thấy ứng dụng nào phù hợp với \"%1$s\"" "Tìm kiếm thêm ứng dụng" - - + "Ứng dụng" "Thông báo" "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 hành động tùy chỉnh." @@ -66,7 +65,10 @@ "Đây là ứng dụng hệ thống và không thể gỡ cài đặt." "Thư mục chưa đặt tên" "Đã vô hiệu hóa %1$s" - + + %1$s, có %2$d thông báo + %1$s, có %2$d thông báo + "Trang %1$d / %2$d" "Màn hình chính %1$d / %2$d" "Trang màn hình chính mới" @@ -82,17 +84,13 @@ "Bị tắt bởi quản trị viên của bạn" "Cho phép xoay Màn hình chính" "Khi xoay điện thoại" - - - - - - + "Dấu chấm thông báo" + "Bật" + "Tắt" "Cần quyền truy cập thông báo" "Để hiển thị Dấu chấm thông báo, hãy bật thông báo ứng dụng cho %1$s" "Thay đổi cài đặt" - - + "Hiển thị dấu chấm thông báo" "Thêm biểu tượng vào màn hình chính" "Cho ứng dụng mới" "Thay đổi hình dạng biểu tượng" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index f1f3b9759c..cbec49ec9a 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -39,8 +39,7 @@ "正在加载应用…" "未找到与“%1$s”相符的应用" "搜索更多应用" - - + "应用" "通知" "触摸并按住快捷方式即可选择快捷方式。" "点按两次并按住快捷方式即可选择快捷方式,您也可以使用自定义操作。" @@ -66,7 +65,10 @@ "这是系统应用,无法卸载。" "未命名文件夹" "已停用%1$s" - + + %1$s,有 %2$d 个通知 + %1$s,有 %2$d 个通知 + "第%1$d页,共%2$d页" "主屏幕:第%1$d屏,共%2$d屏" "主屏幕新页面" @@ -82,17 +84,13 @@ "已被您的管理员停用" "允许旋转主屏幕" "手机旋转时" - - - - - - + "通知圆点" + "开启" + "关闭" "需要获取通知使用权" "要显示通知圆点,请开启%1$s的应用通知功能" "更改设置" - - + "显示通知圆点" "将图标添加到主屏幕" "适用于新应用" "更改图标形状" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 0f70e9ea9d..648b1cc279 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -39,8 +39,7 @@ "正在載入應用程式…" "找不到與「%1$s」相符的應用程式" "搜尋更多應用程式" - - + "應用程式" "通知" "按住捷徑即可選取。" "連㩒兩下之後繼續㩒住,就可以揀選捷徑或者用自訂嘅操作。" @@ -66,7 +65,10 @@ "這是系統應用程式,無法將其解除安裝。" "未命名的資料夾" "「%1$s」已停用" - + + %1$s,有 %2$d 項通知 + %1$s,有 %2$d 項通知 + "第 %1$d 頁,共 %2$d 頁" "主畫面 %1$d,共 %2$d 個" "新主畫面頁面" @@ -82,17 +84,13 @@ "已由您的管理員停用" "允許主畫面旋轉" "當手機旋轉時" - - - - - - + "通知圓點" + "開啟" + "關閉" "需要獲取通知存取權" "如要顯示「通知圓點」,請開啟「%1$s」的應用程式通知功能" "變更設定" - - + "顯示通知圓點" "將圖示加到主畫面" "適用於新安裝的應用程式" "變更圖示形狀" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 652679a017..74f2949b39 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -39,8 +39,7 @@ "正在載入應用程式…" "找不到與「%1$s」相符的應用程式" "搜尋更多應用程式" - - + "應用程式" "通知" "按住捷徑即可選取。" "輕觸兩下並按住捷徑即可選取,你也可以使用自訂動作。" @@ -66,7 +65,10 @@ "這是系統應用程式,不可解除安裝。" "未命名的資料夾" "已停用 %1$s" - + + %1$s,有 %2$d 則通知 + %1$s,有 %2$d 則通知 + "第 %1$d 頁,共 %2$d 頁" "主螢幕:第 %1$d 頁,共 %2$d 頁" "新的主畫面頁面" @@ -82,17 +84,13 @@ "已由你的管理員停用" "允許旋轉主螢幕" "當手機旋轉時" - - - - - - + "通知圓點" + "開啟" + "關閉" "需要取得通知存取權" "如要顯示通知圓點,請開啟「%1$s」的應用程式通知功能" "變更設定" - - + "顯示通知圓點" "將圖示加到主螢幕" "適用於新安裝的應用程式" "變更圖示形狀" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 22fba2bc06..89893fc6ff 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -39,8 +39,7 @@ "Ilayisha izinhlelo zokusebenza..." "Azikho izinhlelo zokusebenza ezitholiwe ezifana ne-\"%1$s\"" "Sesha izinhlelo zokusebenza eziningi" - - + "Uhlelo lokusebenza" "Izaziso" "Thinta futhi ubambe ukuze ukhethe isinqamuleli." "Thepha kabili uphinde ubambe ukuze uphakamise isinqamuleli noma usebenzise izenzo zangokwezifiso." @@ -66,7 +65,10 @@ "Lolu uhlelo lokusebenza lwesistimu futhi alikwazi ukukhishwa." "Ifolda engenagama" "Kukhutshaziwe %1$s" - + + %1$s, unezaziso ezingu-%2$d + %1$s, unezaziso ezingu-%2$d + "Ikhasi elingu-%1$d kwangu-%2$d" "Isikrini sasekhaya esingu-%1$d se-%2$d" "Ikhasi elisha lesikrini sasekhaya" @@ -82,17 +84,13 @@ "Kukhutshazwe umlawuli wakho" "Vumela ukuphendukiswa kwesikrini sasekhaya" "Uma ifoni iphendukiswa" - - - - - - + "Amacashazi esaziso" + "Vuliwe" + "Valiwe" "Ukufinyelela izaziso kuyadingeka" "Ukuze ubonisa amcashazi esaziso, vula izaziso zohlelo lokusebenza ze-%1$s" "Shintsha izilungiselelo" - - + "Bonisa amacashazi esaziso" "Engeza isithonjana eskrinini sasekhaya" "Kwezinhlelo zokusebenza ezintsha" "Shintsha isimo sesithonjana" From 381a75c19497342c1ffe62aa6553425231eb3da5 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 11 Dec 2018 13:02:00 -0800 Subject: [PATCH 08/15] Fix issue with sync rt applier - Use the shared lib call to ensure that we always have the sync rt applier with viewroot. Change-Id: I911362d105a2c0223693640a28d358caf6dd29d0 --- quickstep/libs/sysui_shared.jar | Bin 143883 -> 145046 bytes .../WindowTransformSwipeHandler.java | 15 ++------------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar index 5958d02029563c6c59eab17c710ab3bc1286bb03..6e7534dc6d651329cc382b6c817aaf3be519a54f 100644 GIT binary patch delta 4372 zcmY*bc{tQv^q(2KL6jl8k|o<9%b2mG5ZN^(hIo;(Zw<11vrJ@3vJBam?E9LXRI-jO zhP+DFVQks=U+?oizuw>P-aqa=pZhuI+~+=@=bjTaPn)zx`@9y6sshxd!LVYZ6PDn9aaI^vYQRyPAQJa(K(}o2gGpw^PIt2tShZ45A~|-;_RTZ@O}_s zKkZoAVQ;@3@B^pK>$CsOkg{O+mRJAXbx-7glmL^%2r+HtFB*q|a=SB>L(=wVZn-|H z@F*rcckivEVEXE(0IVpHI2&0RSkLnJy^OYDZ@P8$%PWQ4g^2MgDSw~dk}_7bS&U;) z9dpI!msU>>aK73a&$=Z0%U{gsj@)YED3UU@`Z@7IXZP8URgq)O=r`8FIzed?^tLWH z6?~UYh72@ucN(#vpyz4FOOz#;631+Z-V3{RpL;`IxfbJYLIG61V+Q>qdY-F!p;k90 z>@Mm(LsFPaUFF3hm@->Yct~QZY(jmvTicl~DyQ{yN?$C(-P)1jD7b=;&77vMPU@wj znl|&p*K}8&5~N^u#;?_hd*-a!fLH?A>5h)(%*$Wv1|`o*ib<2^0>8XJDQNETq@F?;@hsLv&+Cd$uq39 zkFgD#Vl%!V)PPw`_Bnh(XH&`;D#Lf8B_hc`Q|8@RQ_zLh8aGmIDsLDAPfB#kz1Ka-*;L*jf0D)ltH`LD@KC(!9%~OD zaQDs`M|x~3%|2Kjl4he?+3eRCP7y#okRHq$7P?bL5vfN{V>YO&mSKCUnO|oiuuHqT zRY7dXoW=C1X3ybFc%2G*7&d0;g z4!8SMsmI-yXvT@I@3HcYOtX+BVwc~ZXRwN-XNXR;dx}x7?v2kplE0K;viG+*+!o~` z2WamgKH3;ZSAUPTcRu2n^=j*oIc({DmXbTqe3YD*Y3uFDz5IEq>!BUD^I^OVlH;-D z_$DP)N6r_1RB)FWIqQpXaz)c_<^X=4bhXR=Gr1gqfI#QxhB`E~#;a`#wfNau@Rj(t zQvCQVaflFbO-9nz*~ZH&FTv7{OM~@AW)1e_t04BCBjiaI6~(LLsvjLxGPgt}<6bi) zy4#KQZ9V(TpgAK3+x_aO=C!%#&7U-zxy(~__Y5zkM3Fx^4o)f({FYiu4p%q6pHng& z=G?_ysGeBkG+7@zcpckY>*&0-C8shwDzhd-V~_l>2N-Ke6uc?I3gi;PxG3y}wVj1J zN0w{&b@nJ#zp)jIaF%SQRI2(GCyAONE>Q_XxsaE>W$}IUmY&cy5D9cC_4rO3zNX{O z6?H-LRu!K?ts&p#5&+ZRjZ`$9(}JQx5$ItpL7}LLo}APa^k#d5sqm@RyCQvDuG(cn z==LHB*d8MtexM}j3LYsjy&$+8#B)i$xddC8Q=ddHc=BdsXle?Vxf(qFEPwBGND(%; zGmki%Bx(l;$-+?GWPJV|$&Uu}z^tx_gbXuNQr5C`&_;p+@1X9A`?^&||w92vwFo#Vm3YHX{m* zHXdIjP5Zx`@Y9%O@35s2x$^uc^^c`hq}wQEm=Dp?HpB2E#U2X&da!~O1>ZcgUe#u6 z&)MO!j|H;7`4Q+~vJHry*#Vd}Bf)fIkrB6V)o>^y{Jf=TV-jHg#d*a^J-9XCTw*Wy zsznPy&zdHdzC^g0xSmvePWg{4nf}pbqo4(k*Kd^`QpOKMx$%%Xur19Tv5lDKq=0v> z19Jg7fnN^?r%(#>6q}jw&@h;qpbChOKD$*&3(PgGaDzZ558fd3pKUFm)Ni@qlKqbM zNo>+_k9U6cjJ18Z7;=gW6DY!Z++zmawYj`XSQ-s<;VnGXf?9N4GaSBce~XKc4`8d& zPNuJ$V_LtSn_u)}{Zp0vzbYO!zsfXcoxsEX%o?3m%nyw}n41)*uOp@9EYtani#9pS z+}aJ2Q3&P@Grhe8B)cgY86@_}H}GIBRkCJ{8y3YaZaIBQSPMl-E+OEuc&6!@gQ0gl zRCqRa%PD8YoiP7ZTK~8wbO2*XXDs@Jc>dS5r2jZea{R~jKO9@^;UA-%t*1gHJh675cRka(4; za+T-GOx;5fapEQt8aZ?0ZfrT9k<|}h0x@7rlGo^g;qKdaRB*qtUpA0^hpY}Jcbwi2 zr^tZNzJ{~~6!w5OmhXK}?DV3r6<8%uzqC7mrzZ|(_$4l}GEP7&Cs{x&H$gxw zPd8Y9@QfNCEP5-(qD6C|0`$KhqGNisi2rZlDaLo|@ZgUc!1}kIT+laE-4Z5{(W4iZFByZEXlWy2pzdQX*v0xFyxck_FelsDYT928TW8P z#+lY2iSO%9zoUe6DXp0Fk&VwfIsN!_2IaG8b-E9nA6;;d2Civu4O3p1Ebi`pL$*cs z&`Dn3nxmuk(+B1buX(7%*)bRK-niSTYuI5N+n1Vbuis@_U;Y@QH=<`mO1MbwHj4Fp z!y@Xq6T;c(IA0W3p=l!b_I@svTvI-86ldnxK|+>O&Wcr1zMPQdgI|)C+MefB^e`a1nH(~^plWY{&G z_;*32o*ZE(6)lTc zUHVJ{PG0~~A!T~B#lA-)El5!@FgV7*DL`|sCPb2uRzv?a=Uu-9eg09t!gKUS@fsAu zS`ucVxCH`Hrsn-@Pm_f2meJVaCNYiZxFD=@$&_tAhP}<&T{(Z^;>G9+2OIx1O6k$M zJU6;ma(zoDFh%$clkbv`B=4tp7z*9Twm9~9QUKvU^TpX5^88FH3*J>DlS@W`s_FpB zep6_;doA0Kv z{)G}t@|M=t&5^k-19Md0N6 z^J;*r5sOx)rtEp?`BkpW#^T+RjX-hb>|b{rA_|@!Nqh6oW$C|NMP@ERk+Gu%+Zs&t zgKhp(t#=Yha8f`@1t}mM@7>nV2=@-^sqhXOC;^b|vkl1hxqYOCD3@ei%0~ z$NSNZC5LjeeE8*WprHL7t_x+2*D0I7*E=vfJ0-Pq0x+ev!P`R1%l8UA``$jXH+Ts2 zVFj%mYt<^8zs&lAsLcK9N9!KB5E`aE0Aiw`7&{wFOgprm>YjsTqcy6gQPZzy251#> zuzZkGqX+lWZ^BWL%;%EsRbu+qT&-6m&LF3_vKj9M$T?Meczg|4&50k zc427hzW$)JShKD`!;j_T7!`U8)_T(Vga=W1pN)PgeY6ce&`9_2$kbIISz~I28?M5{ zOi(IIuu@X!MOwKsbW?1sg7EBTvw z3a@JcMv&dPz|iVT<3gnMl6mf&Xh-p3-3e4oHq#A{u`b~GE4|t*B_1Lz9^sz^G)cay zrFQMxAI!m^QE<%_=EEjmzKA$1zjqB8nS_#rV!vK;-V#@Ba1>e@NMr{>%>SmZ;rWum zR?MkD6}myrVCHsR4WQlon>`{hk4WP^RCWZ;vXFyxHuF(L2%udw+%Nlv(z5JMOuyF{ z(-J)6@lTJ4Yr8FDnY&GGw1t%JGP{Zmm)teKRYJf{GgxPUutRj0)%_SuocU&%DY%6$ z1wi|~!g86TsSz)JAfy2G9SJPUu-22bn~(EmLSA5i3;OcuLGTGbKH=L6qTbX98rDw= zFK5sj-#)@QNfy@}uO(t^?=hZQO@)fsdgxb2DIIfIsvX}9-2-P_;~H7N`B7Wy))A&(UcP9B$Q! z>b6gpVzi1dM!IqWfsaj+N-UE~qS*b^G z-nKgj+STm_Xp!iGwbWRN$tzdr_s(;&jH!+A8 z_kW!g2z2+i*MEali#HO52;t8w!F*sDJeUT;#`UKhQh`9G|51PM#_+-75DmOm9henQ z3x_as|Cbm9()xeY(WXCvdGR;jgQ@ZT;t)~Dawk3;{yQJ91VkMo`SD-FvIESG&k%yJ z;2R_$91x+NKQJ4fNfL4cQaJK|5J2*`D|zhyAYeE|8XSygk%9>0E2qF*c(@RR8IOZQ zI3d|T{^7YnFhBoUrSSX05H`G-)bEp%g?}T6{RFe&E2Vzl4Oqpi2}1<&Zqg7Ko=qAe p1CiMHgJ?j;xBnQ_c=}B+E1RJX)$d0KfpEWPr2+^vbO!!y{STY?E{*^I delta 3418 zcmYk8cQ_kb8^9yPo>hCbViPSfVpj(hqxQ9FW7V!$wNk5!T1_QZQM8n*+9MUS)MzMb z)E>3h#T79>y?yR?@A>DP_xC&RIp;agdEVz>HmMU9sh?DnsZ^ly(x1>mz8!*7XhAi3 zhBeSlCuGcLC-nH#%Fama8QTHVN)w-`23aXrxGM`_uTnMI;oxV%95 z=QumhLsF3Co!}ute_715$KcIImUq|9?dC_@bpHyTT^BpHdY;X+|6R+d$Bf;#(UMVOydicxjI;Jyl;9y##~9e{M;dGan<+v`(A&1 zK!y|HC#9n8lBEynsm}dR49T)Wj(WJX9#+IPg{M{`YTwQ>@H~F}t^C0TyIn%?!Ey%hXc%ZXNq;GlJBr9;K zFVj4yXaQy|b~)O6LKagy5@s~klxFX95@ZJouhChp^>N@)qNOT5`jBKt69UycnH3%j zZ14;Tbayk^9xTaXHXf;A78y zpM!aY@5DtpOCg5(#d3GKFx|^eBa*zLu>)O~PqXvT=o^Y7>Suxr4!yb02f7`qWS_EjQIo4l#XHHq*o25%s7J-7lZq1Z52C7rr z8ny)cwc5Im? z;0<+6?|;2_bA4Mo)?B|+q^Etm$Mlb4fh@n5d_)fgmdtZJY}jaSt#j?RwdMgxqsOCU z(=f45j>C;f-z~m8`aSenrBJA?phh>{D?R=6W8`!RRw!3m1W_4Q4cpqE}waPMR!bM6(hfR=?j}3;*jZt-TPge zJm1lb20+QV}B%9KR>isaxcL%`NNJY*L`nU z$o<}j)QB|xry9JxtHsRbDqd3|y*^*L@;_!|YjAwu7Qf$hO1&voHNwVtf8ah zvp_>cFNAu`S4HAfSQ?9OO&e5fusSl&;E3j%)~csGfrFUF=nPV4N3Ol^vtamvf=aaN zmh^k&8fVRcu33hRlw?<`7x2rKK&NRlYq-w(TWE1D3?omLO<^4_eRt?_yevE5z_^Bc zZ7MBwaY7X>Ir-#rv0EbSxmLtVZIgXrqhX7!ecDeMUAKq1;AE3`+j18TijL zd=>TLlix+81Ofoi9lG4u%|#TzQwvR8y2?XwIqIeV?T823 zk$unD{V57{RQ%@YIS{^YK1)~Pm^-oqwmKU6OH`MH%O9~ZESIP%n~@6Uhou-JL~fH| zqGQLmGIGxFTjQ&CCq&fwq2dk@rI)(o_CjtixE?c4J!+zdyj7}*?%TP8it>%8pc8kt z7;Z29;UL~ETfRE?mykB;1;4qm%`5{X%u?6>+hCT}Q3<9HV_xI<@LfKY(+;LJv$fG7 z^z~M=FvQ>FsFItyPifRFygOAh57@f3mcKu0I#zp$Hy!KsnYaO;ODf}zIS4iSSnk>2 zSgJL?*Vf?nm8GyQlPJxO0=-*%P@}LOB&&MuSy>-#r}WqdKD-z#WeQ&fs}XvJ{S<#` zBcsmNzsb(l>@45L|E0tBCl?(Touk^33G|;nQ;ZbYWk|Wz3XEPM($H)@;Hm`{zqS$+ z!!RllC}_L?hUcziwHon3+0t0gXlT3Fv&gV8>b20PgNQ-K!P9*d9#>TyrXkGIGl zHg+opbuVURw$vTgb_WJcEb`&qch&ITyX4`nyWnt-UDj}v+pe?*l%&*ro%AN>I4$Q` zzL~`)I4CKS=GBWx@KjA(;&<^zqyuQ}Q<{2L69qU#kxgB}y zUGteNwTZ@wZyUo&rx2sfgRdHDFGh(nrha_mn)YSmn#Cu+u=U;&37sy>v=Ps!8M*^) z6KvS{$Eg|=AwDmtJf)0OS?gu3ITyb#$*@{l=_}duNBG;B5$bO%wckXKe;N|4CYr!} zIKf-OFtrveVyRYWTlJy$-m8GW<*CG9ZY4#X496$8|g@lx6MjX|; z9e7Pwn@Ul^M3i3Q;XeHN50Eb)+Z6OmN~alKxYQe z)6Y~;=;J3rUV^0Z3S!*PU4a)pid?63kN#9gG)#&h1Y|!5WO0^_rxFFz#b*HpH!v`C zy56H`-l8w)gb_jFq7qH&{=*z?Lx42%`LkOc^n;W`)KUA|1K+LtGd|;oih^P}U{j0* zovzW)cj9NUhapF#dzZ?WcLh>BUJM4KZT0(5$wTUitz4I~7nsX^vP;#fMRC=lO6}tc zn=H2@g_aNXcut+P1d*@u{tWd(PoZwPW?Mv~)3j#9raOD{=57ZR4k+97huX3;pyn~bF_aY=!Tsm`Mw))aQsJ^c^OreW%LUrQnO9Q;K+v2WhU13vTh$Lr}u?lC@wdyFD`uwP?oi^2b zY&n!ktjl5#a|CrFN49~CxnP|y+r{k3!si12ROlzjfIFy*>P*f2_eY`Ml1#Ktyp7D% z6ZH2N0vmY^h~)Wi88-*~x2<5AuLHHPgzG>s@4rg{0C)d82{2oSWw{Q#jYWch>{u5W zAUE)P6SkEPD2%<>iU<2j8pw^|~vt(?)QzPUq zQgx>P?^u4HZ{ZhSo%@Z|mdH4MV_o?R?6Hj1Q~*k16o5?FG)W*Qw&54$UjK(`0Nb~J VjkOu00nq@MA^^~IM0RmQ{{tGYZZrS@ diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 878af1b92a..c403e274e2 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -403,19 +403,8 @@ public class WindowTransformSwipeHandler { } mRecentsView = activity.getOverviewPanel(); - mRecentsView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View v) { - // We can only initialize the SyncRtSurfaceTransactionApplier when the view has been - // attached - mSyncTransactionApplier = new SyncRtSurfaceTransactionApplier(mRecentsView); - mRecentsView.removeOnAttachStateChangeListener(this); - } - - @Override - public void onViewDetachedFromWindow(View v) { - // Do nothing - } + SyncRtSurfaceTransactionApplier.create(mRecentsView, (applier) -> { + mSyncTransactionApplier = applier; }); mQuickScrubController = mRecentsView.getQuickScrubController(); mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity); From 3516bd89d9665787fdb3db73e4922361bb307380 Mon Sep 17 00:00:00 2001 From: Chilun Date: Thu, 29 Nov 2018 20:38:22 +0800 Subject: [PATCH 09/15] Add a secondary launcher activity (1/2) This secondary launcher activity with new category SECONDARY_HOME and multiple instance supporrted could be used on sencondary display. Bug: 118206886 Bug: 114329798 Test: Manual Change-Id: Ibaecf8ef7614389760d0fcc547ef6d378a921583 --- Android.mk | 4 +- SecondaryDisplayLauncher/Android.mk | 39 ++++ SecondaryDisplayLauncher/AndroidManifest.xml | 40 ++++ .../res/drawable/ic_apps.xml | 22 ++ .../res/drawable/ic_settings.xml | 22 ++ .../secondary_display_launcher.xml | 56 +++++ .../secondary_display_launcher.xml | 57 +++++ .../res/layout/app_grid_item.xml | 35 +++ .../res/layout/app_picker_dialog.xml | 34 +++ .../res/layout/app_picker_layout.xml | 46 ++++ .../res/layout/secondary_display_launcher.xml | 56 +++++ .../res/menu/context_menu.xml | 23 ++ .../res/values-sw600dp/dimens.xml | 22 ++ .../res/values-sw720dp/dimens.xml | 22 ++ .../res/values/colors.xml | 22 ++ .../res/values/dimens.xml | 31 +++ .../res/values/strings.xml | 25 ++ .../res/values/styles.xml | 30 +++ .../src/com/android/launcher3/AppEntry.java | 58 +++++ .../com/android/launcher3/AppListAdapter.java | 63 +++++ .../android/launcher3/AppListViewModel.java | 126 ++++++++++ .../launcher3/PinnedAppListViewModel.java | 120 ++++++++++ .../launcher3/PinnedAppPickerDialog.java | 74 ++++++ .../launcher3/SecondaryDisplayLauncher.java | 217 ++++++++++++++++++ 24 files changed, 1243 insertions(+), 1 deletion(-) create mode 100644 SecondaryDisplayLauncher/Android.mk create mode 100644 SecondaryDisplayLauncher/AndroidManifest.xml create mode 100644 SecondaryDisplayLauncher/res/drawable/ic_apps.xml create mode 100644 SecondaryDisplayLauncher/res/drawable/ic_settings.xml create mode 100644 SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml create mode 100644 SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml create mode 100644 SecondaryDisplayLauncher/res/layout/app_grid_item.xml create mode 100644 SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml create mode 100644 SecondaryDisplayLauncher/res/layout/app_picker_layout.xml create mode 100644 SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml create mode 100644 SecondaryDisplayLauncher/res/menu/context_menu.xml create mode 100644 SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml create mode 100644 SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml create mode 100644 SecondaryDisplayLauncher/res/values/colors.xml create mode 100644 SecondaryDisplayLauncher/res/values/dimens.xml create mode 100644 SecondaryDisplayLauncher/res/values/strings.xml create mode 100644 SecondaryDisplayLauncher/res/values/styles.xml create mode 100644 SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java create mode 100644 SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java create mode 100644 SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java create mode 100644 SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java create mode 100644 SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java create mode 100644 SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java diff --git a/Android.mk b/Android.mk index e5a712f191..28f0bc23bc 100644 --- a/Android.mk +++ b/Android.mk @@ -108,7 +108,9 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_ANDROID_LIBRARIES := Launcher3CommonDepsLib +LOCAL_STATIC_ANDROID_LIBRARIES := \ + Launcher3CommonDepsLib \ + SecondaryDisplayLauncherLib LOCAL_SRC_FILES := \ $(call all-java-files-under, src) \ $(call all-java-files-under, src_shortcuts_overrides) \ diff --git a/SecondaryDisplayLauncher/Android.mk b/SecondaryDisplayLauncher/Android.mk new file mode 100644 index 0000000000..4fb5eba172 --- /dev/null +++ b/SecondaryDisplayLauncher/Android.mk @@ -0,0 +1,39 @@ +# +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_USE_AAPT2 := true +LOCAL_AAPT2_ONLY := true +LOCAL_MODULE_TAGS := optional + +LOCAL_STATIC_ANDROID_LIBRARIES := androidx.design_design + +LOCAL_STATIC_JAVA_LIBRARIES := LauncherPluginLib + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PROGUARD_ENABLED := disabled + +LOCAL_SDK_VERSION := current +LOCAL_MIN_SDK_VERSION := 21 +LOCAL_MODULE := SecondaryDisplayLauncherLib +LOCAL_PRIVILEGED_MODULE := true + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/SecondaryDisplayLauncher/AndroidManifest.xml b/SecondaryDisplayLauncher/AndroidManifest.xml new file mode 100644 index 0000000000..ebf6b02cb8 --- /dev/null +++ b/SecondaryDisplayLauncher/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + diff --git a/SecondaryDisplayLauncher/res/drawable/ic_apps.xml b/SecondaryDisplayLauncher/res/drawable/ic_apps.xml new file mode 100644 index 0000000000..db779c2d12 --- /dev/null +++ b/SecondaryDisplayLauncher/res/drawable/ic_apps.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/SecondaryDisplayLauncher/res/drawable/ic_settings.xml b/SecondaryDisplayLauncher/res/drawable/ic_settings.xml new file mode 100644 index 0000000000..c269c3bafc --- /dev/null +++ b/SecondaryDisplayLauncher/res/drawable/ic_settings.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml b/SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml new file mode 100644 index 0000000000..46f1674e47 --- /dev/null +++ b/SecondaryDisplayLauncher/res/layout-sw600dp/secondary_display_launcher.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + diff --git a/SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml b/SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml new file mode 100644 index 0000000000..6653a77968 --- /dev/null +++ b/SecondaryDisplayLauncher/res/layout-sw720dp/secondary_display_launcher.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + diff --git a/SecondaryDisplayLauncher/res/layout/app_grid_item.xml b/SecondaryDisplayLauncher/res/layout/app_grid_item.xml new file mode 100644 index 0000000000..ee5158ad32 --- /dev/null +++ b/SecondaryDisplayLauncher/res/layout/app_grid_item.xml @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml b/SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml new file mode 100644 index 0000000000..563a1afa78 --- /dev/null +++ b/SecondaryDisplayLauncher/res/layout/app_picker_dialog.xml @@ -0,0 +1,34 @@ + + + + + + + diff --git a/SecondaryDisplayLauncher/res/layout/app_picker_layout.xml b/SecondaryDisplayLauncher/res/layout/app_picker_layout.xml new file mode 100644 index 0000000000..fbaeac4605 --- /dev/null +++ b/SecondaryDisplayLauncher/res/layout/app_picker_layout.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + diff --git a/SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml b/SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml new file mode 100644 index 0000000000..49cd499a50 --- /dev/null +++ b/SecondaryDisplayLauncher/res/layout/secondary_display_launcher.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + diff --git a/SecondaryDisplayLauncher/res/menu/context_menu.xml b/SecondaryDisplayLauncher/res/menu/context_menu.xml new file mode 100644 index 0000000000..626384229e --- /dev/null +++ b/SecondaryDisplayLauncher/res/menu/context_menu.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml b/SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml new file mode 100644 index 0000000000..f33a8db400 --- /dev/null +++ b/SecondaryDisplayLauncher/res/values-sw600dp/dimens.xml @@ -0,0 +1,22 @@ + + + + + 400dp + 400dp + 60dp + diff --git a/SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml b/SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml new file mode 100644 index 0000000000..524e52af71 --- /dev/null +++ b/SecondaryDisplayLauncher/res/values-sw720dp/dimens.xml @@ -0,0 +1,22 @@ + + + + + 660dp + 660dp + 70dp + diff --git a/SecondaryDisplayLauncher/res/values/colors.xml b/SecondaryDisplayLauncher/res/values/colors.xml new file mode 100644 index 0000000000..66b41a2ba6 --- /dev/null +++ b/SecondaryDisplayLauncher/res/values/colors.xml @@ -0,0 +1,22 @@ + + + + #884e8391 + diff --git a/SecondaryDisplayLauncher/res/values/dimens.xml b/SecondaryDisplayLauncher/res/values/dimens.xml new file mode 100644 index 0000000000..7cca60719c --- /dev/null +++ b/SecondaryDisplayLauncher/res/values/dimens.xml @@ -0,0 +1,31 @@ + + + + + 72dp + 24dp + 24dp + 64dp + 64dp + 24dp + 8dp + 8dp + + 300dp + 300dp + 20dp + 20dp + diff --git a/SecondaryDisplayLauncher/res/values/strings.xml b/SecondaryDisplayLauncher/res/values/strings.xml new file mode 100644 index 0000000000..0f906c4837 --- /dev/null +++ b/SecondaryDisplayLauncher/res/values/strings.xml @@ -0,0 +1,25 @@ + + + + + SecondaryDisplayLauncher + Couldn\'t launch the activity + Add app shortcut + Set wallpaper + diff --git a/SecondaryDisplayLauncher/res/values/styles.xml b/SecondaryDisplayLauncher/res/values/styles.xml new file mode 100644 index 0000000000..4bfda6a2a5 --- /dev/null +++ b/SecondaryDisplayLauncher/res/values/styles.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java b/SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java new file mode 100644 index 0000000000..3017b81c1d --- /dev/null +++ b/SecondaryDisplayLauncher/src/com/android/launcher3/AppEntry.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; + +/** An entry that represents a single activity that can be launched. */ +public class AppEntry { + + private String mLabel; + private Drawable mIcon; + private Intent mLaunchIntent; + + AppEntry(ResolveInfo info, PackageManager packageManager) { + mLabel = info.loadLabel(packageManager).toString(); + mIcon = info.loadIcon(packageManager); + mLaunchIntent = new Intent(); + mLaunchIntent.setComponent(new ComponentName(info.activityInfo.packageName, + info.activityInfo.name)); + } + + String getLabel() { + return mLabel; + } + + Drawable getIcon() { + return mIcon; + } + + Intent getLaunchIntent() { return mLaunchIntent; } + + ComponentName getComponentName() { + return mLaunchIntent.getComponent(); + } + + @Override + public String toString() { + return mLabel; + } +} diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java new file mode 100644 index 0000000000..aa115cb575 --- /dev/null +++ b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListAdapter.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.launcher3.R; + +import java.util.List; + +/** Adapter for available apps list. */ +public class AppListAdapter extends ArrayAdapter { + private final LayoutInflater mInflater; + + AppListAdapter(Context context) { + super(context, android.R.layout.simple_list_item_2); + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } + + void setData(List data) { + clear(); + if (data != null) { + addAll(data); + } + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view; + + if (convertView == null) { + view = mInflater.inflate(R.layout.app_grid_item, parent, false); + } else { + view = convertView; + } + + AppEntry item = getItem(position); + ((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(item.getIcon()); + ((TextView)view.findViewById(R.id.app_name)).setText(item.getLabel()); + + return view; + } +} diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java new file mode 100644 index 0000000000..914fd5e01a --- /dev/null +++ b/SecondaryDisplayLauncher/src/com/android/launcher3/AppListViewModel.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.app.Application; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.AsyncTask; + +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; + +import java.util.ArrayList; +import java.util.List; + +/** + * A view model that provides a list of activities that can be launched. + */ +public class AppListViewModel extends AndroidViewModel { + + private final AppListLiveData mLiveData; + private final PackageIntentReceiver + mPackageIntentReceiver; + + public AppListViewModel(Application application) { + super(application); + mLiveData = new AppListLiveData(application); + mPackageIntentReceiver = new PackageIntentReceiver(mLiveData, application); + } + + public LiveData> getAppList() { + return mLiveData; + } + + protected void onCleared() { + getApplication().unregisterReceiver(mPackageIntentReceiver); + } +} + +class AppListLiveData extends LiveData> { + + private final PackageManager mPackageManager; + private int mCurrentDataVersion; + + public AppListLiveData(Context context) { + mPackageManager = context.getPackageManager(); + loadData(); + } + + void loadData() { + final int loadDataVersion = ++mCurrentDataVersion; + + new AsyncTask>() { + @Override + protected List doInBackground(Void... voids) { + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); + + List apps = mPackageManager.queryIntentActivities(mainIntent, + PackageManager.GET_META_DATA); + + List entries = new ArrayList<>(); + if (apps != null) { + for (ResolveInfo app : apps) { + AppEntry entry = new AppEntry(app, mPackageManager); + entries.add(entry); + } + } + return entries; + } + + @Override + protected void onPostExecute(List data) { + if (mCurrentDataVersion == loadDataVersion) { + setValue(data); + } + } + }.execute(); + } +} + +/** + * Receiver used to notify live data about app list changes. + */ +class PackageIntentReceiver extends BroadcastReceiver { + + private final AppListLiveData mLiveData; + + public PackageIntentReceiver(AppListLiveData liveData, Context context) { + mLiveData = liveData; + IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addDataScheme("package"); + context.registerReceiver(this, filter); + + // Register for events related to sdcard installation. + IntentFilter sdFilter = new IntentFilter(); + sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE); + sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); + context.registerReceiver(this, sdFilter); + } + + @Override + public void onReceive(Context context, Intent intent) { + mLiveData.loadData(); + } +} \ No newline at end of file diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java new file mode 100644 index 0000000000..4f92038ae4 --- /dev/null +++ b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppListViewModel.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import static com.android.launcher3.PinnedAppListViewModel.PINNED_APPS_KEY; + +import android.app.Application; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.AsyncTask; + +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * A view model that provides a list of activities that were pinned by user to always display on + * home screen. + * The pinned activities are stored in {@link SharedPreferences} to keep the sample simple :). + */ +public class PinnedAppListViewModel extends AndroidViewModel { + + final static String PINNED_APPS_KEY = "pinned_apps"; + + private final PinnedAppListLiveData mLiveData; + + public PinnedAppListViewModel(Application application) { + super(application); + mLiveData = new PinnedAppListLiveData(application); + } + + public LiveData> getPinnedAppList() { + return mLiveData; + } +} + +class PinnedAppListLiveData extends LiveData> { + + private final Context mContext; + private final PackageManager mPackageManager; + // Store listener reference, so it won't be GC-ed. + private final SharedPreferences.OnSharedPreferenceChangeListener mChangeListener; + private int mCurrentDataVersion; + + public PinnedAppListLiveData(Context context) { + mContext = context; + mPackageManager = context.getPackageManager(); + + final SharedPreferences prefs = context.getSharedPreferences(PINNED_APPS_KEY, 0); + mChangeListener = (preferences, key) -> { + loadData(); + }; + prefs.registerOnSharedPreferenceChangeListener(mChangeListener); + + loadData(); + } + + private void loadData() { + final int loadDataVersion = ++mCurrentDataVersion; + + new AsyncTask>() { + @Override + protected List doInBackground(Void... voids) { + List entries = new ArrayList<>(); + + final SharedPreferences sp = mContext.getSharedPreferences(PINNED_APPS_KEY, 0); + final Set pinnedAppsComponents = sp.getStringSet(PINNED_APPS_KEY, null); + if (pinnedAppsComponents == null) { + return null; + } + + for (String componentString : pinnedAppsComponents) { + final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.setComponent(ComponentName.unflattenFromString(componentString)); + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); + + final List apps = mPackageManager.queryIntentActivities(mainIntent, + PackageManager.GET_META_DATA); + + if (apps != null) { + for (ResolveInfo app : apps) { + final AppEntry entry = new AppEntry(app, mPackageManager); + entries.add(entry); + } + } + } + + return entries; + } + + @Override + protected void onPostExecute(List data) { + if (mCurrentDataVersion == loadDataVersion) { + setValue(data); + } + } + }.execute(); + } +} \ No newline at end of file diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java new file mode 100644 index 0000000000..02e6e4a9c6 --- /dev/null +++ b/SecondaryDisplayLauncher/src/com/android/launcher3/PinnedAppPickerDialog.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.GridView; + +import androidx.fragment.app.DialogFragment; + +import com.android.launcher3.R; + +/** + * Callback to be invoked when an app was picked. + */ +interface AppPickedCallback { + void onAppPicked(AppEntry appEntry); +} + +/** + * Dialog that provides the user with a list of available apps to pin to the home screen. + */ +public class PinnedAppPickerDialog extends DialogFragment { + + private AppListAdapter mAppListAdapter; + private AppPickedCallback mAppPickerCallback; + + public PinnedAppPickerDialog() { + } + + public static PinnedAppPickerDialog newInstance(AppListAdapter appListAdapter, + AppPickedCallback callback) { + PinnedAppPickerDialog + frag = new PinnedAppPickerDialog(); + frag.mAppListAdapter = appListAdapter; + frag.mAppPickerCallback = callback; + return frag; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return inflater.inflate(R.layout.app_picker_dialog, container); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + GridView appGridView = view.findViewById(R.id.picker_app_grid); + appGridView.setAdapter(mAppListAdapter); + appGridView.setOnItemClickListener((adapterView, itemView, position, id) -> { + final AppEntry entry = mAppListAdapter.getItem(position); + mAppPickerCallback.onAppPicked(entry); + dismiss(); + }); + } +} \ No newline at end of file diff --git a/SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java b/SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java new file mode 100644 index 0000000000..5e8b40246a --- /dev/null +++ b/SecondaryDisplayLauncher/src/com/android/launcher3/SecondaryDisplayLauncher.java @@ -0,0 +1,217 @@ +/** + * Copyright (c) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import static com.android.launcher3.PinnedAppListViewModel.PINNED_APPS_KEY; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.app.AlertDialog; +import android.app.Application; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.design.circularreveal.cardview.CircularRevealCardView; +import android.support.design.widget.FloatingActionButton; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewAnimationUtils; +import android.widget.GridView; +import android.widget.ImageButton; +import android.widget.PopupMenu; + +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.ViewModelProvider; +import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory; + +import java.util.HashSet; +import java.util.Set; + +/** + * Secondary launcher activity. It's launch mode is configured as "singleTop" to allow showing on + * multiple displays and to ensure a single instance per each display. + */ +public class SecondaryDisplayLauncher extends FragmentActivity implements AppPickedCallback, + PopupMenu.OnMenuItemClickListener { + + private AppListAdapter mAppListAdapter; + private AppListAdapter mPinnedAppListAdapter; + private CircularRevealCardView mAppDrawerView; + private FloatingActionButton mFab; + + private boolean mAppDrawerShown; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.secondary_display_launcher); + + mAppDrawerView = findViewById(R.id.FloatingSheet); + mFab = findViewById(R.id.FloatingActionButton); + + mFab.setOnClickListener((View v) -> { + showAppDrawer(true); + }); + + final ViewModelProvider viewModelProvider = new ViewModelProvider(getViewModelStore(), + new AndroidViewModelFactory((Application) getApplicationContext())); + + mPinnedAppListAdapter = new AppListAdapter(this); + final GridView pinnedAppGridView = findViewById(R.id.pinned_app_grid); + pinnedAppGridView.setAdapter(mPinnedAppListAdapter); + pinnedAppGridView.setOnItemClickListener((adapterView, view, position, id) -> { + final AppEntry entry = mPinnedAppListAdapter.getItem(position); + launch(entry.getLaunchIntent()); + }); + final PinnedAppListViewModel pinnedAppListViewModel = + viewModelProvider.get(PinnedAppListViewModel.class); + pinnedAppListViewModel.getPinnedAppList().observe(this, data -> { + mPinnedAppListAdapter.setData(data); + }); + + mAppListAdapter = new AppListAdapter(this); + final GridView appGridView = findViewById(R.id.app_grid); + appGridView.setAdapter(mAppListAdapter); + appGridView.setOnItemClickListener((adapterView, view, position, id) -> { + final AppEntry entry = mAppListAdapter.getItem(position); + launch(entry.getLaunchIntent()); + }); + final AppListViewModel appListViewModel = viewModelProvider.get(AppListViewModel.class); + appListViewModel.getAppList().observe(this, data -> { + mAppListAdapter.setData(data); + }); + + ImageButton optionsButton = findViewById(R.id.OptionsButton); + optionsButton.setOnClickListener((View v) -> { + PopupMenu popup = new PopupMenu(this,v); + popup.setOnMenuItemClickListener(this); + MenuInflater inflater = popup.getMenuInflater(); + inflater.inflate(R.menu.context_menu, popup.getMenu()); + popup.show(); + }); + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + // Respond to picking one of the popup menu items. + final int id = item.getItemId(); + if (id == R.id.add_app_shortcut) { + FragmentManager fm = getSupportFragmentManager(); + PinnedAppPickerDialog pickerDialogFragment = + PinnedAppPickerDialog.newInstance(mAppListAdapter, this); + pickerDialogFragment.show(fm, "fragment_app_picker"); + return true; + } else if (id == R.id.set_wallpaper) { + Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER); + startActivity(Intent.createChooser(intent, getString(R.string.set_wallpaper))); + return true; + } + + return true; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + showAppDrawer(false); + } + + public void onBackPressed() { + // If the app drawer was shown - hide it. Otherwise, not doing anything since we don't want + // to close the launcher. + showAppDrawer(false); + } + + public void onNewIntent(Intent intent) { + super.onNewIntent(intent); + // A new intent will bring the launcher to top. Hide the app drawer to reset the state. + showAppDrawer(false); + } + + void launch(Intent launchIntent) { + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + try { + startActivity(launchIntent); + } catch (Exception e) { + final AlertDialog.Builder builder = + new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert); + builder.setTitle(R.string.couldnt_launch) + .setMessage(e.getLocalizedMessage()) + .setIcon(android.R.drawable.ic_dialog_alert) + .show(); + } + } + + /** + * Store the picked app to persistent pinned list and update the loader. + */ + @Override + public void onAppPicked(AppEntry appEntry) { + final SharedPreferences sp = getSharedPreferences(PINNED_APPS_KEY, 0); + Set pinnedApps = sp.getStringSet(PINNED_APPS_KEY, null); + if (pinnedApps == null) { + pinnedApps = new HashSet(); + } else { + // Always need to create a new object to make sure that the changes are persisted. + pinnedApps = new HashSet(pinnedApps); + } + pinnedApps.add(appEntry.getComponentName().flattenToString()); + + final SharedPreferences.Editor editor = sp.edit(); + editor.putStringSet(PINNED_APPS_KEY, pinnedApps); + editor.apply(); + } + + /** + * Show/hide app drawer card with animation. + */ + private void showAppDrawer(boolean show) { + if (show == mAppDrawerShown) { + return; + } + + final Animator animator = revealAnimator(mAppDrawerView, show); + if (show) { + mAppDrawerShown = true; + mAppDrawerView.setVisibility(View.VISIBLE); + mFab.setVisibility(View.INVISIBLE); + } else { + mAppDrawerShown = false; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mAppDrawerView.setVisibility(View.INVISIBLE); + mFab.setVisibility(View.VISIBLE); + } + }); + } + animator.start(); + } + + /** + * Create reveal/hide animator for app list card. + */ + private Animator revealAnimator(View view, boolean open) { + final int radius = (int) Math.hypot((double) view.getWidth(), (double) view.getHeight()); + return ViewAnimationUtils.createCircularReveal(view, view.getRight(), view.getBottom(), + open ? 0 : radius, open ? radius : 0); + } +} From d177aba4a261fca4810c1bbba26f81a3aa260975 Mon Sep 17 00:00:00 2001 From: vadimt Date: Thu, 13 Dec 2018 11:53:56 -0800 Subject: [PATCH 10/15] Fixing ConcurrentModificationException Bug: 120664974 Test: Manual Change-Id: I67e88c6980fbabb9afb9f4946baf731852f19b19 --- src/com/android/launcher3/util/TraceHelper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java index 4aa2f37885..a321bcc205 100644 --- a/src/com/android/launcher3/util/TraceHelper.java +++ b/src/com/android/launcher3/util/TraceHelper.java @@ -39,7 +39,7 @@ public class TraceHelper { private static final boolean SYSTEM_TRACE = false; private static final ArrayMap sUpTimes = ENABLED ? new ArrayMap<>() : null; - public static void beginSection(String sectionName) { + public static synchronized void beginSection(String sectionName) { if (ENABLED) { MutableLong time = sUpTimes.get(sectionName); if (time == null) { @@ -55,7 +55,7 @@ public class TraceHelper { } } - public static void partitionSection(String sectionName, String partition) { + public static synchronized void partitionSection(String sectionName, String partition) { if (ENABLED) { MutableLong time = sUpTimes.get(sectionName); if (time != null && time.value >= 0) { @@ -78,7 +78,7 @@ public class TraceHelper { } } - public static void endSection(String sectionName, String msg) { + public static synchronized void endSection(String sectionName, String msg) { if (ENABLED) { MutableLong time = sUpTimes.get(sectionName); if (time != null && time.value >= 0) { From 195d5694e48fa6c0000200b7f78b679265120956 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 11 Dec 2018 17:59:36 -0800 Subject: [PATCH 11/15] Not relying on activity manager when choosing a touch consumer. Activity manager can report launcher activity as running when is hasn't yet been resumed. Bug: 120628042 Test: TaplTests, Fallback tests, manual tests Change-Id: I6b382b17d05066a63360acc19e094674ecca7130 --- .../com/android/quickstep/ActivityControlHelper.java | 6 ++++++ .../com/android/quickstep/TouchInteractionService.java | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index 16f5fa1142..f60572cc32 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -45,6 +45,7 @@ import android.os.Handler; import android.os.Looper; import android.view.View; +import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; @@ -114,6 +115,11 @@ public interface ActivityControlHelper { @Nullable T getCreatedActivity(); + default boolean isResumed() { + BaseDraggingActivity activity = getCreatedActivity(); + return activity != null && activity.hasBeenResumed(); + } + @UiThread @Nullable RecentsView getVisibleRecentsView(); diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index b1a214d9dd..a42ee094f4 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -249,7 +249,7 @@ public class TouchInteractionService extends Service { if (runningTaskInfo == null && !forceToLauncher) { return TouchConsumer.NO_OP; } else if (forceToLauncher || - runningTaskInfo.topActivity.equals(mOverviewCommandHelper.overviewComponent)) { + mOverviewCommandHelper.getActivityControlHelper().isResumed()) { return OverviewTouchConsumer.newInstance( mOverviewCommandHelper.getActivityControlHelper(), false, mTouchInteractionLog); } else { @@ -257,10 +257,10 @@ public class TouchInteractionService extends Service { tracker = VelocityTracker.obtain(); } return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel, - mOverviewCommandHelper.overviewIntent, - mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor, - mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks, - mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog); + mOverviewCommandHelper.overviewIntent, + mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor, + mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks, + mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog); } } From 00d42552725a215e4b98c84e1238a0039582286b Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 11 Dec 2018 17:59:36 -0800 Subject: [PATCH 12/15] Adding tests that would reliably reproduce shifted search. This would guaranteed to repro b/118441555 before it was fixed. The test doesn't use the most powerful feature of race condition reproducer, which is enumerating all possible event sequences. Instead, it uses explicit repro sequences, which makes the test much faster. Bug: 120628042 Test: The added test Change-Id: I89a7a9964f160a8a20ba3d9dda2f248237713014 --- .../quickstep/OtherActivityTouchConsumer.java | 6 ++ .../quickstep/RaceConditionsTests.java | 72 +++++++++++++++++++ .../src/com/android/quickstep/TaplTests.java | 24 +------ src/com/android/launcher3/Launcher.java | 13 +++- .../launcher3/util/RaceConditionTracker.java | 21 ++++++ .../launcher3/ui/AbstractLauncherUiTest.java | 22 ++++++ .../util/RaceConditionReproducer.java | 9 +++ 7 files changed, 142 insertions(+), 25 deletions(-) create mode 100644 quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index b11260ea58..95be188a0e 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -22,6 +22,8 @@ import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.INVALID_POINTER_ID; +import static com.android.launcher3.util.RaceConditionTracker.ENTER; +import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.systemui.shared.system.ActivityManagerWrapper .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; @@ -47,6 +49,7 @@ import android.view.ViewConfiguration; import android.view.WindowManager; import com.android.launcher3.MainThreadExecutor; +import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -70,6 +73,7 @@ import java.util.concurrent.TimeUnit; public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer { private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150; + public static final String DOWN_EVT = "OtherActivityTouchConsumer.DOWN"; private final SparseArray mAnimationStates = new SparseArray<>(); private final RunningTaskInfo mRunningTask; @@ -135,6 +139,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTouchInteractionLog.addMotionEvent(ev); switch (ev.getActionMasked()) { case ACTION_DOWN: { + RaceConditionTracker.onEvent(DOWN_EVT, ENTER); TraceHelper.beginSection("TouchInt"); mActivePointerId = ev.getPointerId(0); mDownPos.set(ev.getX(), ev.getY()); @@ -151,6 +156,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC Display display = getSystemService(WindowManager.class).getDefaultDisplay(); mDisplayRotation = display.getRotation(); WindowManagerWrapper.getInstance().getStableInsets(mStableInsets); + RaceConditionTracker.onEvent(DOWN_EVT, EXIT); break; } case ACTION_POINTER_UP: { diff --git a/quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java b/quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java new file mode 100644 index 0000000000..f132b12b46 --- /dev/null +++ b/quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep; + +import static com.android.launcher3.util.RaceConditionTracker.enterEvt; +import static com.android.launcher3.util.RaceConditionTracker.exitEvt; + +import android.content.Intent; + +import androidx.test.filters.LargeTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.launcher3.Launcher; +import com.android.launcher3.util.RaceConditionReproducer; +import com.android.quickstep.QuickStepOnOffRule.Mode; +import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@LargeTest +@RunWith(AndroidJUnit4.class) +public class RaceConditionsTests extends AbstractQuickStepTest { + private void runTest(String... eventSequence) { + final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(eventSequence); + + // Destroy Launcher activity. + executeOnLauncher(launcher -> { + if (launcher != null) { + launcher.finish(); + } + }); + waitForLauncherCondition( + "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT); + + // Start an activity where we'll press home. + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); + + // The test action. + eventProcessor.startIteration(); + mLauncher.pressHome(); + eventProcessor.finishIteration(); + } + + @Test + @QuickstepOnOff(mode = Mode.ON) + public void testPressHomeToStartLauncher() { + runTest(enterEvt(Launcher.ON_CREATE_EVT), + exitEvt(Launcher.ON_CREATE_EVT), + enterEvt(OtherActivityTouchConsumer.DOWN_EVT), + exitEvt(OtherActivityTouchConsumer.DOWN_EVT)); + + runTest(enterEvt(OtherActivityTouchConsumer.DOWN_EVT), + exitEvt(OtherActivityTouchConsumer.DOWN_EVT), + enterEvt(Launcher.ON_CREATE_EVT), + exitEvt(Launcher.ON_CREATE_EVT)); + } +} diff --git a/quickstep/tests/src/com/android/quickstep/TaplTests.java b/quickstep/tests/src/com/android/quickstep/TaplTests.java index 701229c98c..6a1123e02e 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTests.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTests.java @@ -24,9 +24,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import android.app.Instrumentation; import android.content.Intent; -import android.content.pm.PackageManager; import android.os.RemoteException; import android.util.Log; @@ -66,7 +64,6 @@ import java.io.IOException; @LargeTest @RunWith(AndroidJUnit4.class) public class TaplTests extends AbstractQuickStepTest { - private static final int WAIT_TIME_MS = 60000; private static final String TAG = "TaplTests"; private static int sScreenshotCount = 0; @@ -112,13 +109,6 @@ public class TaplTests extends AbstractQuickStepTest { waitForResumed("Launcher internal state is still Background"); } - private String resolveSystemApp(String category) { - return getInstrumentation().getContext().getPackageManager().resolveActivity( - new Intent(Intent.ACTION_MAIN).addCategory(category), - PackageManager.MATCH_SYSTEM_ONLY). - activityInfo.packageName; - } - private boolean isInState(LauncherState state) { if (!TestHelpers.isInLauncherProcess()) return true; return getFromLauncher(launcher -> launcher.getStateManager().getState() == state); @@ -143,17 +133,6 @@ public class TaplTests extends AbstractQuickStepTest { return !launcher.hasBeenResumed(); } - private void startAppFast(String packageName) { - final Instrumentation instrumentation = getInstrumentation(); - final Intent intent = instrumentation.getContext().getPackageManager(). - getLaunchIntentForPackage(packageName); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - instrumentation.getTargetContext().startActivity(intent); - assertTrue(packageName + " didn't start", - mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), WAIT_TIME_MS)); - } - private void startTestApps() throws Exception { startAppFast(resolveSystemApp(Intent.CATEGORY_APP_MESSAGING)); startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); @@ -338,7 +317,8 @@ public class TaplTests extends AbstractQuickStepTest { assertNotNull("overview.getCurrentTask() returned null (1)", task); assertNotNull("OverviewTask.open returned null", task.open()); assertTrue("Contacts app didn't open from Overview", mDevice.wait(Until.hasObject( - By.pkg(resolveSystemApp(Intent.CATEGORY_APP_CONTACTS)).depth(0)), WAIT_TIME_MS)); + By.pkg(resolveSystemApp(Intent.CATEGORY_APP_CONTACTS)).depth(0)), + LONG_WAIT_TIME_MS)); executeOnLauncher(launcher -> assertTrue( "Launcher activity is the top activity; expecting another activity to be the top " + "one", diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index f8b44d00c2..9125a98433 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -19,6 +19,7 @@ package com.android.launcher3; import static android.content.pm.ActivityInfo.CONFIG_LOCALE; import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; + import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR; import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY; import static com.android.launcher3.LauncherState.ALL_APPS; @@ -26,6 +27,8 @@ import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.logging.LoggerUtils.newTarget; +import static com.android.launcher3.util.RaceConditionTracker.ENTER; +import static com.android.launcher3.util.RaceConditionTracker.EXIT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -71,16 +74,18 @@ import android.view.accessibility.AccessibilityEvent; import android.view.animation.OvershootInterpolator; import android.widget.Toast; +import androidx.annotation.Nullable; + import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.PropertyListBuilder; -import com.android.launcher3.dot.DotInfo; import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.compat.LauncherAppsCompatVO; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dot.DotInfo; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; @@ -116,6 +121,7 @@ import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.PendingRequestArgs; +import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; import com.android.launcher3.util.Thunk; @@ -143,8 +149,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import androidx.annotation.Nullable; - /** * Default launcher application. */ @@ -184,6 +188,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, private static final String RUNTIME_STATE_PENDING_ACTIVITY_RESULT = "launcher.activity_result"; // Type: SparseArray private static final String RUNTIME_STATE_WIDGET_PANEL = "launcher.widget_panel"; + public static final String ON_CREATE_EVT = "Launcher.onCreate"; private LauncherStateManager mStateManager; @@ -255,6 +260,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onCreate(Bundle savedInstanceState) { + RaceConditionTracker.onEvent(ON_CREATE_EVT, ENTER); if (DEBUG_STRICT_MODE) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() @@ -349,6 +355,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mRotationHelper.initialize(); TraceHelper.endSection("Launcher-onCreate"); + RaceConditionTracker.onEvent(ON_CREATE_EVT, EXIT); } @Override diff --git a/src/com/android/launcher3/util/RaceConditionTracker.java b/src/com/android/launcher3/util/RaceConditionTracker.java index 8eafb551dc..8b0678784a 100644 --- a/src/com/android/launcher3/util/RaceConditionTracker.java +++ b/src/com/android/launcher3/util/RaceConditionTracker.java @@ -22,6 +22,9 @@ package com.android.launcher3.util; * orders. */ public class RaceConditionTracker { + public final static boolean ENTER = true; + public final static boolean EXIT = false; + public interface EventProcessor { void onEvent(String eventName); } @@ -35,4 +38,22 @@ public class RaceConditionTracker { public static void onEvent(String eventName) { if (sEventProcessor != null) sEventProcessor.onEvent(eventName); } + + public static void onEvent(String eventName, boolean isEnter) { + if (sEventProcessor != null) { + sEventProcessor.onEvent(enterExitEvt(eventName, isEnter)); + } + } + + public static String enterExitEvt(String eventName, boolean isEnter) { + return eventName + ":" + (isEnter ? "enter" : "exit"); + } + + public static String enterEvt(String eventName) { + return enterExitEvt(eventName, ENTER); + } + + public static String exitEvt(String eventName) { + return enterExitEvt(eventName, EXIT); + } } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index bc5aaeeb75..338fd853e6 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -17,6 +17,7 @@ package com.android.launcher3.ui; import static androidx.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.Instrumentation; @@ -25,11 +26,13 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.LauncherActivityInfo; +import android.content.pm.PackageManager; import android.os.Process; import android.os.RemoteException; import android.view.Surface; import androidx.test.InstrumentationRegistry; +import androidx.test.uiautomator.By; import androidx.test.uiautomator.BySelector; import androidx.test.uiautomator.Direction; import androidx.test.uiautomator.UiDevice; @@ -77,6 +80,7 @@ public abstract class AbstractLauncherUiTest { public static final long SHORT_UI_TIMEOUT= 300; public static final long DEFAULT_UI_TIMEOUT = 10000; + protected static final int LONG_WAIT_TIME_MS = 60000; protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); protected final UiDevice mDevice; @@ -325,4 +329,22 @@ public abstract class AbstractLauncherUiTest { return intent == null ? null : (Intent) intent.getParcelableExtra(Intent.EXTRA_INTENT); } } + + protected void startAppFast(String packageName) { + final Instrumentation instrumentation = getInstrumentation(); + final Intent intent = instrumentation.getContext().getPackageManager(). + getLaunchIntentForPackage(packageName); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + instrumentation.getTargetContext().startActivity(intent); + assertTrue(packageName + " didn't start", + mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), LONG_WAIT_TIME_MS)); + } + + protected String resolveSystemApp(String category) { + return getInstrumentation().getContext().getPackageManager().resolveActivity( + new Intent(Intent.ACTION_MAIN).addCategory(category), + PackageManager.MATCH_SYSTEM_ONLY). + activityInfo.packageName; + } } diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java index c4350de0b7..316e40d825 100644 --- a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java +++ b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java @@ -43,6 +43,11 @@ import java.util.concurrent.TimeUnit; * executing events in previously unseen order. It does it by postponing execution of threads that * would lead to an already seen sequence. * + * If an event A occurs before event B in the sequence, this is how execution order looks like: + * Events: ... A ... B ... + * Events and instructions, guaranteed order: + * (instructions executed prior to A) A ... B (instructions executed after B) + * * Each iteration has 3 parts (phases). * Phase 1. Picking a previously seen event subsequence that we believe can have previously unseen * continuations. Reproducing this sequence by pausing threads that would lead to other sequences. @@ -178,6 +183,10 @@ public class RaceConditionReproducer implements RaceConditionTracker.EventProces mReproString = reproString; } + public RaceConditionReproducer(String... reproSequence) { + this(String.join("|", reproSequence)); + } + public synchronized String getCurrentSequenceString() { return mCurrentSequence.toString(); } From 943b28464d534783b371f850c5078af9c3a02cbf Mon Sep 17 00:00:00 2001 From: vadimt Date: Mon, 17 Dec 2018 18:09:07 -0800 Subject: [PATCH 13/15] Test swiping up from a killed launcher Bug: 121164587 Test: StartLauncherViaGestureTests Change-Id: I01c5bfc0aa23418bad7d44b8d9cf8b95cbe0b320 --- ...java => StartLauncherViaGestureTests.java} | 33 +++++++++++-------- .../launcher3/ui/AbstractLauncherUiTest.java | 11 +++++++ 2 files changed, 31 insertions(+), 13 deletions(-) rename quickstep/tests/src/com/android/quickstep/{RaceConditionsTests.java => StartLauncherViaGestureTests.java} (81%) diff --git a/quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java similarity index 81% rename from quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java rename to quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java index f132b12b46..52f3c538c6 100644 --- a/quickstep/tests/src/com/android/quickstep/RaceConditionsTests.java +++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java @@ -29,26 +29,26 @@ import com.android.launcher3.util.RaceConditionReproducer; import com.android.quickstep.QuickStepOnOffRule.Mode; import com.android.quickstep.QuickStepOnOffRule.QuickstepOnOff; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @LargeTest @RunWith(AndroidJUnit4.class) -public class RaceConditionsTests extends AbstractQuickStepTest { +public class StartLauncherViaGestureTests extends AbstractQuickStepTest { + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + // Start an activity where the gestures start. + startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); + } + private void runTest(String... eventSequence) { final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(eventSequence); // Destroy Launcher activity. - executeOnLauncher(launcher -> { - if (launcher != null) { - launcher.finish(); - } - }); - waitForLauncherCondition( - "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT); - - // Start an activity where we'll press home. - startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR)); + closeLauncherActivity(); // The test action. eventProcessor.startIteration(); @@ -58,7 +58,7 @@ public class RaceConditionsTests extends AbstractQuickStepTest { @Test @QuickstepOnOff(mode = Mode.ON) - public void testPressHomeToStartLauncher() { + public void testPressHome() { runTest(enterEvt(Launcher.ON_CREATE_EVT), exitEvt(Launcher.ON_CREATE_EVT), enterEvt(OtherActivityTouchConsumer.DOWN_EVT), @@ -69,4 +69,11 @@ public class RaceConditionsTests extends AbstractQuickStepTest { enterEvt(Launcher.ON_CREATE_EVT), exitEvt(Launcher.ON_CREATE_EVT)); } -} + + @Test + @QuickstepOnOff(mode = Mode.ON) + public void testSwipeToOverview() { + closeLauncherActivity(); + mLauncher.getBackground().switchToOverview(); + } +} \ No newline at end of file diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 338fd853e6..8c03e4b5f6 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -347,4 +347,15 @@ public abstract class AbstractLauncherUiTest { PackageManager.MATCH_SYSTEM_ONLY). activityInfo.packageName; } + + protected void closeLauncherActivity() { + // Destroy Launcher activity. + executeOnLauncher(launcher -> { + if (launcher != null) { + launcher.finish(); + } + }); + waitForLauncherCondition( + "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT); + } } From a7a9583bb8ffbee7a760c7e6ab8c99f63dddd145 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Mon, 17 Dec 2018 23:38:43 -0800 Subject: [PATCH 14/15] Remove IconShapeOverride Bug: 120736782 Change-Id: Iee44f10ff2b9ec447ae74d9ad6a0aa3668c401d6 --- .../LauncherSearchIndexablesProvider.java | 3 - res/values/strings.xml | 32 +-- res/xml/launcher_preferences.xml | 9 - .../launcher3/MainProcessInitializer.java | 2 - .../launcher3/graphics/IconShapeOverride.java | 214 ------------------ .../launcher3/settings/SettingsActivity.java | 9 - 6 files changed, 16 insertions(+), 253 deletions(-) delete mode 100644 src/com/android/launcher3/graphics/IconShapeOverride.java diff --git a/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java b/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java index f5e1f6ec56..5d6fbe2ca6 100644 --- a/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java +++ b/quickstep/src/com/android/quickstep/LauncherSearchIndexablesProvider.java @@ -29,7 +29,6 @@ import android.provider.SearchIndexablesProvider; import android.util.Xml; import com.android.launcher3.R; -import com.android.launcher3.graphics.IconShapeOverride; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -88,8 +87,6 @@ public class LauncherSearchIndexablesProvider extends SearchIndexablesProvider { } catch (IOException |XmlPullParserException e) { throw new RuntimeException(e); } - } else if (!IconShapeOverride.isSupported(getContext())) { - cursor.addRow(new String[] {IconShapeOverride.KEY_PREFERENCE}); } return cursor; } diff --git a/res/values/strings.xml b/res/values/strings.xml index 3f01278760..b1eff24578 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -205,23 +205,23 @@ For new apps - - Change icon shape - - on Home screen - - Use system default - - Square - - Squircle - - Circle - - Teardrop + + Change icon shape + + on Home screen + + Use system default + + Square + + Squircle + + Circle + + Teardrop - - Applying icon shape changes + + Applying icon shape changes Unknown diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml index be3cb0e28f..7e7220813a 100644 --- a/res/xml/launcher_preferences.xml +++ b/res/xml/launcher_preferences.xml @@ -44,15 +44,6 @@ android:defaultValue="@bool/allow_rotation" android:persistent="true" /> - - Date: Wed, 19 Dec 2018 15:48:11 +0100 Subject: [PATCH 15/15] SyncRtTransactionApplier -> SyncRtTransactionApplierCompat Bug: 118118435 Change-Id: I37bba45db79890f5d7ae6c1d1d63422a89230b35 --- .../launcher3/LauncherAppTransitionManagerImpl.java | 12 ++++++------ .../com/android/quickstep/OverviewCommandHelper.java | 6 +++--- quickstep/src/com/android/quickstep/TaskUtils.java | 6 +++--- .../quickstep/WindowTransformSwipeHandler.java | 6 +++--- .../android/quickstep/util/ClipAnimationHelper.java | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index 20a83b5cd0..a084ca8078 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -80,8 +80,8 @@ import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.WindowManagerWrapper; /** @@ -580,8 +580,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag MODE_OPENING); RemoteAnimationTargetSet closingTargets = new RemoteAnimationTargetSet(targets, MODE_CLOSING); - SyncRtSurfaceTransactionApplier surfaceApplier = new SyncRtSurfaceTransactionApplier( - mFloatingView); + SyncRtSurfaceTransactionApplierCompat surfaceApplier = + new SyncRtSurfaceTransactionApplierCompat(mFloatingView); ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); @@ -740,8 +740,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag * Animator that controls the transformations of the windows the targets that are closing. */ private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) { - SyncRtSurfaceTransactionApplier surfaceApplier = - new SyncRtSurfaceTransactionApplier(mDragLayer); + SyncRtSurfaceTransactionApplierCompat surfaceApplier = + new SyncRtSurfaceTransactionApplierCompat(mDragLayer); Matrix matrix = new Matrix(); ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1); int duration = CLOSING_TRANSITION_DURATION_MS; diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index 61bb75f857..b3f8a113c5 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -66,7 +66,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; import com.android.systemui.shared.system.TransactionCompat; import java.util.ArrayList; @@ -343,8 +343,8 @@ public class OverviewCommandHelper { clipHelper.updateTargetRect(targetRect); clipHelper.prepareAnimation(false /* isOpening */); - SyncRtSurfaceTransactionApplier syncTransactionApplier = - new SyncRtSurfaceTransactionApplier(rootView); + SyncRtSurfaceTransactionApplierCompat syncTransactionApplier = + new SyncRtSurfaceTransactionApplierCompat(rootView); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); valueAnimator.setDuration(RECENTS_LAUNCH_DURATION); valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java index 4b86a7fa88..cab3a4cdf2 100644 --- a/quickstep/src/com/android/quickstep/TaskUtils.java +++ b/quickstep/src/com/android/quickstep/TaskUtils.java @@ -43,7 +43,7 @@ import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; import java.util.List; @@ -145,8 +145,8 @@ public class TaskUtils { */ public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges, RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) { - SyncRtSurfaceTransactionApplier syncTransactionApplier = - new SyncRtSurfaceTransactionApplier(v); + SyncRtSurfaceTransactionApplierCompat syncTransactionApplier = + new SyncRtSurfaceTransactionApplierCompat(v); final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); appAnimator.addUpdateListener(new MultiValueUpdateListener() { diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index c403e274e2..6e2e3d3d7c 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -85,7 +85,7 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; import com.android.systemui.shared.system.WindowCallbacksCompat; import java.util.StringJoiner; @@ -213,7 +213,7 @@ public class WindowTransformSwipeHandler { private T mActivity; private LayoutListener mLayoutListener; private RecentsView mRecentsView; - private SyncRtSurfaceTransactionApplier mSyncTransactionApplier; + private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier; private QuickScrubController mQuickScrubController; private AnimationFactory mAnimationFactory = (t, i) -> { }; @@ -403,7 +403,7 @@ public class WindowTransformSwipeHandler { } mRecentsView = activity.getOverviewPanel(); - SyncRtSurfaceTransactionApplier.create(mRecentsView, (applier) -> { + SyncRtSurfaceTransactionApplierCompat.create(mRecentsView, (applier) -> { mSyncTransactionApplier = applier; }); mQuickScrubController = mRecentsView.getQuickScrubController(); diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java index 1e1f147c16..f6af67a30f 100644 --- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -46,8 +46,8 @@ import com.android.quickstep.views.TaskThumbnailView; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.utilities.RectFEvaluator; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.TransactionCompat; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -152,7 +152,7 @@ public class ClipAnimationHelper { } public RectF applyTransform(RemoteAnimationTargetSet targetSet, float progress, - @Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier) { + @Nullable SyncRtSurfaceTransactionApplierCompat syncTransactionApplier) { RectF currentRect; mTmpRectF.set(mTargetRect); Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale); @@ -218,14 +218,14 @@ public class ClipAnimationHelper { return mCurrentRectWithInsets; } - private void applyParams(@Nullable SyncRtSurfaceTransactionApplier syncTransactionApplier, + private void applyParams(@Nullable SyncRtSurfaceTransactionApplierCompat syncTransactionApplier, SurfaceParams[] params) { if (syncTransactionApplier != null) { syncTransactionApplier.scheduleApply(params); } else { TransactionCompat t = new TransactionCompat(); for (SurfaceParams param : params) { - SyncRtSurfaceTransactionApplier.applyParams(t, param); + SyncRtSurfaceTransactionApplierCompat.applyParams(t, param); } t.setEarlyWakeup(); t.apply();