Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa7a8506 authored by Danny Baumann's avatar Danny Baumann
Browse files

Manage buttons inside of PowerWidget instead of a static map.

Fixes disappearing widgets on theme change due to clashing accesses to
the static map by the old and the new widget instance.

Also convert static to member variables at a few other places.

Change-Id: I42b4ad02c4eb8b57a2f4cf51a31148c4b0546b81
parent 4638a22b
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -429,7 +429,6 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
        mLatestTitle.setVisibility(View.GONE);

        mPowerWidget = (PowerWidget)expanded.findViewById(R.id.exp_power_stat);
        mPowerWidget.setupSettingsObserver(mHandler);
        mPowerWidget.setGlobalButtonOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        if(Settings.System.getInt(getContentResolver(),
@@ -917,7 +916,7 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
        mExpandedVisible = true;
        visibilityChanged(true);

        mPowerWidget.updateWidget();
        mPowerWidget.updateAllButtons();

        updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
        mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+1 −19
Original line number Diff line number Diff line
@@ -14,22 +14,14 @@ import com.android.internal.telephony.Phone;

public class MobileDataButton extends PowerButton {

    public static final String MOBILE_DATA_CHANGED = "com.android.internal.telephony.MOBILE_DATA_CHANGED";

    public static final String ACTION_MODIFY_NETWORK_MODE = "com.android.internal.telephony.MODIFY_NETWORK_MODE";

    public static final String EXTRA_NETWORK_MODE = "networkMode";

    public static boolean STATE_CHANGE_REQUEST = false;

    public MobileDataButton() { mType = BUTTON_MOBILEDATA; }

    @Override
    protected void updateState() {
        if (STATE_CHANGE_REQUEST) {
            mIcon = R.drawable.stat_data_on;
            mState = STATE_INTERMEDIATE;
        } else  if (getDataState(mView.getContext())) {
        if (getDataState(mView.getContext())) {
            mIcon = R.drawable.stat_data_on;
            mState = STATE_ENABLED;
        } else {
@@ -97,14 +89,4 @@ public class MobileDataButton extends PowerButton {
            .getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getMobileDataEnabled();
    }

    public void networkModeChanged(Context context, int networkMode) {
        if (STATE_CHANGE_REQUEST) {
            ConnectivityManager cm = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
            cm.setMobileDataEnabled(true);
            STATE_CHANGE_REQUEST=false;
        }
    }

}
+30 −38
Original line number Diff line number Diff line
@@ -36,16 +36,16 @@ public class NetworkModeButton extends PowerButton{
    private static final int CM_MODE_3GONLY = 1;
    private static final int CM_MODE_BOTH = 2;

    private static int NETWORK_MODE = NO_NETWORK_MODE_YET;
    private static int INTENDED_NETWORK_MODE = NO_NETWORK_MODE_YET;
    private static int CURRENT_INTERNAL_STATE = STATE_INTERMEDIATE;
    private int mMode = NO_NETWORK_MODE_YET;
    private int mIntendedMode = NO_NETWORK_MODE_YET;
    private int mInternalState = STATE_INTERMEDIATE;

    public NetworkModeButton() { mType = BUTTON_NETWORKMODE; }

    @Override
    protected void updateState() {
        Context context = mView.getContext();
        NETWORK_MODE = get2G3G(context);
        mMode = get2G3G(context);
        mState = networkModeToState(context);

        switch (mState) {
@@ -53,7 +53,7 @@ public class NetworkModeButton extends PowerButton{
            mIcon = R.drawable.stat_2g3g_off;
            break;
        case STATE_ENABLED:
            if (NETWORK_MODE == Phone.NT_MODE_WCDMA_ONLY) {
            if (mMode == Phone.NT_MODE_WCDMA_ONLY) {
                mIcon = R.drawable.stat_3g_on;
            } else {
                mIcon = R.drawable.stat_2g3g_on;
@@ -65,8 +65,8 @@ public class NetworkModeButton extends PowerButton{
            // the top dark-gray-or-bright-white logo shows the
            // user's intent. This is much easier to see in
            // sunlight.
            if (CURRENT_INTERNAL_STATE == STATE_TURNING_ON) {
                if (INTENDED_NETWORK_MODE == Phone.NT_MODE_WCDMA_ONLY) {
            if (mInternalState == STATE_TURNING_ON) {
                if (mIntendedMode == Phone.NT_MODE_WCDMA_ONLY) {
                    mIcon = R.drawable.stat_3g_on;
                } else {
                    mIcon = R.drawable.stat_2g3g_on;
@@ -84,38 +84,38 @@ public class NetworkModeButton extends PowerButton{
        int currentMode = getCurrentCMMode(context);

        Intent intent = new Intent(ACTION_MODIFY_NETWORK_MODE);
        switch (NETWORK_MODE) {
        switch (mMode) {
        case Phone.NT_MODE_WCDMA_PREF:
        case Phone.NT_MODE_GSM_UMTS:
            intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_GSM_ONLY);
            CURRENT_INTERNAL_STATE = STATE_TURNING_OFF;
            INTENDED_NETWORK_MODE=Phone.NT_MODE_GSM_ONLY;
            mInternalState = STATE_TURNING_OFF;
            mIntendedMode = Phone.NT_MODE_GSM_ONLY;
            break;
        case Phone.NT_MODE_WCDMA_ONLY:
            if (currentMode == CM_MODE_3GONLY) {
                intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_GSM_ONLY);
                CURRENT_INTERNAL_STATE = STATE_TURNING_OFF;
                INTENDED_NETWORK_MODE = Phone.NT_MODE_GSM_ONLY;
                mInternalState = STATE_TURNING_OFF;
                mIntendedMode = Phone.NT_MODE_GSM_ONLY;
            } else {
                intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_PREF);
                CURRENT_INTERNAL_STATE = STATE_TURNING_ON;
                INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_PREF;
                mInternalState = STATE_TURNING_ON;
                mIntendedMode = Phone.NT_MODE_WCDMA_PREF;
            }
            break;
        case Phone.NT_MODE_GSM_ONLY:
            if (currentMode == CM_MODE_3GONLY || currentMode == CM_MODE_BOTH) {
                intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_ONLY);
                CURRENT_INTERNAL_STATE = STATE_TURNING_ON;
                INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_ONLY;
                mInternalState = STATE_TURNING_ON;
                mIntendedMode = Phone.NT_MODE_WCDMA_ONLY;
            } else {
                intent.putExtra(EXTRA_NETWORK_MODE, Phone.NT_MODE_WCDMA_PREF);
                CURRENT_INTERNAL_STATE = STATE_TURNING_ON;
                INTENDED_NETWORK_MODE = Phone.NT_MODE_WCDMA_PREF;
                mInternalState = STATE_TURNING_ON;
                mIntendedMode = Phone.NT_MODE_WCDMA_PREF;
            }
            break;
        }

        NETWORK_MODE = NETWORK_MODE_UNKNOWN;
        mMode = NETWORK_MODE_UNKNOWN;
        context.sendBroadcast(intent);
    }

@@ -133,22 +133,14 @@ public class NetworkModeButton extends PowerButton{
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getExtras() != null) {
            NETWORK_MODE = intent.getExtras().getInt(EXTRA_NETWORK_MODE);
            mMode = intent.getExtras().getInt(EXTRA_NETWORK_MODE);
            //Update to actual state
            INTENDED_NETWORK_MODE = NETWORK_MODE;
            mIntendedMode = mMode;
        }

        //need to clear intermediate states
        CURRENT_INTERNAL_STATE = STATE_ENABLED;

        int widgetState = networkModeToState(context);
        CURRENT_INTERNAL_STATE = widgetState;
        if (widgetState == STATE_ENABLED) {
            MobileDataButton mdb = (MobileDataButton)getLoadedButton(BUTTON_MOBILEDATA);
            if(mdb != null) {
                mdb.networkModeChanged(context, NETWORK_MODE);
            }
        }
        mInternalState = STATE_ENABLED;
        mInternalState = networkModeToState(context);
    }

    @Override
@@ -173,12 +165,12 @@ public class NetworkModeButton extends PowerButton{
        return state;
    }

    private static int networkModeToState(Context context) {
        if (CURRENT_INTERNAL_STATE == STATE_TURNING_ON ||
                CURRENT_INTERNAL_STATE == STATE_TURNING_OFF)
    private int networkModeToState(Context context) {
        if (mInternalState == STATE_TURNING_ON || mInternalState == STATE_TURNING_OFF) {
            return STATE_INTERMEDIATE;
        }

        switch(NETWORK_MODE) {
        switch (mMode) {
            case Phone.NT_MODE_WCDMA_PREF:
            case Phone.NT_MODE_WCDMA_ONLY:
            case Phone.NT_MODE_GSM_UMTS:
@@ -190,7 +182,7 @@ public class NetworkModeButton extends PowerButton{
            case Phone.NT_MODE_EVDO_NO_CDMA:
            case Phone.NT_MODE_GLOBAL:
                // need to check wtf is going on
                Log.d(TAG, "Unexpected network mode (" + NETWORK_MODE + ")");
                Log.d(TAG, "Unexpected network mode (" + mMode + ")");
                return STATE_DISABLED;
        }
        return STATE_INTERMEDIATE;
+54 −242
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package com.android.systemui.statusbar.powerwidget;

import com.android.systemui.R;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -18,9 +19,7 @@ import android.provider.Settings;
import android.view.View;
import android.provider.Settings;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class PowerButton {
    public static final String TAG = "PowerButton";
@@ -55,82 +54,50 @@ public abstract class PowerButton {

    private static final Mode MASK_MODE = Mode.SCREEN;

    // this is a list of all of our buttons and their corresponding classes
    private static final HashMap<String, Class<? extends PowerButton>> BUTTONS = new HashMap<String, Class<? extends PowerButton>>();
    static {
        BUTTONS.put(BUTTON_WIFI, WifiButton.class);
        BUTTONS.put(BUTTON_GPS, GPSButton.class);
        BUTTONS.put(BUTTON_BLUETOOTH, BluetoothButton.class);
        BUTTONS.put(BUTTON_BRIGHTNESS, BrightnessButton.class);
        BUTTONS.put(BUTTON_SOUND, SoundButton.class);
        BUTTONS.put(BUTTON_SYNC, SyncButton.class);
        BUTTONS.put(BUTTON_WIFIAP, WifiApButton.class);
        BUTTONS.put(BUTTON_SCREENTIMEOUT, ScreenTimeoutButton.class);
        BUTTONS.put(BUTTON_MOBILEDATA, MobileDataButton.class);
        BUTTONS.put(BUTTON_LOCKSCREEN, LockScreenButton.class);
        BUTTONS.put(BUTTON_NETWORKMODE, NetworkModeButton.class);
        BUTTONS.put(BUTTON_AUTOROTATE, AutoRotateButton.class);
        BUTTONS.put(BUTTON_AIRPLANE, AirplaneButton.class);
        BUTTONS.put(BUTTON_FLASHLIGHT, FlashlightButton.class);
        BUTTONS.put(BUTTON_SLEEP, SleepButton.class);
        BUTTONS.put(BUTTON_MEDIA_PLAY_PAUSE, MediaPlayPauseButton.class);
        BUTTONS.put(BUTTON_MEDIA_PREVIOUS, MediaPreviousButton.class);
        BUTTONS.put(BUTTON_MEDIA_NEXT, MediaNextButton.class);
        BUTTONS.put(BUTTON_WIMAX, WimaxButton.class);
    }
    // this is a list of our currently loaded buttons
    private static final HashMap<String, PowerButton> BUTTONS_LOADED = new HashMap<String, PowerButton>();

    protected int mIcon;
    protected int mState;
    protected View mView;
    protected String mType = BUTTON_UNKNOWN;

    // a static onclicklistener that can be set to register a callback when ANY button is clicked
    private static View.OnClickListener GLOBAL_ON_CLICK_LISTENER = null;
    private ImageView mIconView;
    private ImageView mIndicatorView;

    // a static onlongclicklistener that can be set to register a callback when ANY button is long clicked
    private static View.OnLongClickListener GLOBAL_ON_LONG_CLICK_LISTENER = null;
    private View.OnClickListener mExternalClickListener;
    private View.OnLongClickListener mExternalLongClickListener;

    // we use this to ensure we update our views on the UI thread
    private Handler mViewUpdateHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
                // this is only used to update the view, so do it
                if(mView != null) {
                    Context context = mView.getContext();
                    Resources res = context.getResources();
                    int buttonLayer = R.id.power_widget_button;
                    int buttonIcon = R.id.power_widget_button_image;
                    int buttonState = R.id.power_widget_button_indic;
                    ImageView indic = (ImageView)mView.findViewById(R.id.power_widget_button_indic);
                    if ((Settings.System.getInt(context.getContentResolver(),Settings.System.EXPANDED_HIDE_INDICATOR, 0)) == 1){
                        indic.setVisibility(8);
                    }else{
                        indic.setVisibility(0);
            if (mIconView != null) {
                mIconView.setImageResource(mIcon);
            }
                    updateImageView(buttonIcon, mIcon);
            if (mIndicatorView != null) {
                Context context = mIndicatorView.getContext();
                ContentResolver cr = context.getContentResolver();

                    int sColorMaskBase = Settings.System.getInt(context.getContentResolver(),
                boolean visible = Settings.System.getInt(cr,
                        Settings.System.EXPANDED_HIDE_INDICATOR, 0) != 1;
                int colorMaskBase = Settings.System.getInt(cr,
                        Settings.System.EXPANDED_VIEW_WIDGET_COLOR, 0xFF8DE20D);
                    int sColorMaskOn    = (sColorMaskBase & 0x00FFFFFF) | 0xA0000000;
                    int sColorMaskOff   = (sColorMaskBase & 0x00FFFFFF) | 0x33000000;
                    int sColorMaskInter = (sColorMaskBase & 0x00FFFFFF) | 0x60000000;
                int colorMask;

                mIndicatorView.setVisibility(visible ? View.VISIBLE : View.GONE);

                    /* Button State */
                switch (mState) {
                    case STATE_ENABLED:
                            updateImageView(buttonState,
                                    res.getDrawable(R.drawable.stat_bgon_custom, sColorMaskOn, MASK_MODE));
                        colorMask = (colorMaskBase & 0x00FFFFFF) | 0xA0000000;
                        break;
                    case STATE_DISABLED:
                            updateImageView(buttonState,
                                    res.getDrawable(R.drawable.stat_bgon_custom, sColorMaskOff, MASK_MODE));
                        colorMask = (colorMaskBase & 0x00FFFFFF) | 0x33000000;
                        break;
                    default:
                            updateImageView(buttonState,
                                    res.getDrawable(R.drawable.stat_bgon_custom, sColorMaskInter, MASK_MODE));
                        colorMask = (colorMaskBase & 0x00FFFFFF) | 0x60000000;
                        break;
                }

                mIndicatorView.setImageDrawable(context.getResources().getDrawable(
                            R.drawable.stat_bgon_custom, colorMask, MASK_MODE));
            }
        }
    };
@@ -168,6 +135,12 @@ public abstract class PowerButton {
            mView.setTag(mType);
            mView.setOnClickListener(mClickListener);
            mView.setOnLongClickListener(mLongClickListener);

            mIconView = (ImageView) mView.findViewById(R.id.power_widget_button_image);
            mIndicatorView = (ImageView) mView.findViewById(R.id.power_widget_button_indic);
        } else {
            mIconView = null;
            mIndicatorView = null;
        }
    }

@@ -175,193 +148,32 @@ public abstract class PowerButton {
        mViewUpdateHandler.sendEmptyMessage(0);
    }

    private void updateImageView(int id, int resId) {
        ImageView imageIcon = (ImageView)mView.findViewById(id);
        imageIcon.setImageResource(resId);
    }

    private void updateImageView(int id, Drawable resDraw) {
        ImageView imageIcon = (ImageView)mView.findViewById(id);
        imageIcon.setImageResource(R.drawable.stat_bgon_custom);
        imageIcon.setImageDrawable(resDraw);
    }

    private View.OnClickListener mClickListener = new View.OnClickListener() {
        public void onClick(View v) {
            String type = (String)v.getTag();
            toggleState();

            for(Map.Entry<String, PowerButton> entry : BUTTONS_LOADED.entrySet()) {
                if(entry.getKey().equals(type)) {
                    entry.getValue().toggleState();
                    break;
                }
            }

            // call our static listener if it's set
            if(GLOBAL_ON_CLICK_LISTENER != null) {
                GLOBAL_ON_CLICK_LISTENER.onClick(v);
            if (mExternalClickListener != null) {
                mExternalClickListener.onClick(v);
            }
        }
    };

    private View.OnLongClickListener mLongClickListener = new View.OnLongClickListener() {
        public boolean onLongClick(View v) {
            boolean result = false;
            String type = (String)v.getTag();
            for (Map.Entry<String, PowerButton> entry : BUTTONS_LOADED.entrySet()) {
                if(entry.getKey().endsWith(type)) {
                    result = entry.getValue().handleLongClick();
                    break;
                }
            }
            boolean result = handleLongClick();

            if(result && GLOBAL_ON_LONG_CLICK_LISTENER != null) {
                GLOBAL_ON_LONG_CLICK_LISTENER.onLongClick(v);
            if (result && mExternalLongClickListener != null) {
                mExternalLongClickListener.onLongClick(v);
            }
            return result;
        }
    };

    public static boolean loadButton(String key, View view) {
        // first make sure we have a valid button
        if(BUTTONS.containsKey(key) && view != null) {
            synchronized (BUTTONS_LOADED) {
                if(BUTTONS_LOADED.containsKey(key)) {
                    // setup the button again
                    BUTTONS_LOADED.get(key).setupButton(view);
                } else {
                    try {
                        // we need to instantiate a new button and add it
                        PowerButton pb = BUTTONS.get(key).newInstance();
                        // set it up
                        pb.setupButton(view);
                        // save it
                        BUTTONS_LOADED.put(key, pb);
                    } catch(Exception e) {
                        Log.e(TAG, "Error loading button: " + key, e);
                    }
                }
            }
            return true;
        } else {
            return false;
        }
    }

    public static void unloadButton(String key) {
        synchronized (BUTTONS_LOADED) {
            // first make sure we have a valid button
            if(BUTTONS_LOADED.containsKey(key)) {
                // wipe out the button view
                BUTTONS_LOADED.get(key).setupButton(null);
                // remove the button from our list of loaded ones
                BUTTONS_LOADED.remove(key);
            }
        }
    }

    public static void unloadAllButtons() {
        synchronized (BUTTONS_LOADED) {
            // cycle through setting the buttons to null
            for(PowerButton pb : BUTTONS_LOADED.values()) {
                pb.setupButton(null);
            }

            // clear our list
            BUTTONS_LOADED.clear();
        }
    }

    public static void updateAllButtons() {
        synchronized (BUTTONS_LOADED) {
            // cycle through our buttons and update them
            for(PowerButton pb : BUTTONS_LOADED.values()) {
                pb.update();
            }
        }
    }

    // glue for broadcast receivers
    public static IntentFilter getAllBroadcastIntentFilters() {
        IntentFilter filter = new IntentFilter();

        synchronized(BUTTONS_LOADED) {
            for(PowerButton button : BUTTONS_LOADED.values()) {
                IntentFilter tmp = button.getBroadcastIntentFilter();

                // cycle through these actions, and see if we need them
                int num = tmp.countActions();
                for(int i = 0; i < num; i++) {
                    String action = tmp.getAction(i);
                    if(!filter.hasAction(action)) {
                        filter.addAction(action);
                    }
                }
            }
        }

        // return our merged filter
        return filter;
    }

    // glue for content observation
    public static List<Uri> getAllObservedUris() {
        List<Uri> uris = new ArrayList<Uri>();

        synchronized(BUTTONS_LOADED) {
            for(PowerButton button : BUTTONS_LOADED.values()) {
                List<Uri> tmp = button.getObservedUris();

                for(Uri uri : tmp) {
                    if(!uris.contains(uri)) {
                        uris.add(uri);
                    }
                }
            }
        }

        return uris;
    void setExternalClickListener(View.OnClickListener listener) {
        mExternalClickListener = listener;
    }

    public static void handleOnReceive(Context context, Intent intent) {
        String action = intent.getAction();

        // cycle through power buttons
        synchronized(BUTTONS_LOADED) {
            for(PowerButton button : BUTTONS_LOADED.values()) {
                // call "onReceive" on those that matter
                if(button.getBroadcastIntentFilter().hasAction(action)) {
                    button.onReceive(context, intent);
                }
            }
        }
    }

    public static void handleOnChangeUri(Uri uri) {
        synchronized(BUTTONS_LOADED) {
            for(PowerButton button : BUTTONS_LOADED.values()) {
                if(button.getObservedUris().contains(uri)) {
                    button.onChangeUri(uri);
                }
            }
        }
    }

    public static void setGlobalOnClickListener(View.OnClickListener listener) {
        GLOBAL_ON_CLICK_LISTENER = listener;
    }

    public static void setGlobalOnLongClickListener(View.OnLongClickListener listener) {
        GLOBAL_ON_LONG_CLICK_LISTENER = listener;
    }

    protected static PowerButton getLoadedButton(String key) {
        synchronized(BUTTONS_LOADED) {
            if(BUTTONS_LOADED.containsKey(key)) {
                return BUTTONS_LOADED.get(key);
            } else {
                return null;
            }
        }
    void setExternalLongClickListener(View.OnLongClickListener listener) {
        mExternalLongClickListener = listener;
    }
}
+152 −18

File changed.

Preview size limit exceeded, changes collapsed.

Loading