diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 15cc7cb332..c6636b5128 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1715,6 +1715,21 @@ + + + + + + + + + + + diff --git a/res/drawable-hdpi/ic_menu_save.png b/res/drawable-hdpi/ic_menu_save.png new file mode 100644 index 0000000000..2b29557ab5 Binary files /dev/null and b/res/drawable-hdpi/ic_menu_save.png differ diff --git a/res/drawable-hdpi/ic_screen_state.png b/res/drawable-hdpi/ic_screen_state.png new file mode 100644 index 0000000000..0405a2ac94 Binary files /dev/null and b/res/drawable-hdpi/ic_screen_state.png differ diff --git a/res/drawable-hdpi/ic_wakelock_blocker.png b/res/drawable-hdpi/ic_wakelock_blocker.png new file mode 100644 index 0000000000..f6e855e625 Binary files /dev/null and b/res/drawable-hdpi/ic_wakelock_blocker.png differ diff --git a/res/drawable-mdpi/ic_menu_save.png b/res/drawable-mdpi/ic_menu_save.png new file mode 100644 index 0000000000..283be30aca Binary files /dev/null and b/res/drawable-mdpi/ic_menu_save.png differ diff --git a/res/drawable-mdpi/ic_wakelock_blocker.png b/res/drawable-mdpi/ic_wakelock_blocker.png new file mode 100644 index 0000000000..f6e855e625 Binary files /dev/null and b/res/drawable-mdpi/ic_wakelock_blocker.png differ diff --git a/res/drawable-xhdpi/ic_menu_save.png b/res/drawable-xhdpi/ic_menu_save.png new file mode 100644 index 0000000000..c403206a1f Binary files /dev/null and b/res/drawable-xhdpi/ic_menu_save.png differ diff --git a/res/drawable-xhdpi/ic_screen_state.png b/res/drawable-xhdpi/ic_screen_state.png new file mode 100644 index 0000000000..5635ba32c2 Binary files /dev/null and b/res/drawable-xhdpi/ic_screen_state.png differ diff --git a/res/drawable-xhdpi/ic_wakelock_blocker.png b/res/drawable-xhdpi/ic_wakelock_blocker.png new file mode 100644 index 0000000000..f6e855e625 Binary files /dev/null and b/res/drawable-xhdpi/ic_wakelock_blocker.png differ diff --git a/res/layout/wakelock_blocker.xml b/res/layout/wakelock_blocker.xml new file mode 100644 index 0000000000..cbfe956f6a --- /dev/null +++ b/res/layout/wakelock_blocker.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/wakelock_item.xml b/res/layout/wakelock_item.xml new file mode 100644 index 0000000000..85e8022561 --- /dev/null +++ b/res/layout/wakelock_item.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/res/mipmap-hdpi/ic_launcher.png b/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..32da776f3e Binary files /dev/null and b/res/mipmap-hdpi/ic_launcher.png differ diff --git a/res/mipmap-mdpi/ic_launcher.png b/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..32a22ac93b Binary files /dev/null and b/res/mipmap-mdpi/ic_launcher.png differ diff --git a/res/mipmap-xhdpi/ic_launcher.png b/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..9bfdd78493 Binary files /dev/null and b/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/res/values/bs_strings.xml b/res/values/bs_strings.xml index d19f9ff76e..80118d30c6 100644 --- a/res/values/bs_strings.xml +++ b/res/values/bs_strings.xml @@ -448,4 +448,29 @@ There was a problem setting the region code. Enable Wi-Fi to change this option. + + + @null + Suspend Actions + Enable + Actions will be executed on screen off. On screen on the previous state will be restored. + Mobile networks + Location + Switch to 2G + Network mode will be switched to 2G on screen off + Disable GPS + GPS based location service will be disabled on screen off + Disable mobile data + Mobile data will be disabled on screen off + + + @null + Wakelock Blocker + Enable + Activate blocking for checked wakelocks + Save + Available Wakelocks + Reload + Proceed with Caution + Blocking wakelocks have the potential to cause instability, crashes or data loss. diff --git a/res/xml/beanstalk_interface_settings.xml b/res/xml/beanstalk_interface_settings.xml index d9f8f5f1eb..1c781febae 100644 --- a/res/xml/beanstalk_interface_settings.xml +++ b/res/xml/beanstalk_interface_settings.xml @@ -34,6 +34,18 @@ android:key="navbar_settings" android:fragment="com.android.settings.beanstalk.NavigationSettings" android:title="@string/navigation_settings_title" /> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java index f71df1d6f1..fc2d9c1f1f 100644 --- a/src/com/android/settings/CreateShortcut.java +++ b/src/com/android/settings/CreateShortcut.java @@ -50,6 +50,17 @@ protected void onListItemClick(ListView l, View v, int position, long id) { finish(); } + private int getProperShortcutIcon(String className) { + String c = className.substring(className.lastIndexOf(".") + 1); + + if (c.equals("ScreenStateToggles")) + return R.drawable.ic_screen_state; + else if (c.equals("WakeLockBlocker")) + return R.drawable.ic_wakelock_blocker; + else + return R.mipmap.ic_launcher; + } + @Override protected boolean onEvaluateShowIcons() { return false; diff --git a/src/com/android/settings/cyanogenmod/fragments/ScreenStateToggles.java b/src/com/android/settings/cyanogenmod/fragments/ScreenStateToggles.java new file mode 100644 index 0000000000..15bbd92680 --- /dev/null +++ b/src/com/android/settings/cyanogenmod/fragments/ScreenStateToggles.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2013 Android Open Kang Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.cyanogenmod.fragments; + +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.SwitchPreference; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.preference.PreferenceCategory; +import android.provider.Settings; +import android.content.Intent; +import android.util.Log; +import android.net.ConnectivityManager; +import android.content.Context; +import android.os.UserManager; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.R; + +public class ScreenStateToggles extends SettingsPreferenceFragment implements OnPreferenceChangeListener { + private static final String TAG = "ScreenStateToggles"; + private static final String SCREEN_STATE_TOOGLES_ENABLE = "screen_state_toggles_enable_key"; + private static final String SCREEN_STATE_TOOGLES_TWOG = "screen_state_toggles_twog"; + private static final String SCREEN_STATE_TOOGLES_GPS = "screen_state_toggles_gps"; + private static final String SCREEN_STATE_TOOGLES_MOBILE_DATA = "screen_state_toggles_mobile_data"; + private static final String SCREEN_STATE_CATGEGORY_LOCATION = "screen_state_toggles_location_key"; + private static final String SCREEN_STATE_CATGEGORY_MOBILE_DATA = "screen_state_toggles_mobile_key"; + + private SwitchPreference mEnableScreenStateToggles; + private CheckBoxPreference mEnableScreenStateTogglesTwoG; + private CheckBoxPreference mEnableScreenStateTogglesGps; + private CheckBoxPreference mEnableScreenStateTogglesMobileData; + private PreferenceCategory mMobileDateCategory; + private PreferenceCategory mLocationCategory; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTitle(R.string.screen_state_toggles_title); + + addPreferencesFromResource(R.xml.prefs_screen_state_toggles); + PreferenceScreen prefSet = getPreferenceScreen(); + + mEnableScreenStateToggles = (SwitchPreference) prefSet.findPreference( + SCREEN_STATE_TOOGLES_ENABLE); + + boolean enabled = Settings.System.getBoolean(getContentResolver(), Settings.System.START_SCREEN_STATE_SERVICE, false); + mEnableScreenStateToggles.setChecked(enabled); + mEnableScreenStateToggles.setOnPreferenceChangeListener(this); + + mMobileDateCategory = (PreferenceCategory) prefSet.findPreference( + SCREEN_STATE_CATGEGORY_MOBILE_DATA); + mLocationCategory = (PreferenceCategory) prefSet.findPreference( + SCREEN_STATE_CATGEGORY_LOCATION); + + mEnableScreenStateTogglesTwoG = (CheckBoxPreference) prefSet.findPreference( + SCREEN_STATE_TOOGLES_TWOG); + + ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + if (!cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)){ + getPreferenceScreen().removePreference(mEnableScreenStateTogglesTwoG); + } else { + mEnableScreenStateTogglesTwoG.setChecked( + Settings.System.getBoolean(getContentResolver(), Settings.System.SCREEN_STATE_TWOG, false)); + mEnableScreenStateTogglesTwoG.setOnPreferenceChangeListener(this); + } + + mEnableScreenStateTogglesMobileData = (CheckBoxPreference) prefSet.findPreference( + SCREEN_STATE_TOOGLES_MOBILE_DATA); + + if (!cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)){ + getPreferenceScreen().removePreference(mEnableScreenStateTogglesMobileData); + } else { + mEnableScreenStateTogglesMobileData.setChecked( + Settings.System.getBoolean(getContentResolver(), Settings.System.SCREEN_STATE_MOBILE_DATA, false)); + mEnableScreenStateTogglesMobileData.setOnPreferenceChangeListener(this); + } + + // Only enable these controls if this user is allowed to change location + // sharing settings. + final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); + boolean isLocationChangeAllowed = !um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION); + + // TODO: check if gps is available on this device? + mEnableScreenStateTogglesGps = (CheckBoxPreference) prefSet.findPreference( + SCREEN_STATE_TOOGLES_GPS); + + if (!isLocationChangeAllowed){ + getPreferenceScreen().removePreference(mEnableScreenStateTogglesGps); + mEnableScreenStateTogglesGps = null; + } else { + mEnableScreenStateTogglesGps.setChecked( + Settings.System.getBoolean(getContentResolver(), Settings.System.SCREEN_STATE_GPS, false)); + mEnableScreenStateTogglesGps.setOnPreferenceChangeListener(this); + } + + mMobileDateCategory.setEnabled(enabled); + mLocationCategory.setEnabled(enabled); + } + + public boolean onPreferenceChange(Preference preference, Object newValue) { + if (preference == mEnableScreenStateToggles) { + boolean value = ((Boolean) newValue).booleanValue(); + Settings.System.putBoolean(getContentResolver(), + Settings.System.START_SCREEN_STATE_SERVICE, value); + + Intent service = (new Intent()) + .setClassName("com.android.systemui", "com.android.systemui.screenstate.ScreenStateService"); + if (value) { + getActivity().stopService(service); + getActivity().startService(service); + } else { + getActivity().stopService(service); + } + + mMobileDateCategory.setEnabled(value); + mLocationCategory.setEnabled(value); + + return true; + } else if (preference == mEnableScreenStateTogglesTwoG) { + Settings.System.putBoolean(getContentResolver(), + Settings.System.SCREEN_STATE_TWOG, (Boolean) newValue); + + Intent intent = new Intent("android.intent.action.SCREEN_STATE_SERVICE_UPDATE"); + mContext.sendBroadcast(intent); + + return true; + } else if (preference == mEnableScreenStateTogglesGps) { + Settings.System.putBoolean(getContentResolver(), + Settings.System.SCREEN_STATE_GPS, (Boolean) newValue); + + Intent intent = new Intent("android.intent.action.SCREEN_STATE_SERVICE_UPDATE"); + mContext.sendBroadcast(intent); + + return true; + } else if (preference == mEnableScreenStateTogglesMobileData) { + Settings.System.putBoolean(getContentResolver(), + Settings.System.SCREEN_STATE_MOBILE_DATA, (Boolean) newValue); + + Intent intent = new Intent("android.intent.action.SCREEN_STATE_SERVICE_UPDATE"); + mContext.sendBroadcast(intent); + + return true; + } + + + return false; + } + + private void restartService(){ + Intent service = (new Intent()) + .setClassName("com.android.systemui", "com.android.systemui.screenstate.ScreenStateService"); + getActivity().stopService(service); + getActivity().startService(service); + } +} diff --git a/src/com/android/settings/cyanogenmod/fragments/WakeLockBlocker.java b/src/com/android/settings/cyanogenmod/fragments/WakeLockBlocker.java new file mode 100644 index 0000000000..6bf5232101 --- /dev/null +++ b/src/com/android/settings/cyanogenmod/fragments/WakeLockBlocker.java @@ -0,0 +1,271 @@ +package com.android.settings.cyanogenmod.fragments; + +import android.content.Context; +import android.os.Bundle; +import android.os.PowerManager; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.preference.PreferenceFragment; +import android.view.LayoutInflater; +import android.widget.Switch; +import android.widget.ListView; +import android.widget.ArrayAdapter; +import android.widget.TextView; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.AdapterView; +import android.provider.Settings; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.app.AlertDialog; +import android.content.DialogInterface; + +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Collections; + +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.R; + +public class WakeLockBlocker extends SettingsPreferenceFragment { + private Switch mBlockerEnabled; + private ListView mWakeLockList; + private List mSeenWakeLocks; + private List mBlockedWakeLocks; + private LayoutInflater mInflater; + private Map mWakeLockState; + private WakeLockListAdapter mListAdapter; + private boolean mEnabled; + private AlertDialog mAlertDialog; + private boolean mAlertShown = false; + private TextView mWakeLockListHeader; + + private static final int MENU_RELOAD = Menu.FIRST; + private static final int MENU_SAVE = Menu.FIRST + 1; + + public class WakeLockListAdapter extends ArrayAdapter { + + public WakeLockListAdapter(Context context, int resource, List values) { + super(context, R.layout.wakelock_item, resource, values); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View rowView = mInflater.inflate(R.layout.wakelock_item, parent, false); + final CheckBox check = (CheckBox)rowView.findViewById(R.id.wakelock_blocked); + check.setText(mSeenWakeLocks.get(position)); + + Boolean checked = mWakeLockState.get(check.getText().toString()); + check.setChecked(checked.booleanValue()); + + if(checked.booleanValue()){ + check.setTextColor(getResources().getColor(android.R.color.holo_red_light)); + } + + check.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton v, boolean checked) { + mWakeLockState.put(v.getText().toString(), new Boolean(checked)); + if(checked){ + check.setTextColor(getResources().getColor(android.R.color.holo_red_light)); + } else { + check.setTextColor(getResources().getColor(android.R.color.primary_text_dark)); + } + } + }); + return rowView; + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + mInflater = inflater; + setHasOptionsMenu(true); + return inflater.inflate(R.layout.wakelock_blocker, container, false); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + mWakeLockState = new HashMap(); + updateSeenWakeLocksList(); + updateBlockedWakeLocksList(); + + mBlockerEnabled = (Switch) getActivity().findViewById( + R.id.wakelock_blocker_switch); + mWakeLockList = (ListView) getActivity().findViewById( + R.id.wakelock_list); + mWakeLockListHeader = (TextView) getActivity().findViewById( + R.id.wakelock_list_header); + + mListAdapter = new WakeLockListAdapter(mContext, android.R.layout.simple_list_item_multiple_choice, mSeenWakeLocks); + mWakeLockList.setAdapter(mListAdapter); + + updateSwitches(); + + // after updateSwitches!!! + mBlockerEnabled + .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton v, boolean checked) { + if (checked && isFirstEnable() && !mAlertShown){ + showAlert(); + mAlertShown = true; + } + + Settings.System.putInt(mContext.getContentResolver(), Settings.System.WAKELOCK_BLOCKING_ENABLED, + checked?1:0); + + updateSwitches(); + } + }); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + private boolean isFirstEnable() { + return Settings.System.getString(mContext.getContentResolver(), + Settings.System.WAKELOCK_BLOCKING_ENABLED) == null; + } + + private void updateSwitches() { + mBlockerEnabled.setChecked(Settings.System.getInt(mContext.getContentResolver(), + Settings.System.WAKELOCK_BLOCKING_ENABLED, 0)==1?true:false); + + mEnabled = mBlockerEnabled.isChecked(); + //mWakeLockList.setEnabled(mEnabled); + mWakeLockList.setVisibility(mEnabled ?View.VISIBLE : View.INVISIBLE); + mWakeLockListHeader.setVisibility(mEnabled ?View.VISIBLE : View.INVISIBLE); + } + + private void updateSeenWakeLocksList() { + PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE); + Log.d("maxwen", pm.getSeenWakeLocks()); + + String seenWakeLocks = pm.getSeenWakeLocks(); + mSeenWakeLocks = new ArrayList(); + + if (seenWakeLocks!=null && seenWakeLocks.length()!=0){ + String[] parts = seenWakeLocks.split("\\|"); + for(int i = 0; i < parts.length; i++){ + mSeenWakeLocks.add(parts[i]); + mWakeLockState.put(parts[i], new Boolean(false)); + } + } + } + + private void updateBlockedWakeLocksList() { + String blockedWakelockList = Settings.System.getString(mContext.getContentResolver(), + Settings.System.WAKELOCK_BLOCKING_LIST); + + mBlockedWakeLocks = new ArrayList(); + + if (blockedWakelockList!=null && blockedWakelockList.length()!=0){ + String[] parts = blockedWakelockList.split("\\|"); + for(int i = 0; i < parts.length; i++){ + mBlockedWakeLocks.add(parts[i]); + + // add all blocked but not seen so far + if(!mSeenWakeLocks.contains(parts[i])){ + mSeenWakeLocks.add(parts[i]); + } + mWakeLockState.put(parts[i], new Boolean(true)); + } + } + + Collections.sort(mSeenWakeLocks); + } + + private void save(){ + StringBuffer buffer = new StringBuffer(); + Iterator nextState = mWakeLockState.keySet().iterator(); + while(nextState.hasNext()){ + String name = nextState.next(); + Boolean state=mWakeLockState.get(name); + if(state.booleanValue()){ + buffer.append(name + "|"); + } + } + if(buffer.length()>0){ + buffer.deleteCharAt(buffer.length() - 1); + } + Log.d("maxwen", buffer.toString()); + Settings.System.putString(mContext.getContentResolver(), + Settings.System.WAKELOCK_BLOCKING_LIST, buffer.toString()); + } + + private void reload(){ + mWakeLockState = new HashMap(); + updateSeenWakeLocksList(); + updateBlockedWakeLocksList(); + + mListAdapter.notifyDataSetChanged(); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.add(0, MENU_RELOAD, 0, R.string.wakelock_blocker_reload) + .setIcon(R.drawable.ic_menu_refresh_holo_dark) + .setAlphabeticShortcut('r') + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | + MenuItem.SHOW_AS_ACTION_WITH_TEXT); + menu.add(0, MENU_SAVE, 0, R.string.wakelock_blocker_save) + .setIcon(R.drawable.ic_menu_save) + .setAlphabeticShortcut('s') + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | + MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_RELOAD: + if (mEnabled){ + reload(); + } + return true; + case MENU_SAVE: + if (mEnabled){ + save(); + } + return true; + default: + return false; + } + } + + private void showAlert() { + /* Display the warning dialog */ + mAlertDialog = new AlertDialog.Builder(getActivity()).create(); + mAlertDialog.setTitle(R.string.wakelock_blocker_warning_title); + mAlertDialog.setMessage(getResources().getString(R.string.wakelock_blocker_warning)); + mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE, + getResources().getString(com.android.internal.R.string.ok), + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + return; + } + }); + mAlertDialog.show(); + } +}