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

Commit 22aa2130 authored by Brad Fitzpatrick's avatar Brad Fitzpatrick Committed by Android (Google) Code Review
Browse files

Merge "Make power control widget be more responsive. Fix StrictMode violations." into gingerbread

parents 92669a51 ae0ff952
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -817,7 +817,9 @@
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
                <action android:name="android.net.conn.BACKGROUND_DATA_SETTING_CHANGED" />
                <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
                <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" /> <!-- pick up misc changes -->
                <action android:name="android.location.PROVIDERS_CHANGED" />
                <!-- hack: using CLOSE_SYSTEM_DIALOGS to pick up (possible) sync changes -->
                <action android:name="android.intent.action.CLOSE_SYSTEM_DIALOGS" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
        </receiver>
+204 −156
Original line number Diff line number Diff line
@@ -78,10 +78,12 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {

    private static final StateTracker sWifiState = new WifiStateTracker();
    private static final StateTracker sBluetoothState = new BluetoothStateTracker();
    private static final StateTracker sGpsState = new GpsStateTracker();
    private static final StateTracker sSyncState = new SyncStateTracker();

    /**
     * The state machine for Wifi and Bluetooth toggling, tracking
     * reality versus the user's intent.
     * The state machine for a setting's toggling, tracking reality
     * versus the user's intent.
     *
     * This is necessary because reality moves relatively slowly
     * (turning on &amp; off radio drivers), compared to user's
@@ -133,6 +135,59 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
            }
        }

        /**
         * Return the ID of the main large image button for the setting.
         */
        public abstract int getButtonId();

        /**
         * Returns the small indicator image ID underneath the setting.
         */
        public abstract int getIndicatorId();

        /**
         * Returns the resource ID of the image to show as a function of
         * the on-vs-off state.
         */
        public abstract int getButtonImageId(boolean on);

        /**
         * Updates the remote views depending on the state (off, on,
         * turning off, turning on) of the setting.
         */
        public final void setImageViewResources(Context context, RemoteViews views) {
            int buttonId = getButtonId();
            int indicatorId = getIndicatorId();
            switch (getTriState(context)) {
                case STATE_DISABLED:
                    views.setImageViewResource(buttonId, getButtonImageId(false));
                    views.setImageViewResource(
                        indicatorId, R.drawable.appwidget_settings_ind_off_l);
                    break;
                case STATE_ENABLED:
                    views.setImageViewResource(buttonId, getButtonImageId(true));
                    views.setImageViewResource(
                        indicatorId, R.drawable.appwidget_settings_ind_on_l);
                    break;
                case STATE_INTERMEDIATE:
                    // In the transitional state, the bottom green bar
                    // shows the tri-state (on, off, transitioning), but
                    // the top dark-gray-or-bright-white logo shows the
                    // user's intent.  This is much easier to see in
                    // sunlight.
                    if (isTurningOn()) {
                        views.setImageViewResource(buttonId, getButtonImageId(true));
                        views.setImageViewResource(
                            indicatorId, R.drawable.appwidget_settings_ind_mid_l);
                    } else {
                        views.setImageViewResource(buttonId, getButtonImageId(false));
                        views.setImageViewResource(
                            indicatorId, R.drawable.appwidget_settings_ind_off_l);
                    }
                    break;
            }
        }

        /**
         * Update internal state from a broadcast state change.
         */
@@ -236,6 +291,13 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
     * Subclass of StateTracker to get/set Wifi state.
     */
    private static final class WifiStateTracker extends StateTracker {
        public int getButtonId() { return R.id.img_wifi; }
        public int getIndicatorId() { return R.id.ind_wifi; }
        public int getButtonImageId(boolean on) {
            return on ? R.drawable.ic_appwidget_settings_wifi_on
                    : R.drawable.ic_appwidget_settings_wifi_off;
        }

        @Override
        public int getActualState(Context context) {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -247,7 +309,8 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {

        @Override
        protected void requestStateChange(Context context, final boolean desiredState) {
            final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            final WifiManager wifiManager =
                    (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if (wifiManager == null) {
                Log.d(TAG, "No wifiManager.");
                return;
@@ -308,6 +371,12 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
     * Subclass of StateTracker to get/set Bluetooth state.
     */
    private static final class BluetoothStateTracker extends StateTracker {
        public int getButtonId() { return R.id.img_bluetooth; }
        public int getIndicatorId() { return R.id.ind_bluetooth; }
        public int getButtonImageId(boolean on) {
            return on ? R.drawable.ic_appwidget_settings_bluetooth_on
                    : R.drawable.ic_appwidget_settings_bluetooth_off;
        }

        @Override
        public int getActualState(Context context) {
@@ -368,6 +437,120 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
        }
    }

    /**
     * Subclass of StateTracker for GPS state.
     */
    private static final class GpsStateTracker extends StateTracker {
        public int getButtonId() { return R.id.img_gps; }
        public int getIndicatorId() { return R.id.ind_gps; }
        public int getButtonImageId(boolean on) {
            return on ? R.drawable.ic_appwidget_settings_gps_on
                    : R.drawable.ic_appwidget_settings_gps_off;
        }

        @Override
        public int getActualState(Context context) {
            ContentResolver resolver = context.getContentResolver();
            boolean on = Settings.Secure.isLocationProviderEnabled(
                resolver, LocationManager.GPS_PROVIDER);
            return on ? STATE_ENABLED : STATE_DISABLED;
        }

        @Override
        public void onActualStateChange(Context context, Intent unused) {
            // Note: the broadcast location providers changed intent
            // doesn't include an extras bundles saying what the new value is.
            setCurrentState(context, getActualState(context));
        }

        @Override
        public void requestStateChange(final Context context, final boolean desiredState) {
            final ContentResolver resolver = context.getContentResolver();
            new AsyncTask<Void, Void, Boolean>() {
                @Override
                protected Boolean doInBackground(Void... args) {
                    Settings.Secure.setLocationProviderEnabled(
                        resolver,
                        LocationManager.GPS_PROVIDER,
                        desiredState);
                    return desiredState;
                }

                @Override
                protected void onPostExecute(Boolean result) {
                    setCurrentState(
                        context,
                        result ? STATE_ENABLED : STATE_DISABLED);
                    updateWidget(context);
                }
            }.execute();
        }
    }

    /**
     * Subclass of StateTracker for sync state.
     */
    private static final class SyncStateTracker extends StateTracker {
        public int getButtonId() { return R.id.img_sync; }
        public int getIndicatorId() { return R.id.ind_sync; }
        public int getButtonImageId(boolean on) {
            return on ? R.drawable.ic_appwidget_settings_sync_on
                    : R.drawable.ic_appwidget_settings_sync_off;
        }

        @Override
        public int getActualState(Context context) {
            boolean on = getBackgroundDataState(context) &&
                    ContentResolver.getMasterSyncAutomatically();
            return on ? STATE_ENABLED : STATE_DISABLED;
        }

        @Override
        public void onActualStateChange(Context context, Intent unused) {
            // Well, ACTION_CLOSE_SYSTEM_DIALOGS fired.  So _maybe_
            // the Sync settings changed.
            // TODO: find something more reliable.
            setCurrentState(context, getActualState(context));
        }

        @Override
        public void requestStateChange(final Context context, final boolean desiredState) {
            final ConnectivityManager connManager =
                    (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            final boolean backgroundData = getBackgroundDataState(context);
            final boolean sync = ContentResolver.getMasterSyncAutomatically();

            new AsyncTask<Void, Void, Boolean>() {
                @Override
                protected Boolean doInBackground(Void... args) {
                    // Turning sync on.
                    if (desiredState) {
                        if (!backgroundData) {
                            connManager.setBackgroundDataSetting(true);
                        }
                        if (!sync) {
                            ContentResolver.setMasterSyncAutomatically(true);
                        }
                        return true;
                    }

                    // Turning sync off
                    if (sync) {
                        ContentResolver.setMasterSyncAutomatically(false);
                    }
                    return false;
                }

                @Override
                protected void onPostExecute(Boolean result) {
                    setCurrentState(
                        context,
                        result ? STATE_ENABLED : STATE_DISABLED);
                    updateWidget(context);
                }
            }.execute();
        }
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
@@ -442,38 +625,11 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
     * @param context
     */
    private static void updateButtons(RemoteViews views, Context context) {
        switch (sWifiState.getTriState(context)) {
            case STATE_DISABLED:
                views.setImageViewResource(R.id.img_wifi,
                                           R.drawable.ic_appwidget_settings_wifi_off);
                views.setImageViewResource(R.id.ind_wifi,
                                           R.drawable.appwidget_settings_ind_off_l);
                break;
            case STATE_ENABLED:
                views.setImageViewResource(R.id.img_wifi,
                                           R.drawable.ic_appwidget_settings_wifi_on);
                views.setImageViewResource(R.id.ind_wifi,
                                           R.drawable.appwidget_settings_ind_on_l);
                break;
            case STATE_INTERMEDIATE:
                // In the transitional state, the bottom green bar
                // shows the tri-state (on, off, transitioning), but
                // the top dark-gray-or-bright-white logo shows the
                // user's intent.  This is much easier to see in
                // sunlight.
                if (sWifiState.isTurningOn()) {
                    views.setImageViewResource(R.id.img_wifi,
                                               R.drawable.ic_appwidget_settings_wifi_on);
                    views.setImageViewResource(R.id.ind_wifi,
                                               R.drawable.appwidget_settings_ind_mid_l);
                } else {
                    views.setImageViewResource(R.id.img_wifi,
                                               R.drawable.ic_appwidget_settings_wifi_off);
                    views.setImageViewResource(R.id.ind_wifi,
                                               R.drawable.appwidget_settings_ind_off_l);
                }
                break;
        }
        sWifiState.setImageViewResources(context, views);
        sBluetoothState.setImageViewResources(context, views);
        sGpsState.setImageViewResources(context, views);
        sSyncState.setImageViewResources(context, views);

        if (getBrightnessMode(context)) {
            views.setImageViewResource(R.id.img_brightness,
                                       R.drawable.ic_appwidget_settings_brightness_auto);
@@ -490,52 +646,6 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
            views.setImageViewResource(R.id.ind_brightness,
                                       R.drawable.appwidget_settings_ind_off_r);
        }
        if (getSync(context)) {
            views.setImageViewResource(R.id.img_sync, R.drawable.ic_appwidget_settings_sync_on);
            views.setImageViewResource(R.id.ind_sync, R.drawable.appwidget_settings_ind_on_c);
        } else {
            views.setImageViewResource(R.id.img_sync, R.drawable.ic_appwidget_settings_sync_off);
            views.setImageViewResource(R.id.ind_sync, R.drawable.appwidget_settings_ind_off_c);
        }
        if (getGpsState(context)) {
            views.setImageViewResource(R.id.img_gps, R.drawable.ic_appwidget_settings_gps_on);
            views.setImageViewResource(R.id.ind_gps, R.drawable.appwidget_settings_ind_on_c);
        } else {
            views.setImageViewResource(R.id.img_gps, R.drawable.ic_appwidget_settings_gps_off);
            views.setImageViewResource(R.id.ind_gps, R.drawable.appwidget_settings_ind_off_c);
        }
        switch (sBluetoothState.getTriState(context)) {
            case STATE_DISABLED:
                views.setImageViewResource(R.id.img_bluetooth,
                                           R.drawable.ic_appwidget_settings_bluetooth_off);
                views.setImageViewResource(R.id.ind_bluetooth,
                                           R.drawable.appwidget_settings_ind_off_c);
                break;
            case STATE_ENABLED:
                views.setImageViewResource(R.id.img_bluetooth,
                                           R.drawable.ic_appwidget_settings_bluetooth_on);
                views.setImageViewResource(R.id.ind_bluetooth,
                                           R.drawable.appwidget_settings_ind_on_c);
                break;
            case STATE_INTERMEDIATE:
                // In the transitional state, the bottom green bar
                // shows the tri-state (on, off, transitioning), but
                // the top dark-gray-or-bright-white logo shows the
                // user's intent.  This is much easier to see in
                // sunlight.
                if (sBluetoothState.isTurningOn()) {
                    views.setImageViewResource(R.id.img_bluetooth,
                                               R.drawable.ic_appwidget_settings_bluetooth_on);
                    views.setImageViewResource(R.id.ind_bluetooth,
                                               R.drawable.appwidget_settings_ind_mid_c);
                } else {
                    views.setImageViewResource(R.id.img_bluetooth,
                                               R.drawable.ic_appwidget_settings_bluetooth_off);
                    views.setImageViewResource(R.id.ind_bluetooth,
                                               R.drawable.appwidget_settings_ind_off_c);
                }
                break;
        }
    }

    /**
@@ -565,10 +675,19 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
        String action = intent.getAction();
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
            sWifiState.onActualStateChange(context, intent);
        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
            sBluetoothState.onActualStateChange(context, intent);
        } else if (LocationManager.PROVIDERS_CHANGED_ACTION.equals(action)) {
            sGpsState.onActualStateChange(context, intent);
        } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
            // Sadly, for lack of a "sync settings changed" intent,
            // this is where we check where sync is enabled or not.
            // It's not 100% reliable though as there are paths where
            // this doesn't fire.
            sSyncState.onActualStateChange(context, intent);
        } else if (intent.hasCategory(Intent.CATEGORY_ALTERNATIVE)) {
            Uri data = intent.getData();
            int buttonId = Integer.parseInt(data.getSchemeSpecificPart());
@@ -577,9 +696,9 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
            } else if (buttonId == BUTTON_BRIGHTNESS) {
                toggleBrightness(context);
            } else if (buttonId == BUTTON_SYNC) {
                toggleSync(context);
                sSyncState.toggleState(context);
            } else if (buttonId == BUTTON_GPS) {
                toggleGps(context);
                sGpsState.toggleState(context);
            } else if (buttonId == BUTTON_BLUETOOTH) {
                sBluetoothState.toggleState(context);
            }
@@ -606,77 +725,6 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
        return connManager.getBackgroundDataSetting();
    }

    /**
     * Gets the state of auto-sync.
     *
     * @param context
     * @return true if enabled
     */
    private static boolean getSync(Context context) {
        boolean backgroundData = getBackgroundDataState(context);
        boolean sync = ContentResolver.getMasterSyncAutomatically();
        return backgroundData && sync;
    }

    /**
     * Toggle auto-sync
     *
     * @param context
     */
    private void toggleSync(Context context) {
        ConnectivityManager connManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        boolean backgroundData = getBackgroundDataState(context);
        boolean sync = ContentResolver.getMasterSyncAutomatically();

        // four cases to handle:
        // setting toggled from off to on:
        // 1. background data was off, sync was off: turn on both
        if (!backgroundData && !sync) {
            connManager.setBackgroundDataSetting(true);
            ContentResolver.setMasterSyncAutomatically(true);
        }

        // 2. background data was off, sync was on: turn on background data
        if (!backgroundData && sync) {
            connManager.setBackgroundDataSetting(true);
        }

        // 3. background data was on, sync was off: turn on sync
        if (backgroundData && !sync) {
            ContentResolver.setMasterSyncAutomatically(true);
        }

        // setting toggled from on to off:
        // 4. background data was on, sync was on: turn off sync
        if (backgroundData && sync) {
            ContentResolver.setMasterSyncAutomatically(false);
        }
    }

    /**
     * Gets the state of GPS location.
     *
     * @param context
     * @return true if enabled.
     */
    private static boolean getGpsState(Context context) {
        ContentResolver resolver = context.getContentResolver();
        return Settings.Secure.isLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER);
    }

    /**
     * Toggles the state of GPS.
     *
     * @param context
     */
    private void toggleGps(Context context) {
        ContentResolver resolver = context.getContentResolver();
        boolean enabled = getGpsState(context);
        Settings.Secure.setLocationProviderEnabled(resolver, LocationManager.GPS_PROVIDER,
                !enabled);
    }

    /**
     * Gets state of brightness.
     *