Split app info into several screens

The root screen now only has the uninstall/force stop/disable buttons
and the rest has moved to sub screens listed in a preference list.
The root screen as UI approximate to the new mocks, but the separated
screens (storage, launch by default, etc.) have yet to receive their
visual overhaul.

Bug: 19511439
Change-Id: I4e01fbaefc69e0652edea2429d9e9b028c78e825
This commit is contained in:
Jason Monk
2015-02-24 11:35:29 -05:00
parent a330b1a093
commit cd91128a2d
16 changed files with 2066 additions and 1493 deletions

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2015, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbarStyle="@integer/preference_scrollbar_style">
<LinearLayout
android:id="@+id/all_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="5dip"
android:orientation="vertical">
<!-- Prefered activities section -->
<TextView android:id="@+id/auto_launch_title"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/auto_launch_label" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView android:id="@+id/auto_launch"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_alignParentStart="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/auto_launch"
android:paddingTop="4dip"
android:orientation="horizontal">
<View
android:layout_width="120dip"
android:layout_height="0dip"
android:layout_weight="0.4" />
<View
android:layout_width="0dip"
android:layout_height="0dip"
android:visibility="invisible"
android:layout_weight="0.2" />
<Button
android:id="@+id/clear_activities_button"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_weight="0.4"
android:text="@string/clear_activities" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@@ -16,448 +16,43 @@
** limitations under the License.
*/
-->
<ScrollView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/all_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbarStyle="@integer/preference_scrollbar_style">
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<!-- App snippet with buttons -->
<LinearLayout
android:id="@+id/all_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="5dip"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingTop="5dip"
android:paddingBottom="10dip"
android:orientation="vertical">
<!-- App snippet with buttons -->
<LinearLayout
<!-- Application snippet label, version and icon -->
<include
layout="@layout/manage_applications_item"
android:id="@+id/app_snippet" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
android:layout_height="5dp" />
<!-- Application snippet label, version and icon -->
<include
layout="@layout/manage_applications_item"
android:id="@+id/app_snippet" />
<!-- Force stop and uninstall buttons -->
<include
layout="@layout/two_buttons_panel"
android:id="@+id/control_buttons_panel"/>
<!-- Force stop and uninstall buttons -->
<include
layout="@layout/two_buttons_panel"
android:id="@+id/control_buttons_panel"/>
<!-- Force stop and uninstall buttons -->
<include
layout="@layout/two_buttons_panel"
android:id="@+id/more_control_buttons_panel"/>
<!-- Force stop and uninstall buttons -->
<include
layout="@layout/two_buttons_panel"
android:id="@+id/more_control_buttons_panel"/>
<!-- Ban notifications for this package -->
<CheckBox android:id="@+id/notification_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginTop="4dip"
android:text="@string/app_notifications_switch_label" />
</LinearLayout>
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/storage_label" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/total_size_prefix"
android:text="@string/total_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/total_size_text"
android:paddingTop="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/application_size_prefix"
android:text="@string/application_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/application_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/external_code_size_prefix"
android:text="@string/external_code_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/external_code_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/info_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/data_size_prefix"
android:text="@string/data_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/data_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/external_data_size_prefix"
android:text="@string/external_data_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/external_data_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<!-- Clear data and install location buttons -->
<include
layout="@layout/two_buttons_panel"
android:id="@+id/data_buttons_panel"/>
</LinearLayout>
<!-- Clear cache section -->
<RelativeLayout
android:id="@+id/cache_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/cache_header"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/cache_header_label" />
<LinearLayout
android:id="@+id/cache_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:layout_below="@id/cache_header"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="-1dip">
<TextView
android:text="@string/cache_size_label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:gravity="center_vertical" />
<ImageView
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/cache_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/cache_size"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="4dip"
android:orientation="horizontal">
<View
android:layout_width="120dip"
android:layout_height="0dip"
android:layout_weight="0.4" />
<View
android:layout_width="0dip"
android:layout_height="0dip"
android:visibility="invisible"
android:layout_weight="0.2" />
<Button
android:id="@+id/clear_cache_button"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_weight="0.4"
android:text="@string/clear_cache_btn_text" />
</LinearLayout>
</RelativeLayout>
<!-- Prefered activities section -->
<TextView android:id="@+id/auto_launch_title"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/auto_launch_label" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView android:id="@+id/auto_launch"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_alignParentStart="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/auto_launch"
android:paddingTop="4dip"
android:orientation="horizontal">
<View
android:layout_width="120dip"
android:layout_height="0dip"
android:layout_weight="0.4" />
<View
android:layout_width="0dip"
android:layout_height="0dip"
android:visibility="invisible"
android:layout_weight="0.2" />
<Button
android:id="@+id/clear_activities_button"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_weight="0.4"
android:text="@string/clear_activities" />
</LinearLayout>
</RelativeLayout>
<!-- Screen compatibility section -->
<LinearLayout android:id="@+id/screen_compatibility_section"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/screen_compatibility_label" />
<TextView android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_alignParentStart="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:text="@string/screen_compatibility_text"/>
<CheckBox android:id="@+id/ask_compatibility_cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dip"
android:layout_gravity="start"
android:text="@string/ask_compatibility" />
<CheckBox android:id="@+id/enable_compatibility_cb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dip"
android:layout_gravity="start"
android:text="@string/enable_compatibility" />
</LinearLayout>
<!-- Permissions section -->
<LinearLayout
android:id="@+id/permissions_section"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/permissions_label" />
<TextView android:id="@+id/security_settings_billing_desc"
android:text="@string/security_settings_billing_desc"
android:textColor="#ffffb060"
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/security_settings_billing_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/security_settings_premium_sms_desc" />
<Spinner
android:id="@+id/security_settings_premium_sms_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:spinnerMode="dropdown" />
</LinearLayout>
<TextView android:id="@+id/security_settings_desc"
android:text="@string/security_settings_desc"
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/security_settings_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2015, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbarStyle="@integer/preference_scrollbar_style">
<LinearLayout
android:id="@+id/all_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="5dip"
android:orientation="vertical">
<!-- Permissions section -->
<LinearLayout
android:id="@+id/permissions_section"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/permissions_label" />
<TextView android:id="@+id/security_settings_billing_desc"
android:text="@string/security_settings_billing_desc"
android:textColor="#ffffb060"
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/security_settings_billing_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/security_settings_premium_sms_desc" />
<Spinner
android:id="@+id/security_settings_premium_sms_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:spinnerMode="dropdown" />
</LinearLayout>
<TextView android:id="@+id/security_settings_desc"
android:text="@string/security_settings_desc"
android:textAppearance="?android:attr/textAppearanceSmall"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/security_settings_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -0,0 +1,307 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2015, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbarStyle="@integer/preference_scrollbar_style">
<LinearLayout
android:id="@+id/all_details"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="5dip"
android:orientation="vertical">
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/storage_label" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/total_size_prefix"
android:text="@string/total_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/total_size_text"
android:paddingTop="6dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/application_size_prefix"
android:text="@string/application_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/application_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/external_code_size_prefix"
android:text="@string/external_code_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/external_code_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/info_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/data_size_prefix"
android:text="@string/data_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/data_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:paddingTop="-1dip">
<TextView
android:id="@+id/external_data_size_prefix"
android:text="@string/external_data_size_label"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:paddingTop="6dip" />
<ImageView
android:id="@+id/info_size_dots"
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/external_data_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<!-- Clear data and install location buttons -->
<include
layout="@layout/two_buttons_panel"
android:id="@+id/data_buttons_panel"/>
</LinearLayout>
<!-- Clear cache section -->
<RelativeLayout
android:id="@+id/cache_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/cache_header"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="8dip"
android:text="@string/cache_header_label" />
<LinearLayout
android:id="@+id/cache_size"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="true"
android:layout_below="@id/cache_header"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="-1dip">
<TextView
android:text="@string/cache_size_label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:gravity="center_vertical" />
<ImageView
android:src="@drawable/dotted_line_480px"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="1px"
android:layout_gravity="bottom"
android:layout_marginStart="1dip"
android:layout_marginEnd="1dip"
android:layout_marginBottom="4dip"
android:scaleType="center"
android:contentDescription="@null" />
<TextView
android:id="@+id/cache_size_text"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="6dip"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:maxLines="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/cache_size"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="4dip"
android:orientation="horizontal">
<View
android:layout_width="120dip"
android:layout_height="0dip"
android:layout_weight="0.4" />
<View
android:layout_width="0dip"
android:layout_height="0dip"
android:visibility="invisible"
android:layout_weight="0.2" />
<Button
android:id="@+id/clear_cache_button"
android:layout_width="120dip"
android:layout_height="wrap_content"
android:layout_weight="0.4"
android:text="@string/clear_cache_btn_text" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@@ -5922,4 +5922,37 @@
<string name="imei_information_summary">IMEI relative information</string>
<string name="slot_number">(Slot<xliff:g id="slot_num">%1$d</xliff:g>)</string>
<!-- New strings needed for App Info 2 -->
<!-- Preference label for app default launch settings -->
<string name="launch_by_default">Launch by default</string>
<!-- Summary for app storage preference -->
<string name="storage_summary_format"><xliff:g id="size" example="30.00MB">%1$s</xliff:g> used in <xliff:g id="storage_type" example="internal memory">%2$s</xliff:g></string>
<!-- Internal storage label -->
<string name="storage_type_internal">internal memory</string>
<!-- External storage label -->
<string name="storage_type_external">external memory</string>
<!-- App notification summary with notifications enabled -->
<string name="notifications_enabled">On</string>
<!-- App notification summary with notifications disabled -->
<string name="notifications_disabled">Block</string>
<!-- App notification summary with notifications sensitive -->
<string name="notifications_sensitive">Sensitive</string>
<!-- App notification summary with notifications priority -->
<string name="notifications_priority">Priority</string>
<!-- App notification summary with notifications priority and sensitive -->
<string name="notifications_priority_sensitive">Priority &amp; Sensitive</string>
<!-- Permissions preference summary -->
<plurals name="permissions_summary">
<item quantity="one"><xliff:g id="count" example="1">%d</xliff:g> permission granted</item>
<item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> permissions granted</item>
</plurals>
<!-- Launch defaults preference summary with some set -->
<string name="launch_defaults_some">Some defaults set</string>
<!-- Launch defaults preference summary with none set -->
<string name="launch_defaults_none">No defaults set</string>
</resources>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/application_info_label">
<com.android.settings.applications.HeaderPreference
android:key="header_view"
android:layout="@layout/installed_app_details" />
<Preference
android:key="notification_settings"
android:title="@string/notification_section_header"
android:selectable="true" />
<Preference
android:key="storage_settings"
android:title="@string/storage_settings"
android:selectable="true" />
<Preference
android:key="permission_settings"
android:title="@string/permissions_label"
android:selectable="true" />
<Preference
android:key="data_settings"
android:title="@string/data_size_label"
android:selectable="true" />
<Preference
android:key="preferred_settings"
android:title="@string/launch_by_default"
android:selectable="true" />
</PreferenceScreen>

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
public class AppHeader {
public static void createAppHeader(final Activity activity, Drawable icon, CharSequence label,
final Intent settingsIntent) {
final View content = activity.findViewById(R.id.main_content);
final ViewGroup contentParent = (ViewGroup) content.getParent();
final View bar = activity.getLayoutInflater().inflate(R.layout.app_header,
contentParent, false);
final ImageView appIcon = (ImageView) bar.findViewById(R.id.app_icon);
appIcon.setImageDrawable(icon);
final TextView appName = (TextView) bar.findViewById(R.id.app_name);
appName.setText(label);
final View appSettings = bar.findViewById(R.id.app_settings);
if (settingsIntent == null) {
appSettings.setVisibility(View.GONE);
} else {
appSettings.setClickable(true);
appSettings.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
activity.startActivity(settingsIntent);
}
});
}
contentParent.addView(bar, 0);
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.hardware.usb.IUsbManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ServiceManager;
import android.os.UserManager;
import android.preference.PreferenceFragment;
import android.util.Log;
import com.android.settings.SettingsActivity;
import com.android.settings.applications.ApplicationsState.AppEntry;
import java.util.ArrayList;
public abstract class AppInfoBase extends PreferenceFragment
implements ApplicationsState.Callbacks {
public static final String ARG_PACKAGE_NAME = "package";
protected static final String TAG = AppInfoBase.class.getSimpleName();
protected static final boolean localLOGV = false;
protected boolean mAppControlRestricted = false;
protected ApplicationsState mState;
private ApplicationsState.Session mSession;
protected ApplicationsState.AppEntry mAppEntry;
protected PackageInfo mPackageInfo;
protected String mPackageName;
protected IUsbManager mUsbManager;
protected DevicePolicyManager mDpm;
protected UserManager mUserManager;
protected PackageManager mPm;
// Dialog identifiers used in showDialog
protected static final int DLG_BASE = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mState = ApplicationsState.getInstance(getActivity().getApplication());
mSession = mState.newSession(this);
Context context = getActivity();
mDpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mPm = context.getPackageManager();
IBinder b = ServiceManager.getService(Context.USB_SERVICE);
mUsbManager = IUsbManager.Stub.asInterface(b);
// Need to make sure we have loaded applications at this point.
mSession.resume();
retrieveAppEntry();
}
@Override
public void onResume() {
super.onResume();
mAppControlRestricted = mUserManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL);
mSession.resume();
if (!refreshUi()) {
setIntentAndFinish(true, true);
}
}
@Override
public void onPause() {
super.onPause();
mSession.pause();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mSession.release();
}
protected String retrieveAppEntry() {
final Bundle args = getArguments();
mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
if (mPackageName == null) {
Intent intent = (args == null) ?
getActivity().getIntent() : (Intent) args.getParcelable("intent");
if (intent != null) {
mPackageName = intent.getData().getSchemeSpecificPart();
}
}
mAppEntry = mState.getEntry(mPackageName);
if (mAppEntry != null) {
// Get application info again to refresh changed properties of application
try {
mPackageInfo = mPm.getPackageInfo(mAppEntry.info.packageName,
PackageManager.GET_DISABLED_COMPONENTS |
PackageManager.GET_UNINSTALLED_PACKAGES |
PackageManager.GET_SIGNATURES);
} catch (NameNotFoundException e) {
Log.e(TAG, "Exception when retrieving package:" + mAppEntry.info.packageName, e);
}
} else {
Log.w(TAG, "Missing AppEntry; maybe reinstalling?");
mPackageInfo = null;
}
return mPackageName;
}
protected void setIntentAndFinish(boolean finish, boolean appChanged) {
if (localLOGV) Log.i(TAG, "appChanged="+appChanged);
Intent intent = new Intent();
intent.putExtra(ManageApplications.APP_CHG, appChanged);
SettingsActivity sa = (SettingsActivity)getActivity();
sa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
}
protected void showDialogInner(int id, int moveErrorCode) {
DialogFragment newFragment = new MyAlertDialogFragment(id, moveErrorCode);
newFragment.setTargetFragment(this, 0);
newFragment.show(getFragmentManager(), "dialog " + id);
}
protected abstract boolean refreshUi();
protected abstract AlertDialog createDialog(int id, int errorCode);
@Override
public void onRunningStateChanged(boolean running) { }
@Override
public void onRebuildComplete(ArrayList<AppEntry> apps) { }
@Override
public void onPackageIconChanged() { }
@Override
public void onPackageSizeChanged(String packageName) { }
@Override
public void onAllSizesComputed() { }
@Override
public void onPackageListChanged() {
refreshUi();
}
public class MyAlertDialogFragment extends DialogFragment {
public MyAlertDialogFragment(int id, int errorCode) {
Bundle args = new Bundle();
args.putInt("id", id);
args.putInt("moveError", errorCode);
setArguments(args);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int id = getArguments().getInt("id");
int errorCode = getArguments().getInt("moveError");
Dialog dialog = createDialog(id, errorCode);
if (dialog == null) {
throw new IllegalArgumentException("unknown id " + id);
}
return dialog;
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.os.Bundle;
import android.util.Log;
import com.android.settings.AppHeader;
public abstract class AppInfoWithHeader extends AppInfoBase {
private boolean mCreated;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (mCreated) {
Log.w(TAG, "onActivityCreated: ignoring duplicate call");
return;
}
mCreated = true;
if (mPackageInfo == null) return;
AppHeader.createAppHeader(getActivity(), mPackageInfo.applicationInfo.loadIcon(mPm),
mPackageInfo.applicationInfo.loadLabel(mPm), null);
}
}

View File

@@ -0,0 +1,190 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.app.AlertDialog;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.BulletSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AppLaunchSettings extends AppInfoWithHeader implements OnClickListener {
private Button mActivitiesButton;
private AppWidgetManager mAppWidgetManager;
private View mRootView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAppWidgetManager = AppWidgetManager.getInstance(getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.app_preferred_settings, container, false);
final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
Utils.forceCustomPadding(allDetails, true /* additive padding */);
mActivitiesButton = (Button) view.findViewById(R.id.clear_activities_button);
mRootView = view;
return view;
}
@Override
protected boolean refreshUi() {
retrieveAppEntry();
boolean hasBindAppWidgetPermission =
mAppWidgetManager.hasBindAppWidgetPermission(mAppEntry.info.packageName);
TextView autoLaunchTitleView = (TextView) mRootView.findViewById(R.id.auto_launch_title);
TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch);
boolean autoLaunchEnabled = hasPreferredActivities(mPm, mPackageName)
|| hasUsbDefaults(mUsbManager, mPackageName);
if (!autoLaunchEnabled && !hasBindAppWidgetPermission) {
resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView);
} else {
boolean useBullets = hasBindAppWidgetPermission && autoLaunchEnabled;
if (hasBindAppWidgetPermission) {
autoLaunchTitleView.setText(R.string.auto_launch_label_generic);
} else {
autoLaunchTitleView.setText(R.string.auto_launch_label);
}
CharSequence text = null;
int bulletIndent = getResources()
.getDimensionPixelSize(R.dimen.installed_app_details_bullet_offset);
if (autoLaunchEnabled) {
CharSequence autoLaunchEnableText = getText(R.string.auto_launch_enable_text);
SpannableString s = new SpannableString(autoLaunchEnableText);
if (useBullets) {
s.setSpan(new BulletSpan(bulletIndent), 0, autoLaunchEnableText.length(), 0);
}
text = (text == null) ?
TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n");
}
if (hasBindAppWidgetPermission) {
CharSequence alwaysAllowBindAppWidgetsText =
getText(R.string.always_allow_bind_appwidgets_text);
SpannableString s = new SpannableString(alwaysAllowBindAppWidgetsText);
if (useBullets) {
s.setSpan(new BulletSpan(bulletIndent),
0, alwaysAllowBindAppWidgetsText.length(), 0);
}
text = (text == null) ?
TextUtils.concat(s, "\n") : TextUtils.concat(text, "\n", s, "\n");
}
autoLaunchView.setText(text);
mActivitiesButton.setEnabled(true);
mActivitiesButton.setOnClickListener(this);
}
return true;
}
private void resetLaunchDefaultsUi(TextView title, TextView autoLaunchView) {
title.setText(R.string.auto_launch_label);
autoLaunchView.setText(R.string.auto_launch_disable_text);
// Disable clear activities button
mActivitiesButton.setEnabled(false);
}
@Override
protected AlertDialog createDialog(int id, int errorCode) {
// No dialogs for preferred launch settings.
return null;
}
@Override
public void onClick(View v) {
if (v == mActivitiesButton) {
if (mUsbManager != null) {
mPm.clearPackagePreferredActivities(mPackageName);
try {
mUsbManager.clearDefaults(mPackageName, UserHandle.myUserId());
} catch (RemoteException e) {
Log.e(TAG, "mUsbManager.clearDefaults", e);
}
mAppWidgetManager.setBindAppWidgetPermission(mPackageName, false);
TextView autoLaunchTitleView =
(TextView) mRootView.findViewById(R.id.auto_launch_title);
TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch);
resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView);
}
}
}
private static boolean hasUsbDefaults(IUsbManager usbManager, String packageName) {
try {
if (usbManager != null) {
return usbManager.hasDefaults(packageName, UserHandle.myUserId());
}
} catch (RemoteException e) {
Log.e(TAG, "mUsbManager.hasDefaults", e);
}
return false;
}
private static boolean hasPreferredActivities(PackageManager pm, String packageName) {
// Get list of preferred activities
List<ComponentName> prefActList = Collections.emptyList();
// Intent list cannot be null. so pass empty list
List<IntentFilter> intentList = Collections.emptyList();
pm.getPreferredActivities(intentList, prefActList, packageName);
if (localLOGV) {
Log.i(TAG, "Have " + prefActList.size() + " number of activities in preferred list");
}
return prefActList.size() > 0;
}
public static CharSequence getSummary(AppEntry appEntry, IUsbManager usbManager,
PackageManager pm, Context context) {
String packageName = appEntry.info.packageName;
boolean hasPreferred = hasPreferredActivities(pm, packageName)
|| hasUsbDefaults(usbManager, packageName);
return context.getString(hasPreferred
? R.string.launch_defaults_some
: R.string.launch_defaults_none);
}
}

View File

@@ -0,0 +1,221 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.app.AlertDialog;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AppSecurityPermissions;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.android.internal.telephony.ISms;
import com.android.internal.telephony.SmsUsageMonitor;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import java.util.ArrayList;
public class AppPermissionSettings extends AppInfoWithHeader {
private ISms mSmsManager;
private View mRootView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSmsManager = ISms.Stub.asInterface(ServiceManager.getService("isms"));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.permission_settings, container, false);
final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
Utils.forceCustomPadding(allDetails, true /* additive padding */);
mRootView = view;
return view;
}
@Override
protected boolean refreshUi() {
retrieveAppEntry();
// Security permissions section
LinearLayout permsView = (LinearLayout) mRootView.findViewById(R.id.permissions_section);
AppSecurityPermissions asp = new AppSecurityPermissions(getActivity(), mPackageName);
int premiumSmsPermission = getPremiumSmsPermission(mPackageName);
// Premium SMS permission implies the app also has SEND_SMS permission, so the original
// application permissions list doesn't have to be shown/hidden separately. The premium
// SMS subsection should only be visible if the app has tried to send to a premium SMS.
if (asp.getPermissionCount() > 0
|| premiumSmsPermission != SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
permsView.setVisibility(View.VISIBLE);
} else {
permsView.setVisibility(View.GONE);
}
// Premium SMS permission subsection
TextView securityBillingDesc = (TextView) permsView.findViewById(
R.id.security_settings_billing_desc);
LinearLayout securityBillingList = (LinearLayout) permsView.findViewById(
R.id.security_settings_billing_list);
if (premiumSmsPermission != SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN) {
// Show the premium SMS permission selector
securityBillingDesc.setVisibility(View.VISIBLE);
securityBillingList.setVisibility(View.VISIBLE);
Spinner spinner = (Spinner) permsView.findViewById(
R.id.security_settings_premium_sms_list);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(),
R.array.security_settings_premium_sms_values,
android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
// List items are in the same order as SmsUsageMonitor constants, offset by 1.
spinner.setSelection(premiumSmsPermission - 1);
spinner.setOnItemSelectedListener(new PremiumSmsSelectionListener(
mPackageName, mSmsManager));
} else {
// Hide the premium SMS permission selector
securityBillingDesc.setVisibility(View.GONE);
securityBillingList.setVisibility(View.GONE);
}
// App permissions subsection
if (asp.getPermissionCount() > 0) {
// Make the security sections header visible
LinearLayout securityList = (LinearLayout) permsView.findViewById(
R.id.security_settings_list);
securityList.removeAllViews();
securityList.addView(asp.getPermissionsViewWithRevokeButtons());
// If this app is running under a shared user ID with other apps,
// update the description to explain this.
String[] packages = mPm.getPackagesForUid(mPackageInfo.applicationInfo.uid);
if (packages != null && packages.length > 1) {
ArrayList<CharSequence> pnames = new ArrayList<CharSequence>();
for (int i=0; i<packages.length; i++) {
String pkg = packages[i];
if (mPackageInfo.packageName.equals(pkg)) {
continue;
}
try {
ApplicationInfo ainfo = mPm.getApplicationInfo(pkg, 0);
pnames.add(ainfo.loadLabel(mPm));
} catch (PackageManager.NameNotFoundException e) {
}
}
final int N = pnames.size();
if (N > 0) {
final Resources res = getActivity().getResources();
String appListStr;
if (N == 1) {
appListStr = pnames.get(0).toString();
} else if (N == 2) {
appListStr = res.getString(R.string.join_two_items, pnames.get(0),
pnames.get(1));
} else {
appListStr = pnames.get(N-2).toString();
for (int i=N-3; i>=0; i--) {
appListStr = res.getString(i == 0 ? R.string.join_many_items_first
: R.string.join_many_items_middle, pnames.get(i), appListStr);
}
appListStr = res.getString(R.string.join_many_items_last,
appListStr, pnames.get(N-1));
}
TextView descr = (TextView) mRootView.findViewById(
R.id.security_settings_desc);
descr.setText(res.getString(R.string.security_settings_desc_multi,
mPackageInfo.applicationInfo.loadLabel(mPm), appListStr));
}
}
}
return true;
}
private int getPremiumSmsPermission(String packageName) {
try {
if (mSmsManager != null) {
return mSmsManager.getPremiumSmsPermission(packageName);
}
} catch (RemoteException ex) {
// ignored
}
return SmsUsageMonitor.PREMIUM_SMS_PERMISSION_UNKNOWN;
}
@Override
protected AlertDialog createDialog(int id, int errorCode) {
// No dialogs for Permissions screen.
return null;
}
public static CharSequence getSummary(AppEntry appEntry, Context context) {
AppSecurityPermissions asp = new AppSecurityPermissions(context,
appEntry.info.packageName);
int count = asp.getPermissionCount();
return context.getResources().getQuantityString(R.plurals.permissions_summary,
count, count);
}
private static class PremiumSmsSelectionListener implements AdapterView.OnItemSelectedListener {
private final String mPackageName;
private final ISms mSmsManager;
PremiumSmsSelectionListener(String packageName, ISms smsManager) {
mPackageName = packageName;
mSmsManager = smsManager;
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
if (position >= 0 && position < 3) {
if (localLOGV) Log.d(TAG, "Selected premium SMS policy " + position);
setPremiumSmsPermission(mPackageName, (position + 1));
} else {
Log.e(TAG, "Error: unknown premium SMS policy " + position);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Ignored
}
private void setPremiumSmsPermission(String packageName, int permission) {
try {
if (mSmsManager != null) {
mSmsManager.setPremiumSmsPermission(packageName, permission);
}
} catch (RemoteException ex) {
// ignored
}
}
}
}

View File

@@ -0,0 +1,501 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.applications.ApplicationsState.Callbacks;
public class AppStorageSettings extends AppInfoWithHeader implements OnClickListener, Callbacks {
private static final String TAG = "AppStorageSettings";
//internal constants used in Handler
private static final int OP_SUCCESSFUL = 1;
private static final int OP_FAILED = 2;
private static final int MSG_CLEAR_USER_DATA = 1;
private static final int MSG_CLEAR_CACHE = 3;
private static final int MSG_PACKAGE_MOVE = 4;
// invalid size value used initially and also when size retrieval through PackageManager
// fails for whatever reason
private static final int SIZE_INVALID = -1;
// Result code identifiers
public static final int REQUEST_MANAGE_SPACE = 2;
private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 2;
private static final int DLG_MOVE_FAILED = DLG_BASE + 3;
private CanBeOnSdCardChecker mCanBeOnSdCardChecker;
private TextView mTotalSize;
private TextView mAppSize;
private TextView mDataSize;
private TextView mExternalCodeSize;
private TextView mExternalDataSize;
// Views related to cache info
private TextView mCacheSize;
private Button mClearDataButton;
private Button mClearCacheButton;
private Button mMoveAppButton;
private boolean mMoveInProgress = false;
private boolean mCanClearData = true;
private boolean mHaveSizes = false;
private long mLastCodeSize = -1;
private long mLastDataSize = -1;
private long mLastExternalCodeSize = -1;
private long mLastExternalDataSize = -1;
private long mLastCacheSize = -1;
private long mLastTotalSize = -1;
private ClearCacheObserver mClearCacheObserver;
private ClearUserDataObserver mClearDataObserver;
private PackageMoveObserver mPackageMoveObserver;
// Resource strings
private CharSequence mInvalidSizeStr;
private CharSequence mComputingStr;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCanBeOnSdCardChecker = new CanBeOnSdCardChecker();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.storage_settings, container, false);
final ViewGroup allDetails = (ViewGroup)view.findViewById(R.id.all_details);
Utils.forceCustomPadding(allDetails, true /* additive padding */);
mComputingStr = getActivity().getText(R.string.computing_size);
mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
// Set default values on sizes
mTotalSize = (TextView)view.findViewById(R.id.total_size_text);
mAppSize = (TextView)view.findViewById(R.id.application_size_text);
mDataSize = (TextView)view.findViewById(R.id.data_size_text);
mExternalCodeSize = (TextView)view.findViewById(R.id.external_code_size_text);
mExternalDataSize = (TextView)view.findViewById(R.id.external_data_size_text);
if (Environment.isExternalStorageEmulated()) {
((View)mExternalCodeSize.getParent()).setVisibility(View.GONE);
((View)mExternalDataSize.getParent()).setVisibility(View.GONE);
}
// Initialize clear data and move install location buttons
View data_buttons_panel = view.findViewById(R.id.data_buttons_panel);
mMoveAppButton = (Button) data_buttons_panel.findViewById(R.id.left_button);
// Cache section
mCacheSize = (TextView)view.findViewById(R.id.cache_size_text);
mClearCacheButton = (Button)view.findViewById(R.id.clear_cache_button);
mClearDataButton = (Button) data_buttons_panel.findViewById(R.id.right_button);
return view;
}
@Override
public void onClick(View v) {
if (v == mClearCacheButton) {
// Lazy initialization of observer
if (mClearCacheObserver == null) {
mClearCacheObserver = new ClearCacheObserver();
}
mPm.deleteApplicationCacheFiles(mPackageName, mClearCacheObserver);
} else if(v == mClearDataButton) {
if (mAppEntry.info.manageSpaceActivityName != null) {
if (!Utils.isMonkeyRunning()) {
Intent intent = new Intent(Intent.ACTION_DEFAULT);
intent.setClassName(mAppEntry.info.packageName,
mAppEntry.info.manageSpaceActivityName);
startActivityForResult(intent, REQUEST_MANAGE_SPACE);
}
} else {
showDialogInner(DLG_CLEAR_DATA, 0);
}
} else if (v == mMoveAppButton) {
if (mPackageMoveObserver == null) {
mPackageMoveObserver = new PackageMoveObserver();
}
int moveFlags = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
PackageManager.MOVE_INTERNAL : PackageManager.MOVE_EXTERNAL_MEDIA;
mMoveInProgress = true;
refreshButtons();
mPm.movePackage(mAppEntry.info.packageName, mPackageMoveObserver, moveFlags);
}
}
private String getSizeStr(long size) {
if (size == SIZE_INVALID) {
return mInvalidSizeStr.toString();
}
return Formatter.formatFileSize(getActivity(), size);
}
private void refreshSizeInfo() {
if (mAppEntry.size == ApplicationsState.SIZE_INVALID
|| mAppEntry.size == ApplicationsState.SIZE_UNKNOWN) {
mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1;
if (!mHaveSizes) {
mAppSize.setText(mComputingStr);
mDataSize.setText(mComputingStr);
mCacheSize.setText(mComputingStr);
mTotalSize.setText(mComputingStr);
}
mClearDataButton.setEnabled(false);
mClearCacheButton.setEnabled(false);
} else {
mHaveSizes = true;
long codeSize = mAppEntry.codeSize;
long dataSize = mAppEntry.dataSize;
if (Environment.isExternalStorageEmulated()) {
codeSize += mAppEntry.externalCodeSize;
dataSize += mAppEntry.externalDataSize;
} else {
if (mLastExternalCodeSize != mAppEntry.externalCodeSize) {
mLastExternalCodeSize = mAppEntry.externalCodeSize;
mExternalCodeSize.setText(getSizeStr(mAppEntry.externalCodeSize));
}
if (mLastExternalDataSize != mAppEntry.externalDataSize) {
mLastExternalDataSize = mAppEntry.externalDataSize;
mExternalDataSize.setText(getSizeStr( mAppEntry.externalDataSize));
}
}
if (mLastCodeSize != codeSize) {
mLastCodeSize = codeSize;
mAppSize.setText(getSizeStr(codeSize));
}
if (mLastDataSize != dataSize) {
mLastDataSize = dataSize;
mDataSize.setText(getSizeStr(dataSize));
}
long cacheSize = mAppEntry.cacheSize + mAppEntry.externalCacheSize;
if (mLastCacheSize != cacheSize) {
mLastCacheSize = cacheSize;
mCacheSize.setText(getSizeStr(cacheSize));
}
if (mLastTotalSize != mAppEntry.size) {
mLastTotalSize = mAppEntry.size;
mTotalSize.setText(getSizeStr(mAppEntry.size));
}
if ((mAppEntry.dataSize+ mAppEntry.externalDataSize) <= 0 || !mCanClearData) {
mClearDataButton.setEnabled(false);
} else {
mClearDataButton.setEnabled(true);
mClearDataButton.setOnClickListener(this);
}
if (cacheSize <= 0) {
mClearCacheButton.setEnabled(false);
} else {
mClearCacheButton.setEnabled(true);
mClearCacheButton.setOnClickListener(this);
}
}
if (mAppControlRestricted) {
mClearCacheButton.setEnabled(false);
mClearDataButton.setEnabled(false);
}
}
@Override
protected boolean refreshUi() {
retrieveAppEntry();
refreshButtons();
refreshSizeInfo();
return true;
}
private void refreshButtons() {
if (!mMoveInProgress) {
initMoveButton();
initDataButtons();
} else {
mMoveAppButton.setText(R.string.moving);
mMoveAppButton.setEnabled(false);
}
}
private void initDataButtons() {
// If the app doesn't have its own space management UI
// And it's a system app that doesn't allow clearing user data or is an active admin
// Then disable the Clear Data button.
if (mAppEntry.info.manageSpaceActivityName == null
&& ((mAppEntry.info.flags&(ApplicationInfo.FLAG_SYSTEM
| ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA))
== ApplicationInfo.FLAG_SYSTEM
|| mDpm.packageHasActiveAdmins(mPackageName))) {
mClearDataButton.setText(R.string.clear_user_data_text);
mClearDataButton.setEnabled(false);
mCanClearData = false;
} else {
if (mAppEntry.info.manageSpaceActivityName != null) {
mClearDataButton.setText(R.string.manage_space_text);
} else {
mClearDataButton.setText(R.string.clear_user_data_text);
}
mClearDataButton.setOnClickListener(this);
}
if (mAppControlRestricted) {
mClearDataButton.setEnabled(false);
}
}
private void initMoveButton() {
if (Environment.isExternalStorageEmulated()) {
mMoveAppButton.setVisibility(View.INVISIBLE);
return;
}
boolean dataOnly = (mPackageInfo == null) && (mAppEntry != null);
boolean moveDisable = true;
if (dataOnly) {
mMoveAppButton.setText(R.string.move_app);
} else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
mMoveAppButton.setText(R.string.move_app_to_internal);
// Always let apps move to internal storage from sdcard.
moveDisable = false;
} else {
mMoveAppButton.setText(R.string.move_app_to_sdcard);
mCanBeOnSdCardChecker.init();
moveDisable = !mCanBeOnSdCardChecker.check(mAppEntry.info);
}
if (moveDisable || mAppControlRestricted) {
mMoveAppButton.setEnabled(false);
} else {
mMoveAppButton.setOnClickListener(this);
mMoveAppButton.setEnabled(true);
}
}
/*
* Private method to initiate clearing user data when the user clicks the clear data
* button for a system package
*/
private void initiateClearUserData() {
mClearDataButton.setEnabled(false);
// Invoke uninstall or clear user data based on sysPackage
String packageName = mAppEntry.info.packageName;
Log.i(TAG, "Clearing user data for package : " + packageName);
if (mClearDataObserver == null) {
mClearDataObserver = new ClearUserDataObserver();
}
ActivityManager am = (ActivityManager)
getActivity().getSystemService(Context.ACTIVITY_SERVICE);
boolean res = am.clearApplicationUserData(packageName, mClearDataObserver);
if (!res) {
// Clearing data failed for some obscure reason. Just log error for now
Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
showDialogInner(DLG_CANNOT_CLEAR_DATA, 0);
} else {
mClearDataButton.setText(R.string.recompute_size);
}
}
private void processMoveMsg(Message msg) {
int result = msg.arg1;
String packageName = mAppEntry.info.packageName;
// Refresh the button attributes.
mMoveInProgress = false;
if (result == PackageManager.MOVE_SUCCEEDED) {
Log.i(TAG, "Moved resources for " + packageName);
// Refresh size information again.
mState.requestSize(mAppEntry.info.packageName);
} else {
showDialogInner(DLG_MOVE_FAILED, result);
}
refreshUi();
}
/*
* Private method to handle clear message notification from observer when
* the async operation from PackageManager is complete
*/
private void processClearMsg(Message msg) {
int result = msg.arg1;
String packageName = mAppEntry.info.packageName;
mClearDataButton.setText(R.string.clear_user_data_text);
if(result == OP_SUCCESSFUL) {
Log.i(TAG, "Cleared user data for package : "+packageName);
mState.requestSize(mAppEntry.info.packageName);
} else {
mClearDataButton.setEnabled(true);
}
}
private CharSequence getMoveErrMsg(int errCode) {
switch (errCode) {
case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
return getActivity().getString(R.string.insufficient_storage);
case PackageManager.MOVE_FAILED_DOESNT_EXIST:
return getActivity().getString(R.string.does_not_exist);
case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
return getActivity().getString(R.string.app_forward_locked);
case PackageManager.MOVE_FAILED_INVALID_LOCATION:
return getActivity().getString(R.string.invalid_location);
case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE:
return getActivity().getString(R.string.system_package);
case PackageManager.MOVE_FAILED_INTERNAL_ERROR:
return "";
}
return "";
}
@Override
protected AlertDialog createDialog(int id, int errorCode) {
switch (id) {
case DLG_CLEAR_DATA:
return new AlertDialog.Builder(getActivity())
.setTitle(getActivity().getText(R.string.clear_data_dlg_title))
.setMessage(getActivity().getText(R.string.clear_data_dlg_text))
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Clear user data here
initiateClearUserData();
}
})
.setNegativeButton(R.string.dlg_cancel, null)
.create();
case DLG_CANNOT_CLEAR_DATA:
return new AlertDialog.Builder(getActivity())
.setTitle(getActivity().getText(R.string.clear_failed_dlg_title))
.setMessage(getActivity().getText(R.string.clear_failed_dlg_text))
.setNeutralButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mClearDataButton.setEnabled(false);
//force to recompute changed value
setIntentAndFinish(false, false);
}
})
.create();
case DLG_MOVE_FAILED:
CharSequence msg = getActivity().getString(R.string.move_app_failed_dlg_text,
getMoveErrMsg(errorCode));
return new AlertDialog.Builder(getActivity())
.setTitle(getActivity().getText(R.string.move_app_failed_dlg_title))
.setMessage(msg)
.setNeutralButton(R.string.dlg_ok, null)
.create();
}
return null;
}
@Override
public void onPackageSizeChanged(String packageName) {
if (packageName.equals(mAppEntry.info.packageName)) {
refreshSizeInfo();
}
}
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (getView() == null) {
return;
}
switch (msg.what) {
case MSG_CLEAR_USER_DATA:
processClearMsg(msg);
break;
case MSG_CLEAR_CACHE:
// Refresh size info
mState.requestSize(mPackageName);
break;
case MSG_PACKAGE_MOVE:
processMoveMsg(msg);
break;
}
}
};
public static CharSequence getSummary(AppEntry appEntry, Context context) {
if (appEntry.size == ApplicationsState.SIZE_INVALID
|| appEntry.size == ApplicationsState.SIZE_UNKNOWN) {
return context.getText(R.string.computing_size);
} else {
CharSequence storageType = context.getString(
(appEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0
? R.string.storage_type_external
: R.string.storage_type_internal);
return context.getString(R.string.storage_summary_format,
getSize(appEntry, context), storageType);
}
}
private static CharSequence getSize(AppEntry appEntry, Context context) {
long size = appEntry.size;
if (size == SIZE_INVALID) {
return context.getText(R.string.invalid_size_value);
}
return Formatter.formatFileSize(context, size);
}
class ClearCacheObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
final Message msg = mHandler.obtainMessage(MSG_CLEAR_CACHE);
msg.arg1 = succeeded ? OP_SUCCESSFUL : OP_FAILED;
mHandler.sendMessage(msg);
}
}
class ClearUserDataObserver extends IPackageDataObserver.Stub {
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
final Message msg = mHandler.obtainMessage(MSG_CLEAR_USER_DATA);
msg.arg1 = succeeded?OP_SUCCESSFUL:OP_FAILED;
mHandler.sendMessage(msg);
}
}
class PackageMoveObserver extends IPackageMoveObserver.Stub {
public void packageMoved(String packageName, int returnCode) throws RemoteException {
final Message msg = mHandler.obtainMessage(MSG_PACKAGE_MOVE);
msg.arg1 = returnCode;
mHandler.sendMessage(msg);
}
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.settings.R;
import com.android.settings.Utils;
public class HeaderPreference extends Preference {
private View mRootView;
public HeaderPreference(Context context, AttributeSet attrs) {
super(context, attrs);
final TypedArray a = context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.Preference, 0, 0);
int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
0);
if (layoutResource == 0) {
throw new IllegalArgumentException("HeaderPreference requires a layout to be defined");
}
// Need to create view now so that findViewById can be called immediately.
final View view = LayoutInflater.from(getContext())
.inflate(layoutResource, null, false);
final ViewGroup allDetails = (ViewGroup) view.findViewById(R.id.all_details);
Utils.forceCustomPadding(allDetails, true /* additive padding */);
mRootView = view;
}
@Override
protected View onCreateView(ViewGroup parent) {
return mRootView;
}
public View findViewById(int id) {
return mRootView.findViewById(id);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -37,6 +37,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
@@ -74,30 +75,8 @@ public class AppNotificationSettings extends SettingsPreferenceFragment {
}
mCreated = true;
if (mAppRow == null) return;
final View content = getActivity().findViewById(R.id.main_content);
final ViewGroup contentParent = (ViewGroup) content.getParent();
final View bar = getActivity().getLayoutInflater().inflate(R.layout.app_notification_header,
contentParent, false);
final ImageView appIcon = (ImageView) bar.findViewById(R.id.app_icon);
appIcon.setImageDrawable(mAppRow.icon);
final TextView appName = (TextView) bar.findViewById(R.id.app_name);
appName.setText(mAppRow.label);
final View appSettings = bar.findViewById(R.id.app_settings);
if (mAppRow.settingsIntent == null) {
appSettings.setVisibility(View.GONE);
} else {
appSettings.setClickable(true);
appSettings.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mContext.startActivity(mAppRow.settingsIntent);
}
});
}
contentParent.addView(bar, 0);
AppHeader.createAppHeader(getActivity(), mAppRow.icon, mAppRow.label,
mAppRow.settingsIntent);
}
@Override