summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authord34d <clark@cyngn.com>2015-07-17 10:06:20 -0700
committercretin45 <cretin45@gmail.com>2016-03-15 14:25:30 -0700
commit772f61de9ad6a86dcccbab308c7202e770975ce6 (patch)
tree4dc0f27c7e9d8a9cf461cf4aebedbab23d604df5
parent1129f556e5097e777bd2071890cc622db6a14f5e (diff)
downloadandroid_packages_apps_Trebuchet-772f61de9ad6a86dcccbab308c7202e770975ce6.zip
android_packages_apps_Trebuchet-772f61de9ad6a86dcccbab308c7202e770975ce6.tar.gz
android_packages_apps_Trebuchet-772f61de9ad6a86dcccbab308c7202e770975ce6.tar.bz2
Show apps as unavailable when on unmounted storage
This patch allows shortcuts to apps that are currently unavailable due to being on unmounted external storage to remain on the workspace and in folders. The icons will be disabled and grayed out until the external storage is mounted. Issue-id: CYNGNOS-1344 Change-Id: I971483806b27e3a75ef0d5bb89d8dfb86f97511e
-rw-r--r--res/values/cm_strings.xml3
-rw-r--r--src/com/android/launcher3/Launcher.java45
-rw-r--r--src/com/android/launcher3/LauncherModel.java58
-rw-r--r--src/com/android/launcher3/Workspace.java97
4 files changed, 195 insertions, 8 deletions
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 8d3527e..1c6aaf8 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -74,4 +74,7 @@
<!-- Search Manager doesn't exist -->
<string name="search_activity_not_found">A search activity could not be found!</string>
+
+ <!-- App not available toast text -->
+ <string name="app_not_available">App not available</string>
</resources>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index b135fef..7396933 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3068,6 +3068,10 @@ public class Launcher extends Activity
final Intent intent;
if (tag instanceof ShortcutInfo) {
shortcut = (ShortcutInfo) tag;
+ if (shortcut.isDisabled == 1) {
+ Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_SHORT).show();
+ return;
+ }
intent = shortcut.intent;
int[] pos = new int[2];
v.getLocationOnScreen(pos);
@@ -4784,12 +4788,53 @@ public class Launcher extends Activity
}
}
+ /**
+ * A package has become unavailable.
+ *
+ * Implementation of the method from LauncherModel.Callbacks.
+ */
+ public void bindComponentsUnavailable(final ArrayList<String> packageNames,
+ final ArrayList<AppInfo> appInfos) {
+ if (!packageNames.isEmpty()) {
+ mWorkspace.updateUnavailableItemsByPackageName(packageNames);
+ }
+ HashSet<ComponentName> cns = new HashSet<>();
+ for (AppInfo appInfo : appInfos) {
+ cns.add(appInfo.componentName);
+ }
+ // Notify the drag controller
+ mDragController.onAppsRemoved(packageNames, cns);
+ mAppsView.removeApps(appInfos);
+ }
+
+ /**
+ * A package has become unavailable.
+ *
+ * Implementation of the method from LauncherModel.Callbacks.
+ */
+ public void bindComponentsAvailable(final ArrayList<ItemInfo> itemInfos) {
+ if (!itemInfos.isEmpty()) {
+ mWorkspace.updateAvailableItems(itemInfos);
+ }
+ }
+
+ /**
+ * A number of packages were updated.
+ */
+ private ArrayList<Object> mWidgetsAndShortcuts;
private Runnable mBindPackagesUpdatedRunnable = new Runnable() {
public void run() {
bindAllPackages(mWidgetsModel);
}
};
+ public void bindPackagesUpdated(final ArrayList<Object> widgetsAndShortcuts) {
+ if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
+ mWidgetsAndShortcuts = widgetsAndShortcuts;
+ return;
+ }
+ }
+
@Override
public void bindAllPackages(final WidgetsModel model) {
if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index e90ea17..687e565 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -211,8 +211,12 @@ public class LauncherModel extends BroadcastReceiver
public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
public void bindComponentsRemoved(ArrayList<String> packageNames,
ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
+ public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);
public void bindAllPackages(WidgetsModel model);
public void bindSearchProviderChanged();
+ public void bindComponentsUnavailable(ArrayList<String> packageNames,
+ ArrayList<AppInfo> appInfos);
+ public void bindComponentsAvailable(ArrayList<ItemInfo> itemInfos);
public boolean isAllAppsButtonRank(int rank);
public void onPageBoundSynchronously(int page);
public void dumpLogsToLocalData();
@@ -3290,6 +3294,7 @@ public class LauncherModel extends BroadcastReceiver
final String[] packages = mPackages;
final int N = packages.length;
+ final ArrayList<String> unavailable = new ArrayList<String>();
switch (mOp) {
case OP_ADD: {
for (int i=0; i<N; i++) {
@@ -3328,6 +3333,9 @@ public class LauncherModel extends BroadcastReceiver
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
mBgAllAppsList.removePackage(packages[i], mUser);
mApp.getWidgetCache().removePackage(packages[i], mUser);
+ if (mOp == OP_UNAVAILABLE) {
+ unavailable.add(packages[i]);
+ }
}
break;
}
@@ -3359,10 +3367,21 @@ public class LauncherModel extends BroadcastReceiver
new HashMap<ComponentName, AppInfo>();
if (added != null) {
+ final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
addAppsToAllApps(context, added);
for (AppInfo ai : added) {
addedOrUpdatedApps.put(ai.componentName, ai);
}
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
+ if (DEBUG_LOADERS) Log.d(TAG, "bindComponentsAvailable: " +
+ addedInfos.size());
+ callbacks.bindComponentsAvailable(addedInfos);
+ }
+ }
+ });
}
if (modified != null) {
@@ -3536,6 +3555,17 @@ public class LauncherModel extends BroadcastReceiver
final int removeReason;
if (mOp == OP_UNAVAILABLE) {
removeReason = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
+ // Call the packages-unavailable callback
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
+ if (DEBUG_LOADERS) Log.d(TAG, "bindComponentsUnavailable: " +
+ removedApps.size());
+ callbacks.bindComponentsUnavailable(unavailable, removedApps);
+ }
+ }
+ });
} else {
// Remove all the components associated with this package
for (String pn : removedPackageNames) {
@@ -3551,16 +3581,28 @@ public class LauncherModel extends BroadcastReceiver
// Remove any queued items from the install queue
InstallShortcutReceiver.removeFromInstallQueue(context, removedPackageNames, mUser);
- // Call the components-removed callback
- mHandler.post(new Runnable() {
- public void run() {
- Callbacks cb = getCallback();
- if (callbacks == cb && cb != null) {
- callbacks.bindComponentsRemoved(
+ if (mOp == OP_UNAVAILABLE) {
+ // Call the packages-unavailable callback
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
+ callbacks.bindComponentsUnavailable(unavailable, removedApps);
+ }
+ }
+ });
+ } else {
+ // Call the components-removed callback
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks cb = getCallback();
+ if (callbacks == cb && cb != null) {
+ callbacks.bindComponentsRemoved(
removedPackageNames, removedApps, mUser, removeReason);
+ }
}
- }
- });
+ });
+ }
}
// Update widgets
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 4364e6b..6114157 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -28,6 +28,7 @@ import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -4346,6 +4347,102 @@ public class Workspace extends PagedView
stripEmptyScreens();
}
+ void updateUnvailableItemsInCellLayout(CellLayout parent, ArrayList<String> packages) {
+ final HashSet<String> packageNames = new HashSet<String>();
+ packageNames.addAll(packages);
+
+ ViewGroup layout = parent.getShortcutsAndWidgets();
+ int childCount = layout.getChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ View view = layout.getChildAt(i);
+ if (view instanceof BubbleTextView) {
+ ItemInfo info = (ItemInfo) view.getTag();
+ if (info instanceof ShortcutInfo) {
+ Intent intent = info.getIntent();
+ ComponentName cn = intent != null ? intent.getComponent() : null;
+ if (cn != null && packageNames.contains(cn.getPackageName())) {
+ ShortcutInfo shortcut = (ShortcutInfo) info;
+ if (shortcut.isDisabled == 0) {
+ shortcut.isDisabled = 1;
+ ((BubbleTextView) view)
+ .applyFromShortcutInfo(shortcut, mIconCache, true);
+ }
+ }
+ }
+ } else if (view instanceof FolderIcon) {
+ final Folder folder = ((FolderIcon)view).getFolder();
+ final FolderPagedView folderPagedView = (FolderPagedView)folder.getContent();
+ final int N = folderPagedView.getItemCount();
+ for (int page = 0; page < N; page++) {
+ final CellLayout cellLayout = folderPagedView.getPageAt(page);
+ updateUnvailableItemsInCellLayout(cellLayout, packages);
+ }
+ folder.invalidate();
+ }
+ }
+ }
+
+ void updateUnavailableItemsByPackageName(final ArrayList<String> packages) {
+ ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
+ for (CellLayout layoutParent : cellLayouts) {
+ updateUnvailableItemsInCellLayout(layoutParent, packages);
+ }
+ }
+
+ /**
+ * Updates shortcuts to an app that was previously unavailable in the given cell layout
+ * @param parent CellLayout to check childen for shortcuts to the available app
+ * @param appInfos List of item infos. Items are assumed to be of type AppInfo
+ */
+ void updateAvailabeItemsInCellLayout(CellLayout parent, final ArrayList<ItemInfo> appInfos) {
+ ViewGroup layout = parent.getShortcutsAndWidgets();
+ int childCount = layout.getChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ View view = layout.getChildAt(i);
+ if (view instanceof BubbleTextView) {
+ ItemInfo info = (ItemInfo) view.getTag();
+ if (info instanceof ShortcutInfo) {
+ Intent intent = info.getIntent();
+ ComponentName cn = intent != null ? intent.getComponent() : null;
+ for (ItemInfo itemInfo : appInfos) {
+ AppInfo appInfo = (AppInfo) itemInfo;
+ if (cn != null && cn.getPackageName().equals(
+ appInfo.componentName.getPackageName())) {
+ ShortcutInfo shortcut = (ShortcutInfo) info;
+ if (shortcut.isDisabled == 1) {
+ shortcut.isDisabled = 0;
+ ((BubbleTextView) view)
+ .applyFromShortcutInfo(shortcut, mIconCache, true);
+ }
+ }
+ }
+ }
+ } else if (view instanceof FolderIcon) {
+ final Folder folder = ((FolderIcon) view).getFolder();
+ final FolderPagedView folderPagedView = (FolderPagedView) folder.getContent();
+ final int N = folderPagedView.getItemCount();
+ for (int page = 0; page < N; page++) {
+ final CellLayout cellLayout = folderPagedView.getPageAt(page);
+ if (cellLayout != null) {
+ updateAvailabeItemsInCellLayout(cellLayout, appInfos);
+ }
+ }
+ folder.invalidate();
+ }
+ }
+ }
+
+ /**
+ * Updates shortcuts to an app that was previously unavailable
+ * @param appInfos List of item infos. Items are assumed to be of type AppInfo
+ */
+ void updateAvailableItems(final ArrayList<ItemInfo> appInfos) {
+ ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
+ for (CellLayout layoutParent : cellLayouts) {
+ updateAvailabeItemsInCellLayout(layoutParent, appInfos);
+ }
+ }
+
interface ItemOperator {
/**
* Process the next itemInfo, possibly with side-effect on {@link ItemOperator#value}.