diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-01-20 09:38:15 +0100 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-01-20 09:38:15 +0100 |
commit | a3edd3be2ce0504cb485573b34cc32d60fecfe7a (patch) | |
tree | d29d0b9980fccf25d5ef55e4f088484d218ba85f /packages | |
parent | 69a68b55dfbb1603ca549610bfd14dd4698a3c67 (diff) | |
parent | d1295657d03c605ea20f0881f6adff2762167e04 (diff) | |
download | frameworks_base-a3edd3be2ce0504cb485573b34cc32d60fecfe7a.zip frameworks_base-a3edd3be2ce0504cb485573b34cc32d60fecfe7a.tar.gz frameworks_base-a3edd3be2ce0504cb485573b34cc32d60fecfe7a.tar.bz2 |
Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_frameworks_base into replicant-6.0
Signed-off-by: Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de>
Diffstat (limited to 'packages')
49 files changed, 1097 insertions, 304 deletions
diff --git a/packages/Keyguard/res/values/cm_strings.xml b/packages/Keyguard/res/values/cm_strings.xml index 40921c7..3276211 100644 --- a/packages/Keyguard/res/values/cm_strings.xml +++ b/packages/Keyguard/res/values/cm_strings.xml @@ -26,4 +26,7 @@ <item quantity="one">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempt before you must contact your carrier to unlock your device.</item> <item quantity="other">Enter SIM PIN, you have <xliff:g id="number">%d</xliff:g> remaining attempts.</item> </plurals> + + <!-- Shown in the KeyguardSimPinView when entry length is too short. --> + <string name="kg_invalid_sim_length">Error: Input shorter than minimum length</string> </resources> diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java index f04db02..8dd56fa 100644 --- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java +++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java @@ -46,6 +46,7 @@ public class CarrierText extends TextView { private static final String TAG = "CarrierText"; private static CharSequence mSeparator; + private static CharSequence mSubSeparator; private final boolean mIsEmergencyCallCapable; @@ -168,7 +169,7 @@ public class CarrierText extends TextView { } if (carrierTextForSimState != null) { allSimsMissing = false; - displayText = concatenate(displayText, carrierTextForSimState); + displayText = concatenate(displayText, carrierTextForSimState, mSubSeparator); } if (simState == IccCardConstants.State.READY) { ServiceState ss = mKeyguardUpdateMonitor.mServiceStates.get(subId); @@ -242,6 +243,8 @@ public class CarrierText extends TextView { super.onFinishInflate(); mSeparator = getResources().getString( com.android.internal.R.string.kg_text_message_separator); + mSubSeparator = getResources().getString( + com.android.internal.R.string.kg_sub_separator); boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive(); setSelected(shouldMarquee); // Allow marquee to work. } @@ -381,10 +384,15 @@ public class CarrierText extends TextView { } private static CharSequence concatenate(CharSequence plmn, CharSequence spn) { + return concatenate(plmn, spn, mSeparator); + } + + private static CharSequence concatenate(CharSequence plmn, CharSequence spn, + CharSequence separator) { final boolean plmnValid = !TextUtils.isEmpty(plmn); final boolean spnValid = !TextUtils.isEmpty(spn); if (plmnValid && spnValid) { - return new StringBuilder().append(plmn).append(mSeparator).append(spn).toString(); + return new StringBuilder().append(plmn).append(separator).append(spn).toString(); } else if (plmnValid) { return plmn; } else if (spnValid) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java index 3aa36c8..4d26adf 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java @@ -238,7 +238,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { if (entry.length() < 4) { // otherwise, display a message to the user, and don't submit. - mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true); + mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_length, true); resetPasswordText(true); mCallback.userActivity(); return; diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 8c941f6..c361c70 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -2001,7 +2001,22 @@ public class SettingsProvider extends ContentProvider { final int newVersion = SETTINGS_VERSION; // If up do date - done. + // + // CYANOGENMOD + // We moved our settings out to another settings provider (CMSettingsProvider) + // however, we still have a problem of being a few versions ahead of AOSP. + // We could approach this in the manner we have previously, and bump the version + // to replay the defaults for specific os upgrade changes and have that maintenance + // overhead forever OR we can take the approach below: + // + // Logic as follows: + // Until version 125 of this "DATABASE" + // force replay AOSP defaults as they get introduced + // once 125 is hit, we never have to maintain this again. if ((oldVersion == newVersion || oldVersion == CM_SETTINGS_DB_VERSION)) { + if (oldVersion == CM_SETTINGS_DB_VERSION) { + forceReplayAOSPDefaults(mUserId); + } return; } @@ -2140,6 +2155,42 @@ public class SettingsProvider extends ContentProvider { // Return the current version. return currentVersion; } + + private void forceReplayAOSPDefaults(int userId) { + // v119: Reset zen + ringer mode. + if (userId == UserHandle.USER_OWNER) { + final SettingsState globalSettings = getGlobalSettingsLocked(); + globalSettings.updateSettingLocked(Settings.Global.ZEN_MODE, + Integer.toString(Settings.Global.ZEN_MODE_OFF), + SettingsState.SYSTEM_PACKAGE_NAME); + globalSettings.updateSettingLocked(Settings.Global.MODE_RINGER, + Integer.toString(AudioManager.RINGER_MODE_NORMAL), + SettingsState.SYSTEM_PACKAGE_NAME); + } + + // v120: Add double tap to wake setting. + SettingsState secureSettings = getSecureSettingsLocked(userId); + secureSettings.insertSettingLocked(Settings.Secure.DOUBLE_TAP_TO_WAKE, + getContext().getResources().getBoolean( + R.bool.def_double_tap_to_wake) ? "1" : "0", + SettingsState.SYSTEM_PACKAGE_NAME); + + // Version 122: allow OEMs to set a default payment component in resources. + // Note that we only write the default if no default has been set; + // if there is, we just leave the default at whatever it currently is. + String defaultComponent = (getContext().getResources().getString( + R.string.def_nfc_payment_component)); + Setting currentSetting = secureSettings.getSettingLocked( + Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT); + if (defaultComponent != null && !defaultComponent.isEmpty() && + currentSetting == null) { + secureSettings.insertSettingLocked( + Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT, + defaultComponent, + SettingsState.SYSTEM_PACKAGE_NAME); + } + } + } } } diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml new file mode 100644 index 0000000..0301872 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_battery_saver_off.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2015 The CyanogenMod 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="#4DFFFFFF" + android:pathData="M16.67,4H15V2H9V4H7.33A1.33,1.33 0 0,0 6,5.33V20.67C6,21.4 6.6,22 7.33,22H16.67A1.33,1.33 0 0,0 18,20.67V5.33C18,4.6 17.4,4 16.67,4Z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml b/packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml new file mode 100644 index 0000000..0e11796 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_battery_saver_on.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2015 The CyanogenMod 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M16.67,4C17.4,4 18,4.6 18,5.33V20.67A1.33,1.33 0 0,1 16.67,22H7.33C6.6,22 6,21.4 6,20.67V5.33A1.33,1.33 0 0,1 7.33,4H9V2H15V4H16.67M16,14V12H13V9H11V12H8V14H11V17H13V14H16Z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml b/packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml new file mode 100644 index 0000000..904ccdf --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_heads_up_off.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2014 The Android Open Source 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,10.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7C9.5,4.3 9.0,4.5 8.6,4.7l9.4,9.4L18.0,10.5zM17.7,19.0l2.0,2.0l1.3,-1.3L4.3,3.0L3.0,4.3l2.9,2.9C5.3,8.2 5.0,9.3 5.0,10.5L5.0,16.0l-2.0,2.0l0.0,1.0L17.7,19.0z" /> +</vector> diff --git a/packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml b/packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml new file mode 100644 index 0000000..9c5983d --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_heads_up_on.xml @@ -0,0 +1,25 @@ +<!-- +Copyright (C) 2014 The Android Open Source 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="64dp" + android:height="64dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0"> + + <path + android:fillColor="#FFFFFFFF" + android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z"/> +</vector> diff --git a/packages/SystemUI/res/layout/qs_tile_top.xml b/packages/SystemUI/res/layout/qs_tile_top.xml index 0a6736a..4413ec3 100644 --- a/packages/SystemUI/res/layout/qs_tile_top.xml +++ b/packages/SystemUI/res/layout/qs_tile_top.xml @@ -17,11 +17,12 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/qs_panel_top" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:paddingTop="@dimen/qs_brightness_padding_top" + android:clipToPadding="false" + android:layout_height="wrap_content"> <!-- brightness --> <include android:id="@+id/brightness_container" - android:paddingTop="@dimen/qs_brightness_padding_top" layout="@layout/quick_settings_brightness_dialog"/> <!-- delete target --> @@ -29,7 +30,6 @@ android:id="@+id/delete_container" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingTop="@dimen/qs_brightness_padding_top" android:paddingLeft="16dp" android:paddingRight="16dp" android:orientation="horizontal"> @@ -49,7 +49,6 @@ android:id="@+id/edit_container" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingTop="@dimen/qs_brightness_padding_top" android:paddingLeft="16dp" android:paddingRight="16dp" android:orientation="horizontal"> @@ -75,7 +74,6 @@ <TextView android:id="@+id/qs_toast" android:layout_height="match_parent" - android:paddingTop="@dimen/qs_brightness_padding_top" android:paddingLeft="16dp" android:paddingRight="16dp" android:gravity="center_vertical" diff --git a/packages/SystemUI/res/values/cm_colors.xml b/packages/SystemUI/res/values/cm_colors.xml index cedeeee..85b3d58 100644 --- a/packages/SystemUI/res/values/cm_colors.xml +++ b/packages/SystemUI/res/values/cm_colors.xml @@ -74,6 +74,13 @@ <color name="qs_edit_header_instruction_text_color">@android:color/white</color> <color name="qs_row_text_color">@android:color/white</color> + <!-- natural color of the trash can --> + <color name="qs_tile_trash">#FFFFFF</color> + <!-- tint to color trash can when tile is hovering over it --> + <color name="qs_tile_trash_delete_tint">#FF0000</color> + <!-- tint to color trash can when hovering edit tile, user cannot delete it --> + <color name="qs_tile_trash_delete_tint_warning">#FF9C00</color> + <!-- More exposed hard coded colors --> <color name="toggle_slider_text_color">#666666</color> <color name="no_recent_apps_text_color">@android:color/holo_blue_light</color> @@ -103,4 +110,10 @@ <color name="qs_detailed_expansion_indicator_color">@color/qs_title_text_color</color> <color name="qs_detailed_title_text_color">@color/qs_title_text_color</color> <color name="qs_detailed_icon_tint_color">@color/qs_title_text_color</color> + + <!-- Quick tile text color when the tile is disabled --> + <color name="qs_tile_text_disabled">#ff747474</color> + + <!-- Active color for volume slider --> + <color name="volume_slider_active">@color/system_accent_color</color> </resources> diff --git a/packages/SystemUI/res/values/cm_dimens.xml b/packages/SystemUI/res/values/cm_dimens.xml index 73608b7..3bce97b 100644 --- a/packages/SystemUI/res/values/cm_dimens.xml +++ b/packages/SystemUI/res/values/cm_dimens.xml @@ -39,6 +39,9 @@ <!-- Padding end for weather text --> <dimen name="status_bar_weather_padding_end">16dp</dimen> + <!-- height of the qs page indicator --> + <dimen name="qs_panel_page_indicator_height">8dp</dimen> + <dimen name="lockscreen_icon_side_padding">10dp</dimen> <dimen name="lockscreen_icon_size">35dp</dimen> <dimen name="phone_side_padding">10dp</dimen> diff --git a/packages/SystemUI/res/values/cm_strings.xml b/packages/SystemUI/res/values/cm_strings.xml index 481bdf5..cfad226 100644 --- a/packages/SystemUI/res/values/cm_strings.xml +++ b/packages/SystemUI/res/values/cm_strings.xml @@ -101,6 +101,8 @@ <string name="quick_settings_nfc_label">NFC</string> <string name="quick_settings_profiles">System profiles</string> <string name="quick_settings_profiles_off">Profiles disabled</string> + <string name="quick_settings_heads_up_label">Heads up</string> + <string name="quick_settings_battery_saver_label">Battery saver</string> <!-- Content description of the sync tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_quick_settings_sync_off">Sync off.</string> @@ -168,6 +170,26 @@ <!-- Announcement made when ambient display changes to on (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_quick_settings_ambient_display_changed_on">Ambient display turned on.</string> + <!-- Content description of the heads up tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_heads_up_off">Heads up off.</string> + <!-- Content description of the heads up tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_heads_up_on">Heads up on.</string> + + <!-- Announcement made when heads up changes to off (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_heads_up_changed_off">Heads up turned off.</string> + <!-- Announcement made when heads up changes to on (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_heads_up_changed_on">Heads up turned on.</string> + + <!-- Content description of the battery saver tile in quick settings when off (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_battery_saver_off">Battery saver off.</string> + <!-- Content description of the battery saver tile in quick settings when on (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_battery_saver_on">Battery saver on.</string> + + <!-- Announcement made when battery saver changes to off (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_battery_saver_changed_off">Battery saver turned off.</string> + <!-- Announcement made when battery saver changes to on (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_quick_settings_battery_saver_changed_on">Battery saver turned on.</string> + <!-- Dynamic tiles --> <string name="quick_settings_dynamic_tile_detail_title">Dynamic tile</string> <string name="dynamic_qs_tile_next_alarm_label">Next alarm</string> diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 0b066af..565fbd7 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; +import android.content.res.ThemeConfig; import android.os.SystemProperties; import android.util.Log; @@ -58,6 +59,7 @@ public class SystemUIApplication extends Application { private boolean mServicesStarted; private boolean mBootCompleted; private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>(); + private Configuration mConfig; @Override public void onCreate() { @@ -85,6 +87,7 @@ public class SystemUIApplication extends Application { } } }, filter); + mConfig = new Configuration(getResources().getConfiguration()); } /** @@ -134,6 +137,12 @@ public class SystemUIApplication extends Application { @Override public void onConfigurationChanged(Configuration newConfig) { + if (isThemeChange(mConfig, newConfig)) { + // theme resource changed so recreate styles and attributes + recreateTheme(); + } + + mConfig.setTo(newConfig); if (mServicesStarted) { int len = mServices.length; for (int i = 0; i < len; i++) { @@ -150,4 +159,11 @@ public class SystemUIApplication extends Application { public SystemUI[] getServices() { return mServices; } + + private static boolean isThemeChange(Configuration oldConfig, Configuration newConfig) { + final ThemeConfig oldThemeConfig = oldConfig != null ? oldConfig.themeConfig : null; + final ThemeConfig newThemeConfig = newConfig != null ? newConfig.themeConfig : null; + + return newThemeConfig != null && !newThemeConfig.equals(oldThemeConfig); + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 8555ef0..563dfa1 100755 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -290,7 +290,7 @@ public class KeyguardViewMediator extends SystemUI { /** * Whether we are disabling the lock screen internally */ - private boolean mInternallyDisabled = false; + private Boolean mInternallyDisabled = null; /** * we send this intent when the keyguard is dismissed. @@ -690,9 +690,20 @@ public class KeyguardViewMediator extends SystemUI { CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED, getPersistedDefaultOldSetting() ? 1 : 0, UserHandle.USER_CURRENT) == 0; - if (newDisabledState != mInternallyDisabled && mKeyguardBound) { - // it was updated, - setKeyguardEnabledInternal(!newDisabledState); + + if (mKeyguardBound) { + if (mInternallyDisabled == null) { + // if it's enabled on boot, don't go through the notions of + // setting it enabled, as it might cause a flicker, just set the state + if (newDisabledState) { + setKeyguardEnabledInternal(false); // will set mInternallyDisabled + } else { + mInternallyDisabled = false; + } + } else if (newDisabledState != mInternallyDisabled) { + // it was updated, + setKeyguardEnabledInternal(!newDisabledState); + } } } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java index df45120..5769f58 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java @@ -36,6 +36,7 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.UserHandle; +import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.ArrayMap; @@ -46,7 +47,6 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.widget.BaseExpandableListAdapter; import android.widget.EditText; import android.widget.ExpandableListView; @@ -72,21 +72,21 @@ import org.cyanogenmod.internal.logging.CMMetricsLogger; import org.cyanogenmod.internal.util.QSUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; public class QSDragPanel extends QSPanel implements View.OnDragListener, View.OnLongClickListener { private static final String TAG = "QSDragPanel"; + public static final boolean DEBUG_TILES = false; public static final boolean DEBUG_DRAG = false; private static final int MAX_ROW_COUNT = 3; - private static final int INITIAL_OFFSCREEN_PAGE_LIMIT = 3; private static final String BROADCAST_TILE_SPEC_PLACEHOLDER = "broadcast_placeholder"; protected final ArrayList<QSPage> mPages = new ArrayList<>(); @@ -95,6 +95,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On protected PagerAdapter mPagerAdapter; QSPanelTopView mQsPanelTop; CirclePageIndicator mPageIndicator; + private int mPageIndicatorHeight; private TextView mDetailRemoveButton; private DragTileRecord mDraggingRecord, mLastDragRecord; @@ -114,7 +115,6 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On List<TileRecord> mCurrentlyAnimating = Collections.synchronizedList(new ArrayList<TileRecord>()); - private Collection<QSTile<?>> mTempTiles = null; private Point mDisplaySize; private int[] mTmpLoc; @@ -140,35 +140,24 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mDetail.setVisibility(GONE); mDetail.setClickable(true); - mQsPanelTop = (QSPanelTopView) LayoutInflater.from(mContext).inflate(R.layout.qs_tile_top, this, false); + mQsPanelTop = (QSPanelTopView) LayoutInflater.from(mContext).inflate(R.layout.qs_tile_top, + this, false); + + // tint trash can to default color + final int color = mContext.getColor(R.color.qs_tile_trash); + DrawableCompat.setTint(mQsPanelTop.getDropTargetIcon().getDrawable(), color); mBrightnessView = mQsPanelTop.getBrightnessView(); mFooter = new QSFooter(this, mContext); - getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - getViewTreeObserver().removeOnGlobalLayoutListener(this); - - ViewPager.LayoutParams params = new ViewPager.LayoutParams(); - params.isDecor = true; - - mViewPager.addView(mQsPanelTop, params); - - mQsPanelTop.setOnDragListener(QSDragPanel.this); - mPageIndicator.setOnDragListener(QSDragPanel.this); - mViewPager.setOnDragListener(QSDragPanel.this); - } - }); - // add target click listener mQsPanelTop.getAddTarget().setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { TilesListAdapter adapter = new TilesListAdapter(mContext, QSDragPanel.this); - showDetailAdapter(true, adapter, - v.getLocationOnScreen()); + showDetailAdapter(true, adapter, v.getLocationOnScreen()); + mDetail.bringToFront(); } }); mViewPager = new QSViewPager(getContext()); @@ -176,6 +165,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mPageIndicator = new CirclePageIndicator(getContext()); addView(mDetail); + addView(mQsPanelTop); addView(mViewPager); addView(mPageIndicator); addView(mFooter.getView()); @@ -198,7 +188,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mPagerAdapter = new PagerAdapter() { @Override public Object instantiateItem(ViewGroup container, int position) { - if (DEBUG_DRAG) { + if (DEBUG_TILES) { Log.d(TAG, "instantiateItem() called with " + "container = [" + container + "], position = [" + position + "]"); } @@ -210,31 +200,22 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On container.addView(qss, 0); return qss; } else { - QSPage page = new QSPage(container.getContext(), - QSDragPanel.this, mEditing ? position - 1 : position); + final int adjustedPosition = mEditing ? position - 1 : position; + QSPage page = mPages.get(adjustedPosition); - container.addView(page); - int viewPos = page.getPageIndex(); - if (viewPos > mPages.size()) { - mPages.add(page); - } else { - mPages.add(viewPos, page); - } + container.addView(page, position); return page; } } @Override public void destroyItem(ViewGroup container, int position, Object object) { - if (DEBUG_DRAG) { + if (DEBUG_TILES) { Log.d(TAG, "destroyItem() called with " + "container = [" + container + "], position = [" + position + "], object = [" + object + "]"); } if (object instanceof View) { - if (object instanceof QSPage) { - mPages.remove(object); - } container.removeView((View) object); } } @@ -242,16 +223,34 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On @Override public int getItemPosition(Object object) { if (object instanceof QSPage) { + if (mEditing != ((QSPage) object).getAdapterEditingState()) { + // position of item changes when we set change the editing mode, + // sync it and send the new position + ((QSPage) object).setAdapterEditingState(mEditing); + + // calculate new position + int indexOf = ((QSPage) object).getPageIndex(); + if (mEditing) return indexOf + 1; + else return indexOf; + + } else if (!mPages.contains(object) && !mDragging) { + // only return none if we aren't dragging (object may be removed from + // the records array temporarily and we might think we have less pages, + // we don't want to prematurely remove this page + return POSITION_NONE; + } else { - final int indexOf = ((QSPage) object).getPageIndex(); - if (mEditing) return indexOf + 1; - else return indexOf; + return POSITION_UNCHANGED; + } } else if (object instanceof QSSettings) { - - if (mEditing) return 0; - else return POSITION_NONE; - + if (((QSSettings) object).getAdapterEditingState() != mEditing) { + ((QSSettings) object).setAdapterEditingState(mEditing); + if (mEditing) return 0 /* locked at position 0 */; + else return POSITION_NONE; + } else { + return POSITION_UNCHANGED; + } } return super.getItemPosition(object); } @@ -260,6 +259,12 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On public int getCount() { final int qsPages = Math.max(getCurrentMaxPageCount(), 1); + if (mPages != null && qsPages > mPages.size()) { + for(int i = mPages.size(); i < qsPages; i++) { + mPages.add(i, new QSPage(mViewPager.getContext(), QSDragPanel.this, i)); + } + } + if (mEditing) return qsPages + 1; return qsPages; } @@ -270,7 +275,6 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On } }; mViewPager.setAdapter(mPagerAdapter); - mViewPager.setOffscreenPageLimit(INITIAL_OFFSCREEN_PAGE_LIMIT); mPageIndicator.setViewPager(mViewPager); mPageIndicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @@ -330,6 +334,13 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On setClipChildren(false); mSettingsObserver = new SettingsObserver(new Handler()); + + mViewPager.setOnDragListener(QSDragPanel.this); + mQsPanelTop.setOnDragListener(QSDragPanel.this); + mPageIndicator.setOnDragListener(QSDragPanel.this); + setOnDragListener(QSDragPanel.this); + + mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER); } @Override @@ -353,6 +364,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On } final int visibility = state.visible ? VISIBLE : GONE; setTileVisibility(r.tileView, visibility); + setTileEnabled(r.tileView, state.enabled); r.tileView.onStateChanged(state); } @@ -406,8 +418,10 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mPageIndicator.setEditing(editing); mPagerAdapter.notifyDataSetChanged(); + mViewPager.setOffscreenPageLimit(mEditing ? getCurrentMaxPageCount() + 1 : 1); + mPagerAdapter.notifyDataSetChanged(); + requestLayout(); - ensurePagerState(); } protected void onStartDrag() { @@ -427,7 +441,6 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mQsPanelTop.onStopDrag(); requestLayout(); - ensurePagerState(); } protected View getDropTarget() { @@ -453,9 +466,6 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On protected int getCurrentMaxPageCount() { int initialSize = mRecords.size(); - if (mTempTiles != null) { - return getPagesForCount(initialSize + mTempTiles.size()); - } return getPagesForCount(initialSize); } @@ -497,102 +507,117 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On public void setTiles(final Collection<QSTile<?>> tilesCollection) { final List<QSTile<?>> tiles = new ArrayList<>(tilesCollection); - if (isLaidOut()) { - if (DEBUG_DRAG) { - Log.i(TAG, "setTiles() called with " + "tiles = [" - + tiles + "], mTempTiles: " + mTempTiles); - if (mTempTiles != null) { - Log.e(TAG, "temp tiles being overridden... : " + - Arrays.toString(mTempTiles.toArray())); - } - } + if (DEBUG_TILES) { + Log.i(TAG, "setTiles() called with " + "tiles = [" + + tiles + "]"); + } - if (mLastDragRecord != null && mRecords.indexOf(mLastDragRecord) == -1) { - // the last removed record might be stored in mLastDragRecord if we just shifted - // re-add it to the list so we'll clean it up below - mRecords.add(mLastDragRecord); - mLastDragRecord = null; - } + if (mLastDragRecord != null && mRecords.indexOf(mLastDragRecord) == -1) { + // the last removed record might be stored in mLastDragRecord if we just shifted + // re-add it to the list so we'll clean it up below + mRecords.add(mLastDragRecord); + mLastDragRecord = null; + } - Map<QSTile<?>, DragTileRecord> recordMap = new ArrayMap<>(); - Iterator<TileRecord> iterator = mRecords.iterator(); + Map<QSTile<?>, DragTileRecord> recordMap = new ArrayMap<>(); + ListIterator<TileRecord> iterator = mRecords.listIterator(mRecords.size()); - int recordsRemoved = 0; - // cleanup current records - while (iterator.hasNext()) { - DragTileRecord dr = (DragTileRecord) iterator.next(); + int recordsRemoved = 0; + // cleanup current records + while (iterator.hasPrevious()) { + DragTileRecord dr = (DragTileRecord) iterator.previous(); - if (tiles.contains(dr.tile)) { - if (DEBUG_DRAG) { - Log.i(TAG, "caching tile: " + dr.tile); - } - recordMap.put(dr.tile, dr); - } else { - if (DEBUG_DRAG) { - Log.i(TAG, "removing tile: " + dr.tile); - } - // clean up view - mPages.get(dr.page).removeView(dr.tileView); + if (tiles.contains(dr.tile)) { + if (DEBUG_TILES) { + Log.i(TAG, "caching tile: " + dr.tile); + } + recordMap.put(dr.tile, dr); + } else { + if (DEBUG_TILES) { + Log.i(TAG, "removing tile: " + dr.tile); + } + // clean up view + mPages.get(dr.page).removeView(dr.tileView); - // remove record - iterator.remove(); - recordsRemoved++; + // remove record + iterator.remove(); + recordsRemoved++; + + if (dr.page >= getCurrentMaxPageCount() - 1) { + final int childCount = mPages.get(dr.page).getChildCount(); + + if (childCount == 0) { + // if current page is the current max page COUNT (off by 1) then move back + final int currentIndex = mViewPager.getCurrentItem(); + if (currentIndex == (getCurrentMaxPageCount()) + (mEditing ? 1 : 0)) { + mViewPager.setCurrentItem(currentIndex - 1, false); + mPagerAdapter.startUpdate(mViewPager); + final int pageIndex = mEditing ? currentIndex - 1 : currentIndex; + mPages.remove(pageIndex); + mPagerAdapter.finishUpdate(mViewPager); + mPagerAdapter.notifyDataSetChanged(); + } + } } } + } + // at this point recordMap should have all retained tiles, no new or old tiles + int delta = tiles.size() - recordMap.size() - recordsRemoved; + if (DEBUG_TILES) { + Log.i(TAG, "record map delta: " + delta); + } + mRecords.ensureCapacity(tiles.size()); + mPagerAdapter.notifyDataSetChanged(); - // at this point recordMap should have all retained tiles, no new or old tiles - int delta = tiles.size() - recordMap.size() - recordsRemoved; - if (DEBUG_DRAG) { - Log.i(TAG, "record map delta: " + delta); - } - mRecords.ensureCapacity(tiles.size()); - mPagerAdapter.notifyDataSetChanged(); - - // add new tiles - for (int i = 0; i < tiles.size(); i++) { - QSTile<?> tile = tiles.get(i); - final int tileDestPage = getPagesForCount(i + 1) - 1; + // add new tiles + for (int i = 0; i < tiles.size(); i++) { + QSTile<?> tile = tiles.get(i); + final int tileDestPage = getPagesForCount(i + 1) - 1; - if (DEBUG_DRAG) { - Log.d(TAG, "tile at : " + i + ": " + tile + " to dest page: " + tileDestPage); + if (DEBUG_TILES) { + Log.d(TAG, "tile at : " + i + ": " + tile + " to dest page: " + tileDestPage); + } + DragTileRecord record; + if (!recordMap.containsKey(tile)) { + if (DEBUG_TILES) { + Log.d(TAG, "tile at: " + i + " not cached, adding it to records"); } - if (!recordMap.containsKey(tile)) { - DragTileRecord record = makeRecord(tile); - record.destinationPage = tileDestPage; - recordMap.put(tile, record); - mRecords.add(i, record); - mPagerAdapter.notifyDataSetChanged(); - - // add the view - mPages.get(record.destinationPage).addView(record.tileView); - record.page = record.destinationPage; - if (DEBUG_DRAG) { - Log.d(TAG, "added new record " + record); + record = makeRecord(tile); + record.destinationPage = tileDestPage; + recordMap.put(tile, record); + mRecords.add(i, record); + mPagerAdapter.notifyDataSetChanged(); + } else { + record = recordMap.get(tile); + if (DEBUG_TILES) { + Log.d(TAG, "tile at : " + i + ": cached, restoring: " + record); + } + int indexOf = mRecords.indexOf(record); + if (indexOf != i) { + if (DEBUG_TILES) { + Log.w(TAG, "moving index of " + record + " from " + + indexOf + " to " + i); } - } else { - DragTileRecord record = recordMap.get(tile); - int indexOf = mRecords.indexOf(record); - if (indexOf != i) { - if (DEBUG_DRAG) { - Log.w(TAG, "moving index of " + record + " from " - + indexOf + " to " + i); - } - Collections.swap(mRecords, indexOf, i); + Collections.swap(mRecords, indexOf, i); - record.destinationPage = tileDestPage; - ensureDestinationPage(record); - } + record.destinationPage = tileDestPage; + ensureDestinationPage(record); } + } - if (isShowingDetail()) { - mDetail.bringToFront(); - } - } else if (!isLaidOut()) { - if (DEBUG_DRAG) { - Log.w(TAG, "setting temporary tiles to layout"); + if (record.page == -1) { + // add the view + mPages.get(record.destinationPage).addView(record.tileView); + record.page = record.destinationPage; + if (DEBUG_TILES) { + Log.d(TAG, "added view " + record); + } } - mTempTiles = Collections.synchronizedCollection(new ArrayList<QSTile<?>>(tiles)); + } + + if (isShowingDetail()) { + mDetail.bringToFront(); } mPagerAdapter.notifyDataSetChanged(); @@ -611,7 +636,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On } private DragTileRecord makeRecord(final QSTile<?> tile) { - if (DEBUG_DRAG) { + if (DEBUG_TILES) { Log.d(TAG, "+++ makeRecord() called with " + "tile = [" + tile + "]"); } final DragTileRecord r = new DragTileRecord(); @@ -688,35 +713,20 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On r.tileView.setVisibility(mEditing ? View.VISIBLE : View.GONE); callback.onStateChanged(r.tile.getState()); - if (DEBUG_DRAG) { + if (DEBUG_TILES) { Log.d(TAG, "--- makeRecord() called with " + "tile = [" + tile + "]"); } return r; } - private void addTile(final QSTile<?> tile) { - if (DEBUG_DRAG) { - Log.d(TAG, "+++ addTile() called with " + "tile = [" + tile + "]"); - } - DragTileRecord r = makeRecord(tile); - mRecords.add(r); - mPagerAdapter.notifyDataSetChanged(); - - r.destinationPage = getPagesForCount(mRecords.size()) - 1; - + private void removeDraggingRecord() { + // what spec is this tile? + String spec = mHost.getSpec(mDraggingRecord.tile); if (DEBUG_DRAG) { - Log.d(TAG, "destinationPage: " + r.destinationPage); - } - - mPages.get(r.destinationPage).addView(r.tileView); - r.page = r.destinationPage; - drawTile(r, r.tile.getState()); - - ensurePagerState(); - - if (DEBUG_DRAG) { - Log.d(TAG, "--- addTile() called with " + "tile = [" + tile + "]"); + Log.w(TAG, "removing tile: " + mDraggingRecord + " with spec: " + spec); } + onStopDrag(); + mHost.remove(spec); } public void ensurePagerState() { @@ -744,16 +754,12 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); - if (isLaidOut()) { - mQsPanelTop.measure(exactly(width), MeasureSpec.UNSPECIFIED); - } + mQsPanelTop.measure(exactly(width), MeasureSpec.UNSPECIFIED); mViewPager.measure(exactly(width), MeasureSpec.UNSPECIFIED); - mPageIndicator.measure(exactly(width), MeasureSpec.UNSPECIFIED); + mPageIndicator.measure(exactly(width), atMost(mPageIndicatorHeight)); mFooter.getView().measure(exactly(width), MeasureSpec.UNSPECIFIED); - int h = mBrightnessPaddingTop - + mViewPager.getMeasuredHeight() - + mPageIndicator.getMeasuredHeight(); + int h = mViewPager.getMeasuredHeight() + mPageIndicatorHeight; if (mFooter.hasFooter()) { h += mFooter.getView().getMeasuredHeight(); } @@ -802,6 +808,10 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); } + public static int atMost(int size) { + return MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST); + } + @Override protected void handleShowDetailTile(TileRecord r, boolean show) { if (r instanceof DragTileRecord) { @@ -824,13 +834,14 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On protected void onLayout(boolean changed, int l, int t, int r, int b) { final int w = getWidth(); - int top = mBrightnessPaddingTop; + mQsPanelTop.layout(0, 0, w, mQsPanelTop.getMeasuredHeight()); - mViewPager.layout(0, top, w, top + mViewPager.getMeasuredHeight()); - top += mViewPager.getMeasuredHeight(); + int viewPagerBottom = mQsPanelTop.getMeasuredHeight() + mViewPager.getMeasuredHeight(); + // view pager laid out from top of brightness view to bottom to page through settings + mViewPager.layout(0, 0, w, viewPagerBottom); - // layout page indicator below view pager - mPageIndicator.layout(0, top, w, top + mPageIndicator.getMeasuredHeight()); + // layout page indicator inside viewpager inset + mPageIndicator.layout(0, b - mPageIndicatorHeight, w, b); mDetail.layout(0, 0, w, mDetail.getMeasuredHeight()); @@ -840,21 +851,15 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On footer.getMeasuredWidth(), getMeasuredHeight()); } - if (mTempTiles != null) { - final Iterator<QSTile<?>> iterator = mTempTiles.iterator(); - while (iterator.hasNext()) { - addTile(iterator.next()); - iterator.remove(); - } - mTempTiles = null; - mPagerAdapter.notifyDataSetChanged(); - requestLayout(); + if (!isShowingDetail() && !isClosingDetail()) { + mQsPanelTop.bringToFront(); } + ensurePagerState(); } protected int getRowTop(int row) { - int baseHeight = mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop; + int baseHeight = mBrightnessView.getMeasuredHeight(); if (row <= 0) return baseHeight; return baseHeight + mLargeCellHeight - mDualTileUnderlap + (row - 1) * mCellHeight; } @@ -955,21 +960,43 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On boolean dragRecordAttached = dragRecordIndex != -1; switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: + if (DEBUG_DRAG) { + Log.v(TAG, "ACTION_DRAG_STARTED on view: " + v); + } + if (originatingTileEvent) { if (DEBUG_DRAG) { Log.v(TAG, "ACTION_DRAG_STARTED on target view."); } mRestored = false; } - return true; + + break; case DragEvent.ACTION_DRAG_ENTERED: if (DEBUG_DRAG) { - Log.v(TAG, "ACTION_DRAG_ENTERED on view with tile: " + targetTile); + if (targetTile != null) { + Log.v(TAG, "ACTION_DRAG_ENTERED on view with tile: " + targetTile); + } else { + Log.v(TAG, "ACTION_DRAG_ENTERED on view: " + v); + } } mLocationHits = 0; mMovedByLocation = false; + if (v == mQsPanelTop) { + int color; + if (mDraggingRecord.tile instanceof EditTile) { + // use a different warning, user can't erase this one + color = mContext.getColor(R.color.qs_tile_trash_delete_tint_warning); + } else { + color = mContext.getColor(R.color.qs_tile_trash_delete_tint); + } + + DrawableCompat.setTint(mQsPanelTop.getDropTargetIcon().getDrawable(), color); + mQsPanelTop.getDropTargetIcon().invalidate(); + } + if (!originatingTileEvent && v != getDropTarget() && targetTile != null) { if (DEBUG_DRAG) { Log.e(TAG, "entered tile " + targetTile); @@ -986,7 +1013,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On } } - return true; + break; case DragEvent.ACTION_DRAG_ENDED: if (DEBUG_DRAG) { Log.v(TAG, "ACTION_DRAG_ENDED on view: " + v + "(tile: " @@ -997,7 +1024,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On restoreDraggingTilePosition(v); } - return true; + break; case DragEvent.ACTION_DROP: if (DEBUG_DRAG) { @@ -1014,21 +1041,15 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On if (mDraggingRecord.tile instanceof EditTile) { mQsPanelTop.toast(R.string.quick_settings_cannot_delete_edit_tile); restoreDraggingTilePosition(v); - return true; + break; } else { mRestored = true; - // what spec is this tile? - String spec = mHost.getSpec(mDraggingRecord.tile); - if (DEBUG_DRAG) { - Log.w(TAG, "removing tile: " + mDraggingRecord + " with spec: " + spec); - } - onStopDrag(); - mHost.remove(spec); + removeDraggingRecord(); } } else { restoreDraggingTilePosition(v); } - return true; + break; case DragEvent.ACTION_DRAG_EXITED: if (DEBUG_DRAG) { @@ -1038,6 +1059,13 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On Log.v(TAG, "ACTION_DRAG_EXITED on view: " + v); } } + + if (v == mQsPanelTop) { + final int color = mContext.getColor(R.color.qs_tile_trash); + DrawableCompat.setTint(mQsPanelTop.getDropTargetIcon().getDrawable(), color); + mQsPanelTop.getDropTargetIcon().invalidate(); + } + if (originatingTileEvent && mCurrentlyAnimating.isEmpty() && !mViewPager.isFakeDragging() @@ -1053,7 +1081,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On // move tiles back shiftTiles(mDraggingRecord, false); - return true; + break; } // fall through so exit events can trigger a left shift case DragEvent.ACTION_DRAG_LOCATION: @@ -1115,17 +1143,20 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On shiftTiles((DragTileRecord) mRecords.get(mLastRightShift), false); mMovedByLocation = true; } + } else { if (DEBUG_DRAG) { Log.i(TAG, "ignoring location event because things are animating, size: " + mCurrentlyAnimating.size()); } } - return true; + break; + default: Log.w(TAG, "unhandled event"); + return false; } - return false; + return true; } private boolean isDropTargetEvent(DragEvent event, View v) { @@ -1697,6 +1728,22 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On } } + @Override + protected void setGridContentVisibility(boolean visible) { + int newVis = visible ? VISIBLE : INVISIBLE; + for (int i = 0; i < mRecords.size(); i++) { + TileRecord tileRecord = mRecords.get(i); + if (tileRecord.tileView.getVisibility() != GONE) { + tileRecord.tileView.setVisibility(newVis); + } + } + mQsPanelTop.setVisibility(showBrightnessSlider() ? newVis : GONE); + if (mGridContentVisible != visible) { + MetricsLogger.visibility(mContext, MetricsLogger.QS_PANEL, newVis); + } + mGridContentVisible = visible; + } + public void updateResources() { final Resources res = mContext.getResources(); final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns)); @@ -1707,6 +1754,7 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom); mDualTileUnderlap = res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical); mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top); + mPageIndicatorHeight = res.getDimensionPixelSize(R.dimen.qs_panel_page_indicator_height); if (isLaidOut()) { if (mColumns != columns) { mColumns = columns; @@ -1767,6 +1815,9 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On // add broadcast tile mPackageTileMap.get(PACKAGE_ANDROID).add(BROADCAST_TILE_SPEC_PLACEHOLDER); + + final List<String> systemTiles = mPackageTileMap.get(PACKAGE_ANDROID); + Collections.sort(systemTiles); } private String getCustomTilePackage(String spec) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPage.java b/packages/SystemUI/src/com/android/systemui/qs/QSPage.java index be2f7e5..57b559e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPage.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPage.java @@ -23,6 +23,8 @@ public class QSPage extends ViewGroup { private int mPage; + private boolean mAdapterEditingState; + public QSPage(Context context, QSDragPanel panel, int page) { super(context); mPanel = panel; @@ -95,7 +97,7 @@ public class QSPage extends ViewGroup { record.tileView.measure(exactly(cw), exactly(ch)); previousView = record.tileView.updateAccessibilityOrder(previousView); } - setMeasuredDimension(width, mGridHeight); + setMeasuredDimension(width, exactly(mGridHeight)); } @Override @@ -137,6 +139,14 @@ public class QSPage extends ViewGroup { } } + public boolean getAdapterEditingState() { + return mAdapterEditingState; + } + + public void setAdapterEditingState(boolean editing) { + this.mAdapterEditingState = editing; + } + public boolean dualRecord(QSPanel.TileRecord record) { return mPanel.mFirstRowLarge && record.row == 0 && mPage == 0; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 1e6867d..60dc787 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -82,7 +82,7 @@ public class QSPanel extends ViewGroup { protected QSTileHost mHost; protected QSFooter mFooter; - private boolean mGridContentVisible = true; + protected boolean mGridContentVisible = true; public QSPanel(Context context) { this(context, null); @@ -281,6 +281,15 @@ public class QSPanel extends ViewGroup { v.setVisibility(visibility); } + protected void setTileEnabled(View v, boolean enabled) { + mHandler.obtainMessage(H.SET_TILE_ENABLED, enabled ? 1 : 0, 0, v).sendToTarget(); + } + + private void handleSetTileEnabled(View v, boolean enabled) { + if (enabled == v.isEnabled()) return; + v.setEnabled(enabled); + } + public void setTiles(Collection<QSTile<?>> tiles) { for (TileRecord record : mRecords) { removeView(record.tileView); @@ -454,7 +463,7 @@ public class QSPanel extends ViewGroup { } } - private void setGridContentVisibility(boolean visible) { + protected void setGridContentVisibility(boolean visible) { int newVis = visible ? VISIBLE : INVISIBLE; for (int i = 0; i < mRecords.size(); i++) { TileRecord tileRecord = mRecords.get(i); @@ -606,12 +615,15 @@ public class QSPanel extends ViewGroup { private class H extends Handler { private static final int SHOW_DETAIL = 1; private static final int SET_TILE_VISIBILITY = 2; + private static final int SET_TILE_ENABLED = 3; @Override public void handleMessage(Message msg) { if (msg.what == SHOW_DETAIL) { handleShowDetail((Record)msg.obj, msg.arg1 != 0); } else if (msg.what == SET_TILE_VISIBILITY) { handleSetTileVisibility((View)msg.obj, msg.arg1); + } else if (msg.what == SET_TILE_ENABLED) { + handleSetTileEnabled((View)msg.obj, msg.arg1 == 1); } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java index 060d06c..bfff5f2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelTopView.java @@ -25,8 +25,8 @@ import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.util.Log; import android.view.View; -import android.view.ViewTreeObserver; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.TextView; import com.android.systemui.R; @@ -48,6 +48,7 @@ public class QSPanelTopView extends FrameLayout { private boolean mDisplayingToast = false; private AnimatorSet mAnimator; + private ImageView mDropTargetIcon; public QSPanelTopView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); @@ -60,6 +61,7 @@ public class QSPanelTopView extends FrameLayout { public QSPanelTopView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); + setFocusable(true); } @Override @@ -71,6 +73,10 @@ public class QSPanelTopView extends FrameLayout { return mDropTarget; } + public ImageView getDropTargetIcon() { + return mDropTargetIcon; + } + public View getBrightnessView() { return mBrightnessView; } @@ -83,6 +89,7 @@ public class QSPanelTopView extends FrameLayout { protected void onFinishInflate() { super.onFinishInflate(); mDropTarget = findViewById(R.id.delete_container); + mDropTargetIcon = (ImageView) findViewById(R.id.delete_target); mEditTileInstructionView = findViewById(R.id.edit_container); mBrightnessView = findViewById(R.id.brightness_container); mToastView = (TextView) findViewById(R.id.qs_toast); @@ -92,14 +99,14 @@ public class QSPanelTopView extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int width = MeasureSpec.getSize(widthMeasureSpec); - mBrightnessView.measure(exactly(width), MeasureSpec.UNSPECIFIED); + mBrightnessView.measure(QSDragPanel.exactly(width), MeasureSpec.UNSPECIFIED); int dh = mBrightnessView.getMeasuredHeight(); - mDropTarget.measure(exactly(width), atMost(dh)); - mEditTileInstructionView.measure(exactly(width), atMost(dh)); - mToastView.measure(exactly(width), atMost(dh)); + mDropTarget.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh)); + mEditTileInstructionView.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh)); + mToastView.measure(QSDragPanel.exactly(width), QSDragPanel.atMost(dh)); - setMeasuredDimension(width, mBrightnessView.getMeasuredHeight()); + setMeasuredDimension(width, QSDragPanel.exactly(mBrightnessView.getMeasuredHeight())); } @Override @@ -112,14 +119,6 @@ public class QSPanelTopView extends FrameLayout { } } - private static int atMost(int height) { - return MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); - } - - private static int exactly(int size) { - return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); - } - public void setEditing(boolean editing) { mEditing = editing; if (editing) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java index fd2fb17..d90c991 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java @@ -29,6 +29,8 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; public class QSSettings extends LinearLayout { private QSTileHost mHost; + private boolean mAdapterEditingState; + public QSSettings(Context context) { super(context); } @@ -57,7 +59,7 @@ public class QSSettings extends LinearLayout { new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - mHost.resetTiles(); + mHost.initiateReset(); } }).create(); SystemUIDialog.makeSystemUIDialog(d); @@ -67,4 +69,12 @@ public class QSSettings extends LinearLayout { public void setHost(QSTileHost host) { mHost = host; } + + public boolean getAdapterEditingState() { + return mAdapterEditingState; + } + + public void setAdapterEditingState(boolean editing) { + this.mAdapterEditingState = editing; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index 7d7e516..2d62724 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -354,6 +354,7 @@ public abstract class QSTile<TState extends State> implements Listenable { void setEditing(boolean editing); boolean isEditing(); void goToSettingsPage(); + void resetTiles(); } } @@ -497,6 +498,7 @@ public abstract class QSTile<TState extends State> implements Listenable { public static class State { public boolean visible; + public boolean enabled = true; public Icon icon; public String label; public String contentDescription; @@ -507,6 +509,7 @@ public abstract class QSTile<TState extends State> implements Listenable { if (other == null) throw new IllegalArgumentException(); if (!other.getClass().equals(getClass())) throw new IllegalArgumentException(); final boolean changed = other.visible != visible + || !Objects.equals(other.enabled, enabled) || !Objects.equals(other.icon, icon) || !Objects.equals(other.label, label) || !Objects.equals(other.contentDescription, contentDescription) @@ -514,6 +517,7 @@ public abstract class QSTile<TState extends State> implements Listenable { || !Objects.equals(other.dualLabelContentDescription, dualLabelContentDescription); other.visible = visible; + other.enabled = enabled; other.icon = icon; other.label = label; other.contentDescription = contentDescription; @@ -530,6 +534,7 @@ public abstract class QSTile<TState extends State> implements Listenable { protected StringBuilder toStringBuilder() { final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('['); sb.append("visible=").append(visible); + sb.append(",enabled=").append(enabled); sb.append(",icon=").append(icon); sb.append(",label=").append(label); sb.append(",contentDescription=").append(contentDescription); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java index d1a1ad5..a95fac3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java @@ -22,6 +22,8 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; @@ -328,9 +330,20 @@ public class QSTileView extends ViewGroup { mDualLabel.setText(state.label); mDualLabel.setContentDescription(state.dualLabelContentDescription); mTopBackgroundView.setContentDescription(state.contentDescription); + if (!Objects.equals(state.enabled, mDualLabel.isEnabled())) { + mTopBackgroundView.setEnabled(state.enabled); + mDualLabel.setEnabled(state.enabled); + mDualLabel.setTextColor(mContext.getResources().getColor(state.enabled ? + R.color.qs_tile_text : R.color.qs_tile_text_disabled)); + } } else { mLabel.setText(state.label); setContentDescription(state.contentDescription); + if (!Objects.equals(state.enabled, mLabel.isEnabled())) { + mLabel.setEnabled(state.enabled); + mLabel.setTextColor(mContext.getResources().getColor(state.enabled ? + R.color.qs_tile_text : R.color.qs_tile_text_disabled)); + } } } @@ -349,6 +362,14 @@ public class QSTileView extends ViewGroup { } } } + if (!Objects.equals(state.enabled, iv.isEnabled())) { + iv.setEnabled(state.enabled); + if (state.enabled) { + iv.setColorFilter(null); + } else { + iv.setColorFilter(Color.GRAY, PorterDuff.Mode.MULTIPLY); + } + } } public void onStateChanged(QSTile.State state) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java b/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java index 94c7c62..01c48b1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSViewPager.java @@ -16,7 +16,6 @@ public class QSViewPager extends ViewPager { protected static final float SCROLL_PERCENT = .10f; private boolean mPagingEnabled; QSDragPanel mDragPanel; - private int mLastHeight = 0; public QSViewPager(Context context) { super(context); @@ -45,14 +44,13 @@ public class QSViewPager extends ViewPager { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int height = mLastHeight; + int height = 0; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = child.getMeasuredHeight(); if (h > height) height = h; } - mLastHeight = height; heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java index d741330..283d617 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AdbOverNetworkTile.java @@ -36,6 +36,8 @@ import org.cyanogenmod.internal.logging.CMMetricsLogger; public class AdbOverNetworkTile extends QSTile<QSTile.BooleanState> { + private boolean mListening; + private static final Intent SETTINGS_DEVELOPMENT = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); @@ -111,16 +113,18 @@ public class AdbOverNetworkTile extends QSTile<QSTile.BooleanState> { @Override public void setListening(boolean listening) { - if (listening) { - mContext.getContentResolver().registerContentObserver( - CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT), - false, mObserver); - mContext.getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(Settings.Global.ADB_ENABLED), - false, mObserver); - } else { - mContext.getContentResolver().unregisterContentObserver(mObserver); + if (mListening != listening) { + mListening = listening; + if (listening) { + mContext.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.ADB_PORT), + false, mObserver); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(Settings.Global.ADB_ENABLED), + false, mObserver); + } else { + mContext.getContentResolver().unregisterContentObserver(mObserver); + } } } - } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java new file mode 100644 index 0000000..37d8d73 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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.systemui.qs.tiles; + +import android.content.Context; +import android.content.Intent; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.PowerManager; +import android.provider.Settings; + +import com.android.systemui.qs.QSTile; +import com.android.systemui.R; + +import cyanogenmod.power.PerformanceManager; + +import org.cyanogenmod.internal.logging.CMMetricsLogger; + +/** Quick settings tile: Battery saver **/ +public class BatterySaverTile extends QSTile<QSTile.BooleanState> { + + private static final Intent BATTERY_SETTINGS = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); + + private final PowerManager mPm; + private final PerformanceManager mPerformanceManager; + private boolean mListening; + + public BatterySaverTile(Host host) { + super(host); + mPm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mPerformanceManager = PerformanceManager.getInstance(mContext); + } + + @Override + protected BooleanState newTileState() { + return new BooleanState(); + } + + @Override + public void handleClick() { + mPm.setPowerSaveMode(!mState.value); + refreshState(); + } + + @Override + public void handleLongClick() { + mHost.startActivityDismissingKeyguard(BATTERY_SETTINGS); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + state.value = mPm.isPowerSaveMode(); + state.visible = mPerformanceManager.getNumberOfProfiles() == 0; + state.label = mContext.getString(R.string.quick_settings_battery_saver_label); + if (state.value) { + state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_battery_saver_on); + } else { + state.icon = ResourceIcon.get(R.drawable.ic_qs_battery_saver_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_battery_saver_off); + } + } + + @Override + protected String composeChangeAnnouncement() { + if (mState.value) { + return mContext.getString( + R.string.accessibility_quick_settings_battery_saver_changed_on); + } else { + return mContext.getString( + R.string.accessibility_quick_settings_battery_saver_changed_off); + } + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.TILE_BATTERY_SAVER; + } + + private ContentObserver mObserver = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange, Uri uri) { + refreshState(); + } + }; + + @Override + public void setListening(boolean listening) { + if (mListening == listening) return; + mListening = listening; + + if (listening) { + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE), + false, mObserver); + } else { + mContext.getContentResolver().unregisterContentObserver(mObserver); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java index f0c4f52..d09ca92 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CustomQSTile.java @@ -55,6 +55,7 @@ public class CustomQSTile extends QSTile<QSTile.State> { private CustomTile.ExpandedStyle mExpandedStyle; private PendingIntent mOnClick; + private PendingIntent mOnLongClick; private Uri mOnClickUri; private int mCurrentUserId; private StatusBarPanelCustomTile mTile; @@ -92,7 +93,16 @@ public class CustomQSTile extends QSTile<QSTile.State> { @Override protected void handleLongClick() { - if (mExpandedStyle == null) { + if (mOnLongClick != null) { + if (mOnLongClick.isActivity()) { + getHost().collapsePanels(); + } + try { + mOnLongClick.send(); + } catch (Throwable e) { + Log.w(TAG, "Error sending long click intent", e); + } + } else if (mExpandedStyle == null) { showDetail(true); } } @@ -143,6 +153,7 @@ public class CustomQSTile extends QSTile<QSTile.State> { state.icon = new ExternalBitmapIcon(customTile.remoteIcon); } mOnClick = customTile.onClick; + mOnLongClick = customTile.onLongClick; mOnClickUri = customTile.onClickUri; mExpandedStyle = customTile.expandedStyle; mCollapsePanel = customTile.collapsePanel; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java index cbc906f..7c9b762 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/EditTile.java @@ -18,9 +18,10 @@ package com.android.systemui.qs.tiles; import com.android.systemui.R; import com.android.systemui.qs.QSTile; +import com.android.systemui.statusbar.policy.KeyguardMonitor; import org.cyanogenmod.internal.logging.CMMetricsLogger; -public class EditTile extends QSTile<QSTile.BooleanState> { +public class EditTile extends QSTile<QSTile.BooleanState> implements KeyguardMonitor.Callback { private boolean mListening; @@ -53,7 +54,10 @@ public class EditTile extends QSTile<QSTile.BooleanState> { @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.visible = !getHost().getKeyguardMonitor().isShowing(); + final boolean showing = getHost().getKeyguardMonitor().isShowing(); + final boolean secure = getHost().getKeyguardMonitor().isSecure(); + state.visible = !showing || !secure; + state.enabled = true; state.label = mContext.getString(R.string.quick_settings_edit_label); if (arg instanceof Boolean) { @@ -79,6 +83,16 @@ public class EditTile extends QSTile<QSTile.BooleanState> { public void setListening(boolean listening) { if (mListening == listening) return; mListening = listening; + if (mListening) { + mHost.getKeyguardMonitor().addCallback(this); + } else { + mHost.getKeyguardMonitor().removeCallback(this); + } + refreshState(); + } + + @Override + public void onKeyguardChanged() { refreshState(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java new file mode 100644 index 0000000..d30bd91 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HeadsUpTile.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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.systemui.qs.tiles; + +import android.content.Context; +import android.content.Intent; +import android.provider.Settings; +import android.provider.Settings.Global; + +import com.android.systemui.qs.GlobalSetting; +import com.android.systemui.qs.QSTile; +import com.android.systemui.R; + +import org.cyanogenmod.internal.logging.CMMetricsLogger; + +/** Quick settings tile: Heads up **/ +public class HeadsUpTile extends QSTile<QSTile.BooleanState> { + + private static final Intent NOTIFICATION_SETTINGS = + new Intent("android.settings.NOTIFICATION_MANAGER"); + + private final GlobalSetting mSetting; + + public HeadsUpTile(Host host) { + super(host); + + mSetting = new GlobalSetting(mContext, mHandler, Global.HEADS_UP_NOTIFICATIONS_ENABLED) { + @Override + protected void handleValueChanged(int value) { + handleRefreshState(value); + } + }; + } + + @Override + protected BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleClick() { + setEnabled(!mState.value); + refreshState(); + } + + @Override + protected void handleLongClick() { + mHost.startActivityDismissingKeyguard(NOTIFICATION_SETTINGS); + } + + private void setEnabled(boolean enabled) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, + enabled ? 1 : 0); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + final int value = arg instanceof Integer ? (Integer)arg : mSetting.getValue(); + final boolean headsUp = value != 0; + state.value = headsUp; + state.visible = true; + state.label = mContext.getString(R.string.quick_settings_heads_up_label); + if (headsUp) { + state.icon = ResourceIcon.get(R.drawable.ic_qs_heads_up_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_heads_up_on); + } else { + state.icon = ResourceIcon.get(R.drawable.ic_qs_heads_up_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_heads_up_off); + } + } + + @Override + protected String composeChangeAnnouncement() { + if (mState.value) { + return mContext.getString(R.string.accessibility_quick_settings_heads_up_changed_on); + } else { + return mContext.getString(R.string.accessibility_quick_settings_heads_up_changed_off); + } + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.TILE_HEADS_UP; + } + + @Override + public void setListening(boolean listening) { + // Do nothing + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java index 6f1a921..2d764ba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java @@ -34,7 +34,6 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> private KeyguardViewMediator mKeyguardViewMediator; private KeyguardMonitor mKeyguard; - private boolean mPersistedState; private boolean mListening; private KeyguardViewMediator.LockscreenEnabledSettingsObserver mSettingsObserver; @@ -52,15 +51,12 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> @Override public void update() { - boolean newEnabledState = CMSettings.Secure.getIntForUser( + boolean newState = CMSettings.Secure.getIntForUser( mContext.getContentResolver(), CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED, getPersistedDefaultOldSetting() ? 1 : 0, UserHandle.USER_CURRENT) != 0; - if (newEnabledState != mPersistedState) { - mPersistedState = newEnabledState; - refreshState(); - } + refreshState(newState); } }; @@ -75,6 +71,7 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> if (listening) { mSettingsObserver.observe(); mKeyguard.addCallback(this); + refreshState(); } else { mSettingsObserver.unobserve(); mKeyguard.removeCallback(this); @@ -88,7 +85,9 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> @Override protected void handleClick() { - setPersistedState(!mPersistedState); + final boolean newState = !getState().value; + setPersistedState(newState); + refreshState(newState); } @Override @@ -99,12 +98,12 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> @Override protected void handleUpdateState(BooleanState state, Object arg) { final boolean lockscreenEnforced = mKeyguardViewMediator.lockscreenEnforcedByDevicePolicy(); - final boolean lockscreenEnabled = lockscreenEnforced - || mPersistedState - || mKeyguardViewMediator.getKeyguardEnabledInternal(); + final boolean lockscreenEnabled = lockscreenEnforced || + arg != null ? (Boolean) arg : mKeyguardViewMediator.getKeyguardEnabledInternal(); state.value = lockscreenEnabled; - state.visible = !mKeyguard.isShowing() || !mKeyguard.isSecure(); + state.visible = mKeyguardViewMediator.isKeyguardBound(); + state.enabled = !mKeyguard.isShowing() || !mKeyguard.isSecure(); state.label = mContext.getString(lockscreenEnforced ? R.string.quick_settings_lockscreen_label_enforced : R.string.quick_settings_lockscreen_label); @@ -144,6 +143,5 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> CMSettings.Secure.putIntForUser(mContext.getContentResolver(), CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED, enabled ? 1 : 0, UserHandle.USER_CURRENT); - mPersistedState = enabled; } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java index 9053643..6f65f6c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ProfilesTile.java @@ -47,7 +47,7 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -public class ProfilesTile extends QSTile<QSTile.State> { +public class ProfilesTile extends QSTile<QSTile.State> implements KeyguardMonitor.Callback { private static final Intent PROFILES_SETTINGS = new Intent("android.settings.PROFILES_SETTINGS"); @@ -57,11 +57,19 @@ public class ProfilesTile extends QSTile<QSTile.State> { private ProfileManager mProfileManager; private QSDetailItemsList mDetails; private ProfileAdapter mAdapter; + private KeyguardMonitor mKeyguardMonitor; public ProfilesTile(Host host) { super(host); mProfileManager = ProfileManager.getInstance(mContext); mObserver = new ProfilesObserver(mHandler); + mKeyguardMonitor = host.getKeyguardMonitor(); + mKeyguardMonitor.addCallback(this); + } + + @Override + protected void handleDestroy() { + mKeyguardMonitor.removeCallback(this); } @Override @@ -82,6 +90,10 @@ public class ProfilesTile extends QSTile<QSTile.State> { @Override protected void handleUpdateState(State state, Object arg) { state.visible = true; + + + + state.enabled = !mKeyguardMonitor.isShowing() || !mKeyguardMonitor.isSecure(); if (profilesEnabled()) { state.icon = ResourceIcon.get(R.drawable.ic_qs_profiles_on); state.label = mProfileManager.getActiveProfile().getName(); @@ -125,6 +137,7 @@ public class ProfilesTile extends QSTile<QSTile.State> { filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_SELECTED); filter.addAction(ProfileManager.INTENT_ACTION_PROFILE_UPDATED); mContext.registerReceiver(mReceiver, filter); + refreshState(); } else { mObserver.endObserving(); mContext.unregisterReceiver(mReceiver); @@ -136,6 +149,11 @@ public class ProfilesTile extends QSTile<QSTile.State> { return new ProfileDetailAdapter(); } + @Override + public void onKeyguardChanged() { + refreshState(); + } + private class ProfileAdapter extends ArrayAdapter<Profile> { public ProfileAdapter(Context context, List<Profile> profiles) { super(context, android.R.layout.simple_list_item_single_choice, profiles); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 03869af..d1d642f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -252,10 +252,17 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView mEmptyView = mEmptyViewStub.inflate(); } mEmptyView.setVisibility(View.VISIBLE); + mEmptyView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dismissRecentsToHome(true); + } + }); mRecentsView.setSearchBarVisibility(View.GONE); } else { if (mEmptyView != null) { mEmptyView.setVisibility(View.GONE); + mEmptyView.setOnClickListener(null); } boolean showSearchBar = CMSettings.System.getInt(getContentResolver(), CMSettings.System.RECENTS_SHOW_SEARCH_BAR, 1) == 1; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 800ee30..ce5cce5 100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -251,6 +251,10 @@ public abstract class BaseStatusBar extends SystemUI implements protected AssistManager mAssistManager; + // last theme that was applied in order to detect theme change (as opposed + // to some other configuration change). + protected ThemeConfig mCurrentTheme; + @Override // NotificationData.Environment public boolean isDeviceProvisioned() { return mDeviceProvisioned; @@ -1341,9 +1345,8 @@ public abstract class BaseStatusBar extends SystemUI implements View contentViewLocal = null; View bigContentViewLocal = null; View headsUpContentViewLocal = null; - final ThemeConfig themeConfig = mContext.getResources().getConfiguration().themeConfig; - String themePackageName = themeConfig != null ? - themeConfig.getOverlayPkgNameForApp(mContext.getPackageName()) : null; + String themePackageName = mCurrentTheme != null ? + mCurrentTheme.getOverlayForStatusBar() : null; try { contentViewLocal = contentView.apply( sbn.getPackageContext(mContext), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index fd84345..318ef5e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -153,6 +153,11 @@ public class KeyguardIndicationController { } } + public void cleanup() { + KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor); + mContext.unregisterReceiver(mReceiver); + } + private void updateIndication() { if (mVisible) { mTextView.switchIndication(computeIndication()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 842d7a4..d38c704 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -136,9 +136,14 @@ public class SignalClusterView public void setSecurityController(SecurityController sc) { if (DEBUG) Log.d(TAG, "SecurityController=" + sc); + if (sc == null && mSC != null) { + mSC.removeCallback(this); + } mSC = sc; - mSC.addCallback(this); - mVpnVisible = mSC.isVpnEnabled(); + if (mSC != null) { + mSC.addCallback(this); + mVpnVisible = mSC.isVpnEnabled(); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java index 47b3463..84eeb31 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ClockController.java @@ -142,4 +142,8 @@ public class ClockController { FontSizeUtils.updateFontSize(mActiveClock, R.dimen.status_bar_clock_size); } } + + public void cleanup() { + mSettingsObserver.unobserve(); + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index f79e051..ecc3a9b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -809,4 +809,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void onChange() { updateCustomShortcuts(); } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mAccessibilityController.removeStateChangedCallback(this); + mContext.unregisterReceiver(mDevicePolicyReceiver); + mShortcutHelper.cleanup(); + mUnlockMethodCache.removeListener(this); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index db378d1..7524732 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -56,6 +56,8 @@ public class KeyguardStatusBarView extends RelativeLayout { private int mSystemIconsSwitcherHiddenExpandedMargin; private Interpolator mFastOutSlowInInterpolator; + private UserInfoController mUserInfoController; + public KeyguardStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -85,6 +87,14 @@ public class KeyguardStatusBarView extends RelativeLayout { com.android.internal.R.dimen.text_size_small_material)); } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mUserInfoController != null) { + mUserInfoController.removeListener(mUserInfoChangedListener); + } + } + private void loadDimens() { mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize( R.dimen.system_icons_switcher_hidden_expanded_margin); @@ -129,13 +139,17 @@ public class KeyguardStatusBarView extends RelativeLayout { mMultiUserSwitch.setUserSwitcherController(controller); } + private UserInfoController.OnUserInfoChangedListener mUserInfoChangedListener = + new UserInfoController.OnUserInfoChangedListener() { + @Override + public void onUserInfoChanged(String name, Drawable picture) { + mMultiUserAvatar.setImageDrawable(picture); + } + }; + public void setUserInfoController(UserInfoController userInfoController) { - userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() { - @Override - public void onUserInfoChanged(String name, Drawable picture) { - mMultiUserAvatar.setImageDrawable(picture); - } - }); + mUserInfoController = userInfoController; + userInfoController.addListener(mUserInfoChangedListener); } public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java index 87f0e8c..7b4d7f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavbarEditor.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.res.Resources; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.os.UserHandle; @@ -90,6 +91,8 @@ public class NavbarEditor implements View.OnTouchListener { // just to avoid reallocations private static final int[] sLocation = new int[2]; + private Resources mResources; + /** * Longpress runnable to assign buttons in edit mode */ @@ -151,11 +154,12 @@ public class NavbarEditor implements View.OnTouchListener { private static final String DEFAULT_SETTING_STRING = "empty|back|home|recent|empty|menu0"; - public NavbarEditor (View parent, boolean orientation, boolean isRtl) { + public NavbarEditor (View parent, boolean orientation, boolean isRtl, Resources res) { mContext = parent.getContext(); mParent = parent; mVertical = orientation; mRtl = isRtl; + mResources = res; mButtonViews = new ArrayList<KeyButtonView>(); @@ -277,7 +281,8 @@ public class NavbarEditor implements View.OnTouchListener { if (!mLongPressed && !view.getTag().equals(NAVBAR_HOME) && !view.getTag().equals(NAVBAR_RECENT) && !view.getTag().equals(NAVBAR_BACK)) { final boolean isSmallButton = ArrayUtils.contains(SMALL_BUTTON_IDS, view.getId()); - final ButtonAdapter list = new ButtonAdapter(mContext, mButtonViews, isSmallButton); + final ButtonAdapter list = new ButtonAdapter(mContext, mButtonViews, isSmallButton, + getResources()); AlertDialog.Builder builder = new AlertDialog.Builder(mContext) .setTitle(mContext.getString(R.string.navbar_dialog_title)) @@ -388,7 +393,7 @@ public class NavbarEditor implements View.OnTouchListener { } } - buttonView.setInfo(button, mVertical, isSmallButton); + buttonView.setInfo(button, mVertical, isSmallButton, getResources()); if (button != NAVBAR_EMPTY && !isSmallButton) { visibleCount++; } @@ -462,6 +467,14 @@ public class NavbarEditor implements View.OnTouchListener { } } + private Resources getResources() { + return mResources != null ? mResources : mContext.getResources(); + } + + public void updateResources(Resources res) { + mResources = res; + } + /** * Class to store info about supported buttons */ @@ -501,9 +514,10 @@ public class NavbarEditor implements View.OnTouchListener { private static class ButtonAdapter extends ArrayAdapter<ButtonInfo> { private ArrayList<ButtonInfo> mTakenItems; + private Resources mResources; public ButtonAdapter(Context context, - ArrayList<KeyButtonView> buttons, boolean smallButtons) { + ArrayList<KeyButtonView> buttons, boolean smallButtons, Resources resources) { super(context, R.layout.navigation_bar_edit_menu_item, R.id.key_text, buildItems(smallButtons)); @@ -514,6 +528,7 @@ public class NavbarEditor implements View.OnTouchListener { mTakenItems.add(info); } } + mResources = resources; } private static List<ButtonInfo> buildItems(boolean smallButtons) { @@ -545,7 +560,7 @@ public class NavbarEditor implements View.OnTouchListener { text.setEnabled(enabled); ImageView icon = (ImageView) view.findViewById(R.id.key_icon); - icon.setImageResource(info.portResource); + icon.setImageDrawable(mResources.getDrawable(info.portResource)); icon.setColorFilter(new PorterDuffColorFilter( text.getCurrentTextColor(), PorterDuff.Mode.SRC_IN)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index a028a7a..b3ba926 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -216,7 +216,7 @@ public class NavigationBarView extends LinearLayout { mDisplay = ((WindowManager)context.getSystemService( Context.WINDOW_SERVICE)).getDefaultDisplay(); - final Resources res = getContext().getResources(); + final Resources res = getResources(); mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size); mVertical = false; mShowMenu = false; @@ -308,7 +308,7 @@ public class NavigationBarView extends LinearLayout { private void getIcons(Resources res) { mBackIcon = new BackButtonDrawable(res.getDrawable(R.drawable.ic_sysbar_back)); - mBackLandIcon = mBackIcon; + mBackLandIcon = mBackIcon; mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent); mRecentLandIcon = mRecentIcon; mHomeIcon = res.getDrawable(R.drawable.ic_sysbar_home); @@ -325,6 +325,9 @@ public class NavigationBarView extends LinearLayout { updateLightsOutResources(container); } } + if (mEditBar != null) { + mEditBar.updateResources(res); + } } private void updateLightsOutResources(ViewGroup container) { @@ -348,7 +351,7 @@ public class NavigationBarView extends LinearLayout { @Override public void setLayoutDirection(int layoutDirection) { - getIcons(mThemedResources != null ? mThemedResources : getContext().getResources()); + getIcons(getResources()); super.setLayoutDirection(layoutDirection); } @@ -606,7 +609,7 @@ public class NavigationBarView extends LinearLayout { } else { mVertical = getWidth() > 0 && getHeight() > getWidth(); } - mEditBar = new NavbarEditor(mCurrentView, mVertical, mIsLayoutRtl); + mEditBar = new NavbarEditor(mCurrentView, mVertical, mIsLayoutRtl, getResources()); updateSettings(); getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener); @@ -700,7 +703,7 @@ public class NavigationBarView extends LinearLayout { private String getResourceName(int resId) { if (resId != 0) { - final android.content.res.Resources res = getContext().getResources(); + final android.content.res.Resources res = getResources(); try { return res.getResourceName(resId); } catch (android.content.res.Resources.NotFoundException ex) { @@ -846,9 +849,9 @@ public class NavigationBarView extends LinearLayout { } } - // TODO LINK TO THIS ONCE THEMES GOES IN - protected void updateResources() { - getIcons(mContext.getResources()); + @Override + public Resources getResources() { + return mThemedResources != null ? mThemedResources : getContext().getResources(); } public class NavBarReceiver extends BroadcastReceiver { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 1536137..bac835c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -80,6 +80,7 @@ import cyanogenmod.externalviews.KeyguardExternalView; import cyanogenmod.providers.CMSettings; import java.util.List; +import java.util.Objects; import org.cyanogenmod.internal.util.CmLockPatternUtils; @@ -283,7 +284,6 @@ public class NotificationPanelView extends PanelView implements mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel); mClockView = (TextView) findViewById(R.id.clock_view); mScrollView = (ObservableScrollView) findViewById(R.id.scroll_view); - mScrollView.setListener(this); mScrollView.setFocusable(false); mReserveNotificationSpace = findViewById(R.id.reserve_notification_space); mNotificationContainerParent = (NotificationsQuickSettingsContainer) @@ -330,6 +330,8 @@ public class NotificationPanelView extends PanelView implements mSettingsObserver.observe(); mContext.registerReceiver(mExternalKeyguardViewChangedReceiver, new IntentFilter(CmLockPatternUtils.ACTION_THIRD_PARTY_KEYGUARD_COMPONENT_CHANGED)); + + mScrollView.setListener(this); } @Override @@ -2688,9 +2690,7 @@ public class NotificationPanelView extends PanelView implements private void updateExternalKeyguardView() { ComponentName cn = mLockPatternUtils.getThirdPartyKeyguardComponent(); // If mThirdPartyKeyguardViewComponent differs from cn, go ahead and update - if ((cn == null && mThirdPartyKeyguardViewComponent != null) || - (cn != null && mThirdPartyKeyguardViewComponent == null) || - !mThirdPartyKeyguardViewComponent.equals(cn)) { + if (!Objects.equals(mThirdPartyKeyguardViewComponent, cn)) { mThirdPartyKeyguardViewComponent = cn; if (mKeyguardExternalView != null) { if (indexOfChild(mKeyguardExternalView) >= 0) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index e1a400d..82b1e1d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -146,6 +146,16 @@ public abstract class PanelBar extends FrameLayout { return result; } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (PanelView pv : mPanels) { + pv.setBar(null); + } + mPanels.clear(); + mPanelHolder.setBar(null); + } + // called from PanelView when self-expanding, too public void startOpeningPanel(PanelView panel) { if (DEBUG) LOG("startOpeningPanel: " + panel); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index b93c17a..6e104ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -136,6 +136,7 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSDragPanel; import com.android.systemui.qs.QSPanel; +import com.android.systemui.qs.QSTile; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.settings.BrightnessController; import com.android.systemui.statusbar.ActivatableNotificationView; @@ -395,9 +396,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, int mInitialTouchX; int mInitialTouchY; - // last theme that was applied in order to detect theme change (as opposed - // to some other configuration change). - ThemeConfig mCurrentTheme; private boolean mRecreating = false; // for disabling the status bar @@ -1166,7 +1164,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mSecurityController); } mQSPanel.setHost(mQSTileHost); - mQSPanel.setTiles(mQSTileHost.getTiles()); if (mBrightnessMirrorController == null) { mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindowContent); } @@ -1209,6 +1206,40 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }, 500); } + + @Override + public void resetTiles() { + mHandler.post(new Runnable() { + @Override + public void run() { + mQSPanel.setEditing(false); + mHeader.setEditing(false); + + // unregister custom tile service while we reset to not get + // callbacks from custom tiles + try { + mCustomTileListenerService.unregisterAsSystemService(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to unregister custom tile listener", e); + } + + // clear out old tile states and views + mQSPanel.setTiles(new ArrayList<QSTile<?>>()); + + mQSTileHost.resetTiles(); + + // reregister service + try { + mCustomTileListenerService.registerAsSystemService(mContext, + new ComponentName(mContext.getPackageName(), + PhoneStatusBar.this.getClass().getCanonicalName()), + UserHandle.USER_ALL); + } catch (RemoteException e) { + Log.e(TAG, "Unable to register custom tile listener", e); + } + } + }); + } }); } @@ -3481,6 +3512,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, else if (Intent.ACTION_SCREEN_ON.equals(action)) { mScreenOn = true; notifyNavigationBarScreenOn(true); + } else if (Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED.equals(action)) { + WallpaperManager wm = (WallpaperManager) mContext.getSystemService( + Context.WALLPAPER_SERVICE); + mKeyguardWallpaper = wm.getKeyguardBitmap(); + updateMediaMetaData(true); } } }; @@ -3633,6 +3669,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, networkController.removeSignalCallback(signalCluster); networkController.removeSignalCallback(signalClusterKeyguard); networkController.removeSignalCallback(signalClusterQs); + + if (signalCluster != null) signalCluster.setSecurityController(null); + if (signalClusterKeyguard != null) signalClusterKeyguard.setSecurityController(null); + if (signalClusterQs != null) signalClusterQs.setSecurityController(null); } private void recreateStatusBar() { @@ -3640,9 +3680,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mNetworkController != null) { removeSignalCallbacks(mNetworkController); + if (mNetworkController.hasVoiceCallingFeature()) { + mNetworkController.removeEmergencyListener(mHeader); + } } if (mHeadsUpManager != null) { mHeadsUpManager.removeListener(mNotificationPanel); + mHeadsUpManager.removeListener(mScrimController); + } + if (mIconController != null) { + mIconController.cleanup(); + } + if (mKeyguardIndicationController != null) { + mKeyguardIndicationController.cleanup(); } mStatusBarWindow.removeContent(mStatusBarWindowContent); @@ -3664,10 +3714,27 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // extract notifications. RankingMap rankingMap = mNotificationData.getRankingMap(); int nNotifs = mNotificationData.size(); - ArrayList<Pair<String, StatusBarNotification>> notifications = - new ArrayList<Pair<String, StatusBarNotification>>(nNotifs); + ArrayList<Pair<String, StatusBarNotification>> notifications = new ArrayList<>(nNotifs); copyNotifications(notifications, mNotificationData); - mNotificationData.clear(); + // now remove all the notification views since we'll be re-inflating these with the copied + // data + for (int i = 0; i < nNotifs; i++) { + final NotificationData.Entry entry = mNotificationData.get(i); + if (entry != null) { + removeNotificationViews(entry.key, rankingMap); + } + } + + if (mCustomTileListenerService != null) { + try { + mCustomTileListenerService.unregisterAsSystemService(); + } catch (RemoteException e) { + Log.e(TAG, "Unable to unregister custom tile listener", e); + } + } + + mQSPanel.getHost().setCustomTileListenerService(null); + mQSPanel.setTiles(new ArrayList<QSTile<?>>()); makeStatusBarView(); repositionNavigationBar(); @@ -3695,15 +3762,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Stop the command queue until the new status bar container settles and has a layout pass mCommandQueue.pause(); - if (mCustomTileListenerService != null) { - try { - mCustomTileListenerService.unregisterAsSystemService(); - } catch (RemoteException e) { - Log.e(TAG, "Unable to unregister custom tile listener", e); - } - } - - mQSPanel.getHost().setCustomTileListenerService(null); + // fix notification panel being shifted to the left by calling + // instantCollapseNotificationPanel() + instantCollapseNotificationPanel(); mStatusBarWindow.requestLayout(); mStatusBarWindow.getViewTreeObserver().addOnGlobalLayoutListener( @@ -3711,6 +3772,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override public void onGlobalLayout() { mStatusBarWindow.getViewTreeObserver().removeOnGlobalLayoutListener(this); + mQSPanel.setTiles(mQSTileHost.getTiles()); mCommandQueue.resume(); mRecreating = false; } @@ -3750,7 +3812,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, final boolean updateNavBar = shouldUpdateNavbar(mCurrentTheme, newTheme); if (newTheme != null) mCurrentTheme = (ThemeConfig) newTheme.clone(); if (updateStatusBar) { - mContext.recreateTheme(); recreateStatusBar(); } else { loadDimens(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index c3428bb..c4ce350 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -40,6 +40,7 @@ import com.android.systemui.qs.QSTile; import com.android.systemui.qs.tiles.AdbOverNetworkTile; import com.android.systemui.qs.tiles.AirplaneModeTile; import com.android.systemui.qs.tiles.AmbientDisplayTile; +import com.android.systemui.qs.tiles.BatterySaverTile; import com.android.systemui.qs.tiles.BluetoothTile; import com.android.systemui.qs.tiles.CastTile; import com.android.systemui.qs.tiles.CellularTile; @@ -49,6 +50,7 @@ import com.android.systemui.qs.tiles.CustomQSTile; import com.android.systemui.qs.tiles.DndTile; import com.android.systemui.qs.tiles.EditTile; import com.android.systemui.qs.tiles.FlashlightTile; +import com.android.systemui.qs.tiles.HeadsUpTile; import com.android.systemui.qs.tiles.HotspotTile; import com.android.systemui.qs.tiles.IntentTile; import com.android.systemui.qs.tiles.LiveDisplayTile; @@ -359,6 +361,8 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (tileSpec.equals("lockscreen")) return new LockscreenToggleTile(this); else if (tileSpec.equals("ambient_display")) return new AmbientDisplayTile(this); else if (tileSpec.equals("live_display")) return new LiveDisplayTile(this); + else if (tileSpec.equals("heads_up")) return new HeadsUpTile(this); + else if (tileSpec.equals("battery_saver")) return new BatterySaverTile(this); else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec); else throw new IllegalArgumentException("Bad tile spec: " + tileSpec); } @@ -409,9 +413,14 @@ public class QSTileHost implements QSTile.Host, Tunable { TextUtils.join(",", tiles), ActivityManager.getCurrentUser()); } + public void initiateReset() { + if (mCallback != null) { + mCallback.resetTiles(); + } + } + @Override public void resetTiles() { - setEditing(false); CMSettings.Secure.putStringForUser(getContext().getContentResolver(), CMSettings.Secure.QS_TILES, "default", ActivityManager.getCurrentUser()); } @@ -445,6 +454,8 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (spec.equals("lockscreen")) return R.string.quick_settings_lockscreen_label; else if (spec.equals("ambient_display")) return R.string.quick_settings_ambient_display_label; else if (spec.equals("live_display")) return R.string.live_display_title; + else if (spec.equals("heads_up")) return R.string.quick_settings_heads_up_label; + else if (spec.equals("battery_saver")) return R.string.quick_settings_battery_saver_label; return 0; } @@ -473,6 +484,8 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (spec.equals("lockscreen")) return R.drawable.ic_qs_lock_screen_on; else if (spec.equals("ambient_display")) return R.drawable.ic_qs_ambientdisplay_on; else if (spec.equals("live_display")) return R.drawable.ic_livedisplay_auto; + else if (spec.equals("heads_up")) return R.drawable.ic_qs_heads_up_on; + else if (spec.equals("battery_saver")) return R.drawable.ic_qs_battery_saver_on; return 0; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index f83fbea..a6593f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -161,6 +161,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private QSTile.DetailAdapter mEditingDetailAdapter; private boolean mEditing; + private UserInfoController mUserInfoController; + public StatusBarHeaderView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -272,6 +274,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL updateClockCollapsedMargin(); } + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mUserInfoController != null) { + mUserInfoController.removeListener(mUserInfoChangedListener); + } + setListening(false); + } + private void updateClockCollapsedMargin() { Resources res = getResources(); int padding = res.getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin); @@ -551,13 +562,17 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL invalidateOutline(); } + private UserInfoController.OnUserInfoChangedListener mUserInfoChangedListener = + new UserInfoController.OnUserInfoChangedListener() { + @Override + public void onUserInfoChanged(String name, Drawable picture) { + mMultiUserAvatar.setImageDrawable(picture); + } + }; + public void setUserInfoController(UserInfoController userInfoController) { - userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() { - @Override - public void onUserInfoChanged(String name, Drawable picture) { - mMultiUserAvatar.setImageDrawable(picture); - } - }); + mUserInfoController = userInfoController; + userInfoController.addListener(mUserInfoChangedListener); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 0c68785..a7fa27d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -486,6 +486,14 @@ public class StatusBarIconController implements Tunable { return mStatusIcons; } + public void cleanup() { + TunerService.get(mContext).removeTunable(this); + mClockController.cleanup(); + if (mSignalCluster != null) { + mSignalCluster.setSecurityController(null); + } + } + private void refreshAllIconsForLayout(LinearLayout ll) { final int count = ll.getChildCount(); for (int n = 0; n < count; n++) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index f6a4566..6fef3d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -192,6 +192,11 @@ public class KeyButtonView extends ImageView { public void setInfo(NavbarEditor.ButtonInfo item, boolean isVertical, boolean isSmall) { final Resources res = getResources(); + setInfo(item, isVertical, isSmall, res); + } + + public void setInfo(NavbarEditor.ButtonInfo item, boolean isVertical, boolean isSmall, + Resources res) { final int keyDrawableResId; setTag(item); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 78507be..7e1bf05 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -245,6 +245,10 @@ public class NetworkControllerImpl extends BroadcastReceiver mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly()); } + public void removeEmergencyListener(EmergencyListener listener) { + mCallbackHandler.setListening(listener, false); + } + public boolean hasMobileDataFeature() { return mHasMobileDataFeature; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java index a8d4f13..7fdf62c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java @@ -73,6 +73,10 @@ public final class UserInfoController { mCallbacks.add(callback); } + public void removeListener (OnUserInfoChangedListener callback) { + mCallbacks.remove(callback); + } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java index b186323..9d63d08 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java @@ -155,6 +155,10 @@ public class QsTuner extends Fragment implements Callback { public void goToSettingsPage() { } + @Override + public void resetTiles() { + } + private static class CustomHost extends QSTileHost { public CustomHost(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index 003662b..aa2f0d3 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -31,6 +31,7 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Color; import android.graphics.PixelFormat; +import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.ColorDrawable; @@ -164,7 +165,7 @@ public class VolumeDialog { window.setAttributes(lp); window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); - mActiveSliderTint = loadColorStateList(R.color.system_accent_color); + mActiveSliderTint = loadColorStateList(R.color.volume_slider_active); mInactiveSliderTint = loadColorStateList(R.color.volume_slider_inactive); mDialog.setContentView(R.layout.volume_dialog); mDialogView = (ViewGroup) mDialog.findViewById(R.id.volume_dialog); @@ -363,6 +364,8 @@ public class VolumeDialog { row.header = (TextView) row.view.findViewById(R.id.volume_row_header); mSpTexts.add(row.header); row.slider = (SeekBar) row.view.findViewById(R.id.volume_row_slider); + row.slider.setProgressTintMode(PorterDuff.Mode.SRC_ATOP); + row.slider.setThumbTintMode(PorterDuff.Mode.SRC_ATOP); row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row)); // forward events above the slider into the slider |