Skip to content

Commit

Permalink
Replace status bar theme change hack with a proper reinflation approach.
Browse files Browse the repository at this point in the history
Now, when the theme changes we reinflate all status bar views and
reattach them.  This is an approximate simulation of the normal Activity
onDestroy/onCreate cycle that the system goes through when a config
change (in our case, a theme change) occurs.

Also reverts "Hack to update status bar service drawables on theme
change.", a478f39
  • Loading branch information
jguilfoyle committed Mar 17, 2011
1 parent 4134864 commit 44ffc93
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 101 deletions.
3 changes: 2 additions & 1 deletion packages/SystemUI/res/layout/status_bar.xml
Expand Up @@ -21,8 +21,9 @@
<!-- android:background="@drawable/status_bar_closed_default_background" -->
<com.android.systemui.statusbar.StatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/statusbar_background"
android:orientation="vertical"
android:focusable="true"
android:descendantFocusability="afterDescendants"
>
Expand Down
2 changes: 1 addition & 1 deletion packages/SystemUI/res/layout/status_bar_expanded.xml
Expand Up @@ -24,7 +24,7 @@
android:descendantFocusability="afterDescendants"
>

<LinearLayout android:id="@+id/exp_view_lin_layout"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
Expand Down
2 changes: 1 addition & 1 deletion packages/SystemUI/res/layout/status_bar_latest_event.xml
Expand Up @@ -14,7 +14,7 @@
>
</com.android.systemui.statusbar.LatestItemView>

<View android:id="@+id/separator"
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/divider_horizontal_light_opaque"
Expand Down
Expand Up @@ -83,6 +83,10 @@ public Entry remove(IBinder key) {
return null;
}

void clear() {
mEntries.clear();
}

private int chooseIndex(final long when) {
final int N = mEntries.size();
for (int i=0; i<N; i++) {
Expand Down
Expand Up @@ -67,30 +67,6 @@ private static boolean streq(String a, String b) {
return a.equals(b);
}

/**
* Refresh resources that might have changed due to a configuration change.
*/
public void updateResources() {
StatusBarIcon icon = mIcon;
if (icon != null) {
Drawable drawable = getIcon(icon);
if (drawable != null) {
setImageDrawable(drawable);
}

if (icon.number > 0) {
mNumberBackground = getContext().getResources().getDrawable(
R.drawable.ic_notification_overlay);
placeNumber();
} else {
mNumberBackground = null;
mNumberText = null;
}

invalidate();
}
}

/**
* Returns whether the set succeeded.
*/
Expand Down Expand Up @@ -180,6 +156,10 @@ public StatusBarIcon getStatusBarIcon() {
return mIcon;
}

public String getStatusBarSlot() {
return mSlot;
}

protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mNumberBackground != null) {
Expand Down
Expand Up @@ -48,6 +48,7 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.Log;
import android.view.Display;
Expand Down Expand Up @@ -100,6 +101,14 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
CommandQueue mCommandQueue;
IStatusBarService mBarService;

/**
* Shallow container for {@link #mStatusBarView} which is added to the
* window manager impl as the actual status bar root view. This is done so
* that the original status_bar layout can be reinflated into this container
* on skin change.
*/
FrameLayout mStatusBarContainer;

int mIconSize;
Display mDisplay;
StatusBarView mStatusBarView;
Expand Down Expand Up @@ -200,8 +209,19 @@ public boolean dispatchKeyEvent(KeyEvent event) {
public void onCreate() {
// First set up our views and stuff.
mDisplay = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
CustomTheme currentTheme = getResources().getConfiguration().customTheme;
if (currentTheme != null) {
mCurrentTheme = (CustomTheme)currentTheme.clone();
}
makeStatusBarView(this);

// receive broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mBroadcastReceiver, filter);

// Connect in to the status bar manager service
StatusBarIconList iconList = new StatusBarIconList();
ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
Expand Down Expand Up @@ -238,6 +258,9 @@ public void onCreate() {
}

// Put up the view
FrameLayout container = new FrameLayout(this);
container.addView(mStatusBarView);
mStatusBarContainer = container;
addStatusBarView();

// Lastly, call to the icon policy to install/update all the icons.
Expand Down Expand Up @@ -318,20 +341,13 @@ private void makeStatusBarView(Context context) {
// set the inital view visibility
setAreThereNotifications();
mDateView.setVisibility(View.INVISIBLE);

// receive broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(mBroadcastReceiver, filter);
}

protected void addStatusBarView() {
Resources res = getResources();
final int height= res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);

final StatusBarView view = mStatusBarView;
final View view = mStatusBarContainer;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
height,
Expand Down Expand Up @@ -1223,6 +1239,10 @@ void onBarViewAttached() {
WindowManagerImpl.getDefault().addView(mTrackingView, lp);
}

void onBarViewDetached() {
WindowManagerImpl.getDefault().removeView(mTrackingView);
}

void onTrackingViewAttached() {
WindowManager.LayoutParams lp;
int pixelFormat;
Expand Down Expand Up @@ -1259,6 +1279,9 @@ void onTrackingViewAttached() {
FrameLayout hack = (FrameLayout)mExpandedView.getParent();
}

void onTrackingViewDetached() {
}

void setDateViewVisibility(boolean visible, int anim) {
mDateView.setUpdates(visible);
mDateView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
Expand Down Expand Up @@ -1453,6 +1476,57 @@ else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
}
};

private static void copyNotifications(ArrayList<Pair<IBinder, StatusBarNotification>> dest,
NotificationData source) {
int N = source.size();
for (int i = 0; i < N; i++) {
NotificationData.Entry entry = source.getEntryAt(i);
dest.add(Pair.create(entry.key, entry.notification));
}
}

private void recreateStatusBar() {
mStatusBarContainer.removeAllViews();

// extract icons from the soon-to-be recreated viewgroup.
int nIcons = mStatusIcons.getChildCount();
ArrayList<StatusBarIcon> icons = new ArrayList<StatusBarIcon>(nIcons);
ArrayList<String> iconSlots = new ArrayList<String>(nIcons);
for (int i = 0; i < nIcons; i++) {
StatusBarIconView iconView = (StatusBarIconView)mStatusIcons.getChildAt(i);
icons.add(iconView.getStatusBarIcon());
iconSlots.add(iconView.getStatusBarSlot());
}

// extract notifications.
int nNotifs = mOngoing.size() + mLatest.size();
ArrayList<Pair<IBinder, StatusBarNotification>> notifications =
new ArrayList<Pair<IBinder, StatusBarNotification>>(nNotifs);
copyNotifications(notifications, mOngoing);
copyNotifications(notifications, mLatest);
mOngoing.clear();
mLatest.clear();

makeStatusBarView(this);

// recreate StatusBarIconViews.
for (int i = 0; i < nIcons; i++) {
StatusBarIcon icon = icons.get(i);
String slot = iconSlots.get(i);
addIcon(slot, i, i, icon);
}

// recreate notifications.
for (int i = 0; i < nNotifs; i++) {
Pair<IBinder, StatusBarNotification> notifData = notifications.get(i);
addNotificationViews(notifData.first, notifData.second);
}

setAreThereNotifications();
mStatusBarContainer.addView(mStatusBarView);
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
}

/**
* Reload some of our resources when the configuration changes.
*
Expand All @@ -1464,76 +1538,18 @@ void updateResources() {
Resources res = getResources();

// detect theme change.
boolean themeChanged = false;
CustomTheme newTheme = res.getConfiguration().customTheme;
if (newTheme != null &&
(mCurrentTheme == null || !mCurrentTheme.equals(newTheme))) {
mCurrentTheme = (CustomTheme)newTheme.clone();
themeChanged = true;
}

mClearButton.setText(getText(R.string.status_bar_clear_all_button));
mOngoingTitle.setText(getText(R.string.status_bar_ongoing_events_title));
mLatestTitle.setText(getText(R.string.status_bar_latest_events_title));
mNoNotificationsTitle.setText(getText(R.string.status_bar_no_notifications_title));

mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);

/*
* HACK: Attempt to re-apply views that could have changed from a theme.
* This will be replaced with a better solution reinflating the
* necessary views.
*/
if (themeChanged) {
// XXX: If this changes in the XML, it must also change here.
mStatusBarView.setBackgroundDrawable(res.getDrawable(R.drawable.statusbar_background));
mDateView.setBackgroundDrawable(res.getDrawable(R.drawable.statusbar_background));
((ImageView)mCloseView.getChildAt(0)).setImageDrawable(res.getDrawable(R.drawable.status_bar_close_on));
mExpandedView.findViewById(R.id.exp_view_lin_layout).setBackgroundDrawable(res.getDrawable(R.drawable.title_bar_portrait));
mClearButton.setBackgroundDrawable(res.getDrawable(android.R.drawable.btn_default_small));

// Update icons.
ArrayList<ViewGroup> iconViewGroups = new ArrayList<ViewGroup>();
iconViewGroups.add(mStatusIcons);
iconViewGroups.add(mNotificationIcons);

for (ViewGroup iconViewGroup: iconViewGroups) {
int nIcons = iconViewGroup.getChildCount();
for (int i = 0; i < nIcons; i++) {
StatusBarIconView iconView = (StatusBarIconView)iconViewGroup.getChildAt(i);
iconView.updateResources();
}
}

// Re-apply notifications.
ArrayList<NotificationData> notifGroups = new ArrayList<NotificationData>();
notifGroups.add(mOngoing);
notifGroups.add(mLatest);
ArrayList<ViewGroup> notifViewGroups = new ArrayList<ViewGroup>();
notifViewGroups.add(mOngoingItems);
notifViewGroups.add(mLatestItems);

int nNotifGroups = notifGroups.size();
for (int i = 0; i < nNotifGroups; i++) {
NotificationData notifGroup = notifGroups.get(i);
ViewGroup notifViewGroup = notifViewGroups.get(i);
int nViews = notifViewGroup.getChildCount();
if (nViews != notifGroup.size()) {
throw new IllegalStateException("unexpected mismatch between number of notification views and items");
}
for (int j = 0; j < nViews; j++) {
ViewGroup container = (ViewGroup)notifViewGroup.getChildAt(j);
NotificationData.Entry entry = notifGroup.getEntryAt(j);
updateNotification(entry.key, entry.notification);

// XXX: If this changes in XML, it must also change here.
container.findViewById(R.id.separator).setBackgroundDrawable(res.getDrawable(R.drawable.divider_horizontal_light_opaque));
container.findViewById(R.id.content).setBackgroundDrawable(res.getDrawable(android.R.drawable.status_bar_item_background));
}
}
recreateStatusBar();
} else {
mClearButton.setText(getText(R.string.status_bar_clear_all_button));
mOngoingTitle.setText(getText(R.string.status_bar_ongoing_events_title));
mLatestTitle.setText(getText(R.string.status_bar_latest_events_title));
mNoNotificationsTitle.setText(getText(R.string.status_bar_no_notifications_title));

// Recalculate the position of the sliding windows and the titles.
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
}

if (false) Slog.v(TAG, "updateResources");
Expand Down
Expand Up @@ -63,7 +63,13 @@ protected void onAttachedToWindow() {
super.onAttachedToWindow();
mService.onBarViewAttached();
}


@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mService.onBarViewDetached();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Expand Down
Expand Up @@ -60,4 +60,10 @@ protected void onAttachedToWindow() {
super.onAttachedToWindow();
mService.onTrackingViewAttached();
}

@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mService.onTrackingViewDetached();
}
}

0 comments on commit 44ffc93

Please sign in to comment.