diff options
21 files changed, 925 insertions, 360 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a11a948..f2e51a1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1315,6 +1315,18 @@ </intent-filter> </activity> + <!-- Special picker for keyguard widgets --> + <activity android:name="KeyguardAppWidgetPickActivity" + android:label="@string/widget_picker_title" + android:theme="@android:style/Theme.Holo.Wallpaper.NoTitleBar" + android:permission="android.permission.BIND_KEYGUARD_APPWIDGET" + android:finishOnCloseSystemDialogs="true"> + <intent-filter> + <action android:name="android.appwidget.action.KEYGUARD_APPWIDGET_PICK" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + <activity android:name="UsageStats" android:label="@string/usage_stats_label" android:taskAffinity="com.android.settings" android:parentActivityName="Settings"> diff --git a/res/drawable-hdpi/appwidget_item_bg_normal.9.png b/res/drawable-hdpi/appwidget_item_bg_normal.9.png Binary files differnew file mode 100644 index 0000000..baff858 --- /dev/null +++ b/res/drawable-hdpi/appwidget_item_bg_normal.9.png diff --git a/res/drawable-hdpi/appwidget_item_bg_pressed.9.png b/res/drawable-hdpi/appwidget_item_bg_pressed.9.png Binary files differnew file mode 100644 index 0000000..7ec33dd --- /dev/null +++ b/res/drawable-hdpi/appwidget_item_bg_pressed.9.png diff --git a/res/drawable-mdpi/appwidget_item_bg_normal.9.png b/res/drawable-mdpi/appwidget_item_bg_normal.9.png Binary files differnew file mode 100644 index 0000000..976083f --- /dev/null +++ b/res/drawable-mdpi/appwidget_item_bg_normal.9.png diff --git a/res/drawable-mdpi/appwidget_item_bg_pressed.9.png b/res/drawable-mdpi/appwidget_item_bg_pressed.9.png Binary files differnew file mode 100644 index 0000000..8f340d3 --- /dev/null +++ b/res/drawable-mdpi/appwidget_item_bg_pressed.9.png diff --git a/res/drawable-xhdpi/appwidget_item_bg_normal.9.png b/res/drawable-xhdpi/appwidget_item_bg_normal.9.png Binary files differnew file mode 100644 index 0000000..b26f1d2 --- /dev/null +++ b/res/drawable-xhdpi/appwidget_item_bg_normal.9.png diff --git a/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png b/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png Binary files differnew file mode 100644 index 0000000..3871689 --- /dev/null +++ b/res/drawable-xhdpi/appwidget_item_bg_pressed.9.png diff --git a/res/drawable/appwidget_item_bg.xml b/res/drawable/appwidget_item_bg.xml new file mode 100644 index 0000000..b9de6d4 --- /dev/null +++ b/res/drawable/appwidget_item_bg.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_pressed="true" + android:drawable="@drawable/appwidget_item_bg_pressed" /> + + <item android:drawable="@drawable/appwidget_item_bg_normal" /> +</selector> diff --git a/res/layout/keyguard_appwidget_item.xml b/res/layout/keyguard_appwidget_item.xml new file mode 100755 index 0000000..7280098 --- /dev/null +++ b/res/layout/keyguard_appwidget_item.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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" > + <TextView + android:id="@+id/icon_and_label" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="8dip" + android:layout_marginRight="8dip" + android:layout_marginTop="4dip" + android:layout_marginBottom="4dip" + android:background="@drawable/appwidget_item_bg" + android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:textAppearance="?android:attr/textAppearanceMedium" + android:gravity="center_vertical" + android:drawablePadding="8dip" + android:paddingStart="11dip" + android:paddingEnd="11dip" /> +</FrameLayout> diff --git a/res/layout/keyguard_appwidget_pick_layout.xml b/res/layout/keyguard_appwidget_pick_layout.xml new file mode 100644 index 0000000..feb85a5 --- /dev/null +++ b/res/layout/keyguard_appwidget_pick_layout.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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:id="@+id/layout_root" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + <GridView android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:listSelector="@android:color/transparent" + android:id="@+id/widget_list" /> +</LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index 2248c23..d6abe94 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -808,15 +808,6 @@ <!-- Title for PreferenceScreen to launch picker for security method when there is none [CHAR LIMIT=22] --> <string name="unlock_set_unlock_launch_picker_title">Screen lock</string> - <!-- Title for PreferenceScreen to launch picker for a user-selected widget that will live on lock screen [CHAR LIMIT=22] --> - <string name="choose_user_selected_lockscreen_widget_picker_title">Add widget</string> - - <!-- String to display if there is no user-selected widget on lock screen [CHAR LIMIT=22] --> - <string name="widget_none">None</string> - - <!-- String to display if the clock status widget is selected (it is the default) [CHAR LIMIT=22] --> - <string name="widget_default">Clock</string> - <!-- Title for PreferenceScreen to change security method: None/Pattern/PIN/Password [CHAR LIMIT=22] --> <string name="unlock_set_unlock_launch_picker_change_title">Change lock screen</string> diff --git a/res/xml/security_settings_biometric_weak.xml b/res/xml/security_settings_biometric_weak.xml index 489a200..c830e6f 100644 --- a/res/xml/security_settings_biometric_weak.xml +++ b/res/xml/security_settings_biometric_weak.xml @@ -52,12 +52,6 @@ android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/> <PreferenceScreen - android:key="choose_user_selected_lockscreen_widget" - android:title="@string/choose_user_selected_lockscreen_widget_picker_title" - android:summary="" - android:persistent="false"/> - - <PreferenceScreen android:fragment="com.android.settings.OwnerInfoSettings" android:key="owner_info_settings" android:title="@string/owner_info_settings_title" diff --git a/res/xml/security_settings_chooser.xml b/res/xml/security_settings_chooser.xml index 98422ba..60d3a9f 100644 --- a/res/xml/security_settings_chooser.xml +++ b/res/xml/security_settings_chooser.xml @@ -27,12 +27,6 @@ android:persistent="false"/> <PreferenceScreen - android:key="choose_user_selected_lockscreen_widget" - android:title="@string/choose_user_selected_lockscreen_widget_picker_title" - android:summary="" - android:persistent="false"/> - - <PreferenceScreen android:fragment="com.android.settings.OwnerInfoSettings" android:key="owner_info_settings" android:title="@string/owner_info_settings_title" diff --git a/res/xml/security_settings_password.xml b/res/xml/security_settings_password.xml index 8374a13..0e9c71d 100644 --- a/res/xml/security_settings_password.xml +++ b/res/xml/security_settings_password.xml @@ -39,12 +39,6 @@ android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/> <PreferenceScreen - android:key="choose_user_selected_lockscreen_widget" - android:title="@string/choose_user_selected_lockscreen_widget_picker_title" - android:summary="" - android:persistent="false"/> - - <PreferenceScreen android:fragment="com.android.settings.OwnerInfoSettings" android:key="owner_info_settings" android:title="@string/owner_info_settings_title" diff --git a/res/xml/security_settings_pattern.xml b/res/xml/security_settings_pattern.xml index 8015785..d47a99d 100644 --- a/res/xml/security_settings_pattern.xml +++ b/res/xml/security_settings_pattern.xml @@ -43,12 +43,6 @@ android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/> <PreferenceScreen - android:key="choose_user_selected_lockscreen_widget" - android:title="@string/choose_user_selected_lockscreen_widget_picker_title" - android:summary="" - android:persistent="false"/> - - <PreferenceScreen android:fragment="com.android.settings.OwnerInfoSettings" android:key="owner_info_settings" android:title="@string/owner_info_settings_title" diff --git a/res/xml/security_settings_pin.xml b/res/xml/security_settings_pin.xml index 70e95bd..d44200f 100644 --- a/res/xml/security_settings_pin.xml +++ b/res/xml/security_settings_pin.xml @@ -39,12 +39,6 @@ android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/> <PreferenceScreen - android:key="choose_user_selected_lockscreen_widget" - android:title="@string/choose_user_selected_lockscreen_widget_picker_title" - android:summary="" - android:persistent="false"/> - - <PreferenceScreen android:fragment="com.android.settings.OwnerInfoSettings" android:key="owner_info_settings" android:title="@string/owner_info_settings_title" diff --git a/src/com/android/settings/ActivityPicker.java b/src/com/android/settings/ActivityPicker.java index ac79cea..edbccc3 100644 --- a/src/com/android/settings/ActivityPicker.java +++ b/src/com/android/settings/ActivityPicker.java @@ -201,7 +201,7 @@ public class ActivityPicker extends AlertActivity implements /** * Item that appears in a {@link PickAdapter} list. */ - public static class Item { + public static class Item implements AppWidgetLoader.LabelledItem { protected static IconResizer sResizer; protected IconResizer getResizer(Context context) { @@ -262,6 +262,10 @@ public class ActivityPicker extends AlertActivity implements } return intent; } + + public CharSequence getLabel() { + return label; + } } private final LayoutInflater mInflater; @@ -471,5 +475,5 @@ public class ActivityPicker extends AlertActivity implements public int getOpacity() { return PixelFormat.TRANSLUCENT; } - } + } } diff --git a/src/com/android/settings/AppWidgetLoader.java b/src/com/android/settings/AppWidgetLoader.java new file mode 100644 index 0000000..9155e60 --- /dev/null +++ b/src/com/android/settings/AppWidgetLoader.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2012 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.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Parcelable; +import android.util.Log; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class AppWidgetLoader<Item extends AppWidgetLoader.LabelledItem> { + private static final String TAG = "AppWidgetAdapter"; + private static final boolean LOGD = AppWidgetPickActivity.LOGD; + + private Context mContext; + private AppWidgetManager mAppWidgetManager; + ItemConstructor<Item> mItemConstructor; + + interface LabelledItem { + CharSequence getLabel(); + } + + public AppWidgetLoader(Context context, AppWidgetManager appWidgetManager, + ItemConstructor<Item> itemConstructor) { + mContext = context; + mAppWidgetManager = appWidgetManager; + mItemConstructor = itemConstructor; + } + + /** + * Create list entries for any custom widgets requested through + * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}. + */ + void putCustomAppWidgets(List<Item> items, Intent intent) { + // get and validate the extras they gave us + ArrayList<AppWidgetProviderInfo> customInfo = null; + ArrayList<Bundle> customExtras = null; + try_custom_items: { + customInfo = intent.getParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_INFO); + if (customInfo == null || customInfo.size() == 0) { + Log.i(TAG, "EXTRA_CUSTOM_INFO not present."); + break try_custom_items; + } + + int customInfoSize = customInfo.size(); + for (int i=0; i<customInfoSize; i++) { + Parcelable p = customInfo.get(i); + if (p == null || !(p instanceof AppWidgetProviderInfo)) { + customInfo = null; + Log.e(TAG, "error using EXTRA_CUSTOM_INFO index=" + i); + break try_custom_items; + } + } + + customExtras = intent.getParcelableArrayListExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS); + if (customExtras == null) { + customInfo = null; + Log.e(TAG, "EXTRA_CUSTOM_INFO without EXTRA_CUSTOM_EXTRAS"); + break try_custom_items; + } + + int customExtrasSize = customExtras.size(); + if (customInfoSize != customExtrasSize) { + customInfo = null; + customExtras = null; + Log.e(TAG, "list size mismatch: EXTRA_CUSTOM_INFO: " + customInfoSize + + " EXTRA_CUSTOM_EXTRAS: " + customExtrasSize); + break try_custom_items; + } + + + for (int i=0; i<customExtrasSize; i++) { + Parcelable p = customExtras.get(i); + if (p == null || !(p instanceof Bundle)) { + customInfo = null; + customExtras = null; + Log.e(TAG, "error using EXTRA_CUSTOM_EXTRAS index=" + i); + break try_custom_items; + } + } + } + + if (LOGD) Log.d(TAG, "Using " + customInfo.size() + " custom items"); + putAppWidgetItems(customInfo, customExtras, items, 0, true); + } + + + /** + * Create list entries for the given {@link AppWidgetProviderInfo} widgets, + * inserting extras if provided. + */ + void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets, + List<Bundle> customExtras, List<Item> items, int categoryFilter, + boolean ignoreFilter) { + if (appWidgets == null) return; + final int size = appWidgets.size(); + for (int i = 0; i < size; i++) { + AppWidgetProviderInfo info = appWidgets.get(i); + + // We remove any widgets whose category isn't included in the filter + if (!ignoreFilter && (info.widgetCategory & categoryFilter) == 0) { + continue; + } + + Item item = mItemConstructor.createItem(mContext, info, + customExtras != null ? customExtras.get(i) : null); + + items.add(item); + } + } + + public interface ItemConstructor<Item> { + Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras); + } + + + /** + * Build and return list of items to be shown in dialog. This will mix both + * installed {@link AppWidgetProviderInfo} and those provided through + * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically. + */ + protected List<Item> getItems(Intent intent) { + boolean sortCustomAppWidgets = + intent.getBooleanExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, true); + + List<Item> items = new ArrayList<Item>(); + + // Default category is home screen + int categoryFilter = intent.getIntExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER, + AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN); + + putInstalledAppWidgets(items, categoryFilter); + + // Sort all items together by label + if (sortCustomAppWidgets) { + putCustomAppWidgets(items, intent); + } + Collections.sort(items, new Comparator<Item>() { + Collator mCollator = Collator.getInstance(); + + public int compare(Item lhs, Item rhs) { + return mCollator.compare(lhs.getLabel(), rhs.getLabel()); + } + }); + if (!sortCustomAppWidgets) { + List<Item> customItems = new ArrayList<Item>(); + putCustomAppWidgets(customItems, intent); + items.addAll(customItems); + } + return items; + } + + /** + * Create list entries for installed {@link AppWidgetProviderInfo} widgets. + */ + void putInstalledAppWidgets(List<Item> items, int categoryFilter) { + List<AppWidgetProviderInfo> installed = mAppWidgetManager.getInstalledProviders(); + putAppWidgetItems(installed, null, items, categoryFilter, false); + } +} diff --git a/src/com/android/settings/AppWidgetPickActivity.java b/src/com/android/settings/AppWidgetPickActivity.java index 953d10c..2bd62c0 100644 --- a/src/com/android/settings/AppWidgetPickActivity.java +++ b/src/com/android/settings/AppWidgetPickActivity.java @@ -18,6 +18,7 @@ package com.android.settings; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; @@ -25,15 +26,11 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.Parcelable; -import android.os.SystemProperties; import android.util.DisplayMetrics; import android.util.Log; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import com.android.settings.ActivityPicker.PickAdapter; + import java.util.List; /** @@ -46,12 +43,11 @@ import java.util.List; * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID}, * otherwise it will return the requested extras. */ -public class AppWidgetPickActivity extends ActivityPicker { +public class AppWidgetPickActivity extends ActivityPicker + implements AppWidgetLoader.ItemConstructor<PickAdapter.Item>{ private static final String TAG = "AppWidgetPickActivity"; - private static final boolean LOGD = false; + static final boolean LOGD = false; - private PackageManager mPackageManager; - private AppWidgetManager mAppWidgetManager; List<PickAdapter.Item> mItems; /** @@ -59,15 +55,16 @@ public class AppWidgetPickActivity extends ActivityPicker { * activity is binding. */ private int mAppWidgetId; - - // Enable testing launcher widgets in keyguard. For testing purposes only. - private final boolean mIgnoreFilter = false || SystemProperties.getBoolean( - "ro.keyguard_ignore_filter", false); + private AppWidgetLoader<PickAdapter.Item> mAppWidgetLoader; + private AppWidgetManager mAppWidgetManager; + private PackageManager mPackageManager; @Override public void onCreate(Bundle icicle) { mPackageManager = getPackageManager(); mAppWidgetManager = AppWidgetManager.getInstance(this); + mAppWidgetLoader = new AppWidgetLoader<PickAdapter.Item> + (this, mAppWidgetManager, this); super.onCreate(icicle); @@ -85,69 +82,69 @@ public class AppWidgetPickActivity extends ActivityPicker { } /** - * Create list entries for any custom widgets requested through - * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}. + * Build and return list of items to be shown in dialog. This will mix both + * installed {@link AppWidgetProviderInfo} and those provided through + * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically. */ - void putCustomAppWidgets(List<PickAdapter.Item> items) { - final Bundle extras = getIntent().getExtras(); - - // get and validate the extras they gave us - ArrayList<AppWidgetProviderInfo> customInfo = null; - ArrayList<Bundle> customExtras = null; - try_custom_items: { - customInfo = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_INFO); - if (customInfo == null || customInfo.size() == 0) { - Log.i(TAG, "EXTRA_CUSTOM_INFO not present."); - break try_custom_items; - } - - int customInfoSize = customInfo.size(); - for (int i=0; i<customInfoSize; i++) { - Parcelable p = customInfo.get(i); - if (p == null || !(p instanceof AppWidgetProviderInfo)) { - customInfo = null; - Log.e(TAG, "error using EXTRA_CUSTOM_INFO index=" + i); - break try_custom_items; - } - } - - customExtras = extras.getParcelableArrayList(AppWidgetManager.EXTRA_CUSTOM_EXTRAS); - if (customExtras == null) { - customInfo = null; - Log.e(TAG, "EXTRA_CUSTOM_INFO without EXTRA_CUSTOM_EXTRAS"); - break try_custom_items; - } - - int customExtrasSize = customExtras.size(); - if (customInfoSize != customExtrasSize) { - Log.e(TAG, "list size mismatch: EXTRA_CUSTOM_INFO: " + customInfoSize - + " EXTRA_CUSTOM_EXTRAS: " + customExtrasSize); - break try_custom_items; - } + @Override + protected List<PickAdapter.Item> getItems() { + mItems = mAppWidgetLoader.getItems(getIntent()); + return mItems; + } + @Override + public PickAdapter.Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) { + CharSequence label = info.label; + Drawable icon = null; - for (int i=0; i<customExtrasSize; i++) { - Parcelable p = customExtras.get(i); - if (p == null || !(p instanceof Bundle)) { - customInfo = null; - customExtras = null; - Log.e(TAG, "error using EXTRA_CUSTOM_EXTRAS index=" + i); - break try_custom_items; + if (info.icon != 0) { + try { + final Resources res = context.getResources(); + final int density = res.getDisplayMetrics().densityDpi; + int iconDensity; + switch (density) { + case DisplayMetrics.DENSITY_MEDIUM: + iconDensity = DisplayMetrics.DENSITY_LOW; + case DisplayMetrics.DENSITY_TV: + iconDensity = DisplayMetrics.DENSITY_MEDIUM; + case DisplayMetrics.DENSITY_HIGH: + iconDensity = DisplayMetrics.DENSITY_MEDIUM; + case DisplayMetrics.DENSITY_XHIGH: + iconDensity = DisplayMetrics.DENSITY_HIGH; + case DisplayMetrics.DENSITY_XXHIGH: + iconDensity = DisplayMetrics.DENSITY_XHIGH; + default: + // The density is some abnormal value. Return some other + // abnormal value that is a reasonable scaling of it. + iconDensity = (int)((density*0.75f)+.5f); } + Resources packageResources = mPackageManager. + getResourcesForApplication(info.provider.getPackageName()); + icon = packageResources.getDrawableForDensity(info.icon, iconDensity); + } catch (NameNotFoundException e) { + Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) + + " for provider: " + info.provider); + } + if (icon == null) { + Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) + + " for provider: " + info.provider); } } - if (LOGD) Log.d(TAG, "Using " + customInfo.size() + " custom items"); - putAppWidgetItems(customInfo, customExtras, items, 0, 0, true); + PickAdapter.Item item = new PickAdapter.Item(context, label, icon); + item.packageName = info.provider.getPackageName(); + item.className = info.provider.getClassName(); + item.extras = extras; + return item; } - + /** * {@inheritDoc} */ @Override public void onClick(DialogInterface dialog, int which) { Intent intent = getIntentForPosition(which); - PickAdapter.Item item = (PickAdapter.Item) mItems.get(which); + PickAdapter.Item item = mItems.get(which); int result; if (item.extras != null) { @@ -173,134 +170,10 @@ public class AppWidgetPickActivity extends ActivityPicker { } setResultData(result, null); } - finish(); - } - - /** - * Create list entries for the given {@link AppWidgetProviderInfo} widgets, - * inserting extras if provided. - */ - void putAppWidgetItems(List<AppWidgetProviderInfo> appWidgets, - List<Bundle> customExtras, List<PickAdapter.Item> items, int categoryFilter, - int featuresFilter, boolean ignoreFilters) { - if (appWidgets == null) return; - final int size = appWidgets.size(); - for (int i = 0; i < size; i++) { - AppWidgetProviderInfo info = appWidgets.get(i); - - // We remove any widgets whose category isn't included in the filter - if (!ignoreFilters && (info.widgetCategory & categoryFilter) == 0) { - continue; - } - - // We remove any widgets who don't have all the features in the features filter - if (!ignoreFilters && (info.widgetFeatures & featuresFilter) != featuresFilter) { - continue; - } - - CharSequence label = info.label; - Drawable icon = null; - - if (info.icon != 0) { - try { - final Resources res = getResources(); - final int density = res.getDisplayMetrics().densityDpi; - int iconDensity; - switch (density) { - case DisplayMetrics.DENSITY_MEDIUM: - iconDensity = DisplayMetrics.DENSITY_LOW; - case DisplayMetrics.DENSITY_TV: - iconDensity = DisplayMetrics.DENSITY_MEDIUM; - case DisplayMetrics.DENSITY_HIGH: - iconDensity = DisplayMetrics.DENSITY_MEDIUM; - case DisplayMetrics.DENSITY_XHIGH: - iconDensity = DisplayMetrics.DENSITY_HIGH; - case DisplayMetrics.DENSITY_XXHIGH: - iconDensity = DisplayMetrics.DENSITY_XHIGH; - default: - // The density is some abnormal value. Return some other - // abnormal value that is a reasonable scaling of it. - iconDensity = (int)((density*0.75f)+.5f); - } - Resources packageResources = mPackageManager. - getResourcesForApplication(info.provider.getPackageName()); - icon = packageResources.getDrawableForDensity(info.icon, iconDensity); - } catch (NameNotFoundException e) { - Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) - + " for provider: " + info.provider); - } - if (icon == null) { - Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) - + " for provider: " + info.provider); - } - } - - PickAdapter.Item item = new PickAdapter.Item(this, label, icon); - - item.packageName = info.provider.getPackageName(); - item.className = info.provider.getClassName(); - - if (customExtras != null) { - item.extras = customExtras.get(i); - } - - items.add(item); - } - } - - /** - * Build and return list of items to be shown in dialog. This will mix both - * installed {@link AppWidgetProviderInfo} and those provided through - * {@link AppWidgetManager#EXTRA_CUSTOM_INFO}, sorting them alphabetically. - */ - @Override - protected List<PickAdapter.Item> getItems() { - final Intent intent = getIntent(); - boolean sortCustomAppWidgets = - intent.getBooleanExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, true); - - List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>(); - - int categoryFilter = AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN; - if (intent.getExtras().containsKey(AppWidgetManager.EXTRA_CATEGORY_FILTER)) { - categoryFilter = intent.getExtras().getInt(AppWidgetManager.EXTRA_CATEGORY_FILTER); - } - - // If not specified, we don't filter on any specific - int featuresFilter = AppWidgetProviderInfo.WIDGET_FEATURES_NONE; - if (intent.getExtras().containsKey(AppWidgetManager.EXTRA_FEATURES_FILTER)) { - featuresFilter = intent.getExtras().getInt(AppWidgetManager.EXTRA_FEATURES_FILTER); - } - - putInstalledAppWidgets(items, categoryFilter, featuresFilter); - // Sort all items together by label - if (sortCustomAppWidgets) { - putCustomAppWidgets(items); - } - Collections.sort(items, new Comparator<PickAdapter.Item>() { - Collator mCollator = Collator.getInstance(); - - public int compare(PickAdapter.Item lhs, PickAdapter.Item rhs) { - return mCollator.compare(lhs.label, rhs.label); - } - }); - if (!sortCustomAppWidgets) { - List<PickAdapter.Item> customItems = new ArrayList<PickAdapter.Item>(); - putCustomAppWidgets(customItems); - items.addAll(customItems); - } - mItems = items; - return items; + finish(); } - /** - * Create list entries for installed {@link AppWidgetProviderInfo} widgets. - */ - void putInstalledAppWidgets(List<PickAdapter.Item> items, int categoryFilter, int featuresFilter) { - List<AppWidgetProviderInfo> installed = mAppWidgetManager.getInstalledProviders(); - putAppWidgetItems(installed, null, items, categoryFilter, featuresFilter, mIgnoreFilter ); - } /** * Convenience method for setting the result code and intent. This method diff --git a/src/com/android/settings/KeyguardAppWidgetPickActivity.java b/src/com/android/settings/KeyguardAppWidgetPickActivity.java new file mode 100644 index 0000000..0afc5b2 --- /dev/null +++ b/src/com/android/settings/KeyguardAppWidgetPickActivity.java @@ -0,0 +1,579 @@ +/* + * Copyright (C) 2012 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.appwidget.AppWidgetHost; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PaintFlagsDrawFilter; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.PaintDrawable; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.IWindowManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.GridView; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.internal.widget.LockPatternUtils; + +import java.util.List; + +/** + * Displays a list of {@link AppWidgetProviderInfo} widgets, along with any + * injected special widgets specified through + * {@link AppWidgetManager#EXTRA_CUSTOM_INFO} and + * {@link AppWidgetManager#EXTRA_CUSTOM_EXTRAS}. + * <p> + * When an installed {@link AppWidgetProviderInfo} is selected, this activity + * will bind it to the given {@link AppWidgetManager#EXTRA_APPWIDGET_ID}, + * otherwise it will return the requested extras. + */ +public class KeyguardAppWidgetPickActivity extends Activity + implements GridView.OnItemClickListener, + AppWidgetLoader.ItemConstructor<KeyguardAppWidgetPickActivity.Item> { + private static final String TAG = "KeyguardAppWidgetPickActivity"; + private static final int REQUEST_PICK_APPWIDGET = 126; + private static final int REQUEST_CREATE_APPWIDGET = 127; + + private AppWidgetLoader<Item> mAppWidgetLoader; + private List<Item> mItems; + private GridView mGridView; + private AppWidgetManager mAppWidgetManager; + private int mAppWidgetId; + // Might make it possible to make this be false in future + private boolean mAddingToKeyguard = true; + private Intent mResultData; + private LockPatternUtils mLockPatternUtils; + private boolean mSuccess; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setContentView(R.layout.keyguard_appwidget_pick_layout); + super.onCreate(savedInstanceState); + + // Set default return data + setResultData(RESULT_CANCELED, null); + + // Read the appWidgetId passed our direction, otherwise bail if not found + final Intent intent = getIntent(); + if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) { + mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID); + } else { + finish(); + } + + mGridView = (GridView) findViewById(R.id.widget_list); + mAppWidgetManager = AppWidgetManager.getInstance(this); + mAppWidgetLoader = new AppWidgetLoader<Item>(this, mAppWidgetManager, this); + mItems = mAppWidgetLoader.getItems(getIntent()); + AppWidgetAdapter adapter = new AppWidgetAdapter(this, mItems); + mGridView.setAdapter(adapter); + mGridView.setOnItemClickListener(this); + + mLockPatternUtils = new LockPatternUtils(this); // TEMP-- we want to delete this + } + + /** + * Convenience method for setting the result code and intent. This method + * correctly injects the {@link AppWidgetManager#EXTRA_APPWIDGET_ID} that + * most hosts expect returned. + */ + void setResultData(int code, Intent intent) { + Intent result = intent != null ? intent : new Intent(); + result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); + mResultData = result; + setResult(code, result); + } + + private static class EmptyDrawable extends Drawable { + private final int mWidth; + private final int mHeight; + + EmptyDrawable(int width, int height) { + mWidth = width; + mHeight = height; + } + + @Override + public int getIntrinsicWidth() { + return mWidth; + } + + @Override + public int getIntrinsicHeight() { + return mHeight; + } + + @Override + public int getMinimumWidth() { + return mWidth; + } + + @Override + public int getMinimumHeight() { + return mHeight; + } + + @Override + public void draw(Canvas canvas) { + } + + @Override + public void setAlpha(int alpha) { + } + + @Override + public void setColorFilter(ColorFilter cf) { + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + } + + /** + * Utility class to resize icons to match default icon size. Code is mostly + * borrowed from Launcher. + */ + private static class IconResizer { + private final int mIconWidth; + private final int mIconHeight; + + private final DisplayMetrics mMetrics; + private final Rect mOldBounds = new Rect(); + private final Canvas mCanvas = new Canvas(); + + public IconResizer(int width, int height, DisplayMetrics metrics) { + mCanvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.DITHER_FLAG, + Paint.FILTER_BITMAP_FLAG)); + + mMetrics = metrics; + mIconWidth = width; + mIconHeight = height; + } + + /** + * Returns a Drawable representing the thumbnail of the specified Drawable. + * The size of the thumbnail is defined by the dimension + * android.R.dimen.launcher_application_icon_size. + * + * This method is not thread-safe and should be invoked on the UI thread only. + * + * @param icon The icon to get a thumbnail of. + * + * @return A thumbnail for the specified icon or the icon itself if the + * thumbnail could not be created. + */ + public Drawable createIconThumbnail(Drawable icon) { + int width = mIconWidth; + int height = mIconHeight; + + if (icon == null) { + return new EmptyDrawable(width, height); + } + + try { + if (icon instanceof PaintDrawable) { + PaintDrawable painter = (PaintDrawable) icon; + painter.setIntrinsicWidth(width); + painter.setIntrinsicHeight(height); + } else if (icon instanceof BitmapDrawable) { + // Ensure the bitmap has a density. + BitmapDrawable bitmapDrawable = (BitmapDrawable) icon; + Bitmap bitmap = bitmapDrawable.getBitmap(); + if (bitmap.getDensity() == Bitmap.DENSITY_NONE) { + bitmapDrawable.setTargetDensity(mMetrics); + } + } + int iconWidth = icon.getIntrinsicWidth(); + int iconHeight = icon.getIntrinsicHeight(); + + if (iconWidth > 0 && iconHeight > 0) { + if (width < iconWidth || height < iconHeight) { + final float ratio = (float) iconWidth / iconHeight; + + if (iconWidth > iconHeight) { + height = (int) (width / ratio); + } else if (iconHeight > iconWidth) { + width = (int) (height * ratio); + } + + final Bitmap.Config c = icon.getOpacity() != PixelFormat.OPAQUE ? + Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; + final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c); + final Canvas canvas = mCanvas; + canvas.setBitmap(thumb); + // Copy the old bounds to restore them later + // If we were to do oldBounds = icon.getBounds(), + // the call to setBounds() that follows would + // change the same instance and we would lose the + // old bounds + mOldBounds.set(icon.getBounds()); + final int x = (mIconWidth - width) / 2; + final int y = (mIconHeight - height) / 2; + icon.setBounds(x, y, x + width, y + height); + icon.draw(canvas); + icon.setBounds(mOldBounds); + //noinspection deprecation + icon = new BitmapDrawable(thumb); + ((BitmapDrawable) icon).setTargetDensity(mMetrics); + canvas.setBitmap(null); + } else if (iconWidth < width && iconHeight < height) { + final Bitmap.Config c = Bitmap.Config.ARGB_8888; + final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c); + final Canvas canvas = mCanvas; + canvas.setBitmap(thumb); + mOldBounds.set(icon.getBounds()); + final int x = (width - iconWidth) / 2; + final int y = (height - iconHeight) / 2; + icon.setBounds(x, y, x + iconWidth, y + iconHeight); + icon.draw(canvas); + icon.setBounds(mOldBounds); + //noinspection deprecation + icon = new BitmapDrawable(thumb); + ((BitmapDrawable) icon).setTargetDensity(mMetrics); + canvas.setBitmap(null); + } + } + + } catch (Throwable t) { + icon = new EmptyDrawable(width, height); + } + + return icon; + } + } + + /** + * Item that appears in the AppWidget picker grid. + */ + public static class Item implements AppWidgetLoader.LabelledItem { + protected static IconResizer sResizer; + + protected IconResizer getResizer(Context context) { + if (sResizer == null) { + final Resources resources = context.getResources(); + int size = (int) resources.getDimension(android.R.dimen.app_icon_size); + sResizer = new IconResizer(size, size, resources.getDisplayMetrics()); + } + return sResizer; + } + CharSequence label; + Drawable icon; + String packageName; + String className; + Bundle extras; + + /** + * Create a list item from given label and icon. + */ + Item(Context context, CharSequence label, Drawable icon) { + this.label = label; + this.icon = getResizer(context).createIconThumbnail(icon); + } + + /** + * Create a list item and fill it with details from the given + * {@link ResolveInfo} object. + */ + Item(Context context, PackageManager pm, ResolveInfo resolveInfo) { + label = resolveInfo.loadLabel(pm); + if (label == null && resolveInfo.activityInfo != null) { + label = resolveInfo.activityInfo.name; + } + + icon = getResizer(context).createIconThumbnail(resolveInfo.loadIcon(pm)); + packageName = resolveInfo.activityInfo.applicationInfo.packageName; + className = resolveInfo.activityInfo.name; + } + + /** + * Build the {@link Intent} described by this item. If this item + * can't create a valid {@link android.content.ComponentName}, it will return + * {@link Intent#ACTION_CREATE_SHORTCUT} filled with the item label. + */ + Intent getIntent() { + Intent intent = new Intent(); + if (packageName != null && className != null) { + // Valid package and class, so fill details as normal intent + intent.setClassName(packageName, className); + if (extras != null) { + intent.putExtras(extras); + } + } else { + // No valid package or class, so treat as shortcut with label + intent.setAction(Intent.ACTION_CREATE_SHORTCUT); + intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label); + } + return intent; + } + + public CharSequence getLabel() { + return label; + } + } + + @Override + public Item createItem(Context context, AppWidgetProviderInfo info, Bundle extras) { + CharSequence label = info.label; + Drawable icon = null; + + if (info.icon != 0) { + try { + final Resources res = context.getResources(); + final int density = res.getDisplayMetrics().densityDpi; + int iconDensity; + switch (density) { + case DisplayMetrics.DENSITY_MEDIUM: + iconDensity = DisplayMetrics.DENSITY_LOW; + case DisplayMetrics.DENSITY_TV: + iconDensity = DisplayMetrics.DENSITY_MEDIUM; + case DisplayMetrics.DENSITY_HIGH: + iconDensity = DisplayMetrics.DENSITY_MEDIUM; + case DisplayMetrics.DENSITY_XHIGH: + iconDensity = DisplayMetrics.DENSITY_HIGH; + case DisplayMetrics.DENSITY_XXHIGH: + iconDensity = DisplayMetrics.DENSITY_XHIGH; + default: + // The density is some abnormal value. Return some other + // abnormal value that is a reasonable scaling of it. + iconDensity = (int)((density*0.75f)+.5f); + } + Resources packageResources = getPackageManager(). + getResourcesForApplication(info.provider.getPackageName()); + icon = packageResources.getDrawableForDensity(info.icon, iconDensity); + } catch (NameNotFoundException e) { + Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) + + " for provider: " + info.provider); + } + if (icon == null) { + Log.w(TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) + + " for provider: " + info.provider); + } + } + + Item item = new Item(context, label, icon); + item.packageName = info.provider.getPackageName(); + item.className = info.provider.getClassName(); + item.extras = extras; + return item; + } + + protected static class AppWidgetAdapter extends BaseAdapter { + private final LayoutInflater mInflater; + private final List<Item> mItems; + + /** + * Create an adapter for the given items. + */ + public AppWidgetAdapter(Context context, List<Item> items) { + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mItems = items; + } + + /** + * {@inheritDoc} + */ + public int getCount() { + return mItems.size(); + } + + /** + * {@inheritDoc} + */ + public Object getItem(int position) { + return mItems.get(position); + } + + /** + * {@inheritDoc} + */ + public long getItemId(int position) { + return position; + } + + /** + * {@inheritDoc} + */ + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = mInflater.inflate(R.layout.keyguard_appwidget_item, parent, false); + } + + Item item = (Item) getItem(position); + TextView textView = (TextView) convertView.findViewById(R.id.icon_and_label); + textView.setText(item.label); + textView.setCompoundDrawablesWithIntrinsicBounds(item.icon, null, null, null); + + return convertView; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + Item item = mItems.get(position); + Intent intent = item.getIntent(); + + int result; + if (item.extras != null) { + // If these extras are present it's because this entry is custom. + // Don't try to bind it, just pass it back to the app. + result = RESULT_OK; + setResultData(result, intent); + } else { + try { + Bundle options = null; + if (intent.getExtras() != null) { + options = intent.getExtras().getBundle( + AppWidgetManager.EXTRA_APPWIDGET_OPTIONS); + } + mAppWidgetManager.bindAppWidgetId(mAppWidgetId, intent.getComponent(), options); + result = RESULT_OK; + } catch (IllegalArgumentException e) { + // This is thrown if they're already bound, or otherwise somehow + // bogus. Set the result to canceled, and exit. The app *should* + // clean up at this point. We could pass the error along, but + // it's not clear that that's useful -- the widget will simply not + // appear. + result = RESULT_CANCELED; + } + setResultData(result, null); + } + if (mAddingToKeyguard) { + onActivityResult(REQUEST_PICK_APPWIDGET, result, mResultData); + } else { + finish(); + } + } + + protected void onDestroy() { + if (!mSuccess && mAddingToKeyguard && + mAppWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { + AppWidgetHost.deleteAppWidgetIdForSystem(mAppWidgetId); + } + super.onDestroy(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET) { + int appWidgetId = (data == null) ? -1 : data.getIntExtra( + AppWidgetManager.EXTRA_APPWIDGET_ID, -1); + if ((requestCode == REQUEST_PICK_APPWIDGET) && + resultCode == Activity.RESULT_OK) { + AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this); + boolean defaultWidget = + data.getBooleanExtra(LockPatternUtils.EXTRA_DEFAULT_WIDGET, false); + + AppWidgetProviderInfo appWidget = null; + if (!defaultWidget) { + appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId); + } + + if (!defaultWidget && appWidget.configure != null) { + // Launch over to configure widget, if needed + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); + intent.setComponent(appWidget.configure); + intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); + + startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET); + } else { + // Otherwise just add it + if (defaultWidget) { + // If we selected "none", delete the allocated id + AppWidgetHost.deleteAppWidgetIdForSystem(appWidgetId); + data.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, + LockPatternUtils.ID_DEFAULT_STATUS_WIDGET); + } + onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); + } + } else if (requestCode == REQUEST_CREATE_APPWIDGET && resultCode == Activity.RESULT_OK) { + mSuccess = true; + mLockPatternUtils.addAppWidget(appWidgetId, 0); + finishDelayedAndShowLockScreen(); + } else { + finishDelayedAndShowLockScreen(); + } + } + } + + private void finishDelayedAndShowLockScreen() { + IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE); + IWindowManager iWm = IWindowManager.Stub.asInterface(b); + try { + iWm.lockNow(null); + } catch (RemoteException e) { + } + + // Change background to all black + ViewGroup root = (ViewGroup) findViewById(R.id.layout_root); + root.setBackgroundColor(0xFF000000); + // Hide all children + final int childCount = root.getChildCount(); + for (int i = 0; i < childCount; i++) { + root.getChildAt(i).setVisibility(View.INVISIBLE); + } + mGridView.postDelayed(new Runnable() { + public void run() { + finish(); + } + }, 500); + } + + void startActivityForResultSafely(Intent intent, int requestCode) { + try { + startActivityForResult(intent, requestCode); + } catch (ActivityNotFoundException e) { + Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); + } catch (SecurityException e) { + Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); + Log.e(TAG, "Settings does not have the permission to launch " + intent, e); + } + } +} diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 7a5118b..22812b2 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -22,20 +22,12 @@ import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; import android.app.Activity; import android.app.AlertDialog; import android.app.admin.DevicePolicyManager; -import android.appwidget.AppWidgetHost; -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProviderInfo; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.UserHandle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; @@ -47,8 +39,6 @@ import android.provider.Settings; import android.security.KeyStore; import android.telephony.TelephonyManager; import android.util.Log; -import android.view.IWindowManager; -import android.widget.Toast; import com.android.internal.widget.LockPatternUtils; @@ -65,8 +55,6 @@ public class SecuritySettings extends SettingsPreferenceFragment // Lock Settings private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; - private static final String KEY_CHOOSE_LOCKSCREEN_WIDGET = - "choose_user_selected_lockscreen_widget"; private static final String KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING = "biometric_weak_improve_matching"; private static final String KEY_BIOMETRIC_WEAK_LIVELINESS = "biometric_weak_liveliness"; @@ -76,12 +64,9 @@ public class SecuritySettings extends SettingsPreferenceFragment private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category"; private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout"; private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings"; - private static final String EXTRA_DEFAULT_WIDGET = "com.android.settings.DEFAULT_WIDGET"; private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123; private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124; private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125; - private static final int REQUEST_PICK_APPWIDGET = 126; - private static final int REQUEST_CREATE_APPWIDGET = 127; // Misc Settings private static final String KEY_SIM_LOCK = "sim_lock"; @@ -421,68 +406,6 @@ public class SecuritySettings extends SettingsPreferenceFragment } } - void startActivityForResultSafely(Intent intent, int requestCode) { - try { - startActivityForResult(intent, requestCode); - } catch (ActivityNotFoundException e) { - Toast.makeText(getActivity(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); - } catch (SecurityException e) { - Toast.makeText(getActivity(), R.string.activity_not_found, Toast.LENGTH_SHORT).show(); - Log.e(TAG, "Settings does not have the permission to launch " + intent, e); - } - } - - private void launchPickActivityIntent(int featuresFilter, int defaultLabelId, int defaultIconId, - ComponentName defaultComponentName, String defaultTag, int widgetType) { - // Create intent to pick widget - Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK); - - // Found in KeyguardHostView.java - final int KEYGUARD_HOST_ID = 0x4B455947; - int appWidgetId = AppWidgetHost.allocateAppWidgetIdForSystem(KEYGUARD_HOST_ID); - if (appWidgetId != -1) { - pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_SORT, false); - pickIntent.putExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER, - AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD); - if (featuresFilter != AppWidgetProviderInfo.WIDGET_FEATURES_NONE) { - pickIntent.putExtra(AppWidgetManager.EXTRA_FEATURES_FILTER, featuresFilter); - } - - // Add an entry for "none" to let someone select no widget - AppWidgetProviderInfo defaultInfo = new AppWidgetProviderInfo(); - ArrayList<AppWidgetProviderInfo> extraInfos = new ArrayList<AppWidgetProviderInfo>(); - defaultInfo.label = getResources().getString(defaultLabelId); - defaultInfo.icon = defaultIconId; - defaultInfo.provider = defaultComponentName; - extraInfos.add(defaultInfo); - - ArrayList<Bundle> extraExtras = new ArrayList<Bundle>(); - Bundle b = new Bundle(); - b.putBoolean(defaultTag, true); - extraExtras.add(b); - - // Launch the widget picker - pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_INFO, extraInfos); - pickIntent.putExtra(AppWidgetManager.EXTRA_CUSTOM_EXTRAS, extraExtras); - pickIntent.putExtra(Intent.EXTRA_INTENT, getBaseIntent()); - startActivityForResult(pickIntent, widgetType); - } else { - Log.e(TAG, "Unable to allocate an AppWidget id in lock screen"); - } - } - - private Intent getBaseIntent() { - Intent baseIntent = new Intent(Intent.ACTION_MAIN, null); - baseIntent.addCategory(Intent.CATEGORY_DEFAULT); - - Bundle options = new Bundle(); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, - AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD); - baseIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options); - return baseIntent; - } - @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { final String key = preference.getKey(); @@ -491,18 +414,6 @@ public class SecuritySettings extends SettingsPreferenceFragment if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) { startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment", SET_OR_CHANGE_LOCK_METHOD_REQUEST, null); - } else if (KEY_CHOOSE_LOCKSCREEN_WIDGET.equals(key)) { - int defaultIconId; - ComponentName clock = new ComponentName( - "com.google.android.deskclock", "com.android.deskclock.DeskClock"); - try { - defaultIconId = getActivity().getPackageManager().getActivityInfo(clock, 0).icon; - } catch (PackageManager.NameNotFoundException e) { - defaultIconId = 0; - } - launchPickActivityIntent(AppWidgetProviderInfo.WIDGET_FEATURES_NONE, - R.string.widget_default, defaultIconId, clock, EXTRA_DEFAULT_WIDGET, - REQUEST_PICK_APPWIDGET); } else if (KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING.equals(key)) { ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this.getActivity(), this); @@ -583,48 +494,6 @@ public class SecuritySettings extends SettingsPreferenceFragment // is called by grabbing the value from lockPatternUtils. We can't set it here // because mBiometricWeakLiveliness could be null return; - } else if (requestCode == REQUEST_PICK_APPWIDGET || requestCode == REQUEST_CREATE_APPWIDGET) { - int appWidgetId = (data == null) ? -1 : data.getIntExtra( - AppWidgetManager.EXTRA_APPWIDGET_ID, -1); - if ((requestCode == REQUEST_PICK_APPWIDGET) && - resultCode == Activity.RESULT_OK) { - AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getActivity()); - boolean defaultWidget = data.getBooleanExtra(EXTRA_DEFAULT_WIDGET, false); - - AppWidgetProviderInfo appWidget = null; - if (!defaultWidget) { - appWidget = appWidgetManager.getAppWidgetInfo(appWidgetId); - } - - if (!defaultWidget && appWidget.configure != null) { - // Launch over to configure widget, if needed - Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); - intent.setComponent(appWidget.configure); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - - startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET); - } else { - // Otherwise just add it - if (defaultWidget) { - // If we selected "none", delete the allocated id - AppWidgetHost.deleteAppWidgetIdForSystem(appWidgetId); - data.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, - LockPatternUtils.ID_DEFAULT_STATUS_WIDGET); - } - onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); - } - } else if (requestCode == REQUEST_CREATE_APPWIDGET && resultCode == Activity.RESULT_OK) { - mLockPatternUtils.addAppWidget(appWidgetId, 0); - - IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE); - IWindowManager iWm = IWindowManager.Stub.asInterface(b); - try { - iWm.lockNow(null); - } catch (RemoteException e) { - } - } else { - AppWidgetHost.deleteAppWidgetIdForSystem(appWidgetId); - } } createPreferenceHierarchy(); } |