am f3364080
: Merge "New and improved silent mode on lockscreen." into ics-mr1
* commit 'f336408000c4be36045401fb4df89528249e7383': New and improved silent mode on lockscreen.
This commit is contained in:
20
core/res/res/drawable/silent_mode_indicator.xml
Normal file
20
core/res/res/drawable/silent_mode_indicator.xml
Normal file
@ -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>
|
@ -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
|
||||
|
97
core/res/res/layout/global_actions_silent_mode.xml
Normal file
97
core/res/res/layout/global_actions_silent_mode.xml
Normal file
@ -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>
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
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();
|
||||
|
||||
if (messageView != null) {
|
||||
messageView.setText(mMessageResId);
|
||||
messageView.setEnabled(enabled);
|
||||
}
|
||||
|
||||
boolean on = ((mState == State.On) || (mState == State.TurningOn));
|
||||
if (icon != null) {
|
||||
icon.setImageDrawable(context.getResources().getDrawable(
|
||||
(on ? mEnabledIconResId : mDisabledIconResid)));
|
||||
icon.setEnabled(enabled);
|
||||
}
|
||||
|
||||
if (statusView != null) {
|
||||
statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
|
||||
statusView.setVisibility(View.VISIBLE);
|
||||
|
||||
final boolean enabled = isEnabled();
|
||||
messageView.setEnabled(enabled);
|
||||
statusView.setEnabled(enabled);
|
||||
icon.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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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() {
|
||||
|
Reference in New Issue
Block a user