Move tuner enable point to QS

Long clicking on settings gear in QS causes it to accelarate and
spin, when released it will open and enable the tuner.  On first
opening there will be a warning dialog.

Also add way to disable tuner from tuner screen. This way it can
be removed from its former home in Developer Settings.  All tuner
settings are reset when disabled to match developer settings
behavior.

Bug: 22462605
Change-Id: Ie700a6a15e6c3caccf7cd1885da73328e6fac6ab
This commit is contained in:
Jason Monk
2015-07-16 08:58:15 -04:00
parent 2ba3fec6e0
commit 431ad737a4
13 changed files with 404 additions and 34 deletions

View File

@@ -405,5 +405,13 @@
android:exported="true"
android:singleUser="true"
android:permission="android.permission.BIND_DREAM_SERVICE" />
<receiver
android:name=".tuner.TunerService$ClearReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.android.systemui.action.CLEAR_TUNER" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@@ -1,7 +1,7 @@
<!--
Copyright (C) 2015 The Android Open Source Project
Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
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
@@ -14,14 +14,11 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48.0dp"
android:height="48.0dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M29.9,24.8c0.0,-0.3 0.1,-0.5 0.1,-0.8s0.0,-0.5 -0.1,-0.8l1.7,-1.3c0.2,-0.1 0.2,-0.3 0.1,-0.5l-1.6,-2.8c-0.1,-0.2 -0.3,-0.2 -0.5,-0.2l-2.0,0.8c-0.4,-0.3 -0.9,-0.6 -1.4,-0.8L26.0,16.3c0.0,-0.2 -0.2,-0.3 -0.4,-0.3l-3.2,0.0c-0.2,0.0 -0.4,0.1 -0.4,0.3l-0.3,2.1c-0.5,0.2 -0.9,0.5 -1.4,0.8l-2.0,-0.8c-0.2,-0.1 -0.4,0.0 -0.5,0.2l-1.6,2.8c-0.1,0.2 -0.1,0.4 0.1,0.5l1.7,1.3c0.0,0.3 -0.1,0.5 -0.1,0.8s0.0,0.5 0.1,0.8l-1.7,1.3c-0.2,0.1 -0.2,0.3 -0.1,0.5l1.6,2.8c0.1,0.2 0.3,0.2 0.5,0.2l2.0,-0.8c0.4,0.3 0.9,0.6 1.4,0.8l0.3,2.1c0.0,0.2 0.2,0.3 0.4,0.3l3.2,0.0c0.2,0.0 0.4,-0.1 0.4,-0.3l0.3,-2.1c0.5,-0.2 0.9,-0.5 1.4,-0.8l2.0,0.8c0.2,0.1 0.4,0.0 0.5,-0.2l1.6,-2.8c0.1,-0.2 0.1,-0.4 -0.1,-0.5L29.9,24.8zM24.0,26.8c-1.5,0.0 -2.8,-1.3 -2.8,-2.8s1.3,-2.8 2.8,-2.8s2.8,1.3 2.8,2.8S25.5,26.8 24.0,26.8z"/>
<path
android:fillColor="#FF000000"
android:pathData="M18.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S18.6,38.0 18.0,38.0zM24.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S24.6,38.0 24.0,38.0zM30.0,38.0c-0.6,0.0 -1.0,-0.4 -1.0,-1.0s0.4,-1.0 1.0,-1.0s1.0,0.4 1.0,1.0S30.6,38.0 30.0,38.0zM42.0,6.0L6.0,6.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,28.0c0.0,2.2 1.8,4.0 4.0,4.0l36.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,10.0C46.0,7.8 44.2,6.0 42.0,6.0zM42.0,34.0L6.0,34.0L6.0,14.0l36.0,0.0L42.0,34.0zM9.0,12.0L7.0,12.0l0.0,-2.0l2.0,0.0L9.0,12.0zM13.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0L13.0,12.0zM17.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0L17.0,12.0z"/>
android:fillColor="#FFFFFFFF"
android:pathData="M22.7,19.0l-9.1,-9.1c0.9,-2.0 0.4,-5.0 -1.5,-6.9 -2.0,-2.0 -5.0,-2.4 -7.4,-1.3L9.0,6.0 6.0,9.0 1.6,4.7C0.4,7.0 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1.0,0.4 1.4,0.0l2.3,-2.3c0.5,-0.4 0.5,-1.0 0.1,-1.4z"/>
</vector>

View File

@@ -44,14 +44,31 @@
android:scaleType="centerInside"/>
</com.android.systemui.statusbar.phone.MultiUserSwitch>
<com.android.keyguard.AlphaOptimizedImageButton android:id="@+id/settings_button"
style="@android:style/Widget.Material.Button.Borderless"
android:layout_toStartOf="@id/multi_user_switch"
<com.android.keyguard.AlphaOptimizedLinearLayout
android:id="@+id/settings_button_container"
android:layout_width="48dp"
android:layout_height="@dimen/status_bar_header_height"
android:background="@drawable/ripple_drawable"
android:src="@drawable/ic_settings"
android:contentDescription="@string/accessibility_desc_settings" />
android:paddingStart="12dp"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_toStartOf="@id/multi_user_switch">
<com.android.systemui.statusbar.phone.SettingsButton android:id="@+id/settings_button"
style="@android:style/Widget.Material.Button.Borderless"
android:layout_width="24dp"
android:layout_height="@dimen/status_bar_header_height"
android:background="@drawable/ripple_drawable"
android:src="@drawable/ic_settings"
android:contentDescription="@string/accessibility_desc_settings" />
<com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/tuner_icon"
android:layout_width="12dp"
android:layout_height="@dimen/status_bar_header_height"
android:tint="#4DFFFFFF"
android:tintMode="src_in"
android:visibility="invisible"
android:src="@drawable/tuner" />
</com.android.keyguard.AlphaOptimizedLinearLayout>
<LinearLayout android:id="@+id/system_icons_super_container"
android:layout_width="wrap_content"

View File

@@ -1032,7 +1032,7 @@
<string name="volume_stream_vibrate_dnd" translatable="false">%s vibrate — Priority only</string>
<!-- Name of special SystemUI debug settings -->
<string name="system_ui_tuner">System UI tuner</string>
<string name="system_ui_tuner">System UI Tuner</string>
<!-- Preference to show/hide embedded battery percentage [CHAR LIMIT=50] -->
<string name="show_battery_percentage">Show embedded battery percentage</string>
@@ -1099,4 +1099,25 @@
<!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
<string name="accessibility_managed_profile">Work profile</string>
<!-- Title of warning when entering System UI tuner for first time [CHAR LIMIT=NONE] -->
<string name="tuner_warning_title">Fun for some but not for all</string>
<!-- Warning for users entering the System UI tuner for the first time [CHAR LIMIT=NONE]-->
<string name="tuner_warning">System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution.</string>
<!-- Warning for users entering the System UI tuner [CHAR LIMIT=NONE]-->
<string name="tuner_persistent_warning">These experimental features may change, break, or disappear in future releases. Proceed with caution.</string>
<!-- Generic "got it" acceptance of dialog or cling [CHAR LIMIT=NONE] -->
<string name="got_it">Got it</string>
<!-- Toast describing tuner has been enabled [CHAR LIMIT=NONE] -->
<string name="tuner_toast">Congrats! System UI Tuner has been added to Settings</string>
<!-- Option to remove the tuner from settings [CHAR LIMIT=NONE] -->
<string name="remove_from_settings">Remove from Settings</string>
<!-- Dialog asking if the tuner should really be removed from settings [CHAR LIMIT=NONE]-->
<string name="remove_from_settings_prompt">Remove System UI Tuner from Settings and stop using all of its features?"</string>
</resources>

View File

@@ -76,4 +76,8 @@
android:key="demo_mode"
android:title="@string/demo_mode" />
<Preference
android:summary="@string/tuner_persistent_warning"
android:selectable="false" />
</PreferenceScreen>

View File

@@ -20,6 +20,8 @@ import android.os.Bundle;
public interface DemoMode {
public static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed";
void dispatchDemoCommand(String command, Bundle args);
public static final String ACTION_DEMO = "com.android.systemui.demo";

View File

@@ -3211,7 +3211,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoModeAllowed) {
mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(),
"sysui_demo_allowed", 0) != 0;
DEMO_MODE_ALLOWED, 0) != 0;
}
if (!mDemoModeAllowed) return;
if (command.equals(COMMAND_ENTER)) {

View File

@@ -0,0 +1,174 @@
/*
* Copyright (C) 2015 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.
*/
package com.android.systemui.statusbar.phone;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.android.keyguard.AlphaOptimizedImageButton;
public class SettingsButton extends AlphaOptimizedImageButton {
private static final long LONG_PRESS_LENGTH = 1000;
private static final long ACCEL_LENGTH = 750;
private static final long FULL_SPEED_LENGTH = 375;
private static final long RUN_DURATION = 350;
private boolean mUpToSpeed;
private ObjectAnimator mAnimator;
private float mSlop;
public SettingsButton(Context context, AttributeSet attrs) {
super(context, attrs);
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
public boolean isAnimating() {
return mAnimator != null && mAnimator.isRunning();
}
public boolean isTunerClick() {
return mUpToSpeed;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
postDelayed(mLongPressCallback, LONG_PRESS_LENGTH);
break;
case MotionEvent.ACTION_UP:
if (mUpToSpeed) {
startExitAnimation();
} else {
cancelLongClick();
}
break;
case MotionEvent.ACTION_CANCEL:
cancelLongClick();
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
if ((x < -mSlop) || (y < -mSlop) || (x > getWidth() + mSlop)
|| (y > getHeight() + mSlop)) {
cancelLongClick();
}
break;
}
return super.onTouchEvent(event);
}
private void cancelLongClick() {
cancelAnimation();
mUpToSpeed = false;
removeCallbacks(mLongPressCallback);
}
private void cancelAnimation() {
if (mAnimator != null) {
mAnimator.removeAllListeners();
mAnimator.cancel();
mAnimator = null;
}
}
private void startExitAnimation() {
animate()
.translationX(((View) getParent().getParent()).getWidth() - getX())
.alpha(0)
.setDuration(RUN_DURATION)
.setInterpolator(AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.accelerate_cubic))
.setListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
setAlpha(1f);
setTranslationX(0);
cancelLongClick();
}
@Override
public void onAnimationCancel(Animator animation) {
}
})
.start();
}
protected void startAccelSpin() {
cancelAnimation();
mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360);
mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.accelerate_quad));
mAnimator.setDuration(ACCEL_LENGTH);
mAnimator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
startContinuousSpin();
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
mAnimator.start();
}
protected void startContinuousSpin() {
cancelAnimation();
mUpToSpeed = true;
mAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, 0, 360);
mAnimator.setInterpolator(AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear));
mAnimator.setDuration(FULL_SPEED_LENGTH);
mAnimator.setRepeatCount(Animation.INFINITE);
mAnimator.start();
}
private final Runnable mLongPressCallback = new Runnable() {
@Override
public void run() {
startAccelSpin();
}
};
}

View File

@@ -37,6 +37,7 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.BatteryMeterView;
@@ -48,6 +49,7 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.tuner.TunerService;
import java.text.NumberFormat;
@@ -73,7 +75,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private TextView mDateExpanded;
private LinearLayout mSystemIcons;
private View mSignalCluster;
private View mSettingsButton;
private SettingsButton mSettingsButton;
private View mSettingsContainer;
private View mQsDetailHeader;
private TextView mQsDetailHeaderTitle;
private Switch mQsDetailHeaderSwitch;
@@ -142,7 +145,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
mDateCollapsed = (TextView) findViewById(R.id.date_collapsed);
mDateExpanded = (TextView) findViewById(R.id.date_expanded);
mSettingsButton = findViewById(R.id.settings_button);
mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
mSettingsContainer = findViewById(R.id.settings_button_container);
mSettingsButton.setOnClickListener(this);
mQsDetailHeader = findViewById(R.id.qs_detail_header);
mQsDetailHeader.setAlpha(0);
@@ -323,13 +327,15 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mDateCollapsed.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
mDateExpanded.setVisibility(mExpanded && mAlarmShowing ? View.INVISIBLE : View.VISIBLE);
mAlarmStatus.setVisibility(mExpanded && mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
mSettingsContainer.setVisibility(mExpanded ? View.VISIBLE : View.INVISIBLE);
mQsDetailHeader.setVisibility(mExpanded && mShowingDetail? View.VISIBLE : View.INVISIBLE);
if (mSignalCluster != null) {
updateSignalClusterDetachment();
}
mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE);
mBatteryLevel.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
}
private void updateSignalClusterDetachment() {
@@ -352,7 +358,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private void updateSystemIconsLayoutParams() {
RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
int rule = mExpanded
? mSettingsButton.getId()
? mSettingsContainer.getId()
: mMultiUserSwitch.getId();
if (rule != lp.getRules()[RelativeLayout.START_OF]) {
lp.addRule(RelativeLayout.START_OF, rule);
@@ -495,6 +501,20 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
@Override
public void onClick(View v) {
if (v == mSettingsButton) {
if (mSettingsButton.isTunerClick()) {
if (TunerService.isTunerEnabled(mContext)) {
TunerService.showResetRequest(mContext, new Runnable() {
@Override
public void run() {
// Relaunch settings so that the tuner disappears.
startSettingsActivity();
}
});
} else {
Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
TunerService.setTunerEnabled(mContext, true);
}
}
startSettingsActivity();
} else if (v == mSystemIconsSuperContainer) {
startBatteryActivity();
@@ -567,10 +587,10 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
}
target.batteryY = mSystemIconsSuperContainer.getTop() + mSystemIconsContainer.getTop();
target.batteryLevelAlpha = getAlphaForVisibility(mBatteryLevel);
target.settingsAlpha = getAlphaForVisibility(mSettingsButton);
target.settingsAlpha = getAlphaForVisibility(mSettingsContainer);
target.settingsTranslation = mExpanded
? 0
: mMultiUserSwitch.getLeft() - mSettingsButton.getLeft();
: mMultiUserSwitch.getLeft() - mSettingsContainer.getLeft();
target.signalClusterAlpha = mSignalClusterDetached ? 0f : 1f;
target.settingsRotation = !mExpanded ? 90f : 0f;
}
@@ -622,9 +642,11 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mSignalCluster.setTranslationX(0f);
mSignalCluster.setTranslationY(0f);
}
mSettingsButton.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
mSettingsButton.setTranslationX(values.settingsTranslation);
mSettingsButton.setRotation(values.settingsRotation);
if (!mSettingsButton.isAnimating()) {
mSettingsContainer.setTranslationY(mSystemIconsSuperContainer.getTranslationY());
mSettingsContainer.setTranslationX(values.settingsTranslation);
mSettingsButton.setRotation(values.settingsRotation);
}
applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
if (!mShowingDetail && !mDetailTransitioning) {
// Otherwise it needs to stay invisible
@@ -633,7 +655,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
applyAlpha(mDateExpanded, values.dateExpandedAlpha);
applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
applyAlpha(mSettingsButton, values.settingsAlpha);
applyAlpha(mSettingsContainer, values.settingsAlpha);
applyAlpha(mSignalCluster, values.signalClusterAlpha);
if (!mExpanded) {
mTime.setScaleX(1f);

View File

@@ -28,13 +28,13 @@ import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.view.MenuItem;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {
private static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed";
private static final String DEMO_MODE_ON = "sysui_tuner_demo_on";
private static final String[] STATUS_ICONS = {
@@ -75,10 +75,21 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
updateDemoModeEnabled();
updateDemoModeOn();
ContentResolver contentResolver = getContext().getContentResolver();
contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ALLOWED), false,
mDemoModeObserver);
contentResolver.registerContentObserver(Settings.Global.getUriFor(
DemoMode.DEMO_MODE_ALLOWED), false, mDemoModeObserver);
contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ON), false,
mDemoModeObserver);
setHasOptionsMenu(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getFragmentManager().popBackStack();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
@@ -89,7 +100,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
private void updateDemoModeEnabled() {
boolean enabled = Settings.Global.getInt(getContext().getContentResolver(),
DEMO_MODE_ALLOWED, 0) != 0;
DemoMode.DEMO_MODE_ALLOWED, 0) != 0;
mEnabledSwitch.setChecked(enabled);
mOnSwitch.setEnabled(enabled);
}
@@ -108,7 +119,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference
mOnSwitch.setChecked(false);
stopDemoMode();
}
setGlobal(DEMO_MODE_ALLOWED, newValue == Boolean.TRUE ? 1 : 0);
setGlobal(DemoMode.DEMO_MODE_ALLOWED, newValue == Boolean.TRUE ? 1 : 0);
} else if (preference == mOnSwitch) {
if (newValue == Boolean.TRUE) {
startDemoMode();

View File

@@ -85,6 +85,9 @@ public class QsTuner extends Fragment implements Callback {
case MENU_RESET:
mTileHost.reset();
break;
case android.R.id.home:
getFragmentManager().popBackStack();
break;
}
return super.onOptionsItemSelected(item);
}

View File

@@ -17,7 +17,10 @@ package com.android.systemui.tuner;
import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
@@ -28,7 +31,10 @@ import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.provider.Settings.System;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.systemui.R;
@@ -37,10 +43,16 @@ import com.android.systemui.tuner.TunerService.Tunable;
public class TunerFragment extends PreferenceFragment {
private static final String TAG = "TunerFragment";
private static final String KEY_QS_TUNER = "qs_tuner";
private static final String KEY_DEMO_MODE = "demo_mode";
private static final String KEY_BATTERY_PCT = "battery_pct";
public static final String SETTING_SEEN_TUNER_WARNING = "seen_tuner_warning";
private static final int MENU_REMOVE = Menu.FIRST + 1;
private final SettingObserver mSettingObserver = new SettingObserver();
private SwitchPreference mBatteryPct;
@@ -73,6 +85,19 @@ public class TunerFragment extends PreferenceFragment {
}
});
mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT);
if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,
0) == 0) {
new AlertDialog.Builder(getContext())
.setTitle(R.string.tuner_warning_title)
.setMessage(R.string.tuner_warning)
.setPositiveButton(R.string.got_it, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Settings.Secure.putInt(getContext().getContentResolver(),
SETTING_SEEN_TUNER_WARNING, 1);
}
}).show();
}
}
@Override
@@ -119,12 +144,25 @@ public class TunerFragment extends PreferenceFragment {
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(Menu.NONE, MENU_REMOVE, Menu.NONE, R.string.remove_from_settings);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getActivity().finish();
return true;
case MENU_REMOVE:
TunerService.showResetRequest(getContext(), new Runnable() {
@Override
public void run() {
getActivity().finish();
}
});
return true;
}
return super.onOptionsItemSelected(item);
}

View File

@@ -16,8 +16,15 @@
package com.android.systemui.tuner;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
@@ -25,9 +32,13 @@ import android.os.Looper;
import android.provider.Settings;
import android.util.ArrayMap;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.util.ArrayList;
import java.util.HashMap;
@@ -36,6 +47,8 @@ import java.util.List;
public class TunerService extends SystemUI {
public static final String ACTION_CLEAR = "com.android.systemui.action.CLEAR_TUNER";
private final Observer mObserver = new Observer();
// Map of Uris we listen on to their settings keys.
private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
@@ -118,6 +131,19 @@ public class TunerService extends SystemUI {
}
}
public void clearAll() {
// A couple special cases.
Settings.Global.putString(mContentResolver, DemoMode.DEMO_MODE_ALLOWED, null);
Settings.System.putString(mContentResolver, BatteryMeterView.SHOW_PERCENT_SETTING, null);
Intent intent = new Intent(DemoMode.ACTION_DEMO);
intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
mContext.sendBroadcast(intent);
for (String key : mTunableLookup.keySet()) {
Settings.Secure.putString(mContentResolver, key, null);
}
}
// Only used in other processes, such as the tuner.
private static TunerService sInstance;
@@ -141,6 +167,44 @@ public class TunerService extends SystemUI {
return sInstance;
}
public static final void showResetRequest(final Context context, final Runnable onDisabled) {
SystemUIDialog dialog = new SystemUIDialog(context);
dialog.setMessage(R.string.remove_from_settings_prompt);
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel),
(OnClickListener) null);
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Tell the tuner (in main SysUI process) to clear all its settings.
context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
// Disable access to tuner.
TunerService.setTunerEnabled(context, false);
// Make them sit through the warning dialog again.
Settings.Secure.putInt(context.getContentResolver(),
TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
if (onDisabled != null) {
onDisabled.run();
}
}
});
dialog.show();
}
public static final void setTunerEnabled(Context context, boolean enabled) {
context.getPackageManager().setComponentEnabledSetting(
new ComponentName(context, TunerActivity.class),
enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
public static final boolean isTunerEnabled(Context context) {
return context.getPackageManager().getComponentEnabledSetting(
new ComponentName(context, TunerActivity.class))
== PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
}
private class Observer extends ContentObserver {
public Observer() {
super(new Handler(Looper.getMainLooper()));
@@ -157,4 +221,13 @@ public class TunerService extends SystemUI {
public interface Tunable {
void onTuningChanged(String key, String newValue);
}
public static class ClearReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_CLEAR.equals(intent.getAction())) {
get(context).clearAll();
}
}
}
}