summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2011-12-05 19:58:48 -0800
committerAmith Yamasani <yamasani@google.com>2011-12-06 14:48:38 -0800
commit6243edd818b84adfbe712d5d233d6414b33653ac (patch)
tree8f6ee51bc79caa36157a05bed45dc7c22805a9bf
parent40cb30c2df2176c03f24cbdc194e3af5a4f64758 (diff)
downloadframeworks_base-6243edd818b84adfbe712d5d233d6414b33653ac.zip
frameworks_base-6243edd818b84adfbe712d5d233d6414b33653ac.tar.gz
frameworks_base-6243edd818b84adfbe712d5d233d6414b33653ac.tar.bz2
New and improved silent mode on lockscreen.
3-state item to toggle between Silent/Vibrate/Ringer in long-press power menu. No volume dialog on lockscreen, unless Power menu is up. Set VIBRATE_IN_SILENT=1 when upgrading device. Change-Id: I097d216f96c4abdbd83420e0c477106951b3607d
-rw-r--r--core/res/res/drawable/silent_mode_indicator.xml20
-rw-r--r--core/res/res/layout/global_actions_item.xml4
-rw-r--r--core/res/res/layout/global_actions_silent_mode.xml97
-rw-r--r--media/java/android/media/AudioService.java10
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java20
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java185
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewBase.java2
7 files changed, 267 insertions, 71 deletions
diff --git a/core/res/res/drawable/silent_mode_indicator.xml b/core/res/res/drawable/silent_mode_indicator.xml
new file mode 100644
index 0000000..c4e129f
--- /dev/null
+++ b/core/res/res/drawable/silent_mode_indicator.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="false" android:drawable="@android:color/transparent" />
+ <item android:state_selected="true" android:drawable="@drawable/tab_selected_holo" />
+</selector>
diff --git a/core/res/res/layout/global_actions_item.xml b/core/res/res/layout/global_actions_item.xml
index 13ab985..694301e 100644
--- a/core/res/res/layout/global_actions_item.xml
+++ b/core/res/res/layout/global_actions_item.xml
@@ -22,7 +22,7 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
- android:paddingLeft="11dip"
+ android:paddingLeft="16dip"
android:paddingTop="6dip"
android:paddingBottom="6dip"
>
@@ -30,7 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
- android:layout_marginRight="9dip"
+ android:layout_marginRight="16dip"
/>
<LinearLayout
diff --git a/core/res/res/layout/global_actions_silent_mode.xml b/core/res/res/layout/global_actions_silent_mode.xml
new file mode 100644
index 0000000..09b4341
--- /dev/null
+++ b/core/res/res/layout/global_actions_silent_mode.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="horizontal"
+ >
+
+ <LinearLayout
+ android:id="@+id/option1"
+ android:layout_width="64dp"
+ android:layout_height="match_parent"
+ android:background="?android:attr/actionBarItemBackground"
+ >
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:src="@drawable/ic_audio_vol_mute"
+ android:scaleType="center"
+ android:duplicateParentState="true"
+ android:background="@drawable/silent_mode_indicator"
+ />
+ </LinearLayout>
+ <!-- Spacer -->
+ <View android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible"/>
+
+ <LinearLayout
+ android:id="@+id/option2"
+ android:layout_width="64dp"
+ android:layout_height="match_parent"
+ android:background="?android:attr/actionBarItemBackground"
+ >
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:src="@drawable/ic_audio_ring_notif_vibrate"
+ android:scaleType="center"
+ android:duplicateParentState="true"
+ android:background="@drawable/silent_mode_indicator"
+ />
+ </LinearLayout>
+
+ <!-- Spacer -->
+ <View android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:visibility="invisible"/>
+
+ <LinearLayout
+ android:id="@+id/option3"
+ android:layout_width="64dp"
+ android:layout_height="match_parent"
+ android:background="?android:attr/actionBarItemBackground"
+ >
+ <ImageView
+ android:layout_width="48dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="6dp"
+ android:src="@drawable/ic_audio_vol"
+ android:scaleType="center"
+ android:duplicateParentState="true"
+ android:background="@drawable/silent_mode_indicator"
+ />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 228786e..37aacab 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -21,6 +21,7 @@ import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
import android.app.ActivityManagerNative;
+import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.bluetooth.BluetoothA2dp;
@@ -319,6 +320,8 @@ public class AudioService extends IAudioService.Stub {
private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000;
// previous volume adjustment direction received by checkForRingerModeChange()
private int mPrevVolDirection = AudioManager.ADJUST_SAME;
+ // Keyguard manager proxy
+ private KeyguardManager mKeyguardManager;
///////////////////////////////////////////////////////////////////////////
// Construction
@@ -503,9 +506,10 @@ public class AudioService extends IAudioService.Stub {
streamType = getActiveStreamType(suggestedStreamType);
}
- // Play sounds on STREAM_RING only.
+ // Play sounds on STREAM_RING only and if lock screen is not on.
if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
- ((STREAM_VOLUME_ALIAS[streamType] != AudioSystem.STREAM_RING))) {
+ ((STREAM_VOLUME_ALIAS[streamType] != AudioSystem.STREAM_RING)
+ || (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
@@ -2665,6 +2669,8 @@ public class AudioService extends IAudioService.Stub {
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SHARED_MSG, SENDMSG_NOOP,
0, 0, null, 0);
+ mKeyguardManager =
+ (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
resetBluetoothSco();
getBluetoothHeadset();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 6258652..1fbe08d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -63,7 +63,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 72;
+ private static final int DATABASE_VERSION = 73;
private Context mContext;
@@ -961,6 +961,7 @@ public class DatabaseHelper extends SQLiteOpenHelper {
+ " VALUES(?,?);");
loadBooleanSetting(stmt, Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
R.bool.def_accessibility_speak_password);
+ db.setTransactionSuccessful();
} finally {
db.endTransaction();
if (stmt != null) stmt.close();
@@ -968,6 +969,23 @@ public class DatabaseHelper extends SQLiteOpenHelper {
upgradeVersion = 72;
}
+ if (upgradeVersion == 72) {
+ // update vibration settings
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT OR REPLACE INTO system(name,value)"
+ + " VALUES(?,?);");
+ loadBooleanSetting(stmt, Settings.System.VIBRATE_IN_SILENT,
+ R.bool.def_vibrate_in_silent);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ upgradeVersion = 73;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 3fc53aa..0e2d2a8 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -56,7 +56,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private static final String TAG = "GlobalActions";
- private static final boolean SHOW_SILENT_TOGGLE = false;
+ private static final boolean SHOW_SILENT_TOGGLE = true;
private final Context mContext;
private final AudioManager mAudioManager;
@@ -64,7 +64,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private ArrayList<Action> mItems;
private AlertDialog mDialog;
- private ToggleAction mSilentModeToggle;
+ private SilentModeAction mSilentModeAction;
private ToggleAction mAirplaneModeOn;
private MyAdapter mAdapter;
@@ -115,39 +115,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
* @return A new dialog.
*/
private AlertDialog createDialog() {
- mSilentModeToggle = new ToggleAction(
- R.drawable.ic_audio_vol_mute,
- R.drawable.ic_audio_vol,
- R.string.global_action_toggle_silent_mode,
- R.string.global_action_silent_mode_on_status,
- R.string.global_action_silent_mode_off_status) {
-
- void willCreate() {
- mEnabledIconResId =
- mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE
- ? R.drawable.ic_audio_ring_notif_vibrate
- : R.drawable.ic_audio_vol_mute;
- }
-
- void onToggle(boolean on) {
- if (on) {
- mAudioManager.setRingerMode((Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.VIBRATE_IN_SILENT, 1) == 1)
- ? AudioManager.RINGER_MODE_VIBRATE
- : AudioManager.RINGER_MODE_SILENT);
- } else {
- mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- }
- }
-
- public boolean showDuringKeyguard() {
- return true;
- }
-
- public boolean showBeforeProvisioning() {
- return false;
- }
- };
+ mSilentModeAction = new SilentModeAction(mAudioManager, mHandler);
mAirplaneModeOn = new ToggleAction(
R.drawable.ic_lock_airplane_mode,
@@ -191,15 +159,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mItems = new ArrayList<Action>();
- // silent mode
- if (SHOW_SILENT_TOGGLE) {
- mItems.add(mSilentModeToggle);
- }
-
- // next: airplane mode
- mItems.add(mAirplaneModeOn);
-
- // last: power off
+ // first: power off
mItems.add(
new SinglePressAction(
com.android.internal.R.drawable.ic_lock_power_off,
@@ -219,13 +179,20 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
});
+ // next: airplane mode
+ mItems.add(mAirplaneModeOn);
+
+ // last: silent mode
+ if (SHOW_SILENT_TOGGLE) {
+ mItems.add(mSilentModeAction);
+ }
+
mAdapter = new MyAdapter();
final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
ab.setAdapter(mAdapter, this)
- .setInverseBackgroundForced(true)
- .setTitle(R.string.global_actions);
+ .setInverseBackgroundForced(true);
final AlertDialog dialog = ab.create();
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
@@ -238,8 +205,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private void prepareDialog() {
final boolean silentModeOn =
mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
- mSilentModeToggle.updateState(
- silentModeOn ? ToggleAction.State.On : ToggleAction.State.Off);
mAirplaneModeOn.updateState(mAirplaneState);
mAdapter.notifyDataSetChanged();
if (mKeyguardShowing) {
@@ -247,20 +212,28 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
} else {
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
}
+ if (SHOW_SILENT_TOGGLE) {
+ IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
+ mContext.registerReceiver(mRingerModeReceiver, filter);
+ }
}
/** {@inheritDoc} */
public void onDismiss(DialogInterface dialog) {
+ if (SHOW_SILENT_TOGGLE) {
+ mContext.unregisterReceiver(mRingerModeReceiver);
+ }
}
/** {@inheritDoc} */
public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
+ if (!(mAdapter.getItem(which) instanceof SilentModeAction)) {
+ dialog.dismiss();
+ }
mAdapter.getItem(which).onPress();
}
-
/**
* The adapter used for the list within the global actions dialog, taking
* into account whether the keyguard is showing via
@@ -381,9 +354,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public View create(
Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
- View v = (convertView != null) ?
- convertView :
- inflater.inflate(R.layout.global_actions_item, parent, false);
+ View v = inflater.inflate(R.layout.global_actions_item, parent, false);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
TextView messageView = (TextView) v.findViewById(R.id.message);
@@ -460,27 +431,31 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
LayoutInflater inflater) {
willCreate();
- View v = (convertView != null) ?
- convertView :
- inflater.inflate(R
+ View v = inflater.inflate(R
.layout.global_actions_item, parent, false);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
TextView messageView = (TextView) v.findViewById(R.id.message);
TextView statusView = (TextView) v.findViewById(R.id.status);
+ final boolean enabled = isEnabled();
- messageView.setText(mMessageResId);
+ if (messageView != null) {
+ messageView.setText(mMessageResId);
+ messageView.setEnabled(enabled);
+ }
boolean on = ((mState == State.On) || (mState == State.TurningOn));
- icon.setImageDrawable(context.getResources().getDrawable(
- (on ? mEnabledIconResId : mDisabledIconResid)));
- statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
- statusView.setVisibility(View.VISIBLE);
+ if (icon != null) {
+ icon.setImageDrawable(context.getResources().getDrawable(
+ (on ? mEnabledIconResId : mDisabledIconResid)));
+ icon.setEnabled(enabled);
+ }
- final boolean enabled = isEnabled();
- messageView.setEnabled(enabled);
- statusView.setEnabled(enabled);
- icon.setEnabled(enabled);
+ if (statusView != null) {
+ statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
+ statusView.setVisibility(View.VISIBLE);
+ statusView.setEnabled(enabled);
+ }
v.setEnabled(enabled);
return v;
@@ -518,6 +493,72 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
}
+ private static class SilentModeAction implements Action, View.OnClickListener {
+
+ private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 };
+
+ private final AudioManager mAudioManager;
+ private final Handler mHandler;
+
+ SilentModeAction(AudioManager audioManager, Handler handler) {
+ mAudioManager = audioManager;
+ mHandler = handler;
+ }
+
+ private int ringerModeToIndex(int ringerMode) {
+ // They just happen to coincide
+ return ringerMode;
+ }
+
+ private int indexToRingerMode(int index) {
+ // They just happen to coincide
+ return index;
+ }
+
+ public View create(Context context, View convertView, ViewGroup parent,
+ LayoutInflater inflater) {
+ View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false);
+ // Handle clicks outside the icons and ignore
+ v.setOnClickListener(this);
+
+ int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode());
+ for (int i = 0; i < 3; i++) {
+ View itemView = v.findViewById(ITEM_IDS[i]);
+ itemView.setSelected(selectedIndex == i);
+ // Set up click handler
+ itemView.setTag(i);
+ itemView.setOnClickListener(this);
+ }
+ return v;
+ }
+
+ public void onPress() {
+ }
+
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ void willCreate() {
+ }
+
+ public void onClick(View v) {
+ if (!(v.getTag() instanceof Integer)) return;
+
+ int index = (Integer) v.getTag();
+ mAudioManager.setRingerMode(indexToRingerMode(index));
+ mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY);
+ }
+ }
+
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -549,13 +590,27 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
};
+ private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
+ mHandler.sendEmptyMessage(MESSAGE_REFRESH);
+ }
+ }
+ };
+
private static final int MESSAGE_DISMISS = 0;
+ private static final int MESSAGE_REFRESH = 1;
+ private static final int DIALOG_DISMISS_DELAY = 300; // ms
+
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == MESSAGE_DISMISS) {
if (mDialog != null) {
mDialog.dismiss();
}
+ } else if (msg.what == MESSAGE_REFRESH) {
+ mAdapter.notifyDataSetChanged();
}
}
};
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index de7547b..f204070 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -49,7 +49,7 @@ public abstract class KeyguardViewBase extends FrameLayout {
// Whether the volume keys should be handled by keyguard. If true, then
// they will be handled here for specific media types such as music, otherwise
// the audio service will bring up the volume dialog.
- private static final boolean KEYGUARD_MANAGES_VOLUME = false;
+ private static final boolean KEYGUARD_MANAGES_VOLUME = true;
// This is a faster way to draw the background on devices without hardware acceleration
Drawable mBackgroundDrawable = new Drawable() {