Remove all icon bitmaps when a publisher is uninstalled.

- Also show the directory sizes on dumpsys.

Bug 28196831

Change-Id: I3202fcd3151da3b26b436732e8103caf93aba525
This commit is contained in:
Makoto Onuki
2016-04-14 17:19:16 -07:00
parent 95a4791d1a
commit 0033b2a190
3 changed files with 136 additions and 26 deletions

View File

@@ -907,6 +907,16 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
public void cleanupBitmapsForPackage(@UserIdInt int userId, String packageName) {
final File packagePath = new File(getUserBitmapFilePath(userId), packageName);
if (!packagePath.isDirectory()) {
return;
}
if (!(FileUtils.deleteContents(packagePath) && packagePath.delete())) {
Slog.w(TAG, "Unable to remove directory " + packagePath);
}
}
@VisibleForTesting
static class FileOutputStreamWithPath extends FileOutputStream {
private final File mFile;
@@ -1572,7 +1582,7 @@ public class ShortcutService extends IShortcutService.Stub {
// First, remove the package from the package list (if the package is a publisher).
if (packageUserId == owningUserId) {
if (mUser.removePackage(packageName) != null) {
if (mUser.removePackage(this, packageName) != null) {
doNotify = true;
}
}
@@ -2084,11 +2094,11 @@ public class ShortcutService extends IShortcutService.Stub {
pw.println(mIconPersistFormat);
pw.print(" Icon quality: ");
pw.println(mIconPersistQuality);
pw.print(" saveDelayMillis:");
pw.print(" saveDelayMillis: ");
pw.println(mSaveDelayMillis);
pw.print(" resetInterval:");
pw.print(" resetInterval: ");
pw.println(mResetInterval);
pw.print(" maxUpdatesPerInterval:");
pw.print(" maxUpdatesPerInterval: ");
pw.println(mMaxUpdatesPerInterval);
pw.print(" maxDynamicShortcuts:");
pw.println(mMaxDynamicShortcuts);
@@ -2416,7 +2426,6 @@ public class ShortcutService extends IShortcutService.Stub {
return mPackageManagerInternal;
}
@VisibleForTesting
File getUserBitmapFilePath(@UserIdInt int userId) {
return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
}

View File

@@ -18,6 +18,7 @@ package com.android.server.pm;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.text.format.Formatter;
import android.util.ArrayMap;
import android.util.Slog;
@@ -29,6 +30,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -103,8 +105,12 @@ class ShortcutUser {
return mPackages;
}
public ShortcutPackage removePackage(@NonNull String packageName) {
return mPackages.remove(packageName);
public ShortcutPackage removePackage(@NonNull ShortcutService s, @NonNull String packageName) {
final ShortcutPackage removed = mPackages.remove(packageName);
s.cleanupBitmapsForPackage(mUserId, packageName);
return removed;
}
public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() {
@@ -279,18 +285,51 @@ class ShortcutUser {
pw.print(mUserId);
pw.println();
prefix += prefix + " ";
pw.print(prefix);
pw.print(" ");
pw.print("Default launcher: ");
pw.print(mLauncherComponent);
pw.println();
for (int i = 0; i < mLaunchers.size(); i++) {
mLaunchers.valueAt(i).dump(s, pw, prefix + " ");
mLaunchers.valueAt(i).dump(s, pw, prefix);
}
for (int i = 0; i < mPackages.size(); i++) {
mPackages.valueAt(i).dump(s, pw, prefix + " ");
mPackages.valueAt(i).dump(s, pw, prefix);
}
pw.println();
pw.print(prefix);
pw.println("Bitmap directories: ");
dumpDirectorySize(s, pw, prefix + " ", s.getUserBitmapFilePath(mUserId));
}
private void dumpDirectorySize(@NonNull ShortcutService s, @NonNull PrintWriter pw,
@NonNull String prefix, File path) {
int numFiles = 0;
long size = 0;
final File[] children = path.listFiles();
if (children != null) {
for (File child : path.listFiles()) {
if (child.isFile()) {
numFiles++;
size += child.length();
} else if (child.isDirectory()) {
dumpDirectorySize(s, pw, prefix + " ", child);
}
}
}
pw.print(prefix);
pw.print("Path: ");
pw.print(path.getName());
pw.print("/ has ");
pw.print(numFiles);
pw.print(" files, size=");
pw.print(size);
pw.print(" (");
pw.print(Formatter.formatFileSize(s.mContext, size));
pw.println(")");
}
}

View File

@@ -15,9 +15,36 @@
*/
package com.android.server.pm;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIcon;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconFile;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIconResId;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveIntents;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllHaveTitle;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllKeyFieldsOnly;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotHaveIntents;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotHaveTitle;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllNotKeyFieldsOnly;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllPinned;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllUnique;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBitmapSize;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundleEmpty;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackNotReceived;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertCallbackReceived;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicAndPinned;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertDynamicOnly;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertShortcutIds;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.pfdToBitmap;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.resetAll;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -27,7 +54,6 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -57,13 +83,11 @@ import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
@@ -71,7 +95,6 @@ import android.os.UserManager;
import android.test.InstrumentationTestCase;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
@@ -84,9 +107,6 @@ import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
import com.android.server.pm.ShortcutService.ConfigConstants;
import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
import com.android.server.pm.ShortcutUser.PackageWithUser;
import com.android.server.testutis.TestUtils;
import libcore.io.IoUtils;
import org.junit.Assert;
import org.mockito.ArgumentCaptor;
@@ -98,8 +118,6 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -4018,24 +4036,33 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
checkCanRestoreTo(false, spi2, 11, "x", "sig2x", "sig1", "y");
}
private boolean bitmapDirectoryExists(String packageName, int userId) {
final File path = new File(mService.getUserBitmapFilePath(userId), packageName);
return path.isDirectory();
}
public void testHandlePackageDelete() {
final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
getTestContext().getResources(), R.drawable.black_32x32));
setCaller(CALLING_PACKAGE_1, USER_0);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertTrue(mManager.addDynamicShortcuts(list(
makeShortcutWithIcon("s1", bmp32x32), makeShortcutWithIcon("s2", bmp32x32)
)));
setCaller(CALLING_PACKAGE_2, USER_0);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
setCaller(CALLING_PACKAGE_3, USER_0);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
setCaller(CALLING_PACKAGE_1, USER_10);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
setCaller(CALLING_PACKAGE_2, USER_10);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
setCaller(CALLING_PACKAGE_3, USER_10);
assertTrue(mManager.addDynamicShortcuts(list(makeShortcut("s1"))));
assertTrue(mManager.addDynamicShortcuts(list(makeShortcutWithIcon("s1", bmp32x32))));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_0));
@@ -4044,6 +4071,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
uninstallPackage(USER_0, CALLING_PACKAGE_1);
mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDeleteIntent(CALLING_PACKAGE_1, USER_0));
@@ -4055,6 +4089,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
uninstallPackage(USER_10, CALLING_PACKAGE_2);
mService.mPackageMonitor.onReceive(getTestContext(),
genPackageDeleteIntent(CALLING_PACKAGE_2, USER_10));
@@ -4066,6 +4107,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
mInjectedPackages.remove(CALLING_PACKAGE_1);
mInjectedPackages.remove(CALLING_PACKAGE_3);
@@ -4078,6 +4126,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNotNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
mService.handleUnlockUser(USER_10);
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_0));
@@ -4086,6 +4141,13 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "s1", USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, "s1", USER_10));
assertNull(mService.getPackageShortcutForTest(CALLING_PACKAGE_3, "s1", USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_0));
assertTrue(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_0));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_0));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_1, USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_2, USER_10));
assertFalse(bitmapDirectoryExists(CALLING_PACKAGE_3, USER_10));
}
private void backupAndRestore() {