Fix a bug resolving the correct icon/logo in action bars
Remove some abstraction-breaking magic in ActionBarView and replace it
with proper resolution of the icon/logo when creating a window. The
old implementation relied on the ActionBarView's context being an
Activity.
Bug 9171554
Change-Id: Idbbb1942622195dcb55e8119f2d64287b07bb509
diff --git a/api/current.txt b/api/current.txt
index f792bcd..0e21703 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6808,6 +6808,7 @@
ctor public ComponentInfo(android.content.pm.ComponentInfo);
ctor protected ComponentInfo(android.os.Parcel);
method public final int getIconResource();
+ method public final int getLogoResource();
method public boolean isEnabled();
field public android.content.pm.ApplicationInfo applicationInfo;
field public int descriptionRes;
@@ -27040,7 +27041,9 @@
method public void setFlags(int, int);
method public void setFormat(int);
method public void setGravity(int);
+ method public void setIcon(int);
method public void setLayout(int, int);
+ method public void setLogo(int);
method public void setSoftInputMode(int);
method public abstract void setTitle(java.lang.CharSequence);
method public abstract void setTitleColor(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6b5df7f..7f2f744 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1877,9 +1877,12 @@
if (isChild() || !window.hasFeature(Window.FEATURE_ACTION_BAR) || mActionBar != null) {
return;
}
-
+
mActionBar = new ActionBarImpl(this);
mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
+
+ mWindow.setDefaultIcon(mActivityInfo.getIconResource());
+ mWindow.setDefaultLogo(mActivityInfo.getLogoResource());
}
/**
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index b3d99c5..634fa30 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -16,6 +16,8 @@
package android.app;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import com.android.internal.app.ActionBarImpl;
import com.android.internal.policy.PolicyManager;
@@ -264,6 +266,9 @@
mDecor = mWindow.getDecorView();
if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
+ final ApplicationInfo info = mContext.getApplicationInfo();
+ mWindow.setDefaultIcon(info.icon);
+ mWindow.setDefaultLogo(info.logo);
mActionBar = new ActionBarImpl(this);
}
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index 2812477..4dbcf23 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -116,6 +116,17 @@
public final int getIconResource() {
return icon != 0 ? icon : applicationInfo.icon;
}
+
+ /**
+ * Return the logo resource identifier to use for this component. If
+ * the component defines a logo, that is used; else, the application
+ * logo is used.
+ *
+ * @return The logo associated with this component.
+ */
+ public final int getLogoResource() {
+ return logo != 0 ? logo : applicationInfo.logo;
+ }
protected void dumpFront(Printer pw, String prefix) {
super.dumpFront(pw, prefix);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8007d9a..ad3082e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -97,7 +97,7 @@
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
+ int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded);
void setAppWillBeHidden(IBinder token);
void setAppVisibility(IBinder token, boolean visible);
void startAppFreezingScreen(IBinder token, int configChanges);
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 06974d3..39d48a7 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1256,4 +1256,38 @@
* @param mask Flags specifying which options should be modified. Others will remain unchanged.
*/
public void setUiOptions(int uiOptions, int mask) { }
+
+ /**
+ * Set the primary icon for this window.
+ *
+ * @param resId resource ID of a drawable to set
+ */
+ public void setIcon(int resId) { }
+
+ /**
+ * Set the default icon for this window.
+ * This will be overridden by any other icon set operation which could come from the
+ * theme or another explicit set.
+ *
+ * @hide
+ */
+ public void setDefaultIcon(int resId) { }
+
+ /**
+ * Set the logo for this window. A logo is often shown in place of an
+ * {@link #setIcon(int) icon} but is generally wider and communicates window title information
+ * as well.
+ *
+ * @param resId resource ID of a drawable to set
+ */
+ public void setLogo(int resId) { }
+
+ /**
+ * Set the default logo for this window.
+ * This will be overridden by any other logo set operation which could come from the
+ * theme or another explicit set.
+ *
+ * @hide
+ */
+ public void setDefaultLogo(int resId) { }
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 6a35f20..6291e62 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -642,7 +642,7 @@
*/
public View addStartingWindow(IBinder appToken, String packageName,
int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel,
- int labelRes, int icon, int windowFlags);
+ int labelRes, int icon, int logo, int windowFlags);
/**
* Called when the first window of an application has been displayed, while
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index acbb2b1..e092fff 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -1210,6 +1210,10 @@
mActionView.setIcon(icon);
}
+ public boolean hasIcon() {
+ return mActionView.hasIcon();
+ }
+
@Override
public void setLogo(int resId) {
mActionView.setLogo(resId);
@@ -1220,6 +1224,10 @@
mActionView.setLogo(logo);
}
+ public boolean hasLogo() {
+ return mActionView.hasLogo();
+ }
+
public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
if (!mDisplayHomeAsUpSet) {
setDisplayHomeAsUpEnabled(enable);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index dda1a10..f2bd522 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -16,24 +16,12 @@
package com.android.internal.widget;
-import com.android.internal.R;
-import com.android.internal.view.menu.ActionMenuItem;
-import com.android.internal.view.menu.ActionMenuPresenter;
-import com.android.internal.view.menu.ActionMenuView;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuPresenter;
-import com.android.internal.view.menu.MenuView;
-import com.android.internal.view.menu.SubMenuBuilder;
-
import android.animation.LayoutTransition;
import android.app.ActionBar;
import android.app.ActionBar.OnNavigationListener;
-import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
@@ -42,7 +30,6 @@
import android.text.Layout;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.CollapsibleActionView;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -62,6 +49,15 @@
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
+import com.android.internal.R;
+import com.android.internal.view.menu.ActionMenuItem;
+import com.android.internal.view.menu.ActionMenuPresenter;
+import com.android.internal.view.menu.ActionMenuView;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
+import com.android.internal.view.menu.MenuView;
+import com.android.internal.view.menu.SubMenuBuilder;
/**
* @hide
@@ -188,34 +184,8 @@
ActionBar.NAVIGATION_MODE_STANDARD);
mTitle = a.getText(R.styleable.ActionBar_title);
mSubtitle = a.getText(R.styleable.ActionBar_subtitle);
-
mLogo = a.getDrawable(R.styleable.ActionBar_logo);
- if (mLogo == null) {
- if (context instanceof Activity) {
- try {
- mLogo = pm.getActivityLogo(((Activity) context).getComponentName());
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Activity component name not found!", e);
- }
- }
- if (mLogo == null) {
- mLogo = appInfo.loadLogo(pm);
- }
- }
-
mIcon = a.getDrawable(R.styleable.ActionBar_icon);
- if (mIcon == null) {
- if (context instanceof Activity) {
- try {
- mIcon = pm.getActivityIcon(((Activity) context).getComponentName());
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Activity component name not found!", e);
- }
- }
- if (mIcon == null) {
- mIcon = appInfo.loadIcon(pm);
- }
- }
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -729,7 +699,11 @@
}
public void setIcon(int resId) {
- setIcon(mContext.getResources().getDrawable(resId));
+ setIcon(resId != 0 ? mContext.getResources().getDrawable(resId) : null);
+ }
+
+ public boolean hasIcon() {
+ return mIcon != null;
}
public void setLogo(Drawable logo) {
@@ -740,7 +714,11 @@
}
public void setLogo(int resId) {
- setLogo(mContext.getResources().getDrawable(resId));
+ setLogo(resId != 0 ? mContext.getResources().getDrawable(resId) : null);
+ }
+
+ public boolean hasLogo() {
+ return mLogo != null;
}
public void setNavigationMode(int mode) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 6b28e8e..085134d 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -139,6 +139,12 @@
private ActionMenuPresenterCallback mActionMenuPresenterCallback;
private PanelMenuPresenterCallback mPanelMenuPresenterCallback;
+ static final int FLAG_RESOURCE_SET_ICON = 1 << 0;
+ static final int FLAG_RESOURCE_SET_LOGO = 1 << 1;
+ int mResourcesSetFlags;
+ int mIconRes;
+ int mLogoRes;
+
private DrawableFeatureState[] mDrawables;
private PanelFeatureState[] mPanels;
@@ -1393,6 +1399,46 @@
}
}
+ @Override
+ public void setIcon(int resId) {
+ mIconRes = resId;
+ mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON;
+ if (mActionBar != null) {
+ mActionBar.setIcon(resId);
+ }
+ }
+
+ @Override
+ public void setDefaultIcon(int resId) {
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0) {
+ return;
+ }
+ mIconRes = resId;
+ if (mActionBar != null && !mActionBar.hasIcon()) {
+ mActionBar.setIcon(resId);
+ }
+ }
+
+ @Override
+ public void setLogo(int resId) {
+ mLogoRes = resId;
+ mResourcesSetFlags |= FLAG_RESOURCE_SET_LOGO;
+ if (mActionBar != null) {
+ mActionBar.setLogo(resId);
+ }
+ }
+
+ @Override
+ public void setDefaultLogo(int resId) {
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0) {
+ return;
+ }
+ mLogoRes = resId;
+ if (mActionBar != null && !mActionBar.hasLogo()) {
+ mActionBar.setLogo(resId);
+ }
+ }
+
/**
* Request that key events come to this activity. Use this if your activity
* has no views with focus, but the activity still wants a chance to process
@@ -2946,6 +2992,15 @@
"incompatible window decor! Ignoring request.");
}
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
+ (mIconRes != 0 && !mActionBar.hasIcon())) {
+ mActionBar.setIcon(mIconRes);
+ }
+ if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
+ (mLogoRes != 0 && !mActionBar.hasLogo())) {
+ mActionBar.setLogo(mLogoRes);
+ }
+
// Post the panel invalidate for later; avoid application onCreateOptionsMenu
// being called in the middle of onCreate or similar.
mDecor.post(new Runnable() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 79753a6..b8a9797 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1582,7 +1582,7 @@
@Override
public View addStartingWindow(IBinder appToken, String packageName, int theme,
CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
- int icon, int windowFlags) {
+ int icon, int logo, int windowFlags) {
if (!SHOW_STARTING_ANIMATIONS) {
return null;
}
@@ -1639,6 +1639,9 @@
win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
}
+ win.setDefaultIcon(icon);
+ win.setDefaultLogo(logo);
+
win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index a40b13c..561dd0f 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -86,6 +86,7 @@
CharSequence nonLocalizedLabel; // the label information from the package mgr.
int labelRes; // the label information from the package mgr.
int icon; // resource identifier of activity's icon.
+ int logo; // resource identifier of activity's logo.
int theme; // resource identifier of activity's theme.
int realTheme; // actual theme resource we will use, never 0.
int windowFlags; // custom window flags for preview window.
@@ -399,6 +400,7 @@
labelRes = app.labelRes;
}
icon = aInfo.getIconResource();
+ logo = aInfo.getLogoResource();
theme = aInfo.getThemeResource();
realTheme = theme;
if (realTheme == 0) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index d6a6eb8..50ed21b 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1465,8 +1465,8 @@
mWindowManager.setAppStartingWindow(
next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
- next.nonLocalizedLabel, next.labelRes, next.icon, next.windowFlags,
- null, true);
+ next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
+ next.windowFlags, null, true);
}
mStackSupervisor.startSpecificActivityLocked(next, true, false);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
@@ -1500,7 +1500,7 @@
mService.compatibilityInfoForPackageLocked(
next.info.applicationInfo),
next.nonLocalizedLabel,
- next.labelRes, next.icon, next.windowFlags,
+ next.labelRes, next.icon, next.logo, next.windowFlags,
null, true);
}
if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
@@ -1639,7 +1639,7 @@
r.appToken, r.packageName, r.theme,
mService.compatibilityInfoForPackageLocked(
r.info.applicationInfo), r.nonLocalizedLabel,
- r.labelRes, r.icon, r.windowFlags,
+ r.labelRes, r.icon, r.logo, r.windowFlags,
prev != null ? prev.appToken : null, showStartingIcon);
}
} else {
diff --git a/services/java/com/android/server/wm/StartingData.java b/services/java/com/android/server/wm/StartingData.java
index 46bb480..7115b0f 100644
--- a/services/java/com/android/server/wm/StartingData.java
+++ b/services/java/com/android/server/wm/StartingData.java
@@ -25,17 +25,19 @@
final CharSequence nonLocalizedLabel;
final int labelRes;
final int icon;
+ final int logo;
final int windowFlags;
StartingData(String _pkg, int _theme, CompatibilityInfo _compatInfo,
CharSequence _nonLocalizedLabel,
- int _labelRes, int _icon, int _windowFlags) {
+ int _labelRes, int _icon, int _logo, int _windowFlags) {
pkg = _pkg;
theme = _theme;
compatInfo = _compatInfo;
nonLocalizedLabel = _nonLocalizedLabel;
labelRes = _labelRes;
icon = _icon;
+ logo = _logo;
windowFlags = _windowFlags;
}
}
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a1e07dc..b4dcdec 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3878,7 +3878,7 @@
@Override
public void setAppStartingWindow(IBinder token, String pkg,
int theme, CompatibilityInfo compatInfo,
- CharSequence nonLocalizedLabel, int labelRes, int icon,
+ CharSequence nonLocalizedLabel, int labelRes, int icon, int logo,
int windowFlags, IBinder transferFrom, boolean createIfNeeded) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppStartingWindow()")) {
@@ -4079,7 +4079,7 @@
if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Creating StartingData");
mStartingIconInTransition = true;
wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel,
- labelRes, icon, windowFlags);
+ labelRes, icon, logo, windowFlags);
Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
// Note: we really want to do sendMessageAtFrontOfQueue() because we
// want to process the message ASAP, before any other queued
@@ -7083,7 +7083,7 @@
try {
view = mPolicy.addStartingWindow(
wtoken.token, sd.pkg, sd.theme, sd.compatInfo,
- sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags);
+ sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, sd.windowFlags);
} catch (Exception e) {
Slog.w(TAG, "Exception when adding starting window", e);
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 0ca230c..a7b48bb 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -304,7 +304,7 @@
@Override
public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3,
- CharSequence arg4, int arg5, int arg6, int arg7, IBinder arg8, boolean arg9)
+ CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10)
throws RemoteException {
// TODO Auto-generated method stub
}