Fix a crash where activityInfo should not be stored.
Change-Id: I7d4790490164eb07764dba86cbdd5224a3d64bc1 Fixes: 111860183 Test: robotests
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@@ -18,11 +18,9 @@ package com.android.settingslib.drawer;
|
||||
|
||||
import static java.lang.String.CASE_INSENSITIVE_ORDER;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -31,9 +29,6 @@ import java.util.List;
|
||||
|
||||
public class DashboardCategory implements Parcelable {
|
||||
|
||||
private static final String TAG = "DashboardCategory";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
/**
|
||||
* Title of the category that is shown to the user.
|
||||
*/
|
||||
@@ -54,21 +49,14 @@ public class DashboardCategory implements Parcelable {
|
||||
*/
|
||||
private List<Tile> mTiles = new ArrayList<>();
|
||||
|
||||
DashboardCategory(DashboardCategory in) {
|
||||
if (in != null) {
|
||||
title = in.title;
|
||||
key = in.key;
|
||||
priority = in.priority;
|
||||
for (Tile tile : in.mTiles) {
|
||||
mTiles.add(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DashboardCategory() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
DashboardCategory(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of the list of the category's children.
|
||||
*
|
||||
@@ -107,22 +95,6 @@ public class DashboardCategory implements Parcelable {
|
||||
return mTiles.get(n);
|
||||
}
|
||||
|
||||
public synchronized boolean containsComponent(ComponentName component) {
|
||||
for (Tile tile : mTiles) {
|
||||
if (TextUtils.equals(tile.intent.getComponent().getClassName(),
|
||||
component.getClassName())) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "category " + key + "contains component" + component);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "category " + key + " does not contain component" + component);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort priority value for tiles in this category.
|
||||
*/
|
||||
@@ -190,9 +162,6 @@ public class DashboardCategory implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
DashboardCategory(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
public static final Creator<DashboardCategory> CREATOR = new Creator<DashboardCategory>() {
|
||||
public DashboardCategory createFromParcel(Parcel source) {
|
||||
|
||||
@@ -22,8 +22,11 @@ import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON
|
||||
import static com.android.settingslib.drawer.TileUtils.PROFILE_ALL;
|
||||
import static com.android.settingslib.drawer.TileUtils.PROFILE_PRIMARY;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
@@ -32,6 +35,7 @@ import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Description of a single dashboard tile that the user can select.
|
||||
@@ -39,7 +43,6 @@ import java.util.ArrayList;
|
||||
public class Tile implements Parcelable {
|
||||
|
||||
private static final String TAG = "Tile";
|
||||
private ActivityInfo mActivityInfo;
|
||||
|
||||
/**
|
||||
* Title of the tile that is shown to the user.
|
||||
@@ -96,8 +99,15 @@ public class Tile implements Parcelable {
|
||||
*/
|
||||
public String key;
|
||||
|
||||
|
||||
private final String mActivityPackage;
|
||||
private final String mActivityName;
|
||||
private ActivityInfo mActivityInfo;
|
||||
|
||||
public Tile(ActivityInfo activityInfo) {
|
||||
mActivityInfo = activityInfo;
|
||||
mActivityPackage = mActivityInfo.packageName;
|
||||
mActivityName = mActivityInfo.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +117,8 @@ public class Tile implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeParcelable(mActivityInfo, flags);
|
||||
dest.writeString(mActivityPackage);
|
||||
dest.writeString(mActivityName);
|
||||
TextUtils.writeToParcel(title, dest, flags);
|
||||
TextUtils.writeToParcel(summary, dest, flags);
|
||||
if (intent != null) {
|
||||
@@ -134,10 +145,11 @@ public class Tile implements Parcelable {
|
||||
*
|
||||
* @attr ref android.R.styleable#PreferenceHeader_icon
|
||||
*/
|
||||
public Icon getIcon() {
|
||||
if (mActivityInfo == null || metaData == null) {
|
||||
public Icon getIcon(Context context) {
|
||||
if (context == null || metaData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int iconResId = metaData.getInt(META_DATA_PREFERENCE_ICON);
|
||||
// Set the icon
|
||||
if (iconResId == 0) {
|
||||
@@ -145,18 +157,19 @@ public class Tile implements Parcelable {
|
||||
// ICON_URI should be loaded in app UI when need the icon object. Handling IPC at this
|
||||
// level is too complex because we don't have a strong threading contract for this class
|
||||
if (!metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
|
||||
iconResId = mActivityInfo.icon;
|
||||
iconResId = getActivityInfo(context).icon;
|
||||
}
|
||||
}
|
||||
if (iconResId != 0) {
|
||||
return Icon.createWithResource(mActivityInfo.packageName, iconResId);
|
||||
return Icon.createWithResource(getActivityInfo(context).packageName, iconResId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void readFromParcel(Parcel in) {
|
||||
mActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
|
||||
Tile(Parcel in) {
|
||||
mActivityPackage = in.readString();
|
||||
mActivityName = in.readString();
|
||||
title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||
summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||
if (in.readByte() != 0) {
|
||||
@@ -174,8 +187,17 @@ public class Tile implements Parcelable {
|
||||
isIconTintable = in.readBoolean();
|
||||
}
|
||||
|
||||
Tile(Parcel in) {
|
||||
readFromParcel(in);
|
||||
private ActivityInfo getActivityInfo(Context context) {
|
||||
if (mActivityInfo == null) {
|
||||
final PackageManager pm = context.getApplicationContext().getPackageManager();
|
||||
final Intent intent = new Intent().setClassName(mActivityPackage, mActivityName);
|
||||
final List<ResolveInfo> infoList =
|
||||
pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
|
||||
if (infoList != null && !infoList.isEmpty()) {
|
||||
mActivityInfo = infoList.get(0).activityInfo;
|
||||
}
|
||||
}
|
||||
return mActivityInfo;
|
||||
}
|
||||
|
||||
public static final Creator<Tile> CREATOR = new Creator<Tile>() {
|
||||
|
||||
@@ -59,32 +59,32 @@ public class TileTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIcon_noActivityOrMetadata_returnNull() {
|
||||
final Tile tile1 = new Tile((ActivityInfo) null);
|
||||
assertThat(tile1.getIcon()).isNull();
|
||||
|
||||
final Tile tile2 = new Tile(new ActivityInfo());
|
||||
assertThat(tile2.getIcon()).isNull();
|
||||
public void getIcon_noContextOrMetadata_returnNull() {
|
||||
final Tile tile = new Tile(new ActivityInfo());
|
||||
assertThat(tile.getIcon(null)).isNull();
|
||||
assertThat(tile.getIcon(RuntimeEnvironment.application)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIcon_providedByUri_returnNull() {
|
||||
mTile.metaData.putString(META_DATA_PREFERENCE_ICON_URI, "content://foobar/icon");
|
||||
|
||||
assertThat(mTile.getIcon()).isNull();
|
||||
assertThat(mTile.getIcon(RuntimeEnvironment.application)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIcon_hasIconMetadata_returnIcon() {
|
||||
mTile.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_info);
|
||||
|
||||
assertThat(mTile.getIcon().getResId()).isEqualTo(R.drawable.ic_info);
|
||||
assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
|
||||
.isEqualTo(R.drawable.ic_info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getIcon_noIconMetadata_returnActivityIcon() {
|
||||
mTile.metaData.putInt(META_DATA_PREFERENCE_ICON, 0);
|
||||
|
||||
assertThat(mTile.getIcon().getResId()).isEqualTo(mActivityInfo.icon);
|
||||
assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
|
||||
.isEqualTo(mActivityInfo.icon);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ public class TileUtilsTest {
|
||||
false /* checkCategory */, true /* forceTintExternalIcon */);
|
||||
|
||||
assertThat(outTiles.size()).isEqualTo(1);
|
||||
assertThat(outTiles.get(0).getIcon().getResId()).isEqualTo(314159);
|
||||
assertThat(outTiles.get(0).getIcon(mContext).getResId()).isEqualTo(314159);
|
||||
assertThat(outTiles.get(0).summary).isEqualTo("static-summary");
|
||||
|
||||
// Case 2: Empty bundle.
|
||||
@@ -332,7 +332,7 @@ public class TileUtilsTest {
|
||||
false /* checkCategory */, true /* forceTintExternalIcon */);
|
||||
|
||||
assertThat(outTiles.size()).isEqualTo(1);
|
||||
assertThat(outTiles.get(0).getIcon().getResId()).isEqualTo(314159);
|
||||
assertThat(outTiles.get(0).getIcon(mContext).getResId()).isEqualTo(314159);
|
||||
assertThat(outTiles.get(0).summary).isEqualTo("static-summary");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user