Snap for 5124112 from ee817568b6 to qt-release

Change-Id: I893897309f661f082b92f3fff3c52e8ba18c0769
This commit is contained in:
android-build-team Robot
2018-11-11 04:05:18 +00:00
31 changed files with 494 additions and 266 deletions
+2 -4
View File
@@ -36,16 +36,14 @@
android:restoreAnyVersion="true"
android:supportsRtl="true" >
<!-- Activity for handling PinItemRequest. Only supports shortcuts -->
<!-- Activity for handling PinItemRequest is disabled on Android Go. -->
<activity android:name="com.android.launcher3.dragndrop.AddItemActivity"
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:excludeFromRecents="true"
android:autoRemoveFromRecents="true"
android:label="@string/action_add_to_workspace"
android:enabled="false"
tools:node="replace" >
<intent-filter>
<action android:name="android.content.pm.action.CONFIRM_PIN_SHORTCUT" />
</intent-filter>
</activity>
</application>
-66
View File
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/widget_preview_label_vertical_padding"
android:paddingBottom="@dimen/widget_preview_label_vertical_padding"
android:paddingLeft="@dimen/widget_preview_label_horizontal_padding"
android:paddingRight="@dimen/widget_preview_label_horizontal_padding"
android:orientation="horizontal">
<!-- The name of the widget. -->
<TextView
android:id="@+id/widget_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:fadingEdge="horizontal"
android:fontFamily="sans-serif-condensed"
android:gravity="center"
android:singleLine="true"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" />
<!-- The original dimensions of the widget (can't be the same text as above due to different
style. -->
<TextView
android:id="@+id/widget_dims"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:visibility="gone"
android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp"
android:fontFamily="sans-serif-condensed"
android:alpha="0.8" />
</LinearLayout>
<!-- The image of the widget. This view does not support padding. Any placement adjustment
should be done using margins. -->
<com.android.launcher3.widget.WidgetImageView
android:id="@+id/widget_preview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</merge>
+5
View File
@@ -37,6 +37,11 @@ android {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.graphics;
package com.android.launcher3.icons;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
@@ -21,14 +21,12 @@ import android.graphics.Canvas;
import android.graphics.Picture;
import android.os.Build;
import com.android.launcher3.Utilities;
/**
* Interface representing a bitmap draw operation.
*/
public interface BitmapRenderer {
boolean USE_HARDWARE_BITMAP = Utilities.ATLEAST_P;
boolean USE_HARDWARE_BITMAP = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
static Bitmap createSoftwareBitmap(int width, int height, BitmapRenderer renderer) {
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
@@ -15,10 +15,18 @@
*/
package com.android.launcher3.icons;
import android.graphics.Bitmap;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import androidx.annotation.ColorInt;
public class GraphicsUtils {
private static final String TAG = "GraphicsUtils";
/**
* Set the alpha component of {@code color} to be {@code alpha}. Unlike the support lib version,
* it bounds the alpha in valid range instead of throwing an exception to allow for safer
@@ -33,4 +41,23 @@ public class GraphicsUtils {
}
return (color & 0x00ffffff) | (alpha << 24);
}
/**
* Compresses the bitmap to a byte array for serialization.
*/
public static byte[] flattenBitmap(Bitmap bitmap) {
// Try go guesstimate how much space the icon will take when serialized
// to avoid unnecessary allocations/copies during the write (4 bytes per pixel).
int size = bitmap.getWidth() * bitmap.getHeight() * 4;
ByteArrayOutputStream out = new ByteArrayOutputStream(size);
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
return out.toByteArray();
} catch (IOException e) {
Log.w(TAG, "Could not write bitmap");
return null;
}
}
}
@@ -29,8 +29,9 @@ public class ComponentKey {
private final int mHashCode;
public ComponentKey(ComponentName componentName, UserHandle user) {
Preconditions.assertNotNull(componentName);
Preconditions.assertNotNull(user);
if (componentName == null || user == null) {
throw new NullPointerException();
}
this.componentName = componentName;
this.user = user;
mHashCode = Arrays.hashCode(new Object[] {componentName, user});
@@ -18,8 +18,6 @@ package com.android.launcher3.util;
import static android.database.sqlite.SQLiteDatabase.NO_LOCALIZED_COLLATORS;
import static com.android.launcher3.Utilities.ATLEAST_P;
import android.content.Context;
import android.content.ContextWrapper;
import android.database.DatabaseErrorHandler;
@@ -27,6 +25,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDatabase.OpenParams;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
/**
* Extension of {@link SQLiteOpenHelper} which avoids creating default locale table by
@@ -34,6 +33,9 @@ import android.database.sqlite.SQLiteOpenHelper;
*/
public abstract class NoLocaleSQLiteHelper extends SQLiteOpenHelper {
private static final boolean ATLEAST_P =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
public NoLocaleSQLiteHelper(Context context, String name, int version) {
super(ATLEAST_P ? context : new NoLocalContext(context), name, null, version);
if (ATLEAST_P) {
@@ -9,9 +9,6 @@ import android.database.sqlite.SQLiteFullException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
/**
* An extension of {@link SQLiteOpenHelper} with utility methods for a single table cache DB.
* Any exception during write operations are ignored, and any version change causes a DB reset.
@@ -19,8 +16,7 @@ import com.android.launcher3.config.FeatureFlags;
public abstract class SQLiteCacheHelper {
private static final String TAG = "SQLiteCacheHelper";
private static final boolean NO_ICON_CACHE = FeatureFlags.IS_DOGFOOD_BUILD &&
Utilities.isPropertyEnabled(LogConfig.MEMORY_ONLY_ICON_CACHE);
private static final boolean IN_MEMORY_CACHE = false;
private final String mTableName;
private final MySQLiteOpenHelper mOpenHelper;
@@ -28,7 +24,7 @@ public abstract class SQLiteCacheHelper {
private boolean mIgnoreWrites;
public SQLiteCacheHelper(Context context, String name, int version, String tableName) {
if (NO_ICON_CACHE) {
if (IN_MEMORY_CACHE) {
name = null;
}
mTableName = tableName;
+1 -1
View File
@@ -24,7 +24,7 @@
-keep class androidx.recyclerview.widget.RecyclerView { *; }
# Preference fragments
-keep class ** extends android.preference.PreferenceFragment {
-keep class ** extends android.app.Fragment {
public <init>(...);
}
@@ -462,7 +462,7 @@ public class TaskView extends FrameLayout implements PageCallbacks {
}
if (action == R.string.accessibility_app_usage_settings) {
openAppUsageSettings();
openAppUsageSettings(this);
return true;
}
@@ -484,14 +484,16 @@ public class TaskView extends FrameLayout implements PageCallbacks {
return super.performAccessibilityAction(action, arguments);
}
private void openAppUsageSettings() {
private void openAppUsageSettings(View view) {
final Intent intent = new Intent(SEE_TIME_IN_APP_TEMPLATE)
.putExtra(Intent.EXTRA_PACKAGE_NAME,
mTask.getTopComponent().getPackageName()).addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
try {
final Launcher launcher = Launcher.getLauncher(getContext());
launcher.startActivity(intent);
final ActivityOptions options = ActivityOptions.makeScaleUpAnimation(view, 0, 0,
view.getWidth(), view.getHeight());
launcher.startActivity(intent, options.toBundle());
launcher.getUserEventDispatcher().logActionOnControl(LauncherLogProto.Action.Touch.TAP,
LauncherLogProto.ControlType.APP_USAGE_SETTINGS, this);
} catch (ActivityNotFoundException e) {
+44 -1
View File
@@ -30,7 +30,50 @@
layout="@layout/all_apps_rv_layout"
android:visibility="gone" />
<include layout="@layout/all_apps_floating_header" />
<com.android.launcher3.allapps.FloatingHeaderView
android:id="@+id/all_apps_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:paddingTop="@dimen/all_apps_header_top_padding"
android:orientation="vertical" >
<include layout="@layout/floating_header_content" />
<com.android.launcher3.allapps.PersonalWorkSlidingTabStrip
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/all_apps_header_tab_height"
android:layout_marginLeft="@dimen/all_apps_tabs_side_padding"
android:layout_marginRight="@dimen/all_apps_tabs_side_padding"
android:orientation="horizontal">
<Button
android:id="@+id/tab_personal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:fontFamily="sans-serif-medium"
android:text="@string/all_apps_personal_tab"
android:textAllCaps="true"
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp" />
<Button
android:id="@+id/tab_work"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:fontFamily="sans-serif-medium"
android:text="@string/all_apps_work_tab"
android:textAllCaps="true"
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp" />
</com.android.launcher3.allapps.PersonalWorkSlidingTabStrip>
</com.android.launcher3.allapps.FloatingHeaderView>
<include
android:id="@id/search_container_all_apps"
-58
View File
@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.launcher3.allapps.FloatingHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/all_apps_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/search_container_all_apps"
android:clipToPadding="false"
android:paddingTop="@dimen/all_apps_header_top_padding"
android:orientation="vertical" >
<com.android.launcher3.allapps.PersonalWorkSlidingTabStrip
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/all_apps_header_tab_height"
android:layout_marginLeft="@dimen/all_apps_tabs_side_padding"
android:layout_marginRight="@dimen/all_apps_tabs_side_padding"
android:orientation="horizontal">
<Button
android:id="@+id/tab_personal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:fontFamily="sans-serif-medium"
android:text="@string/all_apps_personal_tab"
android:textAllCaps="true"
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp" />
<Button
android:id="@+id/tab_work"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:fontFamily="sans-serif-medium"
android:text="@string/all_apps_work_tab"
android:textAllCaps="true"
android:textColor="@color/all_apps_tab_text"
android:textSize="14sp" />
</com.android.launcher3.allapps.PersonalWorkSlidingTabStrip>
</com.android.launcher3.allapps.FloatingHeaderView>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<merge />
@@ -39,6 +39,7 @@ import android.util.Patterns;
import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.Thunk;
@@ -47,7 +48,6 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;
/**
@@ -436,7 +436,7 @@ public class AutoInstallsLayout {
// Auto installs should always support the current platform version.
LauncherIcons li = LauncherIcons.obtain(mContext);
mValues.put(LauncherSettings.Favorites.ICON, Utilities.flattenBitmap(
mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(
li.createBadgedIconBitmap(icon, Process.myUserHandle(), VERSION.SDK_INT).icon));
li.recycle();
@@ -41,6 +41,7 @@ import android.util.Pair;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
@@ -457,7 +458,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
.key(LAUNCH_INTENT_KEY).value(launchIntent.toUri(0))
.key(NAME_KEY).value(name);
if (icon != null) {
byte[] iconByteArray = Utilities.flattenBitmap(icon);
byte[] iconByteArray = GraphicsUtils.flattenBitmap(icon);
json = json.key(ICON_KEY).value(
Base64.encodeToString(
iconByteArray, 0, iconByteArray.length, Base64.DEFAULT));
-19
View File
@@ -356,25 +356,6 @@ public final class Utilities {
return null;
}
/**
* Compresses the bitmap to a byte array for serialization.
*/
public static byte[] flattenBitmap(Bitmap bitmap) {
// Try go guesstimate how much space the icon will take when serialized
// to avoid unnecessary allocations/copies during the write.
int size = bitmap.getWidth() * bitmap.getHeight() * 4;
ByteArrayOutputStream out = new ByteArrayOutputStream(size);
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
return out.toByteArray();
} catch (IOException e) {
Log.w(TAG, "Could not write bitmap");
return null;
}
}
/**
* Trims the string, removing all whitespace at the beginning and end of the string.
* Non-breaking whitespaces are also removed.
@@ -31,6 +31,7 @@ import android.util.LongSparseArray;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.launcher3.icons.IconCache;
@@ -149,7 +150,7 @@ public class WidgetPreviewLoader {
values.put(CacheDb.COLUMN_PACKAGE, key.componentName.getPackageName());
values.put(CacheDb.COLUMN_VERSION, versions[0]);
values.put(CacheDb.COLUMN_LAST_UPDATED, versions[1]);
values.put(CacheDb.COLUMN_PREVIEW_BITMAP, Utilities.flattenBitmap(preview));
values.put(CacheDb.COLUMN_PREVIEW_BITMAP, GraphicsUtils.flattenBitmap(preview));
mDb.insertOrReplace(values);
}
+3 -3
View File
@@ -1625,7 +1625,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
// We want the point to be mapped to the dragTarget.
mapPointFromDropLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
int spanX;
int spanY;
@@ -1827,7 +1827,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
// We want the point to be mapped to the dragTarget.
if (dropTargetLayout != null) {
mapPointFromDropLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
}
boolean droppedOnOriginalCell = false;
@@ -2255,7 +2255,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
// Handle the drag over
if (mDragTargetLayout != null) {
// We want the point to be mapped to the dragTarget.
mapPointFromDropLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
mapPointFromDropLayout(mDragTargetLayout, mDragViewVisualCenter);
int minSpanX = item.spanX;
int minSpanY = item.spanY;
@@ -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.allapps;
import android.graphics.Rect;
import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.PropertySetter;
/**
* A abstract representation of a row in all-apps view
*/
public interface FloatingHeaderRow {
FloatingHeaderRow[] NO_ROWS = new FloatingHeaderRow[0];
void setup(FloatingHeaderView parent, FloatingHeaderRow[] allRows, boolean tabsHidden);
void setInsets(Rect insets, DeviceProfile grid);
int getExpectedHeight();
/**
* Returns true if the row should draw based on its current position and layout.
*/
boolean shouldDraw();
/**
* Returns true if the view has anything worth drawing. This is different than
* {@link #shouldDraw()} as this is called earlier in the layout to determine the view
* position.
*/
boolean hasVisibleContent();
void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
PropertySetter setter, Interpolator fadeInterpolator);
/**
* Scrolls the content vertically.
*/
void setVerticalScroll(int scroll, boolean isScrolledOut);
Class<? extends FloatingHeaderRow> getTypeClass();
}
@@ -19,28 +19,34 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.systemui.plugins.AllAppsRow;
import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
import com.android.systemui.plugins.PluginListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
public class FloatingHeaderView extends LinearLayout implements
ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow> {
ValueAnimator.AnimatorUpdateListener, PluginListener<AllAppsRow>, Insettable,
OnHeightUpdatedListener {
private final Rect mClip = new Rect(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
private final ValueAnimator mAnimator = ValueAnimator.ofInt(0, 0);
@@ -62,17 +68,18 @@ public class FloatingHeaderView extends LinearLayout implements
int current = -mCurrentRV.getCurrentScrollY();
moved(current);
apply();
applyVerticalMove();
}
};
private final int mHeaderTopPadding;
protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
protected ViewGroup mTabLayout;
private AllAppsRecyclerView mMainRV;
private AllAppsRecyclerView mWorkRV;
private AllAppsRecyclerView mCurrentRV;
protected final Map<AllAppsRow, View> mPluginRows;
// Contains just the values of the above map so we can iterate without extracting a new list.
protected final List<View> mPluginRowViews;
private ViewGroup mParent;
private boolean mHeaderCollapsed;
private int mSnappedScrolledY;
@@ -85,20 +92,42 @@ public class FloatingHeaderView extends LinearLayout implements
protected int mMaxTranslation;
private boolean mMainRVActive = true;
private boolean mCollapsed = false;
// This is initialized once during inflation and stays constant after that. Fixed views
// cannot be added or removed dynamically.
private FloatingHeaderRow[] mFixedRows = FloatingHeaderRow.NO_ROWS;
// Array of all fixed rows and plugin rows. This is initialized every time a plugin is
// enabled or disabled, and represent the current set of all rows.
private FloatingHeaderRow[] mAllRows = FloatingHeaderRow.NO_ROWS;
public FloatingHeaderView(@NonNull Context context) {
this(context, null);
}
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPluginRows = new HashMap<>();
mPluginRowViews = new ArrayList<>();
mHeaderTopPadding = context.getResources()
.getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mTabLayout = findViewById(R.id.tabs);
// Find all floating header rows.
ArrayList<FloatingHeaderRow> rows = new ArrayList<>();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child instanceof FloatingHeaderRow) {
rows.add((FloatingHeaderRow) child);
}
}
mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
mAllRows = mFixedRows;
}
@Override
@@ -114,50 +143,70 @@ public class FloatingHeaderView extends LinearLayout implements
PluginManagerWrapper.INSTANCE.get(getContext()).removePluginListener(this);
}
@Override
public void onPluginConnected(AllAppsRow allAppsRowPlugin, Context context) {
mPluginRows.put(allAppsRowPlugin, null);
setupPluginRows();
allAppsRowPlugin.setOnHeightUpdatedListener(this::onPluginRowHeightUpdated);
private void recreateAllRowsArray() {
int pluginCount = mPluginRows.size();
if (pluginCount == 0) {
mAllRows = mFixedRows;
} else {
int count = mFixedRows.length;
mAllRows = new FloatingHeaderRow[count + pluginCount];
for (int i = 0; i < count; i++) {
mAllRows[i] = mFixedRows[i];
}
for (PluginHeaderRow row : mPluginRows.values()) {
mAllRows[count] = row;
count++;
}
}
}
protected void onPluginRowHeightUpdated() {
@Override
public void onPluginConnected(AllAppsRow allAppsRowPlugin, Context context) {
PluginHeaderRow headerRow = new PluginHeaderRow(allAppsRowPlugin, this);
addView(headerRow.mView, indexOfChild(mTabLayout));
mPluginRows.put(allAppsRowPlugin, headerRow);
recreateAllRowsArray();
allAppsRowPlugin.setOnHeightUpdatedListener(this);
}
@Override
public void onHeightUpdated() {
int oldMaxHeight = mMaxTranslation;
updateExpectedHeight();
if (mMaxTranslation != oldMaxHeight) {
AllAppsContainerView parent = (AllAppsContainerView) getParent();
if (parent != null) {
parent.setupHeader();
}
}
}
@Override
public void onPluginDisconnected(AllAppsRow plugin) {
View pluginRowView = mPluginRows.get(plugin);
removeView(pluginRowView);
PluginHeaderRow row = mPluginRows.get(plugin);
removeView(row.mView);
mPluginRows.remove(plugin);
mPluginRowViews.remove(pluginRowView);
onPluginRowHeightUpdated();
recreateAllRowsArray();
onHeightUpdated();
}
public void setup(AllAppsContainerView.AdapterHolder[] mAH, boolean tabsHidden) {
for (FloatingHeaderRow row : mAllRows) {
row.setup(this, mAllRows, tabsHidden);
}
updateExpectedHeight();
mTabsHidden = tabsHidden;
mTabLayout.setVisibility(tabsHidden ? View.GONE : View.VISIBLE);
mMainRV = setupRV(mMainRV, mAH[AllAppsContainerView.AdapterHolder.MAIN].recyclerView);
mWorkRV = setupRV(mWorkRV, mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView);
mParent = (ViewGroup) mMainRV.getParent();
setMainActive(mMainRVActive || mWorkRV == null);
setupPluginRows();
reset(false);
}
private void setupPluginRows() {
for (Map.Entry<AllAppsRow, View> rowPluginEntry : mPluginRows.entrySet()) {
if (rowPluginEntry.getValue() == null) {
View pluginRow = rowPluginEntry.getKey().setup(this);
addView(pluginRow, indexOfChild(mTabLayout));
rowPluginEntry.setValue(pluginRow);
mPluginRowViews.add(pluginRow);
}
}
for (View plugin : mPluginRowViews) {
plugin.setVisibility(mHeaderCollapsed ? GONE : VISIBLE);
}
}
private AllAppsRecyclerView setupRV(AllAppsRecyclerView old, AllAppsRecyclerView updated) {
if (old != updated && updated != null ) {
updated.addOnScrollListener(mOnScrollListener);
@@ -165,6 +214,16 @@ public class FloatingHeaderView extends LinearLayout implements
return updated;
}
private void updateExpectedHeight() {
mMaxTranslation = 0;
if (mCollapsed) {
return;
}
for (FloatingHeaderRow row : mAllRows) {
mMaxTranslation += row.getExpectedHeight();
}
}
public void setMainActive(boolean active) {
mCurrentRV = active ? mMainRV : mWorkRV;
mMainRVActive = active;
@@ -208,12 +267,21 @@ public class FloatingHeaderView extends LinearLayout implements
}
}
protected void applyScroll(int uncappedY, int currentY) { }
protected void apply() {
protected void applyVerticalMove() {
int uncappedTranslationY = mTranslationY;
mTranslationY = Math.max(mTranslationY, -mMaxTranslation);
applyScroll(uncappedTranslationY, mTranslationY);
if (mCollapsed || uncappedTranslationY < mTranslationY - mHeaderTopPadding) {
// we hide it completely if already capped (for opening search anim)
for (FloatingHeaderRow row : mAllRows) {
row.setVerticalScroll(0, true /* isScrolledOut */);
}
} else {
for (FloatingHeaderRow row : mAllRows) {
row.setVerticalScroll(uncappedTranslationY, false /* isScrolledOut */);
}
}
mTabLayout.setTranslationY(mTranslationY);
mClip.top = mMaxTranslation + mTranslationY;
// clipping on a draw might cause additional redraw
@@ -223,6 +291,16 @@ public class FloatingHeaderView extends LinearLayout implements
}
}
/**
* Hides all the floating rows
*/
public void setCollapsed(boolean collapse) {
if (mCollapsed == collapse) return;
mCollapsed = collapse;
onHeightUpdated();
}
public void reset(boolean animate) {
if (mAnimator.isStarted()) {
mAnimator.cancel();
@@ -234,7 +312,7 @@ public class FloatingHeaderView extends LinearLayout implements
mAnimator.start();
} else {
mTranslationY = 0;
apply();
applyVerticalMove();
}
mHeaderCollapsed = false;
mSnappedScrolledY = -mMaxTranslation;
@@ -248,7 +326,7 @@ public class FloatingHeaderView extends LinearLayout implements
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mTranslationY = (Integer) animation.getAnimatedValue();
apply();
applyVerticalMove();
}
@Override
@@ -287,8 +365,12 @@ public class FloatingHeaderView extends LinearLayout implements
public void setContentVisibility(boolean hasHeader, boolean hasContent, PropertySetter setter,
Interpolator fadeInterpolator) {
setter.setViewAlpha(this, hasContent ? 1 : 0, fadeInterpolator);
for (FloatingHeaderRow row : mAllRows) {
row.setContentVisibility(hasHeader, hasContent, setter, fadeInterpolator);
}
allowTouchForwarding(hasContent);
setter.setFloat(mTabLayout, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
}
protected void allowTouchForwarding(boolean allow) {
@@ -296,6 +378,11 @@ public class FloatingHeaderView extends LinearLayout implements
}
public boolean hasVisibleContent() {
for (FloatingHeaderRow row : mAllRows) {
if (row.hasVisibleContent()) {
return true;
}
}
return false;
}
@@ -303,6 +390,23 @@ public class FloatingHeaderView extends LinearLayout implements
public boolean hasOverlappingRendering() {
return false;
}
@Override
public void setInsets(Rect insets) {
DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
for (FloatingHeaderRow row : mAllRows) {
row.setInsets(insets, grid);
}
}
public <T extends FloatingHeaderRow> T findFixedRowByType(Class<T> type) {
for (FloatingHeaderRow row : mAllRows) {
if (row.getTypeClass() == type) {
return (T) row;
}
}
return null;
}
}
@@ -0,0 +1,85 @@
/*
* 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.allapps;
import static android.view.View.ALPHA;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import android.graphics.Rect;
import android.view.View;
import android.view.animation.Interpolator;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.PropertySetter;
import com.android.systemui.plugins.AllAppsRow;
/**
* Wrapper over an {@link AllAppsRow} plugin with {@link FloatingHeaderRow} interface so that
* it can be easily added in {@link FloatingHeaderView}.
*/
public class PluginHeaderRow implements FloatingHeaderRow {
private final AllAppsRow mPlugin;
final View mView;
PluginHeaderRow(AllAppsRow plugin, FloatingHeaderView parent) {
mPlugin = plugin;
mView = mPlugin.setup(parent);
}
@Override
public void setup(FloatingHeaderView parent, FloatingHeaderRow[] allRows,
boolean tabsHidden) { }
@Override
public void setInsets(Rect insets, DeviceProfile grid) { }
@Override
public int getExpectedHeight() {
return mPlugin.getExpectedHeight();
}
@Override
public boolean shouldDraw() {
return true;
}
@Override
public boolean hasVisibleContent() {
return true;
}
@Override
public void setContentVisibility(boolean hasHeaderExtra, boolean hasContent,
PropertySetter setter, Interpolator fadeInterpolator) {
// Don't use setViewAlpha as we want to control the visibility ourselves.
setter.setFloat(mView, ALPHA, hasContent ? 1 : 0, fadeInterpolator);
}
@Override
public void setVerticalScroll(int scroll, boolean isScrolledOut) {
mView.setVisibility(isScrolledOut ? INVISIBLE : VISIBLE);
if (!isScrolledOut) {
mView.setTranslationY(scroll);
}
}
@Override
public Class<PluginHeaderRow> getTypeClass() {
return PluginHeaderRow.class;
}
}
@@ -36,7 +36,7 @@ import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.Preconditions;
/**
@@ -33,6 +33,7 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -32,6 +32,7 @@ import android.os.Build;
import android.util.AttributeSet;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapRenderer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -36,19 +36,14 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.IconProvider;
import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.SQLiteCacheHelper;
@@ -58,11 +53,10 @@ import java.util.HashSet;
import androidx.annotation.NonNull;
public class BaseIconCache {
public abstract class BaseIconCache {
private static final String TAG = "BaseIconCache";
private static final boolean DEBUG = false;
private static final boolean DEBUG_IGNORE_CACHE = false;
private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
@@ -76,29 +70,30 @@ public class BaseIconCache {
private final HashMap<UserHandle, BitmapInfo> mDefaultIcons = new HashMap<>();
final Context mContext;
final PackageManager mPackageManager;
final IconProvider mIconProvider;
final UserManagerCompat mUserManager;
protected final Context mContext;
protected final PackageManager mPackageManager;
protected final IconProvider mIconProvider;
private final HashMap<ComponentKey, CacheEntry> mCache =
new HashMap<>(INITIAL_ICON_CACHE_CAPACITY);
private final InstantAppResolver mInstantAppResolver;
final Handler mWorkerHandler;
protected final Handler mWorkerHandler;
int mIconDpi;
protected int mIconDpi;
IconDB mIconDb;
private final String mDbFileName;
private final BitmapFactory.Options mDecodeOptions;
private final Looper mBgLooper;
public BaseIconCache(Context context, int iconDpi, int iconPixelSize) {
public BaseIconCache(Context context, String dbFileName, Looper bgLooper,
int iconDpi, int iconPixelSize) {
mContext = context;
mDbFileName = dbFileName;
mPackageManager = context.getPackageManager();
mUserManager = UserManagerCompat.getInstance(mContext);
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
mBgLooper = bgLooper;
mIconProvider = IconProvider.newInstance(context);
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
mWorkerHandler = new Handler(mBgLooper);
if (BitmapRenderer.USE_HARDWARE_BITMAP && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mDecodeOptions = new BitmapFactory.Options();
@@ -108,9 +103,21 @@ public class BaseIconCache {
}
mIconDpi = iconDpi;
mIconDb = new IconDB(context, iconPixelSize);
mIconDb = new IconDB(context, dbFileName, iconPixelSize);
}
/**
* Returns the persistable serial number for {@param user}. Subclass should implement proper
* caching strategy to avoid making binder call every time.
*/
protected abstract long getSerialNumberForUser(UserHandle user);
/**
* Return true if the given app is an instant app and should be badged appropriately.
*/
protected abstract boolean isInstantApp(ApplicationInfo info);
public void updateIconParams(int iconDpi, int iconPixelSize) {
mWorkerHandler.post(() -> updateIconParamsBg(iconDpi, iconPixelSize));
}
@@ -120,13 +127,14 @@ public class BaseIconCache {
mDefaultIcons.clear();
mIconDb.close();
mIconDb = new IconDB(mContext, iconPixelSize);
mIconDb = new IconDB(mContext, mDbFileName, iconPixelSize);
mCache.clear();
}
private Drawable getFullResDefaultActivityIcon() {
return Resources.getSystem().getDrawableForDensity(Utilities.ATLEAST_OREO
? android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon,
return Resources.getSystem().getDrawableForDensity(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon,
mIconDpi);
}
@@ -189,7 +197,7 @@ public class BaseIconCache {
*/
public synchronized void removeIconsForPkg(String packageName, UserHandle user) {
removeFromMemCacheLocked(packageName, user);
long userSerial = mUserManager.getSerialNumberForUser(user);
long userSerial = getSerialNumberForUser(user);
mIconDb.delete(
IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
new String[]{packageName + "/%", Long.toString(userSerial)});
@@ -287,7 +295,7 @@ public class BaseIconCache {
T object = null;
boolean providerFetchedOnce = false;
if (!getEntryFromDB(cacheKey, entry, useLowResIcon) || DEBUG_IGNORE_CACHE) {
if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
object = infoProvider.get();
providerFetchedOnce = true;
@@ -395,7 +403,7 @@ public class BaseIconCache {
// only keep the low resolution icon instead of the larger full-sized icon
BitmapInfo iconInfo = li.createBadgedIconBitmap(
appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion,
mInstantAppResolver.isInstantApp(appInfo));
isInstantApp(appInfo));
li.recycle();
entry.title = appInfo.loadLabel(mPackageManager);
@@ -407,8 +415,7 @@ public class BaseIconCache {
// package updates.
ContentValues values = newContentValues(
iconInfo, entry.title.toString(), packageName);
addIconToDB(values, cacheKey.componentName, info,
mUserManager.getSerialNumberForUser(user));
addIconToDB(values, cacheKey.componentName, info, getSerialNumberForUser(user));
} catch (NameNotFoundException e) {
if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
@@ -432,7 +439,7 @@ public class BaseIconCache {
IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
new String[]{
cacheKey.componentName.flattenToString(),
Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
Long.toString(getSerialNumberForUser(cacheKey.user))});
if (c.moveToNext()) {
// Set the alpha to be 255, so that we never have a wrong color
entry.color = setColorAlphaBound(c.getInt(0), 255);
@@ -485,10 +492,8 @@ public class BaseIconCache {
public final static String[] COLUMNS_LOW_RES = new String[] {
IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL };
public IconDB(Context context, int iconPixelSize) {
super(context, LauncherFiles.APP_ICONS_DB,
(RELEASE_VERSION << 16) + iconPixelSize,
TABLE_NAME);
public IconDB(Context context, String dbFileName, int iconPixelSize) {
super(context, dbFileName, (RELEASE_VERSION << 16) + iconPixelSize, TABLE_NAME);
}
@Override
@@ -510,7 +515,7 @@ public class BaseIconCache {
private ContentValues newContentValues(BitmapInfo bitmapInfo, String label, String packageName) {
ContentValues values = new ContentValues();
values.put(IconDB.COLUMN_ICON,
bitmapInfo.isLowRes() ? null : Utilities.flattenBitmap(bitmapInfo.icon));
bitmapInfo.isLowRes() ? null : GraphicsUtils.flattenBitmap(bitmapInfo.icon));
values.put(IconDB.COLUMN_ICON_COLOR, bitmapInfo.color);
values.put(IconDB.COLUMN_LABEL, label);
+19 -1
View File
@@ -18,6 +18,7 @@ package com.android.launcher3.icons;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -31,13 +32,16 @@ import android.util.Log;
import com.android.launcher3.AppInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
@@ -56,15 +60,29 @@ public class IconCache extends BaseIconCache {
private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic;
private final LauncherAppsCompat mLauncherApps;
private final UserManagerCompat mUserManager;
private final InstantAppResolver mInstantAppResolver;
private int mPendingIconRequestCount = 0;
public IconCache(Context context, InvariantDeviceProfile inv) {
super(context, inv.fillResIconDpi, inv.iconBitmapSize);
super(context, LauncherFiles.APP_ICONS_DB, LauncherModel.getWorkerLooper(),
inv.fillResIconDpi, inv.iconBitmapSize);
mComponentWithLabelCachingLogic = new ComponentCachingLogic(context);
mLauncherActivityInfoCachingLogic = new LauncherActivtiyCachingLogic(this);
mLauncherApps = LauncherAppsCompat.getInstance(mContext);
mUserManager = UserManagerCompat.getInstance(mContext);
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
}
@Override
protected long getSerialNumberForUser(UserHandle user) {
return mUserManager.getSerialNumberForUser(user);
}
@Override
protected boolean isInstantApp(ApplicationInfo info) {
return mInstantAppResolver.isInstantApp(info);
}
/**
@@ -27,11 +27,8 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.SparseBooleanArray;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.BaseIconCache.IconDB;
import com.android.launcher3.util.IntArray;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -131,7 +128,7 @@ public class IconCacheUpdateHandler {
if (ignorePackages == null) {
ignorePackages = Collections.emptySet();
}
long userSerial = mIconCache.mUserManager.getSerialNumberForUser(user);
long userSerial = mIconCache.getSerialNumberForUser(user);
Stack<T> appsToUpdate = new Stack<>();
@@ -204,18 +201,31 @@ public class IconCacheUpdateHandler {
}
}
/**
* Commits all updates as part of the update handler to disk. Not more calls should be made
* to this class after this.
*/
public void finish() {
// Commit all deletes
IntArray deleteIds = new IntArray();
int deleteCount = 0;
StringBuilder queryBuilder = new StringBuilder()
.append(IconDB.COLUMN_ROWID)
.append(" IN (");
int count = mItemsToDelete.size();
for (int i = 0; i < count; i++) {
if (mItemsToDelete.valueAt(i)) {
deleteIds.add(mItemsToDelete.keyAt(i));
if (deleteCount > 0) {
queryBuilder.append(", ");
}
queryBuilder.append(mItemsToDelete.keyAt(i));
deleteCount++;
}
}
if (!deleteIds.isEmpty()) {
mIconCache.mIconDb.delete(
Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, deleteIds), null);
queryBuilder.append(')');
if (deleteCount > 0) {
mIconCache.mIconDb.delete(queryBuilder.toString(), null);
}
}
@@ -31,7 +31,6 @@ import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
@@ -25,8 +25,8 @@ import android.os.UserHandle;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.GraphicsUtils;
/**
* A wrapper around {@link ContentValues} with some utility methods.
@@ -97,7 +97,7 @@ public class ContentWriter {
Preconditions.assertNonUiThread();
if (mIcon != null && !LauncherAppState.getInstance(context).getIconCache()
.isDefaultIcon(mIcon, mUser)) {
mValues.put(LauncherSettings.Favorites.ICON, Utilities.flattenBitmap(mIcon));
mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(mIcon));
mIcon = null;
}
return mValues;
@@ -177,7 +177,7 @@ public final class LauncherInstrumentation {
switch (containerType) {
case WORKSPACE: {
waitUntilGone(APPS_RES_ID);
waitForLauncherObject(APPS_RES_ID);
waitUntilGone(OVERVIEW_RES_ID);
waitUntilGone(WIDGETS_RES_ID);
return waitForLauncherObject(WORKSPACE_RES_ID);