QS: Wifi control panel.
Create first example of an inline detail view with line
items, bind to new access-point controller.
Move the common bits of all control panels into a
common abstraction. Share common parts of layout
(More settings / done button).
Change-Id: I14a1bf548f3291dc628f97bf09dd4e38ac2fb2dc
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index e1c460c..ca46437 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -17,41 +17,36 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/system_primary_color" >
-
- <ImageView
- android:id="@android:id/button1"
- android:layout_width="64dp"
- android:layout_height="64dp"
- android:layout_alignParentStart="true"
- android:contentDescription="@string/accessibility_quick_settings_close"
- android:padding="@dimen/qs_panel_padding"
- android:src="@drawable/ic_qs_back" />
+ android:background="@color/system_primary_color"
+ android:padding="16dp" >
<TextView
- android:id="@android:id/title"
- android:layout_width="match_parent"
- android:layout_height="64dp"
- android:layout_alignParentTop="true"
- android:layout_toEndOf="@android:id/button1"
- android:layout_toStartOf="@android:id/checkbox"
- android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
-
- <ImageView
- android:id="@android:id/custom"
- android:layout_width="match_parent"
+ android:id="@android:id/button1"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@android:id/title"
- android:layout_marginLeft="16dip"
- android:layout_marginRight="16dip"
- android:scaleType="fitXY"
- android:src="?android:attr/dividerHorizontal" />
+ android:minWidth="88dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:text="@string/quick_settings_done"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton" />
+
+ <TextView
+ android:id="@android:id/button2"
+ style="@style/QSBorderlessButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_marginEnd="8dp"
+ android:minWidth="132dp"
+ android:layout_toStartOf="@android:id/button1"
+ android:text="@string/quick_settings_more_settings"
+ android:textAppearance="@style/TextAppearance.QS.DetailButton" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@android:id/custom" />
+ android:layout_above="@android:id/button1" />
</RelativeLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
new file mode 100644
index 0000000..fcbb32c
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/BrightnessDialogContainer"
+ android:background="@drawable/btn_borderless_rect" >
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+ <Switch
+ android:id="@android:id/toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
new file mode 100644
index 0000000..c5eaed9
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_detail_item_height"
+ android:gravity="center_vertical"
+ android:background="@drawable/btn_borderless_rect"
+ android:clickable="true"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginEnd="12dp" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="20dp"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemPrimary" />
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dp"
+ android:textAppearance="@style/TextAppearance.QS.DetailItemSecondary" />
+ </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 97ed9a0..58547b9 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -30,7 +30,7 @@
<com.android.systemui.settings.ToggleSlider
android:id="@+id/brightness_slider"
android:layout_width="0dp"
- android:layout_height="44dp"
+ android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
systemui:text="@string/status_bar_settings_auto_brightness_label" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index d239208..70589b7 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -135,13 +135,22 @@
android:textColor="#ffffff"
android:singleLine="true" />
- <include
- layout="@layout/quick_settings_brightness_dialog"
- android:id="@+id/brightness_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- />
+
+ <include
+ android:id="@+id/qs_detail_header"
+ layout="@layout/qs_detail_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ />
+ <include
+ android:id="@+id/brightness_container"
+ layout="@layout/quick_settings_brightness_dialog"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ />
+
<TextView
android:id="@+id/header_debug_info"
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
index 6d63bb0..6ab8cf3 100644
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ b/packages/SystemUI/res/layout/zen_mode_condition.xml
@@ -41,7 +41,7 @@
<ImageView
android:id="@android:id/button1"
- style="@style/BorderlessButton"
+ style="@style/QSBorderlessButton"
android:layout_width="@dimen/zen_mode_condition_height"
android:layout_height="@dimen/zen_mode_condition_height"
android:layout_alignParentEnd="true"
@@ -53,7 +53,7 @@
<ImageView
android:id="@android:id/button2"
- style="@style/BorderlessButton"
+ style="@style/QSBorderlessButton"
android:layout_width="@dimen/zen_mode_condition_height"
android:layout_height="@dimen/zen_mode_condition_height"
android:layout_alignParentEnd="true"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 0a8f852..0420cbc 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -42,7 +42,7 @@
<TextView
android:id="@android:id/button2"
- style="@style/BorderlessButton"
+ style="@style/QSBorderlessButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bdbedad..a2757c3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -168,6 +168,9 @@
<dimen name="qs_tile_padding_bottom">16dp</dimen>
<dimen name="qs_tile_spacing">4dp</dimen>
<dimen name="qs_panel_padding_bottom">8dp</dimen>
+ <dimen name="qs_detail_item_height">48dp</dimen>
+ <dimen name="qs_detail_item_height_connected">72dp</dimen>
+
<!-- How far the expanded QS panel peeks from the header in collapsed state. -->
<dimen name="qs_peek_height">8dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a8799f7..a5cfdbc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -534,6 +534,10 @@
<string name="quick_settings_color_space_label">Color correction mode</string>
<!-- QuickSettings: Control panel: Label for button that navigates to settings. [CHAR LIMIT=NONE] -->
<string name="quick_settings_more_settings">More settings</string>
+ <!-- QuickSettings: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_done">Done</string>
+ <!-- QuickSettings: Control panel: Label for connected device. [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_connected">Connected</string>
<!-- QuickSettings: Tethering. [CHAR LIMIT=NONE] -->
<string name="quick_settings_tethering_label">Tethering</string>
<!-- QuickSettings: Hotspot. [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index e5d5b03..dd1b749 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -176,6 +176,7 @@
<item name="android:textSize">14sp</item>
<item name="android:textAllCaps">true</item>
<item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:gravity">center</item>
</style>
<style name="BaseBrightnessDialogContainer">
@@ -233,6 +234,11 @@
<item name="android:colorControlActivated">#ffffffff</item>
</style>
+ <style name="QSBorderlessButton">
+ <item name="android:padding">12dp</item>
+ <item name="android:background">@drawable/btn_borderless_rect</item>
+ <item name="android:gravity">center</item>
+ </style>
<style name="BorderlessButton" parent="@android:style/Widget.Material.Button.Borderless" />
<style name="BorderlessButton.Tiny">
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java b/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java
index ff904b3..327ed6a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CircularClipper.java
@@ -21,23 +21,19 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.view.View;
+import android.view.ViewAnimationUtils;
/** Helper for view-level circular clip animations. **/
public class CircularClipper {
private final View mTarget;
- private Utils mUtils;
private ValueAnimator mAnimator;
public CircularClipper(View target) {
mTarget = target;
}
- public void setUtils(Utils utils) {
- mUtils = utils;
- }
-
public void animateCircularClip(int x, int y, boolean in, AnimatorListener listener) {
if (mAnimator != null) {
mAnimator.cancel();
@@ -49,14 +45,7 @@
r = (int) Math.max(r, Math.ceil(Math.sqrt(w * w + h * h)));
r = (int) Math.max(r, Math.ceil(Math.sqrt(x * x + h * h)));
- if (mUtils == null) {
- mTarget.setVisibility(in ? View.VISIBLE : View.GONE);
- if (listener != null) {
- listener.onAnimationEnd(null);
- }
- return;
- }
- mAnimator = mUtils.createRevealAnimator(mTarget, x, y, 0, r);
+ mAnimator = ViewAnimationUtils.createCircularReveal(mTarget, x, y, 0, r);
mAnimator.removeAllListeners();
if (listener != null) {
mAnimator.addListener(listener);
@@ -83,9 +72,4 @@
mTarget.setVisibility(View.GONE);
};
};
-
- public interface Utils {
- ValueAnimator createRevealAnimator(View v, int centerX, int centerY,
- float startRadius, float endRadius);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index d152887..51befd6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -20,15 +20,17 @@
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.qs.QSTile.DetailAdapter;
import java.util.ArrayList;
@@ -38,7 +40,10 @@
private final Context mContext;
private final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>();
- private final FrameLayout mDetail;
+ private final View mDetail;
+ private final ViewGroup mDetailContent;
+ private final View mDetailSettingsButton;
+ private final View mDetailDoneButton;
private final CircularClipper mClipper;
private final H mHandler = new H();
@@ -63,8 +68,10 @@
super(context, attrs);
mContext = context;
- mDetail = new FrameLayout(mContext);
- mDetail.setBackgroundColor(mContext.getResources().getColor(R.color.system_primary_color));
+ mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false);
+ mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content);
+ mDetailSettingsButton = mDetail.findViewById(android.R.id.button2);
+ mDetailDoneButton = mDetail.findViewById(android.R.id.button1);
mDetail.setVisibility(GONE);
mDetail.setClickable(true);
addView(mDetail);
@@ -91,10 +98,6 @@
}
}
- public void setUtils(CircularClipper.Utils utils) {
- mClipper.setUtils(utils);
- }
-
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -141,6 +144,12 @@
public void onShowDetail(boolean show) {
QSPanel.this.showDetail(show, r);
}
+ @Override
+ public void onToggleStateChanged(boolean state) {
+ if (mDetailRecord == r) {
+ fireToggleStateChanged(state);
+ }
+ }
});
final View.OnClickListener click = new View.OnClickListener() {
@Override
@@ -165,20 +174,34 @@
if (r == null) return;
AnimatorListener listener = null;
if (show) {
- if (mDetailRecord != null) return;
- if (r.detailView == null) {
- r.detailView = r.tile.createDetailView(mContext, mDetail);
- }
- if (r.detailView == null) return;
+ if (mDetailRecord != null) return; // already showing something in detail
+ r.detailAdapter = r.tile.getDetailAdapter();
+ if (r.detailAdapter == null) return;
+ r.detailView = r.detailAdapter.createDetailView(mContext, r.detailView, mDetailContent);
+ if (r.detailView == null) throw new IllegalStateException("Must return detail view");
+ mDetailDoneButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showDetail(false, mDetailRecord);
+ }
+ });
+ final Intent settingsIntent = r.detailAdapter.getSettingsIntent();
+ mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
+ mDetailSettingsButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mDetailRecord.tile.mHost.startSettingsActivity(settingsIntent);
+ }
+ });
mDetailRecord = r;
- mDetail.removeAllViews();
+ mDetailContent.removeAllViews();
mDetail.bringToFront();
- mDetail.addView(r.detailView);
+ mDetailContent.addView(r.detailView);
} else {
if (mDetailRecord == null) return;
listener = mTeardownDetailWhenDone;
}
- fireShowingDetail(show);
+ fireShowingDetail(show ? r.detailAdapter : null);
int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
int y = r.tileView.getTop() + r.tileView.getHeight() / 2;
mClipper.animateCircularClip(x, y, show, listener);
@@ -215,11 +238,7 @@
record.tileView.measure(exactly(cw), exactly(ch));
}
int h = rows == 0 ? 0 : (getRowTop(rows) + mPanelPaddingBottom);
- mDetail.measure(exactly(width), unspecified());
- if (mDetail.getVisibility() == VISIBLE && mDetail.getChildCount() > 0) {
- final int dmh = mDetail.getMeasuredHeight();
- if (dmh > 0) h = Math.max(h, dmh);
- }
+ mDetail.measure(exactly(width), exactly(h));
setMeasuredDimension(width, h);
}
@@ -227,10 +246,6 @@
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
- private static int unspecified() {
- return MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- }
-
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int w = getWidth();
@@ -263,9 +278,15 @@
return cols;
}
- private void fireShowingDetail(boolean showingDetail) {
+ private void fireShowingDetail(QSTile.DetailAdapter detail) {
if (mCallback != null) {
- mCallback.onShowingDetail(showingDetail);
+ mCallback.onShowingDetail(detail);
+ }
+ }
+
+ private void fireToggleStateChanged(boolean state) {
+ if (mCallback != null) {
+ mCallback.onToggleStateChanged(state);
}
}
@@ -286,18 +307,20 @@
QSTile<?> tile;
QSTileView tileView;
View detailView;
+ DetailAdapter detailAdapter;
int row;
int col;
}
private final AnimatorListenerAdapter mTeardownDetailWhenDone = new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
- mDetail.removeAllViews();
+ mDetailContent.removeAllViews();
mDetailRecord = null;
};
};
public interface Callback {
- void onShowingDetail(boolean showingDetail);
+ void onShowingDetail(QSTile.DetailAdapter detail);
+ void onToggleStateChanged(boolean state);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 5901dd5..62c9d9f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -83,10 +83,18 @@
return new QSTileView(context);
}
- public View createDetailView(Context context, ViewGroup root) {
+ public DetailAdapter getDetailAdapter() {
return null; // optional
}
+ public interface DetailAdapter {
+ int getTitle();
+ Boolean getToggleState();
+ View createDetailView(Context context, View convertView, ViewGroup parent);
+ Intent getSettingsIntent();
+ void setToggleState(boolean state);
+ }
+
// safe to call from any thread
public void setCallback(Callback callback) {
@@ -117,6 +125,10 @@
mHandler.obtainMessage(H.USER_SWITCH, newUserId).sendToTarget();
}
+ public void fireToggleStateChanged(boolean state) {
+ mHandler.obtainMessage(H.TOGGLE_STATE_CHANGED, state ? 1 : 0, 0).sendToTarget();
+ }
+
// call only on tile worker looper
private void handleSetCallback(Callback callback) {
@@ -148,6 +160,12 @@
}
}
+ private void handleToggleStateChanged(boolean state) {
+ if (mCallback != null) {
+ mCallback.onToggleStateChanged(state);
+ }
+ }
+
protected void handleUserSwitch(int newUserId) {
handleRefreshState(null);
}
@@ -159,6 +177,7 @@
private static final int REFRESH_STATE = 4;
private static final int SHOW_DETAIL = 5;
private static final int USER_SWITCH = 6;
+ private static final int TOGGLE_STATE_CHANGED = 7;
private H(Looper looper) {
super(looper);
@@ -186,6 +205,9 @@
} else if (msg.what == USER_SWITCH) {
name = "handleUserSwitch";
handleUserSwitch(msg.arg1);
+ } else if (msg.what == TOGGLE_STATE_CHANGED) {
+ name = "handleToggleStateChanged";
+ handleToggleStateChanged(msg.arg1 != 0);
}
} catch (Throwable t) {
final String error = "Error in " + name;
@@ -198,6 +220,7 @@
public interface Callback {
void onStateChanged(State state);
void onShowDetail(boolean show);
+ void onToggleStateChanged(boolean state);
}
public interface Host {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
index c4bdb19..3bdea79 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
@@ -22,11 +22,9 @@
import android.content.IntentFilter;
import android.media.AudioManager;
import android.util.Log;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
-import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -47,45 +45,8 @@
}
@Override
- public View createDetailView(Context context, ViewGroup root) {
- final View v = LayoutInflater.from(context).inflate(R.layout.qs_detail, root, false);
- final TextView title = (TextView) v.findViewById(android.R.id.title);
- title.setText(R.string.quick_settings_notifications_label);
- final View close = v.findViewById(android.R.id.button1);
- close.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showDetail(false);
- }
- });
- final ViewGroup content = (ViewGroup) v.findViewById(android.R.id.content);
- final VolumeComponent volumeComponent = mHost.getVolumeComponent();
- final VolumePanel vp = new VolumePanel(mContext, content, mZenController);
- v.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
- @Override
- public void onViewDetachedFromWindow(View v) {
- volumeComponent.setVolumePanel(null);
- }
-
- @Override
- public void onViewAttachedToWindow(View v) {
- vp.updateStates();
- volumeComponent.setVolumePanel(vp);
- }
- });
- vp.setZenModePanelCallback(new ZenModePanel.Callback() {
- @Override
- public void onMoreSettings() {
- mHost.startSettingsActivity(ZenModePanel.ZEN_SETTINGS);
- }
-
- @Override
- public void onInteraction() {
- // noop
- }
- });
- vp.postVolumeChanged(AudioManager.STREAM_RING, AudioManager.FLAG_SHOW_UI);
- return v;
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
}
@Override
@@ -164,4 +125,58 @@
}
}
};
+
+ private final DetailAdapter mDetailAdapter = new DetailAdapter() {
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_notifications_label;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ public void setToggleState(boolean state) {
+ // noop
+ }
+
+ public Intent getSettingsIntent() {
+ return ZenModePanel.ZEN_SETTINGS;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ if (convertView != null) return convertView;
+ final VolumeComponent volumeComponent = mHost.getVolumeComponent();
+ final VolumePanel vp = new VolumePanel(mContext, parent, mZenController);
+ final View v = vp.getContentView();
+ v.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ volumeComponent.setVolumePanel(null);
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ vp.updateStates();
+ volumeComponent.setVolumePanel(vp);
+ }
+ });
+ vp.setZenModePanelCallback(new ZenModePanel.Callback() {
+ @Override
+ public void onMoreSettings() {
+ mHost.startSettingsActivity(ZenModePanel.ZEN_SETTINGS);
+ }
+
+ @Override
+ public void onInteraction() {
+ // noop
+ }
+ });
+ vp.postVolumeChanged(AudioManager.STREAM_RING, AudioManager.FLAG_SHOW_UI);
+ return v;
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index a236497..84eee24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -21,23 +21,34 @@
import android.content.res.Resources;
import android.provider.Settings;
import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
/** Quick settings tile: Wifi **/
public class WifiTile extends QSTile<QSTile.SignalState> {
private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
+ private static final int MAX_ITEMS = 4; // TODO temporary visual restriction
private final NetworkController mController;
+ private final WifiDetailAdapter mDetailAdapter;
public WifiTile(Host host) {
super(host);
mController = host.getNetworkController();
+ mDetailAdapter = new WifiDetailAdapter();
}
@Override
@@ -54,12 +65,20 @@
public void setListening(boolean listening) {
if (listening) {
mController.addNetworkSignalChangedCallback(mCallback);
+ mController.addAccessPointCallback(mDetailAdapter);
+ mController.scanForAccessPoints();
} else {
mController.removeNetworkSignalChangedCallback(mCallback);
+ mController.removeAccessPointCallback(mDetailAdapter);
}
}
@Override
+ public DetailAdapter getDetailAdapter() {
+ return mDetailAdapter;
+ }
+
+ @Override
public QSTileView createTileView(Context context) {
return new SignalTileView(context);
}
@@ -71,7 +90,7 @@
@Override
protected void handleSecondaryClick() {
- mHost.startSettingsActivity(WIFI_SETTINGS);
+ showDetail(true);
}
@Override
@@ -83,6 +102,11 @@
boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
+ boolean enabledChanging = state.enabled != cb.enabled;
+ if (enabledChanging) {
+ mDetailAdapter.postUpdateItems();
+ fireToggleStateChanged(cb.enabled);
+ }
state.enabled = cb.enabled;
state.connected = wifiConnected;
state.activityIn = cb.enabled && cb.activityIn;
@@ -169,4 +193,96 @@
// noop
}
};
+
+ private final class WifiDetailAdapter implements DetailAdapter,
+ NetworkController.AccessPointCallback {
+
+ private LinearLayout mItems;
+ private AccessPoint[] mAccessPoints;
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_wifi_label;
+ }
+
+ public Intent getSettingsIntent() {
+ return WIFI_SETTINGS;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return mState.enabled;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ if (DEBUG) Log.d(TAG, "setToggleState " + state);
+ mController.setWifiEnabled(state);
+ showDetail(false);
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ if (convertView != null) return convertView;
+ mItems = new LinearLayout(context);
+ mItems.setOrientation(LinearLayout.VERTICAL);
+ updateItems();
+ return mItems;
+ }
+
+ @Override
+ public void onAccessPointsChanged(final AccessPoint[] accessPoints) {
+ mUiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAccessPoints = accessPoints;
+ updateItems();
+ }
+ });
+ }
+
+ public void postUpdateItems() {
+ mUiHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ updateItems();
+ }
+ });
+ }
+
+ private void updateItems() {
+ if (mItems == null) return;
+ mItems.removeAllViews();
+ if (mAccessPoints == null || mAccessPoints.length == 0 || !mState.enabled) return;
+ for (int i = 0; i < mAccessPoints.length; i++) {
+ final AccessPoint ap = mAccessPoints[i];
+ if (ap == null) continue;
+ final View item = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item,
+ mItems, false);
+ final ImageView iv = (ImageView) item.findViewById(android.R.id.icon);
+ iv.setImageResource(ap.iconId);
+ final TextView title = (TextView) item.findViewById(android.R.id.title);
+ title.setText(ap.ssid);
+ final TextView summary = (TextView) item.findViewById(android.R.id.summary);
+ if (ap.isConnected) {
+ item.setMinimumHeight(mContext.getResources()
+ .getDimensionPixelSize(R.dimen.qs_detail_item_height_connected));
+ summary.setText(R.string.quick_settings_connected);
+ } else {
+ summary.setVisibility(View.GONE);
+ }
+ item.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (!ap.isConnected) {
+ mController.connect(ap);
+ }
+ showDetail(false);
+ }
+ });
+ mItems.addView(item);
+ if (mItems.getChildCount() == MAX_ITEMS) break;
+ }
+ }
+ };
}
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 3fd3175..b0a7d8b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -32,7 +32,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
@@ -78,7 +77,6 @@
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
-import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewPropertyAnimator;
@@ -101,7 +99,6 @@
import com.android.systemui.R;
import com.android.systemui.doze.DozeService;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.qs.CircularClipper;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -717,14 +714,6 @@
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
if (mQSPanel != null) {
- mQSPanel.setUtils(new CircularClipper.Utils() {
- @Override
- public ValueAnimator createRevealAnimator(View v, int centerX, int centerY,
- float startRadius, float endRadius) {
- return ViewAnimationUtils.createCircularReveal(v, centerX, centerY,
- startRadius, endRadius);
- }
- });
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, null /*tethering*/,
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 3e2dcef..79ae60c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.Intent;
import android.graphics.Outline;
@@ -26,10 +28,12 @@
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
+import android.widget.Switch;
import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.QSTile;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSlider;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -60,6 +64,7 @@
private View mSignalCluster;
private View mSettingsButton;
private View mBrightnessContainer;
+ private View mQsDetailHeader;
private View mEmergencyCallsOnly;
private TextView mChargingInfo;
@@ -104,6 +109,8 @@
mBrightnessController = new BrightnessController(getContext(),
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
+ mQsDetailHeader = findViewById(R.id.qs_detail_header);
+ mQsDetailHeader.setAlpha(0);
mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only);
mChargingInfo = (TextView) findViewById(R.id.header_charging_info);
loadDimens();
@@ -219,6 +226,7 @@
mDate.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
mSettingsButton.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.GONE);
mBrightnessContainer.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
if (mStatusIcons != null) {
mStatusIcons.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
}
@@ -375,13 +383,6 @@
}
}
- private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
- @Override
- public void onShowingDetail(boolean showingDetail) {
- mBrightnessContainer.animate().alpha(showingDetail ? 0 : 1).withLayer().start();
- }
- };
-
@Override
public boolean shouldDelayChildPressedState() {
return true;
@@ -418,4 +419,69 @@
public boolean hasOverlappingRendering() {
return !mKeyguardShowing || mExpanded;
}
+
+ private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
+ @Override
+ public void onToggleStateChanged(final boolean state) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ handleToggleStateChanged(state);
+ }
+ });
+ }
+
+ @Override
+ public void onShowingDetail(final QSTile.DetailAdapter detail) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ handleShowingDetail(detail);
+ }
+ });
+ }
+
+ private void handleToggleStateChanged(boolean state) {
+ final Switch headerSwitch = (Switch)
+ mQsDetailHeader.findViewById(android.R.id.toggle);
+ headerSwitch.setChecked(state);
+ }
+
+ private void handleShowingDetail(final QSTile.DetailAdapter detail) {
+ final boolean showingDetail = detail != null;
+ transition(mBrightnessContainer, !showingDetail);
+ transition(mQsDetailHeader, showingDetail);
+ if (showingDetail) {
+ final TextView headerTitle = (TextView)
+ mQsDetailHeader.findViewById(android.R.id.title);
+ headerTitle.setText(detail.getTitle());
+ final Switch headerSwitch = (Switch)
+ mQsDetailHeader.findViewById(android.R.id.toggle);
+ final Boolean toggleState = detail.getToggleState();
+ if (toggleState == null) {
+ headerSwitch.setVisibility(INVISIBLE);
+ mQsDetailHeader.setClickable(false);
+ } else {
+ headerSwitch.setVisibility(VISIBLE);
+ headerSwitch.setChecked(toggleState);
+ mQsDetailHeader.setClickable(true);
+ mQsDetailHeader.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ detail.setToggleState(!toggleState);
+ }
+ });
+ }
+ } else {
+ mQsDetailHeader.setClickable(false);
+ }
+ }
+
+ private void transition(final View v, final boolean in) {
+ if (in) {
+ v.bringToFront();
+ }
+ v.animate().alpha(in ? 1 : 0).withLayer().start();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 1f68860..7e113699 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -33,4 +33,23 @@
String dataTypeContentDescriptionId, String description, boolean noSim);
void onAirplaneModeChanged(boolean enabled);
}
+
+ void addAccessPointCallback(AccessPointCallback callback);
+ void removeAccessPointCallback(AccessPointCallback callback);
+ void scanForAccessPoints();
+ void connect(AccessPoint ap);
+
+ public interface AccessPointCallback {
+ void onAccessPointsChanged(AccessPoint[] accessPoints);
+ }
+
+ public static class AccessPoint {
+ public static final int NO_NETWORK = -1; // see WifiManager
+
+ public int networkId;
+ public int iconId;
+ public String ssid;
+ public boolean isConnected;
+ public int level; // 0 - 5
+ }
}
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 4e54e41..4b94ebd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -169,6 +169,8 @@
void setIsAirplaneMode(boolean is, int airplaneIcon);
}
+ private final WifiAccessPointController mAccessPoints;
+
/**
* Construct this controller object and register for updates.
*/
@@ -237,6 +239,7 @@
updateAirplaneMode();
mLastLocale = mContext.getResources().getConfiguration().locale;
+ mAccessPoints = new WifiAccessPointController(mContext);
}
public boolean hasMobileDataFeature() {
@@ -282,6 +285,26 @@
}
@Override
+ public void addAccessPointCallback(AccessPointCallback callback) {
+ mAccessPoints.addCallback(callback);
+ }
+
+ @Override
+ public void removeAccessPointCallback(AccessPointCallback callback) {
+ mAccessPoints.removeCallback(callback);
+ }
+
+ @Override
+ public void scanForAccessPoints() {
+ mAccessPoints.scan();
+ }
+
+ @Override
+ public void connect(AccessPoint ap) {
+ mAccessPoints.connect(ap);
+ }
+
+ @Override
public void setWifiEnabled(final boolean enabled) {
new AsyncTask<Void, Void, Void>() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java
new file mode 100644
index 0000000..09e7472
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.ActionListener;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPointCallback;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class WifiAccessPointController {
+ private static final String TAG = "WifiAccessPointController";
+ private static final boolean DEBUG = false;
+
+ private static final int[] ICONS = {
+ R.drawable.ic_qs_wifi_0,
+ R.drawable.ic_qs_wifi_full_1,
+ R.drawable.ic_qs_wifi_full_2,
+ R.drawable.ic_qs_wifi_full_3,
+ R.drawable.ic_qs_wifi_full_4,
+ };
+
+ private final Context mContext;
+ private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
+ private final WifiManager mWifiManager;
+ private final Receiver mReceiver = new Receiver();
+
+ private boolean mScanning;
+
+ public WifiAccessPointController(Context context) {
+ mContext = context;
+ mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ }
+
+ public void addCallback(AccessPointCallback callback) {
+ if (callback == null || mCallbacks.contains(callback)) return;
+ if (DEBUG) Log.d(TAG, "addCallback " + callback);
+ mCallbacks.add(callback);
+ mReceiver.setListening(!mCallbacks.isEmpty());
+ }
+
+ public void removeCallback(AccessPointCallback callback) {
+ if (callback == null) return;
+ if (DEBUG) Log.d(TAG, "removeCallback " + callback);
+ mCallbacks.remove(callback);
+ mReceiver.setListening(!mCallbacks.isEmpty());
+ }
+
+ public void scan() {
+ if (mScanning) return;
+ if (DEBUG) Log.d(TAG, "scan!");
+ mScanning = mWifiManager.startScan();
+ }
+
+ public void connect(AccessPoint ap) {
+ if (ap == null || ap.networkId < 0) return;
+ if (DEBUG) Log.d(TAG, "connect networkId=" + ap.networkId);
+ mWifiManager.connect(ap.networkId, new ActionListener() {
+ @Override
+ public void onSuccess() {
+ if (DEBUG) Log.d(TAG, "connect success");
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
+ }
+ });
+ }
+
+ private void fireCallback(AccessPoint[] aps) {
+ for (AccessPointCallback callback : mCallbacks) {
+ callback.onAccessPointsChanged(aps);
+ }
+ }
+
+ private static String trimDoubleQuotes(String v) {
+ return v != null && v.length() >= 2 && v.charAt(0) == '\"'
+ && v.charAt(v.length() - 1) == '\"' ? v.substring(1, v.length() - 1) : v;
+ }
+
+ private int getConnectedNetworkId() {
+ final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ return wifiInfo != null ? wifiInfo.getNetworkId() : AccessPoint.NO_NETWORK;
+ }
+
+ private ArrayMap<String, WifiConfiguration> getConfiguredNetworksBySsid() {
+ final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ if (configs == null || configs.size() == 0) return ArrayMap.EMPTY;
+ final ArrayMap<String, WifiConfiguration> rt = new ArrayMap<String, WifiConfiguration>();
+ for (WifiConfiguration config : configs) {
+ rt.put(trimDoubleQuotes(config.SSID), config);
+ }
+ return rt;
+ }
+
+ private void updateAccessPoints() {
+ final int connectedNetworkId = getConnectedNetworkId();
+ if (DEBUG) Log.d(TAG, "connectedNetworkId: " + connectedNetworkId);
+ final List<ScanResult> scanResults = mWifiManager.getScanResults();
+ final ArrayMap<String, WifiConfiguration> configured = getConfiguredNetworksBySsid();
+ if (DEBUG) Log.d(TAG, "scanResults: " + scanResults);
+ final List<AccessPoint> aps = new ArrayList<AccessPoint>(scanResults.size());
+ final ArraySet<String> ssids = new ArraySet<String>();
+ for (ScanResult scanResult : scanResults) {
+ final String ssid = scanResult.SSID;
+ if (TextUtils.isEmpty(ssid) || ssids.contains(ssid)) continue;
+ if (!configured.containsKey(ssid)) continue;
+ ssids.add(ssid);
+ final WifiConfiguration config = configured.get(ssid);
+ final int level = WifiManager.calculateSignalLevel(scanResult.level, ICONS.length);
+ final AccessPoint ap = new AccessPoint();
+ ap.networkId = config != null ? config.networkId : AccessPoint.NO_NETWORK;
+ ap.ssid = ssid;
+ ap.iconId = ICONS[level];
+ ap.isConnected = ap.networkId != AccessPoint.NO_NETWORK
+ && ap.networkId == connectedNetworkId;
+ ap.level = level;
+ aps.add(ap);
+ }
+ Collections.sort(aps, mByStrength);
+ fireCallback(aps.toArray(new AccessPoint[aps.size()]));
+ }
+
+ private final Comparator<AccessPoint> mByStrength = new Comparator<AccessPoint> () {
+ @Override
+ public int compare(AccessPoint lhs, AccessPoint rhs) {
+ return -Integer.compare(score(lhs), score(rhs));
+ }
+
+ private int score(AccessPoint ap) {
+ return ap.level + (ap.isConnected ? 10 : 0);
+ }
+ };
+
+ private final class Receiver extends BroadcastReceiver {
+ private boolean mRegistered;
+
+ public void setListening(boolean listening) {
+ if (listening && !mRegistered) {
+ if (DEBUG) Log.d(TAG, "Registering receiver");
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
+ filter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
+ filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
+ filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
+ mContext.registerReceiver(this, filter);
+ mRegistered = true;
+ } else if (!listening && mRegistered) {
+ if (DEBUG) Log.d(TAG, "Unregistering receiver");
+ mContext.unregisterReceiver(this);
+ mRegistered = false;
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
+ if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
+ updateAccessPoints();
+ mScanning = false;
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 99cba4d..53daaae 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -358,7 +358,7 @@
// embedded mode
mDialog = null;
mView = LayoutInflater.from(mContext).inflate(
- com.android.systemui.R.layout.volume_panel, parent, true);
+ com.android.systemui.R.layout.volume_panel, parent, false);
}
mPanel = (ViewGroup) mView.findViewById(com.android.systemui.R.id.visible_panel);
mSliderPanel = (ViewGroup) mView.findViewById(com.android.systemui.R.id.slider_panel);
@@ -384,6 +384,10 @@
listenToRingerMode();
}
+ public View getContentView() {
+ return mView;
+ }
+
private void setLayoutDirection(int layoutDirection) {
mPanel.setLayoutDirection(layoutDirection);
updateStates();
@@ -628,7 +632,8 @@
if (LOGD) Log.d(mTag, "expand mZenPanel=" + mZenPanel);
if (mZenPanel == null) {
mZenPanel = (ZenModePanel) mZenPanelStub.inflate();
- mZenPanel.init(mZenController, mDialog != null ? 'D' : 'E');
+ final boolean isDialog = mDialog != null;
+ mZenPanel.init(mZenController, isDialog ? 'D' : 'E', isDialog);
mZenPanel.setCallback(new ZenModePanel.Callback() {
@Override
public void onMoreSettings() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 798e7fa..9917944 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -67,6 +67,7 @@
private char mLogTag = '?';
private String mTag;
private LinearLayout mConditions;
+ private View mMoreSettings;
private Callback mCallback;
private ZenModeController mController;
private boolean mRequestingConditions;
@@ -91,7 +92,8 @@
protected void onFinishInflate() {
super.onFinishInflate();
mConditions = (LinearLayout) findViewById(android.R.id.content);
- findViewById(android.R.id.button2).setOnClickListener(new View.OnClickListener() {
+ mMoreSettings = findViewById(android.R.id.button2);
+ mMoreSettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
fireMoreSettings();
@@ -154,12 +156,13 @@
}
}
- public void init(ZenModeController controller, char logTag) {
+ public void init(ZenModeController controller, char logTag, boolean moreSettings) {
mController = controller;
mLogTag = logTag;
updateTag();
mExitConditionId = mController.getExitConditionId();
if (DEBUG) Log.d(mTag, "init mExitConditionId=" + mExitConditionId);
+ mMoreSettings.setVisibility(moreSettings ? VISIBLE : GONE);
mConditions.removeAllViews();
mController.addCallback(mZenCallback);
if (mShowing) {