Merge "Calling start/stop listening in onStart/onStop" into ub-launcher3-burnaby-nyc
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 990bde0..918ae52 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -127,13 +127,6 @@
android:process=":settings_process">
</activity>
- <receiver
- android:name="com.android.launcher3.WallpaperChangedReceiver">
- <intent-filter>
- <action android:name="android.intent.action.WALLPAPER_CHANGED" />
- </intent-filter>
- </receiver>
-
<!-- Intent received used to install shortcuts from other applications -->
<receiver
android:name="com.android.launcher3.InstallShortcutReceiver"
diff --git a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
index 8e349b7..2b39b09 100644
--- a/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
+++ b/WallpaperPicker/res/layout/actionbar_set_wallpaper.xml
@@ -28,5 +28,6 @@
android:drawableLeft="@drawable/ic_actionbar_accept"
android:drawablePadding="8dp"
android:gravity="start|center_vertical"
- android:text="@string/wallpaper_instructions">
+ android:text="@string/wallpaper_instructions"
+ android:enabled="false">
</com.android.launcher3.AlphaDisableableButton>
diff --git a/WallpaperPicker/res/values/arrays.xml b/WallpaperPicker/res/values/arrays.xml
new file mode 100644
index 0000000..5c10b98
--- /dev/null
+++ b/WallpaperPicker/res/values/arrays.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <string-array name="which_wallpaper_options">
+ <item>@string/which_wallpaper_option_home_screen</item>
+ <item>@string/which_wallpaper_option_lock_screen</item>
+ <item>@string/which_wallpaper_option_home_screen_and_lock_screen</item>
+ </string-array>
+</resources>
\ No newline at end of file
diff --git a/WallpaperPicker/res/values/strings.xml b/WallpaperPicker/res/values/strings.xml
index 2bfd476..aef6a1a 100644
--- a/WallpaperPicker/res/values/strings.xml
+++ b/WallpaperPicker/res/values/strings.xml
@@ -53,4 +53,11 @@
<string name="pick_wallpaper">Wallpapers</string>
<!-- Title of activity for cropping wallpapers -->
<string name="crop_wallpaper">Crop wallpaper</string>
+
+ <!-- Option for setting the wallpaper only on the home screen. -->
+ <string name="which_wallpaper_option_home_screen">Home screen</string>
+ <!-- Option for setting the wallpaper only on the lock screen. -->
+ <string name="which_wallpaper_option_lock_screen">Lock screen</string>
+ <!-- Option for setting the wallpaper on both the home screen and lock screen. -->
+ <string name="which_wallpaper_option_home_screen_and_lock_screen">Home screen and lock screen</string>
</resources>
diff --git a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
index 8b51447..027e947 100644
--- a/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
+++ b/WallpaperPicker/src/com/android/gallery3d/common/BitmapCropTask.java
@@ -33,7 +33,9 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.launcher3.NycWallpaperUtils;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -42,7 +44,7 @@
import java.io.IOException;
import java.io.InputStream;
-public class BitmapCropTask extends AsyncTask<Void, Void, Boolean> {
+public class BitmapCropTask extends AsyncTask<Integer, Void, Boolean> {
public interface OnBitmapCroppedHandler {
public void onBitmapCropped(byte[] imageBytes);
@@ -71,15 +73,6 @@
BitmapCropTask.OnBitmapCroppedHandler mOnBitmapCroppedHandler;
boolean mNoCrop;
- public BitmapCropTask(Context c, String filePath,
- RectF cropBounds, int rotation, int outWidth, int outHeight,
- boolean setWallpaper, boolean saveCroppedBitmap, OnEndCropHandler onEndCropHandler) {
- mContext = c;
- mInFilePath = filePath;
- init(cropBounds, rotation,
- outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndCropHandler);
- }
-
public BitmapCropTask(byte[] imageBytes,
RectF cropBounds, int rotation, int outWidth, int outHeight,
boolean setWallpaper, boolean saveCroppedBitmap, OnEndCropHandler onEndCropHandler) {
@@ -175,7 +168,7 @@
public Bitmap getCroppedBitmap() {
return mCroppedBitmap;
}
- public boolean cropBitmap() {
+ public boolean cropBitmap(int whichWallpaper) {
boolean failure = false;
@@ -189,7 +182,11 @@
try {
InputStream is = regenerateInputStream();
if (is != null) {
- wallpaperManager.setStream(is);
+ if (!Utilities.isNycOrAbove()) {
+ wallpaperManager.setStream(is);
+ } else {
+ NycWallpaperUtils.setStream(mContext, is, null, true, whichWallpaper);
+ }
Utils.closeSilently(is);
}
} catch (IOException e) {
@@ -375,7 +372,13 @@
if (mSetWallpaper && wallpaperManager != null) {
try {
byte[] outByteArray = tmpOut.toByteArray();
- wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
+ if (!Utilities.isNycOrAbove()) {
+ wallpaperManager.setStream(new ByteArrayInputStream(outByteArray));
+ } else {
+ NycWallpaperUtils.setStream(mContext,
+ new ByteArrayInputStream(outByteArray), null, true,
+ whichWallpaper);
+ }
if (mOnBitmapCroppedHandler != null) {
mOnBitmapCroppedHandler.onBitmapCropped(outByteArray);
}
@@ -393,8 +396,8 @@
}
@Override
- protected Boolean doInBackground(Void... params) {
- return cropBitmap();
+ protected Boolean doInBackground(Integer... params) {
+ return cropBitmap(params.length == 0 ? NycWallpaperUtils.FLAG_SET_SYSTEM : params[0]);
}
@Override
diff --git a/WallpaperPicker/src/com/android/launcher3/NycWallpaperUtils.java b/WallpaperPicker/src/com/android/launcher3/NycWallpaperUtils.java
new file mode 100644
index 0000000..abac830
--- /dev/null
+++ b/WallpaperPicker/src/com/android/launcher3/NycWallpaperUtils.java
@@ -0,0 +1,79 @@
+package com.android.launcher3;
+
+import android.app.AlertDialog;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Rect;
+import android.os.AsyncTask;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Utility class used to help set lockscreen wallpapers on N+.
+ */
+public class NycWallpaperUtils {
+ public static final int FLAG_SET_SYSTEM = 1 << 0; // TODO: use WallpaperManager.FLAG_SET_SYSTEM
+ public static final int FLAG_SET_LOCK = 1 << 1; // TODO: use WallpaperManager.FLAG_SET_LOCK
+
+ /**
+ * Calls cropTask.execute(), once the user has selected which wallpaper to set. On pre-N
+ * devices, the prompt is not displayed since there is no API to set the lockscreen wallpaper.
+ */
+ public static void executeCropTaskAfterPrompt(
+ Context context, final AsyncTask<Integer, ?, ?> cropTask,
+ DialogInterface.OnCancelListener onCancelListener) {
+ if (Utilities.isNycOrAbove()) {
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.wallpaper_instructions)
+ .setItems(R.array.which_wallpaper_options, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int selectedItemIndex) {
+ int whichWallpaper;
+ if (selectedItemIndex == 0) {
+ whichWallpaper = FLAG_SET_SYSTEM;
+ } else if (selectedItemIndex == 1) {
+ whichWallpaper = FLAG_SET_LOCK;
+ } else {
+ whichWallpaper = FLAG_SET_SYSTEM | FLAG_SET_LOCK;
+ }
+ cropTask.execute(whichWallpaper);
+ }
+ })
+ .setOnCancelListener(onCancelListener)
+ .show();
+ } else {
+ cropTask.execute(FLAG_SET_SYSTEM);
+ }
+ }
+
+ public static void setStream(Context context, final InputStream data, Rect visibleCropHint,
+ boolean allowBackup, int whichWallpaper) throws IOException {
+ WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
+ try {
+ // TODO: use mWallpaperManager.setStream(data, visibleCropHint, allowBackup, which)
+ // without needing reflection.
+ Method setStream = WallpaperManager.class.getMethod("setStream", InputStream.class,
+ Rect.class, boolean.class, int.class);
+ setStream.invoke(wallpaperManager, data, visibleCropHint, allowBackup, whichWallpaper);
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+ // Fall back to previous implementation (set system)
+ wallpaperManager.setStream(data);
+ }
+ }
+
+ public static void clear(Context context, int whichWallpaper) throws IOException {
+ WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
+ try {
+ // TODO: use mWallpaperManager.clear(whichWallpaper) without needing reflection.
+ Method clear = WallpaperManager.class.getMethod("clear", int.class);
+ clear.invoke(wallpaperManager, whichWallpaper);
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ // Fall back to previous implementation (clear system)
+ wallpaperManager.clear();
+ }
+ }
+}
\ No newline at end of file
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index 75bdb8a..364cdb8 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -21,6 +21,7 @@
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -86,6 +87,18 @@
@Thunk Set<Bitmap> mReusableBitmaps =
Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
+ private final DialogInterface.OnCancelListener mOnDialogCancelListener =
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ getActionBar().show();
+ View wallpaperStrip = findViewById(R.id.wallpaper_strip);
+ if (wallpaperStrip != null) {
+ wallpaperStrip.setVisibility(View.VISIBLE);
+ }
+ }
+ };
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -242,6 +255,10 @@
}
}
+ public DialogInterface.OnCancelListener getOnDialogCancelListener() {
+ return mOnDialogCancelListener;
+ }
+
protected void onLoadRequestComplete(LoadRequest req, boolean success) {
mCurrentLoadRequest = null;
if (success) {
@@ -326,7 +343,7 @@
};
cropTask.setOnEndRunnable(onEndCrop);
cropTask.setNoCrop(true);
- cropTask.execute();
+ NycWallpaperUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
}
protected void cropImageAndSetWallpaper(Resources res, int resId,
@@ -335,8 +352,7 @@
// this device
int rotation = BitmapUtils.getRotationFromExif(res, resId);
Point inSize = mCropView.getSourceDimensions();
- Point outSize = WallpaperUtils.getDefaultWallpaperSize(getResources(),
- getWindowManager());
+ Point outSize = WallpaperUtils.getDefaultWallpaperSize(getResources(), getWindowManager());
RectF crop = Utils.getMaxCropRect(
inSize.x, inSize.y, outSize.x, outSize.y, false);
BitmapCropTask.OnEndCropHandler onEndCrop = new BitmapCropTask.OnEndCropHandler() {
@@ -355,7 +371,7 @@
};
BitmapCropTask cropTask = new BitmapCropTask(getContext(), res, resId,
crop, rotation, outSize.x, outSize.y, true, false, onEndCrop);
- cropTask.execute();
+ NycWallpaperUtils.executeCropTaskAfterPrompt(this, cropTask, getOnDialogCancelListener());
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 4998bf4..5c6113f 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -44,6 +44,7 @@
import android.os.Bundle;
import android.os.Process;
import android.provider.MediaStore;
+import android.support.annotation.NonNull;
import android.util.Log;
import android.util.Pair;
import android.view.ActionMode;
@@ -77,13 +78,15 @@
import com.android.photos.BitmapRegionTileSource;
import com.android.photos.BitmapRegionTileSource.BitmapSource;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
public class WallpaperPickerActivity extends WallpaperCropActivity {
- static final String TAG = "Launcher.WallpaperPickerActivity";
+ static final String TAG = "WallpaperPickerActivity";
public static final int IMAGE_PICK = 5;
public static final int PICK_WALLPAPER_THIRD_PARTY_ACTIVITY = 6;
@@ -317,15 +320,75 @@
a.onLoadRequestComplete(req, true);
}
@Override
- public void onSave(WallpaperPickerActivity a) {
- try {
- WallpaperManager.getInstance(a.getContext()).clear();
- a.setResult(Activity.RESULT_OK);
- } catch (IOException e) {
- Log.w("Setting wallpaper to default threw exception", e);
+ public void onSave(final WallpaperPickerActivity a) {
+ if (!Utilities.isNycOrAbove()) {
+ try {
+ WallpaperManager.getInstance(a.getContext()).clear();
+ a.setResult(Activity.RESULT_OK);
+ } catch (IOException e) {
+ Log.e(TAG, "Setting wallpaper to default threw exception", e);
+ } catch (SecurityException e) {
+ Log.w(TAG, "Setting wallpaper to default threw exception", e);
+ // In this case, clearing worked; the exception was thrown afterwards.
+ a.setResult(Activity.RESULT_OK);
+ }
+ a.finish();
+ } else {
+ BitmapCropTask.OnEndCropHandler onEndCropHandler
+ = new BitmapCropTask.OnEndCropHandler() {
+ @Override
+ public void run(boolean cropSucceeded) {
+ if (cropSucceeded) {
+ a.setResult(Activity.RESULT_OK);
+ }
+ a.finish();
+ }
+ };
+ BitmapCropTask setWallpaperTask = getDefaultWallpaperCropTask(a, onEndCropHandler);
+
+ NycWallpaperUtils.executeCropTaskAfterPrompt(a, setWallpaperTask,
+ a.getOnDialogCancelListener());
}
- a.finish();
}
+
+ @NonNull
+ private BitmapCropTask getDefaultWallpaperCropTask(final WallpaperPickerActivity a,
+ final BitmapCropTask.OnEndCropHandler onEndCropHandler) {
+ return new BitmapCropTask(a, null, null, -1, -1, -1,
+ true, false, onEndCropHandler) {
+ @Override
+ protected Boolean doInBackground(Integer... params) {
+ int whichWallpaper = params[0];
+ boolean succeeded = true;
+ try {
+ if (whichWallpaper == NycWallpaperUtils.FLAG_SET_LOCK) {
+ Bitmap defaultWallpaper = ((BitmapDrawable) WallpaperManager
+ .getInstance(a.getApplicationContext()).getBuiltInDrawable())
+ .getBitmap();
+ ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048);
+ if (defaultWallpaper.compress(Bitmap.CompressFormat.PNG, 100,
+ tmpOut)) {
+ byte[] outByteArray = tmpOut.toByteArray();
+ NycWallpaperUtils.setStream(a.getApplicationContext(),
+ new ByteArrayInputStream(outByteArray), null, true,
+ NycWallpaperUtils.FLAG_SET_LOCK);
+ }
+ } else {
+ NycWallpaperUtils.clear(a, whichWallpaper);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Setting wallpaper to default threw exception", e);
+ succeeded = false;
+ } catch (SecurityException e) {
+ Log.w(TAG, "Setting wallpaper to default threw exception", e);
+ // In this case, clearing worked; the exception was thrown afterwards.
+ succeeded = true;
+ }
+ return succeeded;
+ }
+ };
+ }
+
@Override
public boolean isSelectable() {
return true;
@@ -442,10 +505,10 @@
}
return;
}
- setWallpaperButtonEnabled(true);
WallpaperTileInfo info = (WallpaperTileInfo) v.getTag();
if (info.isSelectable() && v.getVisibility() == View.VISIBLE) {
selectTile(v);
+ setWallpaperButtonEnabled(true);
}
info.onClick(WallpaperPickerActivity.this);
}
@@ -561,7 +624,7 @@
new View.OnClickListener() {
@Override
public void onClick(View v) {
- // Ensure that a tile is slelected and loaded.
+ // Ensure that a tile is selected and loaded.
if (mSelectedTile != null && mCropView.getTileSource() != null) {
// Prevent user from selecting any new tile.
mWallpaperStrip.setVisibility(View.GONE);
@@ -570,9 +633,9 @@
WallpaperTileInfo info = (WallpaperTileInfo) mSelectedTile.getTag();
info.onSave(WallpaperPickerActivity.this);
} else {
- // no tile was selected, so we just finish the activity and go back
- setResult(Activity.RESULT_OK);
- finish();
+ // This case shouldn't be possible, since "Set wallpaper" is disabled
+ // until user clicks on a title.
+ Log.w(TAG, "\"Set wallpaper\" was clicked when no tile was selected");
}
}
});
@@ -849,7 +912,7 @@
(int) rotatedBounds[0], (int) rotatedBounds[1], width, height, leftAligned);
cropTask.setCropBounds(cropRect);
- if (cropTask.cropBitmap()) {
+ if (cropTask.cropBitmap(NycWallpaperUtils.FLAG_SET_SYSTEM)) {
return cropTask.getCroppedBitmap();
} else {
return null;
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index 427c9c8..c7a6ae4 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -26,6 +26,7 @@
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.PackageManagerHelper;
import java.util.ArrayList;
import java.util.Arrays;
@@ -89,7 +90,7 @@
this.componentName = info.getComponentName();
this.container = ItemInfo.NO_ID;
flags = initFlags(info);
- if ((info.getApplicationInfo().flags & LauncherActivityInfoCompat.FLAG_SUSPENDED) != 0) {
+ if (PackageManagerHelper.isAppSuspended(info.getApplicationInfo())) {
isDisabled |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
}
if (quietModeEnabled) {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 1f7bbe0..e1ade10 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -106,6 +106,9 @@
sContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(sContext).enableAndResetCache();
new ConfigMonitor(sContext).register();
+
+ sContext.registerReceiver(
+ new WallpaperChangedReceiver(), new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
}
/**
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 97fc2dd..c8860e3 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -33,7 +33,6 @@
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -60,6 +59,7 @@
import com.android.launcher3.util.FlagOp;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.ManagedProfileHeuristic;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.StringFilter;
import com.android.launcher3.util.Thunk;
@@ -1825,6 +1825,7 @@
long serialNumber;
Intent intent;
UserHandleCompat user;
+ String targetPackage;
while (!mStopped && c.moveToNext()) {
try {
@@ -1843,6 +1844,7 @@
int promiseType = c.getInt(restoredIndex);
int disabledState = 0;
boolean itemReplaced = false;
+ targetPackage = null;
if (user == null) {
// User has been deleted remove the item.
itemsToRemove.add(id);
@@ -1856,6 +1858,9 @@
cn.getPackageName(), user);
boolean validComponent = validPkg &&
launcherApps.isActivityEnabledForProfile(cn, user);
+ if (validPkg) {
+ targetPackage = cn.getPackageName();
+ }
if (validComponent) {
if (restored) {
@@ -1863,13 +1868,8 @@
restoredRows.add(id);
restored = false;
}
- boolean isSuspended = launcherApps.isPackageSuspendedForProfile(
- cn.getPackageName(), user);
- if (isSuspended) {
- disabledState = ShortcutInfo.FLAG_DISABLED_SUSPENDED;
- }
if (quietMode.get(serialNumber)) {
- disabledState |= ShortcutInfo.FLAG_DISABLED_QUIET_USER;
+ disabledState = ShortcutInfo.FLAG_DISABLED_QUIET_USER;
}
} else if (validPkg) {
intent = null;
@@ -1939,9 +1939,8 @@
itemsToRemove.add(id);
continue;
}
- } else if (launcherApps.isAppEnabled(
- manager, cn.getPackageName(),
- PackageManager.GET_UNINSTALLED_PACKAGES)) {
+ } else if (PackageManagerHelper.isAppOnSdcard(
+ manager, cn.getPackageName())) {
// Package is present but not available.
allowMissingTarget = true;
disabledState = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
@@ -1984,7 +1983,7 @@
if (itemReplaced) {
if (user.equals(UserHandleCompat.myUserHandle())) {
- info = getAppShortcutInfo(manager, intent, user, context, null,
+ info = getAppShortcutInfo(intent, user, context, null,
cursorIconInfo.iconIndex, titleIndex,
false, useLowResIcon);
} else {
@@ -2007,12 +2006,17 @@
}
} else if (itemType ==
LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = getAppShortcutInfo(manager, intent, user, context, c,
+ info = getAppShortcutInfo(intent, user, context, c,
cursorIconInfo.iconIndex, titleIndex,
allowMissingTarget, useLowResIcon);
} else {
info = getShortcutInfo(c, context, titleIndex, cursorIconInfo);
+ // Shortcuts are only available on the primary profile
+ if (PackageManagerHelper.isAppSuspended(manager, targetPackage)) {
+ disabledState |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
+ }
+
// App shortcuts that used to be automatically added to Launcher
// didn't always have the correct intent flags set, so do that
// here
@@ -2040,7 +2044,7 @@
if (info.promisedIntent != null) {
info.promisedIntent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
}
- info.isDisabled = disabledState;
+ info.isDisabled |= disabledState;
if (isSafeMode && !Utilities.isSystemApp(context, intent)) {
info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE;
}
@@ -2957,10 +2961,7 @@
packagesUnavailable.clear();
for (String pkg : entry.getValue()) {
if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
- boolean packageOnSdcard = launcherApps.isAppEnabled(
- manager, pkg, PackageManager.GET_UNINSTALLED_PACKAGES);
- if (packageOnSdcard) {
- Launcher.addDumpLog(TAG, "Package found on sd-card: " + pkg, true);
+ if (PackageManagerHelper.isAppOnSdcard(manager, pkg)) {
packagesUnavailable.add(pkg);
} else {
Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);
@@ -3447,7 +3448,7 @@
*
* If c is not null, then it will be used to fill in missing data like the title and icon.
*/
- public ShortcutInfo getAppShortcutInfo(PackageManager manager, Intent intent,
+ public ShortcutInfo getAppShortcutInfo(Intent intent,
UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
boolean allowMissingTarget, boolean useLowResIcon) {
if (user == null) {
@@ -3477,6 +3478,10 @@
info.setIcon(icon == null ? mIconCache.getDefaultIcon(user) : icon);
}
+ if (lai != null && PackageManagerHelper.isAppSuspended(lai.getApplicationInfo())) {
+ info.isDisabled = ShortcutInfo.FLAG_DISABLED_SUSPENDED;
+ }
+
// from the db
if (TextUtils.isEmpty(info.title) && c != null) {
info.title = Utilities.trim(c.getString(titleIndex));
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
index aaf756e..0bc9588 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompat.java
@@ -24,8 +24,6 @@
public abstract class LauncherActivityInfoCompat {
- public static final int FLAG_SUSPENDED = 1<<30;
-
LauncherActivityInfoCompat() {
}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index bc900bc..237a9e9 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -19,9 +19,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Rect;
import android.os.Bundle;
@@ -59,9 +56,7 @@
public static LauncherAppsCompat getInstance(Context context) {
synchronized (sInstanceLock) {
if (sInstance == null) {
- if (Utilities.isNycOrAbove()) {
- sInstance = new LauncherAppsCompatVN(context.getApplicationContext());
- } else if (Utilities.ATLEAST_LOLLIPOP) {
+ if (Utilities.ATLEAST_LOLLIPOP) {
sInstance = new LauncherAppsCompatVL(context.getApplicationContext());
} else {
sInstance = new LauncherAppsCompatV16(context.getApplicationContext());
@@ -84,13 +79,4 @@
public abstract boolean isActivityEnabledForProfile(ComponentName component,
UserHandleCompat user);
public abstract boolean isPackageSuspendedForProfile(String packageName, UserHandleCompat user);
-
- public boolean isAppEnabled(PackageManager pm, String packageName, int flags) {
- try {
- ApplicationInfo info = pm.getApplicationInfo(packageName, flags);
- return info != null && info.enabled;
- } catch (NameNotFoundException e) {
- return false;
- }
- }
}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
index 2d0778d..4e2fc05 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatV16.java
@@ -27,11 +27,11 @@
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -114,7 +114,7 @@
}
public boolean isPackageEnabledForProfile(String packageName, UserHandleCompat user) {
- return isAppEnabled(mPm, packageName, 0);
+ return PackageManagerHelper.isAppEnabled(mPm, packageName);
}
public boolean isActivityEnabledForProfile(ComponentName component, UserHandleCompat user) {
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVN.java b/src/com/android/launcher3/compat/LauncherAppsCompatVN.java
deleted file mode 100644
index 0d883b6..0000000
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVN.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 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.compat;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.LauncherApps;
-import android.os.UserHandle;
-import android.util.Log;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-//TODO: Once gogole3 SDK is updated to N, add @TargetApi(Build.VERSION_CODES.N)
-public class LauncherAppsCompatVN extends LauncherAppsCompatVL {
-
- private static final String TAG = "LauncherAppsCompatVN";
-
- LauncherAppsCompatVN(Context context) {
- super(context);
- }
-
- @Override
- public boolean isPackageSuspendedForProfile(String packageName, UserHandleCompat user) {
- if (user != null && packageName != null) {
- try {
- //TODO: Replace with proper API call once google3 SDK is updated.
- Method getApplicationInfoMethod = LauncherApps.class.getMethod("getApplicationInfo",
- String.class, int.class, UserHandle.class);
-
- ApplicationInfo info = (ApplicationInfo) getApplicationInfoMethod.invoke(
- mLauncherApps, packageName, 0, user.getUser());
- if (info != null) {
- return (info.flags & LauncherActivityInfoCompat.FLAG_SUSPENDED) != 0;
- }
- } catch (NoSuchMethodError | NoSuchMethodException | IllegalAccessException
- | IllegalArgumentException | InvocationTargetException e) {
- Log.e(TAG, "Running on N without getApplicationInfo", e);
- }
- }
- return false;
- }
-}
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
new file mode 100644
index 0000000..d034572
--- /dev/null
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+
+/**
+ * Utility methods using package manager
+ */
+public class PackageManagerHelper {
+
+ private static final int FLAG_SUSPENDED = 1<<30;
+
+ /**
+ * Returns true if the app can possibly be on the SDCard. This is just a workaround and doesn't
+ * guarantee that the app is on SD card.
+ */
+ public static boolean isAppOnSdcard(PackageManager pm, String packageName) {
+ return isAppEnabled(pm, packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
+ }
+
+ public static boolean isAppEnabled(PackageManager pm, String packageName) {
+ return isAppEnabled(pm, packageName, 0);
+ }
+
+ public static boolean isAppEnabled(PackageManager pm, String packageName, int flags) {
+ try {
+ ApplicationInfo info = pm.getApplicationInfo(packageName, flags);
+ return info != null && info.enabled;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static boolean isAppSuspended(PackageManager pm, String packageName) {
+ try {
+ ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+ return info != null && isAppSuspended(info);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static boolean isAppSuspended(ApplicationInfo info) {
+ return (info.flags & FLAG_SUSPENDED) != 0;
+ }
+}