Merge "Material design for screen pinning cling" into lmp-mr1-dev

This commit is contained in:
Jason Monk
2014-11-07 18:59:22 +00:00
committed by Android (Google) Code Review
23 changed files with 882 additions and 208 deletions

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/* //device/apps/common/res/layout/alert_dialog.xml
**
** Copyright 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.
*/
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="15dip"
android:paddingBottom="0dip"
android:paddingStart="12dip"
android:paddingEnd="25dip"
>
<CheckBox
android:id="@+id/lock_to_app_checkbox"
style="?android:attr/textAppearanceMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>

View File

@@ -4856,16 +4856,6 @@
<string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Overview.</string>
<!-- Notify user that they are locked in lock-to-app mode -->
<string name="lock_to_app_toast_locked">Screen is pinned. Unpinning isn\'t allowed by your organization.</string>
<!-- Lock-to-app dialog title. -->
<string name="lock_to_app_title">Use screen pinning?</string>
<!-- Lock-to-app dialog description. -->
<string name="lock_to_app_description">Screen pinning locks the display in a single view.\n\nTo unpin, touch and hold Back and Overview at the same time.</string>
<!-- Lock-to-app dialog description when in accessibility mode. -->
<string name="lock_to_app_description_accessible">Screen pinning locks the display in a single view.\n\nTo unpin, touch and hold Overview.</string>
<!-- Lock-to-app negative response. -->
<string name="lock_to_app_negative">NO, THANKS</string>
<!-- Lock-to-app positive response. -->
<string name="lock_to_app_positive">START</string>
<!-- Starting lock-to-app indication. -->
<string name="lock_to_app_start">Screen pinned</string>
<!-- Exting lock-to-app indication. -->

View File

@@ -668,13 +668,6 @@
<java-symbol type="string" name="lock_to_app_toast" />
<java-symbol type="string" name="lock_to_app_toast_accessible" />
<java-symbol type="string" name="lock_to_app_toast_locked" />
<java-symbol type="string" name="lock_to_app_title" />
<java-symbol type="string" name="lock_to_app_description" />
<java-symbol type="string" name="lock_to_app_description_accessible" />
<java-symbol type="string" name="lock_to_app_negative" />
<java-symbol type="string" name="lock_to_app_positive" />
<java-symbol type="layout" name="lock_to_app_checkbox" />
<java-symbol type="id" name="lock_to_app_checkbox" />
<java-symbol type="string" name="lock_to_app_start" />
<java-symbol type="string" name="lock_to_app_exit" />
<java-symbol type="string" name="lock_to_app_unlock_pin" />

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 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.
*/
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="@color/system_accent_color" />
<size
android:height="@dimen/screen_pinning_nav_highlight_size"
android:width="@dimen/screen_pinning_nav_highlight_size" />
</shape>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 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.
*/
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="@color/screen_pinning_nav_icon_highlight_outer" />
<size
android:height="@dimen/screen_pinning_nav_highlight_outer_size"
android:width="@dimen/screen_pinning_nav_highlight_outer_size" />
</shape>

View File

@@ -0,0 +1,42 @@
<?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="@dimen/screen_pinning_request_width"
android:layout_height="wrap_content"
android:gravity="bottom|center_horizontal"
android:layoutDirection="ltr"
android:orientation="vertical" >
<include
android:layout_width="@dimen/screen_pinning_request_width"
android:layout_height="wrap_content"
layout="@layout/screen_pinning_request_text_area" />
<View
android:id="@+id/spacer"
android:layout_width="@dimen/screen_pinning_request_width"
android:layout_height="18dp"
android:background="@color/screen_pinning_request_bg" />
<include
android:layout_width="@dimen/screen_pinning_request_width"
android:layout_height="wrap_content"
layout="@layout/screen_pinning_request_buttons" />
</LinearLayout>

View File

@@ -0,0 +1,143 @@
<?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.
*/
-->
<!--
This layout matches the structure of navigation_bar.xml and will need
to be kept up to sync with changes there.
On sw600dp, dimensions are changed to be large enough such that the
empty views between the buttons is reduced to nothing, if (nav bar)
sw600dp layout is changed then this will likely have to be adjusted
and possibly need a sw600dp specific one.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen_pinning_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/screen_pinning_request_button_height"
android:background="@color/screen_pinning_request_bg" >
<View
android:layout_width="@dimen/screen_pinning_request_side_width"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible" />
<FrameLayout
android:id="@+id/screen_pinning_back_group"
android:layout_width="@dimen/screen_pinning_request_button_width"
android:layout_height="@dimen/screen_pinning_request_button_height"
android:layout_weight="0"
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
<ImageView
android:id="@+id/screen_pinning_back_bg_light"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
android:src="@drawable/screen_pinning_light_bg_circ" />
<ImageView
android:id="@+id/screen_pinning_back_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
android:paddingStart="@dimen/screen_pinning_request_inner_padding"
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
android:scaleType="matrix"
android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
android:scaleType="center"
android:src="@drawable/ic_sysbar_back" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible" />
<FrameLayout
android:id="@+id/screen_pinning_home_group"
android:layout_width="@dimen/screen_pinning_request_button_width"
android:layout_height="@dimen/screen_pinning_request_button_height"
android:layout_weight="0"
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
android:scaleType="center"
android:src="@drawable/ic_sysbar_home" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible" />
<FrameLayout
android:id="@+id/screen_pinning_recents_group"
android:layout_width="@dimen/screen_pinning_request_button_width"
android:layout_height="@dimen/screen_pinning_request_button_height"
android:layout_weight="0"
android:paddingStart="@dimen/screen_pinning_request_frame_padding"
android:paddingEnd="@dimen/screen_pinning_request_frame_padding" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
android:src="@drawable/screen_pinning_light_bg_circ" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="@dimen/screen_pinning_request_inner_padding"
android:paddingStart="@dimen/screen_pinning_request_inner_padding"
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
android:scaleType="matrix"
android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingEnd="@dimen/screen_pinning_request_nav_side_padding"
android:paddingStart="@dimen/screen_pinning_request_nav_side_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_icon_padding"
android:scaleType="center"
android:src="@drawable/ic_sysbar_recent" />
</FrameLayout>
<View
android:layout_width="@dimen/screen_pinning_request_side_width"
android:layout_height="match_parent"
android:layout_weight="0"
android:visibility="invisible" />
</LinearLayout>

View File

@@ -0,0 +1,135 @@
<?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.
*/
-->
<!-- Note all width/height dimensions are switched here to handle landspace
rather than duplicating them all.
This layout matches the structure of navigation_bar.xml (rot90) and
will need to be kept up to sync with changes there.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen_pinning_buttons"
android:layout_height="match_parent"
android:layout_width="@dimen/screen_pinning_request_button_height"
android:background="@color/screen_pinning_request_bg"
android:orientation="vertical" >
<View
android:layout_height="@dimen/screen_pinning_request_side_width"
android:layout_width="match_parent"
android:layout_weight="0"
android:visibility="invisible" />
<FrameLayout
android:id="@+id/screen_pinning_recents_group"
android:layout_height="@dimen/screen_pinning_request_button_width"
android:layout_width="@dimen/screen_pinning_request_button_height"
android:layout_weight="0" >
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="matrix"
android:src="@drawable/screen_pinning_light_bg_circ" />
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="matrix"
android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center"
android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
android:src="@drawable/ic_sysbar_recent" />
</FrameLayout>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible" />
<FrameLayout
android:id="@+id/screen_pinning_home_group"
android:layout_height="@dimen/screen_pinning_request_button_width"
android:layout_width="@dimen/screen_pinning_request_button_height"
android:layout_weight="0" >
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center"
android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
android:src="@drawable/ic_sysbar_home" />
</FrameLayout>
<View
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_weight="1"
android:visibility="invisible" />
<FrameLayout
android:id="@+id/screen_pinning_back_group"
android:layout_height="@dimen/screen_pinning_request_button_width"
android:layout_width="@dimen/screen_pinning_request_button_height"
android:layout_weight="0" >
<ImageView
android:id="@+id/screen_pinning_back_bg_light"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="matrix"
android:src="@drawable/screen_pinning_light_bg_circ" />
<ImageView
android:id="@+id/screen_pinning_back_bg"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="matrix"
android:paddingLeft="@dimen/screen_pinning_request_inner_padding"
android:paddingTop="@dimen/screen_pinning_request_inner_padding"
android:paddingBottom="@dimen/screen_pinning_request_inner_padding"
android:src="@drawable/screen_pinning_bg_circ" />
<ImageView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="center"
android:paddingLeft="@dimen/screen_pinning_request_nav_icon_padding"
android:paddingTop="@dimen/screen_pinning_request_nav_side_padding"
android:paddingBottom="@dimen/screen_pinning_request_nav_side_padding"
android:src="@drawable/ic_sysbar_back" />
</FrameLayout>
<View
android:layout_height="@dimen/screen_pinning_request_side_width"
android:layout_width="match_parent"
android:layout_weight="0"
android:visibility="invisible" />
</LinearLayout>

View File

@@ -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"
android:layout_height="@dimen/screen_pinning_request_width"
android:layout_width="wrap_content"
android:gravity="right|center_vertical"
android:orientation="horizontal" >
<include
android:layout_width="360dp"
android:layout_height="@dimen/screen_pinning_request_width"
layout="@layout/screen_pinning_request_text_area" />
<include
android:layout_width="wrap_content"
android:layout_height="@dimen/screen_pinning_request_width"
layout="@layout/screen_pinning_request_buttons_land" />
</LinearLayout>

View File

@@ -0,0 +1,80 @@
<?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.
*/
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/screen_pinning_text_area"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/screen_pinning_request_bg"
android:gravity="center_vertical" >
<TextView
android:id="@+id/screen_pinning_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="48dp"
android:paddingStart="48dp"
android:paddingTop="43dp"
android:text="@string/screen_pinning_title"
android:textColor="@color/screen_pinning_primary_text"
android:textSize="24sp" />
<TextView
android:id="@+id/screen_pinning_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/screen_pinning_title"
android:paddingEnd="48dp"
android:paddingStart="48dp"
android:paddingTop="12.6dp"
android:text="@string/screen_pinning_description"
android:textColor="@color/screen_pinning_primary_text"
android:textSize="16sp" />
<Button
android:id="@+id/screen_pinning_ok_button"
style="@android:style/Widget.Material.Button"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_alignParentEnd="true"
android:layout_below="@+id/screen_pinning_description"
android:layout_marginEnd="40dp"
android:layout_marginTop="18dp"
android:background="@null"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:text="@string/screen_pinning_positive"
android:textColor="@android:color/white"
android:textSize="14sp" />
<Button
android:id="@+id/screen_pinning_cancel_button"
style="@android:style/Widget.Material.Button"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_alignTop="@id/screen_pinning_ok_button"
android:layout_marginEnd="4dp"
android:layout_toStartOf="@id/screen_pinning_ok_button"
android:background="@null"
android:paddingEnd="8dp"
android:paddingStart="8dp"
android:text="@string/screen_pinning_negative"
android:textColor="@android:color/white"
android:textSize="14sp" />
</RelativeLayout>

View File

@@ -23,5 +23,13 @@
navigation_extra_key_width -->
<dimen name="navigation_side_padding">50dp</dimen>
<!-- Screen pinning request padding on side of icons
(makes the width match the nav bar)-->
<dimen name="screen_pinning_request_nav_side_padding">7dp</dimen>
<!-- Screen pinning request side views to match nav bar
navigation_side_padding - 3 / 2 * (screen_pinning_request_button_width
- navigation_key_width) -->
<dimen name="screen_pinning_request_side_width">44dp</dimen>
</resources>

View File

@@ -29,4 +29,15 @@
<dimen name="keyguard_clock_notifications_margin_max">36dp</dimen>
<dimen name="keyguard_indication_margin_bottom">80dp</dimen>
<!-- Screen pinning request width (just a little bit bigger than the three buttons here -->
<dimen name="screen_pinning_request_width">490dp</dimen>
<!-- Screen pinning request bottom button circle widths -->
<dimen name="screen_pinning_request_button_width">162dp</dimen>
<!-- Screen pinning request, controls padding on bigger screens, bigger nav bar -->
<dimen name="screen_pinning_request_frame_padding">39dp</dimen>
<!-- Screen pinning request side views to match nav bar
In sw600dp we want the buttons centered so this fills the space,
(screen_pinning_request_width - 3 * screen_pinning_request_button_width) / 2 -->
<dimen name="screen_pinning_request_side_width">2dp</dimen>
</resources>

View File

@@ -87,4 +87,15 @@
<!-- Margin on the right side of the system icon group on Keyguard. -->
<dimen name="system_icons_keyguard_padding_end">2dp</dimen>
<!-- Screen pinning request width -->
<dimen name="screen_pinning_request_width">400dp</dimen>
<!-- Screen pinning request bottom button circle widths -->
<dimen name="screen_pinning_request_button_width">128dp</dimen>
<!-- Screen pinning request, controls padding on bigger screens, bigger nav bar -->
<dimen name="screen_pinning_request_frame_padding">22dp</dimen>
<!-- Screen pinning request side views to match nav bar
In sw600dp we want the buttons centered so this fills the space,
(screen_pinning_request_width - 3 * screen_pinning_request_button_width) / 2 -->
<dimen name="screen_pinning_request_side_width">8dp</dimen>
</resources>

View File

@@ -123,4 +123,10 @@
<!-- Shadow color for the furthest pixels around the fake shadow for recents. -->
<color name="fake_shadow_end_color">#03000000</color>
<!-- 25% deep teal 200 -->
<color name="screen_pinning_nav_icon_highlight_outer">#4080cbc4</color>
<!-- deep teal 500 -->
<color name="screen_pinning_request_bg">#ff009688</color>
<color name="screen_pinning_request_window_bg">#80000000</color>
</resources>

View File

@@ -520,4 +520,29 @@
<!-- Padding for signal cluster and battery icon when there are not icons in signal cluster -->
<dimen name="no_signal_cluster_battery_padding">3dp</dimen>
<!-- Screen pinning request width -->
<dimen name="screen_pinning_request_width">@dimen/match_parent</dimen>
<!-- Screen pinning request nav button circle heights -->
<dimen name="screen_pinning_request_button_height">66dp</dimen>
<!-- Screen pinning request nav button circle widths -->
<dimen name="screen_pinning_request_button_width">84dp</dimen>
<!-- Screen pinning request padding on top of inner circle -->
<dimen name="screen_pinning_request_inner_padding">14dp</dimen>
<!-- Screen pinning request padding on top of icons -->
<dimen name="screen_pinning_request_nav_icon_padding">18dp</dimen>
<!-- Screen pinning request padding on side of icons
(makes the width match the nav bar)-->
<dimen name="screen_pinning_request_nav_side_padding">7dp</dimen>
<!-- Screen pinning request side views to match nav bar
navigation_side_padding - 3 / 2 * (screen_pinning_request_button_width
- navigation_key_width) -->
<dimen name="screen_pinning_request_side_width">34dp</dimen>
<!-- Screen pinning request controls padding on bigger screens -->
<dimen name="screen_pinning_request_frame_padding">0dp</dimen>
<!-- Screen pinning inner nav bar circle size -->
<dimen name="screen_pinning_nav_highlight_size">56dp</dimen>
<!-- Screen pinning inner nav bar outer circle size -->
<dimen name="screen_pinning_nav_highlight_outer_size">84dp</dimen>
</resources>

View File

@@ -17,5 +17,6 @@
<resources>
<dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
<dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
<color name="screen_pinning_primary_text">@*android:color/primary_text_default_material_light</color>
</resources>

View File

@@ -899,4 +899,16 @@
<!-- Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. [CHAR LIMIT=20] -->
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
<!-- Screen pinning dialog title. -->
<string name="screen_pinning_title">Screen is pinned</string>
<!-- Screen pinning dialog description. -->
<string name="screen_pinning_description">This keeps it in view until you unpin. Touch and hold Back and Overview at the same time to unpin.</string>
<!-- Screen pinning dialog description when in accessibility mode. -->
<string name="screen_pinning_description_accessible">This keeps it in view until you unpin. Touch and hold Overview to unpin.</string>
<!-- Screen pinning positive response. -->
<string name="screen_pinning_positive">Got it</string>
<!-- Screen pinning negative response. -->
<string name="screen_pinning_negative">No thanks</string>
</resources>

View File

@@ -0,0 +1,282 @@
/*
* 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.recent;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.recents.model.RecentsTaskLoader;
import java.util.ArrayList;
public class ScreenPinningRequest implements View.OnClickListener {
private final Context mContext;
private final AccessibilityManager mAccessibilityService;
private final WindowManager mWindowManager;
private RequestWindowView mRequestWindow;
public ScreenPinningRequest(Context context) {
mContext = context;
mAccessibilityService = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
mWindowManager = (WindowManager)
mContext.getSystemService(Context.WINDOW_SERVICE);
}
public void clearPrompt() {
if (mRequestWindow != null) {
mWindowManager.removeView(mRequestWindow);
mRequestWindow = null;
}
}
public void showPrompt(boolean allowCancel) {
clearPrompt();
mRequestWindow = new RequestWindowView(mContext, allowCancel);
mRequestWindow.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
// show the confirmation
WindowManager.LayoutParams lp = getWindowLayoutParams();
mWindowManager.addView(mRequestWindow, lp);
}
public void onConfigurationChanged() {
if (mRequestWindow != null) {
mRequestWindow.onConfigurationChanged();
}
}
private WindowManager.LayoutParams getWindowLayoutParams() {
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
0
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ScreenPinningConfirmation");
lp.gravity = Gravity.FILL;
return lp;
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.screen_pinning_ok_button || mRequestWindow == v) {
try {
ActivityManagerNative.getDefault().startLockTaskModeOnCurrent();
} catch (RemoteException e) {}
}
clearPrompt();
}
public FrameLayout.LayoutParams getRequestLayoutParams(boolean isLandscape) {
return new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
isLandscape ? (Gravity.CENTER_VERTICAL | Gravity.RIGHT)
: (Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
}
private class RequestWindowView extends FrameLayout {
private static final int OFFSET_DP = 96;
private final ColorDrawable mColor = new ColorDrawable(0);
private ValueAnimator mColorAnim;
private ViewGroup mLayout;
private boolean mShowCancel;
public RequestWindowView(Context context, boolean showCancel) {
super(context);
setClickable(true);
setOnClickListener(ScreenPinningRequest.this);
setBackground(mColor);
mShowCancel = showCancel;
}
@Override
public void onAttachedToWindow() {
DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
boolean isLandscape = isLandscapePhone(mContext);
inflateView(isLandscape);
int bgColor = mContext.getResources().getColor(
R.color.screen_pinning_request_window_bg);
if (ActivityManager.isHighEndGfx()) {
mLayout.setAlpha(0f);
if (isLandscape) {
mLayout.setTranslationX(OFFSET_DP * density);
} else {
mLayout.setTranslationY(OFFSET_DP * density);
}
mLayout.animate()
.alpha(1f)
.translationX(0)
.translationY(0)
.setDuration(300)
.setInterpolator(new DecelerateInterpolator())
.start();
mColorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), 0, bgColor);
mColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final int c = (Integer) animation.getAnimatedValue();
mColor.setColor(c);
}
});
mColorAnim.setDuration(1000);
mColorAnim.start();
} else {
mColor.setColor(bgColor);
}
IntentFilter filter = new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_SCREEN_OFF);
mContext.registerReceiver(mReceiver, filter);
}
private boolean isLandscapePhone(Context context) {
Configuration config = mContext.getResources().getConfiguration();
return config.orientation == Configuration.ORIENTATION_LANDSCAPE
&& config.smallestScreenWidthDp < 600;
}
private void inflateView(boolean isLandscape) {
// We only want this landscape orientation on <600dp, so rather than handle
// resource overlay for -land and -sw600dp-land, just inflate this
// other view for this single case.
mLayout = (ViewGroup) View.inflate(getContext(), isLandscape
? R.layout.screen_pinning_request_land_phone : R.layout.screen_pinning_request,
null);
// Catch touches so they don't trigger cancel/activate, like outside does.
mLayout.setClickable(true);
// Status bar is always on the right.
mLayout.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
// Buttons and text do switch sides though.
View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
mLayout.findViewById(R.id.screen_pinning_text_area)
.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
swapChildrenIfRtlAndVertical(buttons);
((Button) mLayout.findViewById(R.id.screen_pinning_ok_button))
.setOnClickListener(ScreenPinningRequest.this);
if (mShowCancel) {
((Button) mLayout.findViewById(R.id.screen_pinning_cancel_button))
.setOnClickListener(ScreenPinningRequest.this);
} else {
((Button) mLayout.findViewById(R.id.screen_pinning_cancel_button))
.setVisibility(View.INVISIBLE);
}
final int description = mAccessibilityService.isEnabled()
? R.string.screen_pinning_description_accessible
: R.string.screen_pinning_description;
((TextView) mLayout.findViewById(R.id.screen_pinning_description))
.setText(description);
final int backBgVisibility =
mAccessibilityService.isEnabled() ? View.INVISIBLE : View.VISIBLE;
mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility);
mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility);
addView(mLayout, getRequestLayoutParams(isLandscape));
}
private void swapChildrenIfRtlAndVertical(View group) {
if (mContext.getResources().getConfiguration().getLayoutDirection()
!= View.LAYOUT_DIRECTION_RTL) {
return;
}
LinearLayout linearLayout = (LinearLayout) group;
if (linearLayout.getOrientation() == LinearLayout.VERTICAL) {
int childCount = linearLayout.getChildCount();
ArrayList<View> childList = new ArrayList<>(childCount);
for (int i = 0; i < childCount; i++) {
childList.add(linearLayout.getChildAt(i));
}
linearLayout.removeAllViews();
for (int i = childCount - 1; i >= 0; i--) {
linearLayout.addView(childList.get(i));
}
}
}
@Override
public void onDetachedFromWindow() {
mContext.unregisterReceiver(mReceiver);
}
protected void onConfigurationChanged() {
removeAllViews();
inflateView(isLandscapePhone(mContext));
}
private final Runnable mUpdateLayoutRunnable = new Runnable() {
@Override
public void run() {
if (mLayout != null && mLayout.getParent() != null) {
mLayout.setLayoutParams(getRequestLayoutParams(isLandscapePhone(mContext)));
}
}
};
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
post(mUpdateLayoutRunnable);
} else if (intent.getAction().equals(Intent.ACTION_USER_SWITCHED)
|| intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
clearPrompt();
}
}
};
}
}

View File

@@ -37,6 +37,7 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.ViewStub;
import android.widget.Toast;
import com.android.systemui.R;
import com.android.systemui.recents.misc.DebugTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
@@ -50,6 +51,8 @@ import com.android.systemui.recents.views.DebugOverlayView;
import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.recents.views.ViewAnimation;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.SystemUIApplication;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
@@ -82,6 +85,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Runnables to finish the Recents activity
FinishRecentsRunnable mFinishLaunchHomeRunnable;
private PhoneStatusBar mStatusBar;
/**
* A common Runnable to finish Recents either by calling finish() (with a custom animation) or
* launching Home with some ActivityOptions. Generally we always launch home when we exit
@@ -430,6 +435,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
});
}
mStatusBar = ((SystemUIApplication) getApplication())
.getComponent(PhoneStatusBar.class);
}
/** Inflates the debug overlay if debug mode is enabled. */
@@ -631,6 +639,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mFinishLaunchHomeRunnable.run();
}
@Override
public void onScreenPinningRequest() {
if (mStatusBar != null) {
mStatusBar.showScreenPinningRequest(false);
}
}
/**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
@Override

View File

@@ -494,17 +494,6 @@ public class SystemServicesProxy {
return windowRect;
}
/**
* Locks the current task.
*/
public void lockCurrentTask() {
if (mIam == null) return;
try {
mIam.startLockTaskModeOnCurrent();
} catch (RemoteException e) {}
}
/**
* Takes a screenshot of the current surface.
*/

View File

@@ -31,6 +31,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
import android.widget.FrameLayout;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -54,6 +55,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public void onTaskLaunchFailed();
public void onAllTaskViewsDismissed();
public void onExitToHomeAnimationTriggered();
public void onScreenPinningRequest();
}
RecentsConfiguration mConfig;
@@ -461,7 +463,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
postDelayed(new Runnable() {
@Override
public void run() {
ssp.lockCurrentTask();
mCb.onScreenPinningRequest();
}
}, 350);
mTriggered = true;
@@ -485,7 +487,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
if (ssp.startActivityFromRecents(getContext(), task.key.id,
task.activityLabel, launchOpts)) {
if (launchOpts == null && lockToTask) {
ssp.lockCurrentTask();
mCb.onScreenPinningRequest();
}
} else {
// Dismiss the task and return the user to home if we fail to

View File

@@ -123,6 +123,7 @@ import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.recent.ScreenPinningRequest;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -356,6 +357,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
? new GestureRecorder("/sdcard/statusbar_gestures.dat")
: null;
private ScreenPinningRequest mScreenPinningRequest;
private int mNavigationIconHints = 0;
// ensure quick settings is disabled until the current user makes it through the setup wizard
@@ -597,6 +600,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
setControllerUsers();
notifyUserAboutHiddenNotifications();
mScreenPinningRequest = new ScreenPinningRequest(mContext);
}
// ================================================================================
@@ -3144,6 +3149,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
updateExpandedViewPos(EXPANDED_LEAVE_ALONE);
updateShowSearchHoldoff();
updateRowStates();
mScreenPinningRequest.onConfigurationChanged();
}
@Override
@@ -4038,7 +4044,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void showScreenPinningRequest() {
// TODO: Show request.
if (mKeyguardMonitor.isShowing()) {
// Don't allow apps to trigger this from keyguard.
return;
}
// Show screen pinning request, since this comes from an app, show 'no thanks', button.
showScreenPinningRequest(true);
}
public void showScreenPinningRequest(boolean allowCancel) {
mScreenPinningRequest.showPrompt(allowCancel);
}
public boolean hasActiveNotifications() {

View File

@@ -1,141 +0,0 @@
package com.android.server.am;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.CheckBox;
import com.android.internal.R;
import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtilsCache;
public class LockToAppRequestDialog implements OnClickListener {
private static final String TAG = "ActivityManager";
final private Context mContext;
final private ActivityManagerService mService;
private AlertDialog mDialog;
private TaskRecord mRequestedTask;
private CheckBox mCheckbox;
private ILockSettings mLockSettingsService;
private AccessibilityManager mAccessibilityService;
public LockToAppRequestDialog(Context context, ActivityManagerService activityManagerService) {
mContext = context;
mAccessibilityService = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
mService = activityManagerService;
}
private ILockSettings getLockSettings() {
if (mLockSettingsService == null) {
mLockSettingsService = LockPatternUtilsCache.getInstance(
ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")));
}
return mLockSettingsService;
}
private int getLockString(int userId) {
try {
int quality = (int) getLockSettings().getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
switch (quality) {
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
return R.string.lock_to_app_unlock_pin;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
return R.string.lock_to_app_unlock_password;
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
if (getLockSettings().getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false,
userId)) {
return R.string.lock_to_app_unlock_pattern;
}
}
} catch (RemoteException e) {
}
return 0;
}
public void clearPrompt() {
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
}
public void showLockTaskPrompt(TaskRecord task) {
clearPrompt();
mRequestedTask = task;
final int unlockStringId = getLockString(task.userId);
final Resources r = Resources.getSystem();
final String description= r.getString(mAccessibilityService.isEnabled()
? R.string.lock_to_app_description_accessible
: R.string.lock_to_app_description);
AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
.setTitle(r.getString(R.string.lock_to_app_title))
.setMessage(description)
.setPositiveButton(r.getString(R.string.lock_to_app_positive), this)
.setNegativeButton(r.getString(R.string.lock_to_app_negative), this);
if (unlockStringId != 0) {
builder.setView(R.layout.lock_to_app_checkbox);
}
mDialog = builder.create();
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mDialog.getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mDialog.show();
if (unlockStringId != 0) {
String unlockString = mContext.getString(unlockStringId);
mCheckbox = (CheckBox) mDialog.findViewById(R.id.lock_to_app_checkbox);
mCheckbox.setText(unlockString);
// Remember state.
try {
boolean useLock = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED) != 0;
mCheckbox.setChecked(useLock);
} catch (SettingNotFoundException e) {
}
} else {
mCheckbox = null;
}
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (DialogInterface.BUTTON_POSITIVE == which) {
Slog.d(TAG, "accept lock-to-app request");
// Set whether to use the lock screen when exiting.
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
mCheckbox != null && mCheckbox.isChecked() ? 1 : 0);
// Start lock-to-app.
mService.startLockTaskMode(mRequestedTask);
} else {
Slog.d(TAG, "ignore lock-to-app request");
}
}
}