diff options
5 files changed, 206 insertions, 98 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index f482335..b94f0b9 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3229,6 +3229,13 @@ public final class Settings { "lock_screen_appwidget_ids"; /** + * Id of the appwidget shown on the lock screen when appwidgets are disabled. + * @hide + */ + public static final String LOCK_SCREEN_FALLBACK_APPWIDGET_ID = + "lock_screen_fallback_appwidget_id"; + + /** * Index of the lockscreen appwidget to restore, -1 if none. * @hide */ diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index e5e1a2b..47d501c 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -18,6 +18,7 @@ package com.android.internal.widget; import android.app.ActivityManagerNative; import android.app.admin.DevicePolicyManager; +import android.appwidget.AppWidgetManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -35,6 +36,7 @@ import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import android.view.IWindowManager; import android.view.View; import android.widget.Button; @@ -1112,6 +1114,25 @@ public class LockPatternUtils { return sb.toString(); } + // appwidget used when appwidgets are disabled (we make an exception for + // default clock widget) + public void writeFallbackAppWidgetId(int appWidgetId) { + Settings.Secure.putIntForUser(mContentResolver, + Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID, + appWidgetId, + UserHandle.USER_CURRENT); + } + + // appwidget used when appwidgets are disabled (we make an exception for + // default clock widget) + public int getFallbackAppWidgetId() { + return Settings.Secure.getIntForUser( + mContentResolver, + Settings.Secure.LOCK_SCREEN_FALLBACK_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID, + UserHandle.USER_CURRENT); + } + private void writeAppWidgets(int[] appWidgetIds) { Settings.Secure.putStringForUser(mContentResolver, Settings.Secure.LOCK_SCREEN_APPWIDGET_IDS, @@ -1325,5 +1346,15 @@ public class LockPatternUtils { public boolean getPowerButtonInstantlyLocks() { return getBoolean(LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS, true); } + + public static boolean isSafeModeEnabled() { + try { + return IWindowManager.Stub.asInterface( + ServiceManager.getService("window")).isSafeModeEnabled(); + } catch (RemoteException e) { + // Shouldn't happen! + } + return false; + } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 9fe3144..68783c3 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -37,6 +37,8 @@ import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; +import android.os.SystemProperties; +import android.os.UserHandle; import android.os.UserManager; import android.util.AttributeSet; import android.util.Log; @@ -57,7 +59,7 @@ import java.io.File; import java.util.List; public class KeyguardHostView extends KeyguardViewBase { - private static final String TAG = "KeyguardViewHost"; + private static final String TAG = "KeyguardHostView"; // Use this to debug all of keyguard public static boolean DEBUG = KeyguardViewMediator.DEBUG; @@ -87,6 +89,12 @@ public class KeyguardHostView extends KeyguardViewBase { private Rect mTempRect = new Rect(); + private int mDisabledFeatures; + + private boolean mCameraDisabled; + + private boolean mSafeModeEnabled; + /*package*/ interface TransportCallback { void onListenerDetached(); void onListenerAttached(); @@ -113,6 +121,25 @@ public class KeyguardHostView extends KeyguardViewBase { mSecurityModel = new KeyguardSecurityModel(context); mViewStateManager = new KeyguardViewStateManager(this); + + DevicePolicyManager dpm = + (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); + if (dpm != null) { + mDisabledFeatures = getDisabledFeatures(dpm); + mCameraDisabled = dpm.getCameraDisabled(null); + } + + mSafeModeEnabled = LockPatternUtils.isSafeModeEnabled(); + + if (mSafeModeEnabled) { + Log.v(TAG, "Keyguard widgets disabled by safe mode"); + } + if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) { + Log.v(TAG, "Keyguard widgets disabled by DPM"); + } + if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) { + Log.v(TAG, "Keyguard secure camera disabled by DPM"); + } } @Override @@ -177,9 +204,10 @@ public class KeyguardHostView extends KeyguardViewBase { } addDefaultWidgets(); + addWidgetsFromSettings(); + checkAppWidgetConsistency(); mSwitchPageRunnable.run(); - // This needs to be called after the pages are all added. mViewStateManager.showUsabilityHints(); @@ -187,6 +215,24 @@ public class KeyguardHostView extends KeyguardViewBase { updateSecurityViews(); } + private int getDisabledFeatures(DevicePolicyManager dpm) { + int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; + if (dpm != null) { + final int currentUser = mLockPatternUtils.getCurrentUser(); + disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser); + } + return disabledFeatures; + } + + private boolean widgetsDisabledByDpm() { + return (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0; + } + + private boolean cameraDisabledByDpm() { + return mCameraDisabled + || (mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0; + } + private void updateSecurityViews() { int children = mSecurityViewContainer.getChildCount(); for (int i = 0; i < children; i++) { @@ -821,15 +867,18 @@ public class KeyguardHostView extends KeyguardViewBase { } } - private boolean addWidget(int appId, int pageIndex) { + private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) { AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId); if (appWidgetInfo != null) { AppWidgetHostView view = getAppWidgetHost().createView(mContext, appId, appWidgetInfo); addWidget(view, pageIndex); return true; } else { - Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting"); - mLockPatternUtils.removeAppWidget(appId); + if (updateDbIfFailed) { + Log.w(TAG, "AppWidgetInfo for app widget id " + appId + " was null, deleting"); + mAppWidgetHost.deleteAppWidgetId(appId); + mLockPatternUtils.removeAppWidget(appId); + } return false; } } @@ -885,9 +934,28 @@ public class KeyguardHostView extends KeyguardViewBase { LayoutInflater inflater = LayoutInflater.from(mContext); inflater.inflate(R.layout.keyguard_transport_control_view, this, true); - View addWidget = inflater.inflate(R.layout.keyguard_add_widget, null, true); - mAppWidgetContainer.addWidget(addWidget); - if (mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) { + if (!mSafeModeEnabled && !widgetsDisabledByDpm()) { + View addWidget = inflater.inflate(R.layout.keyguard_add_widget, this, false); + mAppWidgetContainer.addWidget(addWidget); + View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view); + addWidgetButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); + if (appWidgetId != -1) { + mActivityLauncher.launchWidgetPicker(appWidgetId); + } else { + Log.e(TAG, "Unable to allocate an AppWidget id in lock screen"); + } + } + }); + } + + // We currently disable cameras in safe mode because we support loading 3rd party + // cameras we can't trust. TODO: plumb safe mode into camera creation code and only + // inflate system-provided camera? + if (!mSafeModeEnabled && !cameraDisabledByDpm() + && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) { View cameraWidget = CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher); if (cameraWidget != null) { @@ -895,19 +963,6 @@ public class KeyguardHostView extends KeyguardViewBase { } } - View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view); - addWidgetButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); - if (appWidgetId != -1) { - mActivityLauncher.launchWidgetPicker(appWidgetId); - } else { - Log.e(TAG, "Unable to allocate an AppWidget id in lock screen"); - } - } - }); - enableUserSelectorIfNecessary(); initializeTransportControl(); } @@ -969,14 +1024,15 @@ public class KeyguardHostView extends KeyguardViewBase { } } - private int getAddPageIndex() { + private int getInsertPageIndex() { View addWidget = mAppWidgetContainer.findViewById(R.id.keyguard_add_widget); - int addPageIndex = mAppWidgetContainer.indexOfChild(addWidget); - // This shouldn't happen, but just to be safe! - if (addPageIndex < 0) { - addPageIndex = 0; + int insertionIndex = mAppWidgetContainer.indexOfChild(addWidget); + if (insertionIndex < 0) { + insertionIndex = 0; // no add widget page found + } else { + insertionIndex++; // place after add widget } - return addPageIndex; + return insertionIndex; } private void addDefaultStatusWidget(int index) { @@ -986,18 +1042,11 @@ public class KeyguardHostView extends KeyguardViewBase { } private void addWidgetsFromSettings() { - DevicePolicyManager dpm = - (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); - if (dpm != null) { - final int currentUser = mLockPatternUtils.getCurrentUser(); - final int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, currentUser); - if ((disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_WIDGETS_ALL) != 0) { - Log.v(TAG, "Keyguard widgets disabled because of device policy admin"); - return; - } + if (mSafeModeEnabled || widgetsDisabledByDpm()) { + return; } - int addPageIndex = getAddPageIndex(); + int insertionIndex = getInsertPageIndex(); // Add user-selected widget final int[] widgets = mLockPatternUtils.getAppWidgets(); @@ -1007,50 +1056,90 @@ public class KeyguardHostView extends KeyguardViewBase { } else { for (int i = widgets.length -1; i >= 0; i--) { if (widgets[i] == LockPatternUtils.ID_DEFAULT_STATUS_WIDGET) { - addDefaultStatusWidget(addPageIndex + 1); + addDefaultStatusWidget(insertionIndex); } else { // We add the widgets from left to right, starting after the first page after // the add page. We count down, since the order will be persisted from right // to left, starting after camera. - addWidget(widgets[i], addPageIndex + 1); + addWidget(widgets[i], insertionIndex, true); } } } - checkAppWidgetConsistency(); + } + + private int allocateIdForDefaultAppWidget() { + int appWidgetId; + Resources res = getContext().getResources(); + ComponentName defaultAppWidget = new ComponentName( + res.getString(R.string.widget_default_package_name), + res.getString(R.string.widget_default_class_name)); + + // Note: we don't support configuring the widget + appWidgetId = mAppWidgetHost.allocateAppWidgetId(); + + try { + mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget); + + } catch (IllegalArgumentException e) { + Log.e(TAG, "Error when trying to bind default AppWidget: " + e); + mAppWidgetHost.deleteAppWidgetId(appWidgetId); + appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; + } + return appWidgetId; } public void checkAppWidgetConsistency() { final int childCount = mAppWidgetContainer.getChildCount(); boolean widgetPageExists = false; for (int i = 0; i < childCount; i++) { - if (isWidgetPage(i)) { + if (mAppWidgetContainer.isWidgetPage(i)) { widgetPageExists = true; break; } } if (!widgetPageExists) { - final int addPageIndex = getAddPageIndex(); - - Resources res = getContext().getResources(); - ComponentName defaultAppWidget = new ComponentName( - res.getString(R.string.widget_default_package_name), - res.getString(R.string.widget_default_class_name)); - - // Note: we don't support configuring the widget - int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); - boolean bindSuccessful = false; - try { - mAppWidgetManager.bindAppWidgetId(appWidgetId, defaultAppWidget); - bindSuccessful = true; - } catch (IllegalArgumentException e) { - Log.e(TAG, "Error when trying to bind default AppWidget: " + e); + final int insertPageIndex = getInsertPageIndex(); + + final boolean userAddedWidgetsEnabled = !widgetsDisabledByDpm(); + boolean addedDefaultAppWidget = false; + + if (!mSafeModeEnabled) { + if (userAddedWidgetsEnabled) { + int appWidgetId = allocateIdForDefaultAppWidget(); + if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { + addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, true); + } + } else { + // note: even if widgetsDisabledByDpm() returns true, we still bind/create + // the default appwidget if possible + int appWidgetId = mLockPatternUtils.getFallbackAppWidgetId(); + if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { + appWidgetId = allocateIdForDefaultAppWidget(); + if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { + mLockPatternUtils.writeFallbackAppWidgetId(appWidgetId); + } + } + if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) { + addedDefaultAppWidget = addWidget(appWidgetId, insertPageIndex, false); + if (!addedDefaultAppWidget) { + mAppWidgetHost.deleteAppWidgetId(appWidgetId); + mLockPatternUtils.writeFallbackAppWidgetId( + AppWidgetManager.INVALID_APPWIDGET_ID); + } + } + } } + // Use the built-in status/clock view if we can't inflate the default widget - if (!(bindSuccessful && addWidget(appWidgetId, addPageIndex + 1))) { - addDefaultStatusWidget(addPageIndex + 1); + if (!addedDefaultAppWidget) { + addDefaultStatusWidget(insertPageIndex); + } + + // trigger DB updates only if user-added widgets are enabled + if (!mSafeModeEnabled && userAddedWidgetsEnabled) { + mAppWidgetContainer.onAddView( + mAppWidgetContainer.getChildAt(insertPageIndex), insertPageIndex); } - mAppWidgetContainer.onAddView( - mAppWidgetContainer.getChildAt(addPageIndex + 1), addPageIndex + 1); } } @@ -1154,15 +1243,6 @@ public class KeyguardHostView extends KeyguardViewBase { return null; } - private boolean isWidgetPage(int pageIndex) { - View v = mAppWidgetContainer.getChildAt(pageIndex); - if (v != null && v instanceof KeyguardWidgetFrame) { - KeyguardWidgetFrame kwf = (KeyguardWidgetFrame) v; - return kwf.getContentAppWidgetId() != AppWidgetManager.INVALID_APPWIDGET_ID; - } - return false; - } - private int getStickyWidget() { // The first time we query the persistent state. From that point, we use a locally updated // notion of the sticky widget page. diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java index 9e3424d..6fcacd3 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewBase.java @@ -260,4 +260,5 @@ public abstract class KeyguardViewBase extends FrameLayout { KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) { mViewMediatorCallback = viewMediatorCallback; } + } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index c930ecc..9caeb0d 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -22,9 +22,9 @@ import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.TimeInterpolator; import android.appwidget.AppWidgetHostView; +import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; -import android.content.res.Resources; import android.os.Handler; import android.os.HandlerThread; import android.util.AttributeSet; @@ -38,7 +38,6 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.widget.FrameLayout; -import com.android.internal.R; import com.android.internal.widget.LockPatternUtils; import java.util.ArrayList; @@ -69,8 +68,6 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit private int mPage = 0; private Callbacks mCallbacks; - private boolean mCameraWidgetEnabled; - private int mWidgetToResetAfterFadeOut; // Bouncer @@ -97,10 +94,6 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit setPageSwitchListener(this); - Resources r = getResources(); - mCameraWidgetEnabled = r.getBoolean(R.bool.kg_enable_camera_default_widget); - mCenterSmallWidgetsVertically = - r.getBoolean(com.android.internal.R.bool.kg_center_small_widgets_vertically); mBackgroundWorkerThread = new HandlerThread("KeyguardWidgetPager Worker"); mBackgroundWorkerThread.start(); mBackgroundWorkerHandler = new Handler(mBackgroundWorkerThread.getLooper()); @@ -485,35 +478,31 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } } + public boolean isWidgetPage(int pageIndex) { + if (pageIndex < 0 || pageIndex >= getChildCount()) { + return false; + } + View v = getChildAt(pageIndex); + if (v != null && v instanceof KeyguardWidgetFrame) { + KeyguardWidgetFrame kwf = (KeyguardWidgetFrame) v; + return kwf.getContentAppWidgetId() != AppWidgetManager.INVALID_APPWIDGET_ID; + } + return false; + } + @Override void boundByReorderablePages(boolean isReordering, int[] range) { if (isReordering) { - if (isAddWidgetPageVisible()) { - range[0]++; - } - if (isMusicWidgetVisible()) { + // Remove non-widget pages from the range + while (range[1] > range[0] && !isWidgetPage(range[1])) { range[1]--; } - if (isCameraWidgetVisible()) { - range[1]--; + while (range[0] < range[1] && !isWidgetPage(range[0])) { + range[0]++; } } } - /* - * Special widgets - */ - boolean isAddWidgetPageVisible() { - // TODO: Make proper test once we decide whether the add-page is always showing - return true; - } - boolean isMusicWidgetVisible() { - return mViewStateManager.getTransportState() != KeyguardViewStateManager.TRANSPORT_GONE; - } - boolean isCameraWidgetVisible() { - return mCameraWidgetEnabled; - } - protected void reorderStarting() { showOutlinesAndSidePages(); } @@ -761,7 +750,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit boolean isAddPage(int pageIndex) { View v = getChildAt(pageIndex); - return v != null && v.getId() == R.id.keyguard_add_widget; + return v != null && v.getId() == com.android.internal.R.id.keyguard_add_widget; } boolean isCameraPage(int pageIndex) { |